Действительно, отличная статья, спасибо за время и усилия, которые вы потратили на написание кода и поделились им с сообществом.
Есть простой вопрос: "В исследованиях, которые мы адаптируем, они сосредоточены на стратегиях, которые торгуют между открытием и закрытием рынка (с 9:30 утра до 4:00 вечера по восточному времени).Поскольку наш брокер использует UTC+2/3, это означает 18:30-24:00 по серверному времени - не забудьте сделать поправку на часовой пояс вашего брокера при тестировании".
Можете ли вы объяснить мне ход ваших мыслей по поводу конвертации времени? Я явно что-то упускаю...
Используя общий конвертер времени - мое преобразование 09:30 по восточному времени заканчивается 16:30 для mt5 в GMT+2 и 17:30 для mt5 в GMT+3. 18:30 кажется, что это 1-2 часа после открытия рынка.
Спасибо за помощь и еще раз спасибо.
Можете ли вы объяснить мне ход ваших мыслей по поводу перевода времени? Я явно что-то упускаю...
Используя общий конвертер времени, я перевел 09:30 по восточному времени в 16:30 для mt5 в GMT+2 и 17:30 для mt5 в GMT+3. 18:30 кажется, что это 1-2 часа после открытия рынка.
Спасибо за помощь и еще раз спасибо.
Вы правы, я неправильно перевел время сервера в статье для времени открытия Нью-Йоркского фондового рынка. Оно должно быть 17:30, а не 18:30. Учитывая это, вы можете предположить, что все мои правила стратегии в статье должны торговать через 1 час после открытия рынка. Спасибо, что указали на это, и извините за путаницу.
Спасибо за публикацию, очень интересно!
Вопрос по коду:
В вашей функции MarketOpened вы используете:
"if (currentHour >= startHour && currentMinute>=startMinute)return true;" <- Это похоже на то, что она будет торговать только часть часа, если рынок открыт, так как она вернет false, если вы находитесь в начале каждого часа, даже если рынок открыт. Она работает только в том случае, если минута равна 0, что не является началом рыночной сессии.
Спасибо за публикацию, очень интересно!
Вопрос по поводу кода:
В вашей функции MarketOpened вы используете:
"if (currentHour >= startHour && currentMinute>=startMinute)return true;" <- Это выглядит так, как будто он будет торговать только часть часа, если рынок открыт, поскольку он вернет false, если вы находитесь в начале каждого часа, даже если рынок открыт. Это работает только в том случае, если минута равна 0, что не является началом рыночной сессии.
ОМГ, не могу поверить, что я это пропустил. Так и должно быть:
if ((currentHour >= startHour &¤tMinute>=startMinute)||currentHour>startHour)return true;
Я искренне сожалею о небрежной ошибке. Спасибо, что так внимательно прочитали и указали на нее.
Ps. Для ORB3 я жестко закодировал время открытия рынка на 9:30. Вы можете изменить его в этих функциях, чтобы соответствовать серверному времени открытия рынка в Нью-Йорке.
//+------------------------------------------------------------------+ //| Получите значение верхней полосы бетона.| //+------------------------------------------------------------------+ double getUpperBand(int target_hour = 17, int target_min = 30) { // Получение времени текущего бара datetime current_time = iTime(_Symbol, PERIOD_CURRENT, 0); MqlDateTime current_dt; TimeToStruct(current_time, current_dt); int current_hour = current_dt.hour; int current_min = current_dt.min; // Найдите сегодняшнюю цену открытия в целевое время (например, 17:30 по серверному времени) datetime today_start = iTime(_Symbol, PERIOD_D1, 0); int bar_at_target_today = getBarShiftForTime(today_start, target_hour, target_min); if (bar_at_target_today < 0) return 0; // Возвращает 0, если целевой бар не существует double open_target_today = iOpen(_Symbol, PERIOD_M1, bar_at_target_today); if (open_target_today == 0) return 0; // Нет действующей цены // Рассчитайте сигму на основе последних 14 дней double sum_moves = 0; int valid_days = 0; for (int i = 1; i <= 14; i++) { datetime day_start = iTime(_Symbol, PERIOD_D1, i); int bar_at_target = getBarShiftForTime(day_start, target_hour, target_min); int bar_at_HHMM = getBarShiftForTime(day_start, current_hour, current_min); if (bar_at_target < 0 || bar_at_HHMM < 0) continue; // Пропустить, если бары не существуют double open_target = iOpen(_Symbol, PERIOD_M1, bar_at_target); double close_HHMM = iClose(_Symbol, PERIOD_M1, bar_at_HHMM); if (open_target == 0) continue; // Пропустить, если нет действительной цены открытия double move = MathAbs(close_HHMM / open_target - 1); sum_moves += move; valid_days++; } if (valid_days == 0) return 0; // Возвращаем 0, если нет достоверных данных double sigma = sum_moves / valid_days; // Рассчитайте верхнюю полосу double upper_band = open_target_today * (1 + sigma); // Поставьте синюю точку на уровне верхней полосы string obj_name = "UpperBand_" + TimeToString(current_time, TIME_DATE|TIME_MINUTES|TIME_SECONDS); ObjectCreate(0, obj_name, OBJ_ARROW, 0, current_time, upper_band); ObjectSetInteger(0, obj_name, OBJPROP_ARROWCODE, 159); // Символ точки ObjectSetInteger(0, obj_name, OBJPROP_COLOR, clrBlue); ObjectSetInteger(0, obj_name, OBJPROP_WIDTH, 2); return upper_band; } //+------------------------------------------------------------------+ //| Получите значение нижней полосы Concretum.| //+------------------------------------------------------------------+ double getLowerBand(int target_hour = 17, int target_min = 30) { // Получение времени текущего бара datetime current_time = iTime(_Symbol, PERIOD_CURRENT, 0); MqlDateTime current_dt; TimeToStruct(current_time, current_dt); int current_hour = current_dt.hour; int current_min = current_dt.min; // Найдите сегодняшнюю цену открытия в целевое время (например, 17:30 по серверному времени) datetime today_start = iTime(_Symbol, PERIOD_D1, 0); int bar_at_target_today = getBarShiftForTime(today_start, target_hour, target_min); if (bar_at_target_today < 0) return 0; // Возвращает 0, если целевой бар не существует double open_target_today = iOpen(_Symbol, PERIOD_M1, bar_at_target_today); if (open_target_today == 0) return 0; // Нет действующей цены // Рассчитайте сигму на основе последних 14 дней double sum_moves = 0; int valid_days = 0; for (int i = 1; i <= 14; i++) { datetime day_start = iTime(_Symbol, PERIOD_D1, i); int bar_at_target = getBarShiftForTime(day_start, target_hour, target_min); int bar_at_HHMM = getBarShiftForTime(day_start, current_hour, current_min); if (bar_at_target < 0 || bar_at_HHMM < 0) continue; // Пропустить, если бары не существуют double open_target = iOpen(_Symbol, PERIOD_M1, bar_at_target); double close_HHMM = iClose(_Symbol, PERIOD_M1, bar_at_HHMM); if (open_target == 0) continue; // Пропустить, если нет действительной цены открытия double move = MathAbs(close_HHMM / open_target - 1); sum_moves += move; valid_days++; } if (valid_days == 0) return 0; // Возвращаем 0, если нет достоверных данных double sigma = sum_moves / valid_days; // Рассчитайте нижнюю полосу double lower_band = open_target_today * (1 - sigma); // Поставьте красную точку на уровне нижнего диапазона string obj_name = "LowerBand_" + TimeToString(current_time, TIME_DATE|TIME_MINUTES|TIME_SECONDS); ObjectCreate(0, obj_name, OBJ_ARROW, 0, current_time, lower_band); ObjectSetInteger(0, obj_name, OBJPROP_ARROWCODE, 159); // Символ точки ObjectSetInteger(0, obj_name, OBJPROP_COLOR, clrRed); ObjectSetInteger(0, obj_name, OBJPROP_WIDTH, 2); return lower_band; }
Изменение времени расчета может быть способом дальнейшей оптимизации стратегии :)
ОМГ, не могу поверить, что пропустил это. Так и должно быть:
Я искренне сожалею о небрежной ошибке. Спасибо, что так внимательно читали и указали на нее.
Не беспокойтесь, я уже объединил открытый и закрытый рынок в одну функцию.
bool MarketState() { MqlDateTime structTime; TimeCurrent(structTime); structTime.sec = 0; structTime.hour = startHour; structTime.min = startMinute; datetime timeStart = StructToTime(structTime); structTime.hour = endHour; structTime.min = endMinute; datetime timeEnd = StructToTime(structTime); if(TimeCurrent() >= timeStart && TimeCurrent() < timeEnd)return true; else return false; }
И еще одно: вы используете данные OHLC брокера для бэктестинга, без задержки. Эти бэктесты кажутся немного оптимистичными по сравнению с бэктестами, сделанными на реальных тиковых данных со случайной задержкой на проскальзывание и реквоты.
Еще раз спасибо за ваши усилия!
Не беспокойтесь, я уже объединил открытый и закрытый рынок в одну функцию.
Еще один момент: вы используете данные OHLC брокера для бэктестинга, без задержки. Эти бэктесты кажутся немного оптимистичными по сравнению с бэктестами, сделанными на реальных тиковых данных со случайной задержкой на проскальзывание и реквоты.
Еще раз спасибо за ваши усилия!
Отличная работа над модификацией! Я обновил весь код на своем Github.
К вашему сведению, торговая логика происходит на каждом новом баре и не предполагает тикового движения. Кроме того, среднее время удержания составляет около нескольких часов, что, я думаю, не сделает проскальзывание существенной проблемой. Я бы сказал, что очень немногие брокеры предоставляют реальные тиковые данные за более чем 5 лет, и 1 мин OHLC вполне достаточно.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Опубликована статья Стратегии торговли прорыва: разбор ключевых методов:
Стратегии прорыва диапазона открытия (Opening Range Breakout, ORB) основаны на идее о том, что начальный торговый диапазон, установленный вскоре после открытия рынка, отражает значимые уровни цен, когда покупатели и продавцы договариваются о стоимости. Выявляя прорывы определенного диапазона вверх или вниз, трейдеры могут извлекать выгоду из моментума, который часто возникает, когда направление рынка становится более отчетливым.
В этой статье рассмотрим три стратегии ORB, адаптированные из статей компании Concretum Group. Сначала рассмотрим предпосылки для проведения данного исследования, включая основные концепции и используемую методологию. Затем объясним принцип работы каждой стратегии, перечислим правила использования в ней сигналов и выполним статистический анализ ее эффективности. Наконец, изучим их с точки зрения использования портфеля, уделив особое внимание теме диверсификации.
В настоящей статье мы не будем углубляться в программирование, а напротив, сконцентрируемся на исследовательском процессе, в том числе — на воссоздании, анализе и тестировании стратегий из этих трех публикаций. Это будет полезно читателям, которые ищут потенциальные преимущества в трейдинге, или тем из них, кому интересно узнать, как были изучены и воспроизведены эти стратегии. Несмотря на вышесказанное, будет раскрыт весь MQL5-код для этих советников. Читатели могут самостоятельно расширять и дополнять эту структуру.
Автор: Zhuo Kai Chen