Время MetaTrader 4 / MQL4 отличается на -5 часов, но только при использовании времени эпохи.

Я работаю с MetaTrader4, работающим в WINE в Ubuntu 16.04. У меня есть простая встроенная функция, которая сохраняет время и другую информацию в файл, используя эту строку:

FileWrite(data_filehandle, "sys_time:" + (string)TimeLocal() + "." + StringFormat("%06lu", usec_instance) + ", sym:" + (string)Symbol() + ", tick_time:" + (string)last_tick.time + ", ask:" + (string)last_tick.ask + ", bid:" + (string)last_tick.bid);

Используя директиву:

#property strict

заставит его выводить время в формате даты и времени. Удаление этой директивы приведет к тому, что время будет выводиться в формате epoc.

Когда он использует формат даты и времени (с помощью '#property strict'), время указано правильно.

Он выводит:

sys_time:2020.01.21 07:38:02.994394, sym:EURUSD, tick_time:2020.01.21 14:38:03, ask:1.1104, bid:1.1103

Это правильно соответствует моему системному времени.

Теперь, если я удалю «#property strict», чтобы переключиться на время эпохи

Он выводит:

sys_time:1579592538.630395, sym:EURUSD, tick_time:1579617738, ask:1.1105, bid:1.11041

мое местное время:

$ date '+%s'
1579610544

$ date '+%Z %z'
EST -0500

мое время: 1579610544 - MT4 LocalTime: 1579592538 = 18006 секунд (что на 5 часов и 6 секунд позади меня)

Любая идея о том, что может быть причиной этого? Я был бы немного менее смущен, если бы это было +5 часов, потому что это было бы GMT. Но это -5 часов, а это Гавайи. Кроме того... почему в одном формате время правильное, а в другом нет?



Дополнительная информация

Я провел еще несколько тестов, используя дополнительные функции MQL4. Я заставлял их постоянно выкачивать свои результаты в мой текстовый файл. Затем я быстро собрал сценарий BASH, чтобы проверить результаты. Я нашел следующее:

Использование этого кода в МТ4

FileWrite(data_filehandle, "TimeDaylightSavings(): " + (string)TimeDaylightSavings());
FileWrite(data_filehandle,"TimeLocal(): "+(string)TimeLocal());
FileWrite(data_filehandle,"TimeGMTOffset(): "+(string)TimeGMTOffset());
FileWrite(data_filehandle,"TimeGMT(): "+(string)TimeGMT()+"\n\n");

Дал этот вывод в мой текстовый файл (одна новая запись каждую секунду):

TimeDaylightSavings(): 0
TimeLocal(): 1579601184
TimeGMTOffset(): 18000
TimeGMT(): 1579619184

Я набросал этот BASH-скрипт для сканирования и проверки результатов в режиме реального времени:

#!/bin/bash

IFS=$'\n'$'\b';

while true
do
        my_time=$(date);
        my_epoc=$(date '+%s');
        my_record="$( cat EURUSD_price_data.txt| dos2unix | tail -5 )";


        mt4_time_local=$( echo "$my_record" | grep -w 'TimeLocal' );
        echo "Reading line: $mt4_time_local";
        mt4_time_local=$(echo $mt4_time_local | awk '{print $2}' );

        echo "My time: $my_time  -- My epoc: $my_epoc -- MT4_TimeLocal epoc: $mt4_time_local -- Difference: $(( $my_epoc - $mt4_time_local ))";

        mt4_time_GMT=$( echo "$my_record" | grep -w 'TimeGMT' );
        echo "Reading line: $mt4_time_GMT";
        mt4_time_GMT=$(echo $mt4_time_GMT | awk '{print $2}' );
        echo "My time: $my_time  -- My epoc: $my_epoc -- MT4_TimeGMT epoc: $mt4_time_GMT -- Difference: $(( $my_epoc - $mt4_time_GMT ))";


        echo "";
        sleep 1;
done

и получил такой результат:

