English 中文 Español Deutsch 日本語 Português
preview
Работаем со временем (Часть 1): Основные принципы

Работаем со временем (Часть 1): Основные принципы

MetaTrader 5Тестер | 16 декабря 2021, 13:46
3 931 0
Carl Schreiber
Carl Schreiber

Какое время

Точная работа со временем — очень важный аспект трейдинга. Лондонская или нью-йоркская биржа уже открылась или еще нет? Когда начинается и заканчивается торговая сессия на форексе? Для трейдеров, торгующих вручную, проблема определения времени не такая острая. Есть множество способов определить правильное время для торговли: информация в интернете, спецификация финансового инструмента, собственное настроенное расписание и т.д. Если трейдер торгует только на основе ценовой динамики, покупает и продает при появлении сигнала на основе изменения цены, само время, вероятно, не имеет большого значения. Но ведь есть и другие трейдеры: ночные скальперы, которые торгуют после закрытия торгов на нью-йоркской бирже и до открытия торгов на европейских рынках, или же трейдеры, которые выжидают время наибольшей активности в лондонскую сессию, не говоря уже о тех, кто торгует акциями и фьючерсами. Для них время брокера не подходит, поскольку нужно использовать фактическое местное время в США, Японии, Лондоне, Европе или Москве, чтобы точно понимать, когда конкретная биржа открывается и закрывается, а при торговле фьючерсами важно понимать, когда тот или иной фьючерс торгуется.


Летнее время, зимнее время и сдвиг времени брокера

Итак, работать со временем проще, когда покупаешь и продаешь прямо у экрана компьютера. Узнать время можно в интернете, используя специальные инструменты, десктопные часы, системные функции компьютера, значения которых можно получить с помощью MQL-функций, таких как TimeGMT(), TimeGMTOffset() и др. Однако ситуация иная, если нужно написать и протестировать на исторических данных программу, которая торгует по времени. Вроде, как и в реальной торговле, ответ на этот вопрос найти несложно.

Берем время UTC (Всемирное координированное время) или время по Гринвичу (GMT, https://greenwichmeantime.com/what-is-gmt/) и добавляем необходимое смещение по времени с учетом географического расположения или торгового времени инструмента, чтобы узнать нужное время. Но не все так просто. Есть еще и переход на зимнее и летнее время, при котором время сдвигается вперед или назад на один час. Однако это не единообразный параметр — переход зависит от региональных традиций. Некоторые страны или даже целые регионы используют постоянное расписание переходов в течение многих лет (ЕС и США), а в других этот параметр может меняться, например Россия в 2014 году отменила переход на летнее/зимнее время. Подобные дискуссии проходили в 2018 году и в Европе. Там проводился опрос об отмене перевода часов (https://ec.europa.eu/germany/news/20180831-konsultation-sommerzeit_de), который показал, что большинство респондентов проголосовало за отмену. По результатам опроса Европейская комиссия представила законодательный проект об отмене перехода на зимнее и летнее время (https://ec.europa.eu/germany/news/20180914-kommission-gesetzesvorschlag-ende-zeitumstellung_de), который тем не менее ни к чему не привел.

А в добавок ко всей этой временной неразберихе сами брокеры усложняют работу тем, как они определяют время своего сервера. В 2015 году я получил такое сообщение от немецкого брокера:

  1. До 8 марта 2015 года на нашем сервере MT4 было установлено лондонское время (= GMT).
  2. С 8 по 29 марта 2015 г. время будет установлено в соответствии с CET (GMT + 1).
  3. 19 марта на сервере будет установлено лондонское время (GMT + 1)

То есть немецкий брокер использует время GMT + переход на зимнее (DST) в США или (в основном) лондонское время + DST в США. В принципе это можно понять, ведь торговая сессия на рынке форекс начинается в 17:00 по Нью-Йорку — вот тут опять все зависит от особенностей перевода часов по американскому времени. В результате, для жителей Франкфурта торговая сессия может иногда начинаться в 21:00, чаще в 22:00, а одну-две недели в году — в 23:00.

Для нас, трейдеров и клиентов, это какой-то детский сад. Каждый делает что и как хочет. Трейдерам и разработчикам приходится сталкиваться с разными значениями времени, и каждое из них может быть важным. При этом определять параметры времени нужно с использованием имеющихся ресурсов и возможностей языка MQL. Но это, к сожалению, не работает, если индикатор, скрипт или советник запущен в тестере стратегий.

В этой статье мы попробуем это изменить. Мы не будем отправлять запросы брокеру, а определим необходимое значение сдвига по времени, чтобы в любой момент можно было определить время по Гринвичу для любой временной метки в тестере стратегий и, соответственной, любое локальное время, например время по Нью-Йорку. Также, поскольку мы затронули эту тему, мы сделаем возможность определять оставшееся время до закрытия рынка. Это очень важная информация для тех, кто обычно закрывает открытые позиция перед выходными. Тем не менее, конкретно эти функции будут рассмотрены во второй статье, потому что для начала надо будет разработать макроподстановки, которые позволят упростить расчеты и представления в указанных функциях.

Макроподстановки

Весь рассмотренный здесь код доступен в прикрепленном include-файле DealingWithTimePart1.mqh. В самом начале файла представлены различные макроподстановки.

Во-первых, включены временные сдвиги разных регионов, чтобы вам не приходилось каждый раз выискивать необходимые значения:

//--- defines
#define TokyoShift   -32400                           // always 9h
#define NYShift      18000                            // winter 17h=22h GMT: NYTime + NYshift = GMT
#define LondonShift  0                                // winter London offset
#define SidneyShift  -39600                           // winter Sidney offset
#define FfmShift     -3600                            // winter Frankfurt offset
#define MoskwaShift  -10800                           // winter Moscow offset
#define FxOPEN       61200                            // = NY 17:00 = 17*3600
#define FxCLOSE      61200                            // = NY 17:00 = 17*3600
#define WeekInSec    604800                           // 60sec*60min*24h*7d = 604800 => 1 Week

Для лучшего понимания согласимся, что GMT — это неизменяемая привязка времени, в то время как разное местное время, например Нью-Йорк, Лондон или Москва, отличается от него на некое переменное смещение. Точно так же через переменную мы также будем работать с переходом на летнее или зимнее время. Причина проста. Признаки переменной разницы во времени определяются следующим образом:

                   переменное время + переменный сдвиг времени = GMT

Например:

                   Москва (16 ч) + Сдвиг по Москве (-3 ч)                                   = GMT (13 ч)
                   Нью-Йорк (16 ч) + Сдвиг по Нью-Йорку (+5 ч)                         = GMT (21 ч)
                   Нью-Йорк (16 ч) + (Сдвиг по Нью-Йорку (+5 ч) + DST_US(-1 ч)) = GMT (20 ч)
                   Франкфурт (16 ч) + (Сдвиг по Франкфурту (-1 ч) + DST_US(-1 ч)) = GMT (14 ч)

Обратите внимание на скобки! Скобки важны при расчете переменных времени от времени GMT:

                   Нью-Йорк (16 ч) =  GMT (20 ч) - (Сдвиг по Нью-Йорку (+5 ч) + DST_US(-1 ч)) => 20 -(+5 + -1) = 20 - 5 +1 = 16 ч
                   Франкфурт (16 ч) =  GMT (14 ч) - (Сдвиг по Франкфурту (-1 ч) + DST_US(-1 ч)) => 14 -( -1 + -1) = 14 +1 +1 = 16 ч

Неправильное использование скобок — наиболее частый источник ошибок в знаках.

Таким же образом MQL5 и система компьютера обрабатывают разницу во времени, например: TimeGMTOffset(): TimeLocal() + TimeGMTOffset() = TimeGMT()) или TimeDaylightSavings(): TimeLocal() + TimeDaylightSavings() = зимнее или стандартное местное время ПК.

Ну и в конце этой части упомянем FxOpen и FxClose, а также продолжительность целой недели в секундах WeekInSec - такие обозначения гораздо проще понять, чем если бы в коде мы, к примеру, неожиданно встретили значение 604800.

Добавим далее два упрощения вывода переменных. TOSTR(A) выводит имя переменной и ее значение. Также есть массив с сокращенными названиями дней недели. Такие обозначения встречаются несколько раз в коде этого проекта. Они экономят место в строке, а также позволяют правильно определять рассчитанные временные метки:

#define  TOSTR(A) #A+":"+(string)(A)+"  "             // Print (TOSTR(hGMT)); => hGMT:22 (s.b.)  
string _WkDy[] =                                      // week days
  {
   "Su.",
   "Mo.",
   "Tu.",
   "We.",
   "Th.",
   "Fr.",
   "Sa.",
   "Su."
  };