Reading line: TimeLocal(): 1579601184
My time: Tue Jan 21 10:06:25 EST 2020  -- My epoc: 1579619185 -- MT4_TimeLocal epoc: 1579601184 -- Difference: 18001
Reading line: TimeGMT(): 1579619184
My time: Tue Jan 21 10:06:25 EST 2020  -- My epoc: 1579619185 -- MT4_TimeGMT epoc: 1579619184 -- Difference: 1

Теперь, если я добавлю «#property strict», чтобы вернуться к формату даты и времени, я получаю:

TimeDaylightSavings(): 0
TimeLocal(): 2020.01.21 10:23:56
TimeGMTOffset(): 18000
TimeGMT(): 2020.01.21 15:23:56

Мое системное время:

$ date
Tue Jan 21 10:23:57 EST 2020



Вывод

По какой-то причине при получении времени epoc TimeLocal() дает неправильное время (по какой-то причине гавайское время), но неожиданно TimeGMT() дает правильное время, хотя я нахожусь в часовом поясе EST.

Используя точно такой же код и настройку, при получении времени в формате Date Time (используя директиву #property strict) ситуация обратная. TimeLocal() дает правильное время, а TimeGMT() дает неправильное время (но, по крайней мере, дает правильное время по Гринвичу)

Является ли это ошибкой в ​​МТ4 или что-то происходит за кулисами, чего я еще не до конца понял?


person Hakachukai    schedule 21.01.2020    source источник


Ответы (2)


В : Есть идеи, что может быть причиной этого?

#property strict – это переключатель на этапе компиляции, который изменяет множество деталей того, как синтаксически правильные композиции MQL4 будут пониматься в { "old" | "новый" }-мода

( не читая эту часть документации каждый раз после MT4 IDE обновление может и будет вас удивлять, так что лучше перечитайте ее всегда после каждого обновления )

"Старый"-MQL4 использовал int32 для datetime внутренней памяти, "Новый"-MQL4.56789… использует int64, поэтому любые переносы находятся намного дальше.

FileWrite( data_filehandle, "sys_time:"
                          + (string)TimeLocal()                    // localhost-dependent
                          + "."
                          + StringFormat( "%06lu", usec_instance )
                          + ", sym:"
                          + (string)Symbol()
                          + ", tick_time:"
                          + (string)last_tick.time                 // Fx-QUOTE-dependent
                          + ", ask:"
                          + (string)last_tick.ask
                          + ", bid:"
                          + (string)last_tick.bid
                          );

См. TimeGMT() и TimeGMTOffset() другие встроенные параметры.

person user3666197    schedule 21.01.2020

После долгих прочтений, размышлений и испытаний я нашел ответ (хотя я не знаю, о чем они думали, когда поступали таким образом).

Проблема именно здесь:

TimeDaylightSavings(): 0
TimeLocal(): 1579601184  <-- should be the same as TimeGMT(). Epoc does not respect timezone
TimeGMTOffset(): 18000
TimeGMT(): 1579619184

Время эпохи Unix основано на событии, которое произошло 1 января 1970 года в 00:00 UTC. Он не уважает часовые пояса. Предполагается, что оно должно быть одинаковым для всех на Земле во все времена.

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

date '+%s'

команду, чтобы моя система дала мне правильную эпоху Unix, которая соответствует выходным данным TimeGMT() из MT4. Так что проблема не в моей системе.

Однако выше мы видим, что TimeLocal() не обрабатывает epoc должным образом. Он настраивает эпоху unix, пытаясь компенсировать мой часовой пояс. Такое поведение, вероятно, связано с тем, что он обеспечивает правильное время, когда оно отображается в формате даты и времени. Проблема в том, что когда его просят вывести время в формате epoc, он все еще выполняет преобразования часовых поясов, что нарушает само значение времени epoc в Unix.

Итак, решение (насколько я могу судить) состоит в том, чтобы просто использовать TimeGMT() в любое время, когда мне нужна правильная эпоха Unix. Кажется довольно сумасшедшим, что я должен специально избегать использования TimeLocal() в определенных случаях... но я думаю, что это именно так?

person Hakachukai    schedule 22.01.2020