Далее представлены альтернативные варианты расчета времени, которые позволяют избежать обходного пути, связанного с использованием MQL-структуры MqlDateTime и чтением скалярного значения. Значения рассчитываются напрямую:

#define  DoWi(t) ((int)(((t-259200)%604800)/86400))      // (int)Day of Week Su=0, Mo=1,...
#define  DoWs(t) (_WkDy[DoWi(t)])                        // Day of Week as: Su., Mo., Tu., ....

Функция DoWi(t) (Day of Week as integer) будет определять день недели в виде целого числа (воскресенье = 0, понедельник = 1, и т.д.), а DoWs(t) Day of Week as string) будет возвращать сокращенное название дня недели в виде текста на основе значения DoWi(t) и массива _WkDy[]. Поскольку во второй части статьи мы будем работать с последним и первым часом выходных, мы часто будем использовать следующие макроподстановки.

#define  SoD(t) ((int)((t)%86400))                       // Seconds of Day
#define  SoW(t) ((int)((t-259200)%604800))               // Seconds of Week

Функция SoD(t) (Seconds of the day) возвращает количество секунд, прошедших с 00:00. Таким образом, SoD(TimeCurrent()) вычисляет время, прошедшее с начала формирования дневной свечи, в секундах. Аналогично, SoW(t) рассчитывает количество секунд, прошедших с 00:00 последнего воскресенья. Позволяет рассчитать в процентах прошедшее время и оставшееся. Если разделить значение на 864 (=0.01*24*60*60), получится прошедшее время дня в процентах:

(double)SoD(D’20210817 15:34‘) / 864. = 64.86%
86400 - SoD(D’20210817 15:34‘)      = 
Print("D'20210817 15:34': ",
      DoubleToString((double)SoD(D'20210817 15:34')/864.0, 2),"%  ",
      86400 - SoD(D’20210817 15:34‘),“ sec left“ 
);

Если нужно, можно использовать следующие расчеты:

#define  MoH(t) (int(((t)%3600)/60))                     // Minute of Hour 
#define  MoD(t) ((int)(((t)%86400)/60))                  // Minute of Day 00:00=(int)0 .. 23:59=1439

Функция ToD(t) возвращает количество секунд дня в виде значения типа datetime. Такое представление предотвращает предупреждения компилятора:

#define ToD(t) ((t)%86400)    // Time of Day in Sec (datetime) 86400=24*60*60

Функция HoW(t) возвращает количество часов, которые прошли с 00:00 воскресенья:

#define HoW(t) (DoW(t)*24+HoD(t))  // Hour of Week 0..7*24 = 0..168 0..5*24 = 0..120

Далее, как можно вычислить час дня. Результат будет целым числом, не датой:

#define HoD(t) ((int)(((t)%86400)/3600))  //Hour of Day: 2018.02.03 17:55 => 17

А теперь с округлением:

#define rndHoD(t) ((int)((((t)%86400)+1800)/3600))%24 // rounded Hour of Day 17:55 => 18

А теперь в виде datetime:

#define rndHoT(t) ((t+1800)-((t+1800)%3600))  // rounded Hour of Time: 2018.02.03 17:55:56 => (datetime) 2018.02.03 18:00:00

Время начала дня в виде значения datetime, которое в противном случае пришлось бы дополнительно определять через вызов таймфрейма D1:

#define BoD(t) ((t)-((t)%86400))     // Begin of day 17.5 12:54 => 17.5. 00:00:00

Время начала недели в виде значения datetime, которое в противном случае пришлось бы определять через вызов недельного таймфрейма:

#define BoW(t) ((t)-((t-172800)%604800 - 86400))  // Begin of Week, Su, 00:00

В следующих фрагментах используют структуры и функции MQL, потому что преобразование показалось мне слишком сложным, например, из-за високосных лет. Тем не менее используем тот же формат — функции времени с именами из трех букв или сокращения: DoY - день года, MoY - месяц года и YoY - год года:

MqlDateTime tΤ; // hidden auxiliary variable: the Τ is a Greek characker, so virtually no danger
int DoY(const datetime t) {TimeToStruct(t,tΤ);return(tΤ.day_of_year); } 
int MoY(const datetime t) {TimeToStruct(t,tΤ);return(tΤ.mon); } 
int YoY(const datetime t) {TimeToStruct(t,tΤ);return(tΤ.year); }

Вот еще расчет недели года по американскому определению:

int WoY(datetime t) //Su=newWeek Week of Year = nWeek(t)-nWeeks(1.1.) CalOneWeek:604800, Su.22:00-Su.22:00 = 7*24*60*60 = 604800
  {
   return(int((t-259200) / 604800) - int((t-172800 - DoY(t)*86400) / 604800) + 1); // calculation acc. to USA
  }

(Подробнее о расчетах времени можно почитать тут: https://en.wikipedia.org/wiki/Week#Numbering)



Сезонная и местная разница во времени

Мы провели необходимую подготовительную работу для использования функций. Теперь же нам надо подготовить широкий спектра различных локальных и сезонных сдвигов. Посмотрим, как с ними работают брокеры. Начнем с языка программирования MQL5.


Время в MQL5

Первое и основное, с чем мы сталкиваемся, — это время котировок брокера. Это время открытия баров, получить такое время для последней пришедшей котировки можно через функцию TimeCurrent(). Во многих случаях (и это может прозвучать неожиданно), это время относительно неважно. Оно служит только для сортировки баров, цен, а также торговых операций во времени. То есть это время имеет значение только в среде терминала при реальной торговле.

Также есть функция TimeTradeServer(): "Возвращает расчетное текущее время торгового сервера. В отличие от функции TimeCurrent(), расчет значения времени производится в клиентском терминале и зависит от настроек времени на компьютере пользователя". НО: "При работе в тестере стратегий время TimeTradeServer() моделируется в соответствии с историческими данными и всегда равно TimeCurrent()". То есть от этой функции мало пользы, если нужно провести оптимизацию программы в тестере стратегий.

То же относится и к TimeGMT() и TimeLocal(): "При тестировании значение TimeGMT() всегда равно смоделированному серверному времени TimeTradeServer()", что в свою очередь равно TimeCurrent().

По той же причине в тестере стратегий бесполезна функция TimeGMTOffset(), потому что TimeGMTOffset() = TimeGMT() - TimeLocal(), а это в итоге всегда ноль. :(

И последнее, что осталось, это TimeDaylightSavings(): "Возвращает поправку на летнее время в секундах, если был произведен переход на летнее время. Зависит от настроек времени на компьютере пользователя. ... Если был произведен переход на зимнее (стандартное) время, то возвращается 0".

Вот лог демо-счета (по дате видно, что сейчас летнее время в ЕС и США):

2021.08.26 09:25:45.321    MasteringTime (EURUSD,M1)    Broker: MetaQuotes Software Corp.
2021.08.26 09:25:45.321    MasteringTime (EURUSD,M1)    TimeCurrent:             10:25
2021.08.26 09:25:45.321    MasteringTime (EURUSD,M1)    TimeTradeServer:      10:25
2021.08.26 09:25:45.321    MasteringTime (EURUSD,M1)    TimeLocal:                 09:25
2021.08.26 09:25:45.321    MasteringTime (EURUSD,M1)    TimeGMT:                  07:25
2021.08.26 09:25:45.321    MasteringTime (EURUSD,M1)    TimeDaylightSavings:  -3600 h: -1
2021.08.26 09:25:45.321    MasteringTime (EURUSD,M1)    TimeGMTOffset:         -7200 h: -2

and here the printout of the same account in the strategy tester (debugging):

2021.08.26 10:15:43.407    2021.06.18 23:54:59   Broker: MetaQuotes Software Corp.
2021.08.26 10:15:43.407    2021.06.18 23:54:59   TimeCurrent:             23:54
2021.08.26 10:15:43.407    2021.06.18 23:54:59   TimeTradeServer:      23:54
2021.08.26 10:15:43.407    2021.06.18 23:54:59   TimeLocal:                 23:54
2021.08.26 10:15:43.407    2021.06.18 23:54:59   TimeGMT:                  23:54
2021.08.26 10:15:43.407    2021.06.18 23:54:59   TimeDaylightSavings:  0 h: 0
2021.08.26 10:15:43.407    2021.06.18 23:54:59   TimeGMTOffset:         0 h: 0

То есть все эти функции работают только в реальном времени, но не работают в тестере стратегий. По факту у нас есть только функция TimeCurrent(), на основе которой мы можем самостоятельно вычислить остальное необходимое время.

Теоретически можно отправить запрос брокеру и попытаться узнать, как он определяет время для котировок. Например, вот что ответили в Альпари:

Обратите внимание, что торговые сессии открываются в понедельник в 00:05:00 по времени сервера
(GMT+2/GMT +3 DST) и закрываются в пятницу в 23:55:00 по времени сервера. Летом
торговое время начинается в 21:05 GMT в воскресенье, а зимой —
22:05 GMT в воскресенье.

Но это правда лишь отчасти. Здесь не говорится о том, что время перехода на летнее и зимнее время в ЕС и США разное время, из-за чего сессия в это время перехода, например 26.03.2021, заканчивается не в 23:55, а в 22:55. А до и после этого времени снова в 23:55.

Прежде чем продолжить, небольшой обзор разных часовых поясов и их сокращений. Для меня самый полезный сайт для работы с часовыми поясами: https://24timezones.com/time-zones. Таблица на сайте содержит 200 различных часовых поясов. Вот наиболее важные для нас:


Сокращение

Часовой пояс

Сайт

UTC Diff.

GMT Diff.

CEST

Центральноевропейское летнее время

Франкфурт, летнее время

UTC+2

GMT+2

CET

Центральноевропейское время

Франкфурт, обычное время

UTC+1

GMT+1

EDT

Восточное время

Нью-Йорк, обычное время

UTC-4

GMT-4

EEST

Восточноевропейское летнее время

Кипр, летнее время

UTC+3

GMT+3

EET

Восточноевропейское время

Кипр, нормальное время

UTC+2

GMT+2

EST

Восточное стандартное время

Нью-Йорк, обычное время

UTC-5

GMT-5

ET

Восточное время

Нью-Йорк

UTC-5/UTC-4

GMT-5/GMT-4

GMT

Время по Гринвичу

Лондон, Обычное время

UTC+0

GMT+0

UTC

Всемирное координированное время

Лондон, Обычное время

UTC

GMT


Обратите внимание, что обычная разница во времени с Нью-Йорком составляет -5 часов, а летом -4, то есть на один час меньше, тогда как с Франкфуртом +1 или с сервером MQ +2, а летом +2 и +3, соответственно. Не путайте, не забывайте о примерах!

Теперь давайте посмотрим на временные метки первой и последней котировок на демо-счете от MQ в выходные дни. На графике EURUSD M1 включаем разделитель периодов, затем нажимаем Enter на графике для ввода даты понедельника в формате дд.мм.гггг (не в формате даты MQ). Прокрутим график немного вправо. Теперь бар с вертикальной линией — это первый бар новой недели, а бар слева — последний бар прошлой недели. Вот даты последнего бара пятницы и первого бара после выходных:

Выходные в период перевода часов осенью 2020 года:

Summer-EU

Summer-EU

Summer-EU

Winter-EU

Winter-EU

Winter-EU

Winter-EU

Winter-EU

Winter-EU

Winter-EU

Summer-US

Summer-US

Summer-US

Summer-US

Summer-US

Winter-US

Winter-US

Winter-US

Winter-US

Summer-US

Fr.

Mo.

Fr.

Mo.

Fr.

Mo.

Fr.

Mo.

Fr.

Mo.

2020.10.16

2020.10.19

2020.10.23

2020.10.26

2020.10.30

2020.11.02

2021.03.05

2021.03.08

2021.03.12

2021.03.15

23:54

00:05

23:54

00:05

22:54

00:02

23:54

00:03

23:54

00:00

1,1716

1,17195

1,18612

1,18551

1,16463

1,16468

1,19119

1,19166

1,19516

1,19473

1,17168

1,17208

1,18615

1,18554

1,16477

1,16472

1,19124

1,19171

1,19521

1,19493

1,1716

1,1718

1,18596

1,18529

1,16462

1,16468

1,19115

1,19166

1,19514

1,19473

1,1716

1,17188

1,18598

1,18534

1,16462

1,16472

1,1912

1,19171

1,19519

1,19491

0

0

0

0

0

0

0

0

0

0

29

22

35

48

30

3

33

2

23

25

4

11

2

6

2

61

1

38

1

29

Выходные в период перевода часов весной 2021 года:

Winter-EU

Winter-EU

Winter-EU

Winter-EU

Winter-EU

Winter-EU

Winter-EU

Summer-EU

Summer-EU

Summer-EU

Winter-US

Winter-US

Winter-US

Summer-US

Summer-US

Summer-US

Summer-US

Summer-US

Summer-US

Summer-US

Fr.

Mo.

Fr.

Mo.

Fr.

Mo.

Fr.

Mo.

Fr.

Mo.

2021.03.05

2021.03.08

2021.03.12

2021.03.15

2021.03.19

2021.03.22

2021.03.26

2021.03.29

2021.04.02

2021.04.05

23:54

00:03

23:54

00:00

22:54

00:00

22:54

00:07

23:54

00:03

1,19119

1,19166

1,19516

1,19473

1,19039

1,18828

1,17924

1,17886

1,17607

1,17543

1,19124

1,19171

1,19521

1,19493

1,19055

1,18835

1,17936

1,17886

1,17608

1,17543

1,19115

1,19166

1,19514

1,19473

1,19038

1,18794

1,17922

1,17884

1,17607

1,17511

1,1912

1,19171

1,19519

1,19491

1,19044

1,18795

1,17933

1,17886

1,17608

1,17511

0

0

0

0

0

0

0

0

0

0

33

2

23

25

41

43

17

3

2

3

1

38

1

29

1

20

5

68

28

79

Интересным и не совсем понятным для меня является тот факт, что иногда последние котировки перед выходными приходят примерно в 23:00 (22:54), а не в 24:00 (23:54), и при этом первые котировки всегда приходят в 00:00. Иногда при часовой перспективе это создает "дыру в котировках" в 1 час (закрытие в 23:00, открытие в 00:00), в то время как рынок Forex всегда закрывается в 17:00 (время Нью-Йорка) в пятницу и всегда открывается в 17:00 (время Нью-Йорка) в воскресенье. Давайте специально посмотрим на выходные, в которые происходит перевод часов, и вычислим соответствующее время в нужных часовых поясах:

Дата


Дата посл пт.




Дата






посл бар M1

след бар M1

Switch US



NY-Time

NY-GMT

GMT

Switch EU


CET-GMT

CET

EET-GMT

EET

of MQ

of MQ


Summer-US

Fr, 16. Oct 20

17:00

GMT + 4

21


Summer-EU

GMT + 2

23

GMT + 3

24

23:54



Summer-US

So, 18. Oct 20

17:00

GMT + 4

21


Summer-EU

GMT + 2

23

GMT + 3

24


00:05


Summer-US

Fr, 23. Oct 20

17:00

GMT + 4

21

25.10.20

Summer-EU

GMT + 2

23

GMT + 3

24

23:54



Summer-US

So, 25. Oct 20

17:00

GMT + 4

21


Winter-EU

GMT + 1

22

GMT + 2

23


00:05

01.11.20

Summer-US

Fr, 30. Oct 20

17:00

GMT + 4

21


Winter-EU

GMT + 1

22

GMT + 2

23

22:54



Winter-US

So, 1. Nov 20

17:00

GMT + 5

22


Winter-EU

GMT + 1

23

GMT + 2

24


00:02


Winter-US

Fr, 6. Nov 20

17:00

GMT + 5

22


Winter-EU

GMT + 1

23

GMT + 2

24

23:54



Winter-US

So, 8. Nov 20

17:00

GMT + 5

22


Winter-EU

GMT + 1

23

GMT + 2

24


00:03

14.03.21

Winter-US

Fr, 12. Mrz 21

17:00

GMT + 5

22


Winter-EU

GMT + 1

23

GMT + 2

24

23:54



Summer-US

So, 14. Mrz 21

17:00

GMT + 4

21


Winter-EU

GMT + 1

22

GMT + 2

23


00:00


Summer-US

Fr, 26. Mrz 21

17:00

GMT + 4

21

28.03.21

Winter-EU

GMT + 1

22

GMT + 2

23

22:54



Summer-US

So, 28. Mrz 21

17:00

GMT + 4

21


Summer-EU

GMT + 2

23

GMT + 3

24


00:07


Summer-US

Fr, 2. Apr 21

17:00

GMT + 4

21


Summer-EU

GMT + 2

23

GMT + 3

24

23:54



Summer-US

So, 4. Apr 21

17:00

GMT + 4

21


Summer-EU

GMT + 2

23

GMT + 3

24


00:03

В ту неделю (недели), когда местное летнее/зимнее время в ЕС и США не совпадает, рынок форекс в Нью-Йорке открывается в воскресенье в 23:00 EET, а закрывается в пятницу в 23:00 EET. Тем не менее некоторые брокеры, в том числе и сервер MQ с демо-счетами, всегда поставляют первые котировки в воскресенье в 24:00 (или 00:00 понедельника). Поэтому можно подумать, что время котировок соответствует второму переводу часов, а не первому. Однако в таком случае в пятницу последняя котировка перед закрытием форекс-сессии должна была бы приходить незадолго до 24:00, потому что только в таком случае получается необходимое количество часов 24*5=120. Но одного часа не хватает. Отсюда возникает вопрос, когда же он пропадает: в пятницу перед выходными или в воскресенье после них?

Поскольку недельные цены закрытия важнее, чем первый торговый час в воскресенье, можно предположить, что, если в пятницу последние цены были незадолго до 23:00, а следующие - только в 24:00/00:00, не хватает первого часа работы рынка форекс, воскресенье 23:00-24:00, а не последнего в пятницу с 23:00-24:00. При этом, если бы время первых цен было в воскресенье сразу после 23:00, было бы довольно легко не только распознать смену часов, но и определить, когда рынок Forex снова закроется (5d * 24h = 120 часов после открытия в воскресенье). Например, это важно для осторожных стратегий, которые закрывают все позиции перед выходными.

Сначала мы рассмотрим, какие предположения мы можем сделать. В тестере стратегий у нас есть только функция TimeCurrent(). По ней мы определим время GMT или UTC, на основе чего можно будет легко рассчитать время других часовых поясов. С учетом возможных праздников и прочих причин, которые могут влиять на время открытия и закрытия рынка в США, предположим, что:

  1. Рынок форекс закрывается в пятницу в 17:00 по Нью-Йорку.
  2. Рынок открывается в воскресенье в 17:00 по Нью-Йорку.
  3. Обычно открывается на 5*24=120 часов и закрывается на 2*24=48 часов.
  4. Если отсутствует какие-либо часы между 17:00 в пятницу и 17:00 в воскресенье, тогда будет не хватать котировок воскресенья до получения самой первой котировки, а не последних котировок пятницы.
  5. Входящие котировки (независимо от указанного в них времени) всегда актуальны (а не, например, часовой давности).
  6. Брокер не меняет свою политику смены часов.

Выводы

Мы определили функции или, точнее, макроподстановки, которые будем использовать далее. Также мы определили условия, на основе которых в следующей статье "Работаем со временем (Часть 2): функции" мы разработаем функции, которые будут вычислять GMT в любое заданное время.

К статье приложен файл DealingwithTimePart1.mqh, которые содержит рассмотренные фрагменты кода. В следующей статье в файл добавятся новые функции.

Если есть вопросы, комментарии или предложения, пишите.


Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/9926

Прикрепленные файлы |
Графика в библиотеке DoEasy (Часть 91): События стандартных графических объектов в программе. История изменения имени объекта Графика в библиотеке DoEasy (Часть 91): События стандартных графических объектов в программе. История изменения имени объекта
В статье доработаем базовый функционал для предоставления контроля событий графических объектов из программы, работающей на основе библиотеки. Начнём создание функционала для хранения истории изменений свойств графических объектов на примере свойства "Имя объекта".
Улучшение распознавания свечных паттернов на примере Доджи Улучшение распознавания свечных паттернов на примере Доджи
Как находить свечные паттерны чаще, чем обычно. За простотой свечных паттернов скрывается и серьезный недостаток, который как раз можно устранить, используя существенно выросшие возможности современных средств автоматизации трейдинга.
Визуальная оценка результатов оптимизации Визуальная оценка результатов оптимизации
Разговор в этой статье пойдёт о том, как построить графики всех проходов оптимизации и подобрать оптимальный пользовательский критерий. А также о том, как, имея минимальные знания в MQL5 и большое желание, используя статьи сайта и комментарии на форуме, написать то, что хочется.
Графика в библиотеке DoEasy (Часть 90): События стандартных графических объектов. Базовый функционал Графика в библиотеке DoEasy (Часть 90): События стандартных графических объектов. Базовый функционал
В статье создадим базовый функционал для отслеживания событий стандартных графических объектов. Начнем с события двойного щелчка мыши на графическом объекте.