246 行
28 KiB
MQL5
246 行
28 KiB
MQL5
/*+------------------------------------------------------------------+
|
|
//| test_WeekendData.mq5 |
|
|
//| Calli |
|
|
//| https://www.mql5.com/de/users/gooly |
|
|
//| DST USA spring: 2nd. Su. in Mar. autum: 1st. Su. in Nov. |
|
|
//| DST EU spring: last Su. in Mar. autum: last Su. in Oct. |
|
|
//| DST AUS spring: 1st. Su. in Apr. autum: 1st. Su. in Oct. |
|
|
//| Seq. of Chg: Summer USA, Summer EU, Autum EU, Autum USA |
|
|
//| Timeline Summer: AUS 1st Su.Mar,USA 2nd Su.Mar, EU last Su.Mar |
|
|
//| Timeline Winter: AUS 1st Su.Oct,EU last Su.Oct, USA 1st Su.Nov |
|
|
//+------------------------------------------------------------------*/
|
|
|
|
/*+--------------- Comment Russian/English -------------------------+
|
|
К сожалению, я обнаружил, что некоторые брокеры
|
|
Изменение времени на сервере немного некорректно, чего я не ожидал.
|
|
и что меня очень удивило.
|
|
Вот скрипт, который каждый может использовать для проверки своего брокера.
|
|
|
|
Сессия FOREX длится ровно 120 часов:
|
|
с воскресенья 17:00 по восточному стандартному времени (Северная Америка) или EST
|
|
до 17:00 пятницы по восточному времени.
|
|
|
|
Проблема возникает из-за перехода на летнее и зимнее время,
|
|
которые не проводятся в одни и те же воскресенья в разных регионах мира.
|
|
|
|
В США, например, смена происходит во второе воскресенье марта и первое воскресенье ноября.
|
|
что также влияет на начало и конец сессии FOREX.
|
|
|
|
ЕС представит свой ежегодный отчет в последнее воскресенье марта, после США, а в
|
|
последнее воскресенье октября, т.е. в США (см. хронологию выше).
|
|
|
|
Это создает переходную фазу, в которой США и ЕС имеют разные
|
|
Разница во времени больше обычной разницы в 5 часов.
|
|
часов (Лондон), 6 часов (Франкфурт, CET) или 7 часов (Кипр, EET).
|
|
|
|
В то же время это изменение разницы во времени должно быть отражено в
|
|
Изменена временная метка первого и последнего часа сессии FOREX.
|
|
Таким образом, если сессия FOREX начинается в понедельник в 00:00 (EET, время MQ), она должна
|
|
После этого изменения время в США будет начинаться на час раньше, т.е. в воскресенье в 23:00.
|
|
и заканчивается на час раньше в пятницу, в 23:00 (или 22:59:59).
|
|
|
|
Но, к сожалению, мне пришлось осознать (и с этим скриптом каждый может сделать это самостоятельно)
|
|
Рейтинг брокеров), который доступен на демо-счете MQ и на счетах некоторых реальных брокеров
|
|
первый час всегда(!) появляется в понедельник в 00:00, но последний час, как и ожидалось
|
|
в пятницу в 23:00 (или 22:59) или на час раньше. Итак, первый час отсутствует.
|
|
Сессия FOREX, на которой трейдер или консультант может отреагировать на события выходного дня.
|
|
Кроме того, окончание сессии FOREX больше не может быть определено простым прибавлением 120 к
|
|
первый час сессии FOREX, например, чтобы закрыть все позиции перед выходными.
|
|
|
|
Этот скрипт теперь проверяет, изменилось ли время брокера в прошлом, и регистрирует все
|
|
Сессии FOREX, которые явно странные или не длятся 120 часов. Если между
|
|
Если между первым и последним часом сессии FOREX прошло 120 часов, запись в журнале не производится.
|
|
|
|
В конце скрипт отображает последнюю полученную временную метку, количество найденных
|
|
сокращенные периоды сессий и приблизительное количество лет, принятых во внимание.
|
|
|
|
|
|
Unfortunately, I discovered that some brokers are a bit sloppy with the server time
|
|
change due to the daylight saving time (DST), which I did not expect and which surprised me a lot.
|
|
|
|
The FOREX session is exactly 120 hours:
|
|
from Sunday 5:00 p.m. Eastern Standard Time (North America) or EST
|
|
to Friday 5:00 p.m. EST.
|
|
|
|
The problem arises from the time changes to summer time and winter time, which do not
|
|
take place on the same Sundays in the different regions of the world.
|
|
|
|
For example, the USA changes on the 2nd Sunday in March and the 1st Sunday in November,
|
|
and this also affects the start and end of the FOREX session.
|
|
|
|
The EU changes on the last Sunday in March i.e. after the USA and on the
|
|
last Sunday in October i.e. before the USA (see above Timeline).
|
|
|
|
This creates an interim period in which the USA and the EU have a different time differences
|
|
than the normal differences of 5 hours (London), 6 hours (Frankfurt, CET) or 7 hours (Cyprus, EET).
|
|
|
|
In this interim period, this change of the time difference should be reflected in the changed
|
|
time stamps of the first and last hours of the FOREX session. So if the FOREX session starts
|
|
on Monday at 00:00 (EET, MQ time), after the USA has changed it should start an hour earlier,
|
|
i.e. Sunday at 23:00 and end an hour earlier on Friday, i.e. 23:00 (or 22:59:59).
|
|
|
|
But unfortunately I had to find out (and with this script anyone can check this with their broker)
|
|
that on a MQ demo account and on accounts of some real brokers the first hour always(!) appears
|
|
on Monday at 00:00, but the last hour, as expected,
|
|
on Friday at 23:00 (or 22:59) or one hour earlier. This means that the first hour of the
|
|
FOREX session, in which the trader or an EA could react to weekend events, is missing.
|
|
Also, the end of the FOREX session can no longer be determined by simply adding 120
|
|
to the first hour of the FOREX session, e.g. to close all positions before the weekend.
|
|
|
|
This script now checks the broker's time changes in the past and logs all FOREX sessions
|
|
that are obviously incorrect (odd) or not 120 hours. If there are 120 hours
|
|
between the first and last hour of a FOREX session, nothing is logged.
|
|
|
|
At the end the script prints the last retrieved timestamp, the number of odd sessions
|
|
found and the approximate number of years that have been checked.
|
|
//+------------------------------------------------------------------*/
|
|
|
|
|
|
#property copyright "Calli"
|
|
#property link "https://www.mql5.com/de/users/gooly"
|
|
#property version "1.01"
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| needed #define to shorten code |
|
|
//+------------------------------------------------------------------+
|
|
string _WkDy[] = {"Su.","Mo.","Tu.","We.","Th.","Fr.","Sa."};
|
|
#define DoWs(t) (_WkDy[DoWi(t)]) // Day of Week as string: Sun, Mon, Tue, ...
|
|
#define DoWi(t) ((int)((t)/86400+4)%7) // Day of Week as integer: Sun=0, Mon=1, Tue=2, ...
|
|
#define BoW(t) ((t)-((t)+345600)%604800) // Begin of Week 2017.08.03 11:30 => Sun, 2017.07.30 00:00 (fixed version)
|
|
#define WeekInSec 604800 // 60sec*60min*24h*7d = 604800 => 1 Week
|
|
#define _tSu(t) DoWs(t)+" "+TimeToString(t,TIME_DATE)
|
|
#define _tWkD(t) DoWs(t)+" "+TimeToString(t,TIME_DATE|TIME_MINUTES)
|
|
|
|
MqlDateTime tΤ; // hidden auxiliary variable: the Τ is a Greek character, so virtually no danger
|
|
int MoY(const datetime t) {TimeToStruct(t,tΤ);return(tΤ.mon);} // TimeMonthOfYear: 1,212
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 2 variables to control the printout |
|
|
//+------------------------------------------------------------------+
|
|
datetime tmeEndCheck = D'1970.01.01 00:00'; //2022.01.01 00:00'; // stop if this date is triggered, '1970.01.01 00:00' means max.
|
|
int maxOddSess = 20; // max.number of odd lines found: either sessions (!=120h) or weekend (!=48h)
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Script program start function |
|
|
//+------------------------------------------------------------------+
|
|
void OnStart()
|
|
{
|
|
//---
|
|
if(!TerminalInfoInteger(TERMINAL_CONNECTED))
|
|
{
|
|
Print("Not connected with ",AccountInfoString(ACCOUNT_COMPANY));
|
|
return;
|
|
}
|
|
|
|
//--- Get the earliest possible date to determin a meaninful period: earliest datetime, given datetime, or 1.5 years back form TimeCurrent()
|
|
datetime first_server_date=0;
|
|
if(!SeriesInfoInteger(_Symbol,PERIOD_H1,SERIES_SERVER_FIRSTDATE,first_server_date))
|
|
{
|
|
Print("Calling hist data failed: ",_LastError);
|
|
return;
|
|
}
|
|
tmeEndCheck = fmin(fmin(TimeCurrent() - 47304000, tmeEndCheck),first_server_date); // 47304000 = 1,5*365*24*3600 to look back at least 1.5 years.
|
|
//Print(tmeEndCheck," <=> ",first_server_date," <=> ",TimeCurrent() - 47304000); return;
|
|
|
|
//--- time vars.
|
|
datetime dSu = DoWi(TimeCurrent()) > 1 ? BoW(TimeCurrent()) : BoW(TimeCurrent() - 345600), // 345600 = 4*24*3600 4 days back in case it's Monday
|
|
aTm1[], aTm9[], // arrays for datetime values h1
|
|
startCheck = BoW(TimeCurrent()); // BoW => last Sunday
|
|
|
|
//--- aux. variables
|
|
int hD0, // duration of the time gap of the weekend: Fr 17:00 NYt - So. 17:00 NYt = 48h + 1 (Fr. last full hour 16:00-17:00) = 49 h
|
|
hWk, // duration of Fx-Session from open So. 17:00 to Fr. 17:00 (120 h) - 1h (for Fr. 16:00) = 119 h
|
|
b9, // no. of many h1 bars
|
|
b1 = CopyTime("EURUSD",PERIOD_H1,dSu,1,aTm1), // no. of last h1 bar bfore weekend
|
|
nOdd = 0; // no. of odd weeks detected
|
|
|
|
|
|
|
|
//--- Test for MetaQuotes Ltd. starting week Su. 2025.01.12 - Su. 2025.01.19, last hour before actual week: Fr. 2025.01.10 23:00
|
|
if(b1>-1)
|
|
Print("Weekend test for ",AccountInfoString(ACCOUNT_COMPANY)," on ",_Symbol," with starting at ", _tSu(startCheck)," - ", _tSu(startCheck+WeekInSec),", back into the past."); // Last theoretical timestamp before the actual week: ",_tWkD(aTm1[0]+(59*61)));
|
|
else
|
|
Print("Weekend test for ",AccountInfoString(ACCOUNT_COMPANY)," with start at ", _tSu(startCheck)," ",_tSu(dSu)," b1: ",b1," err of CopyTime():",_LastError);
|
|
Print("Weekend test will end either at tmeEndCheck: ",_tSu(tmeEndCheck)," or if MaxOddSess: ",maxOddSess," is triggered.");
|
|
Print("Weekend test: an odd weekend gap (!= 48h) precedes a possibly odd FOREX session (!= 120)");
|
|
Print("Timeline: Summer: AUS 1st Su.Mar, USA 2nd Su.Mar, EU last Su.Mar => Winter: AUS 1st Su.Oct, EU last Su.Oct, USA 1st Su.Nov");
|
|
|
|
if((dSu - aTm1[0])/3600 > 4*24*3600)
|
|
Print("Quote gap for ",AccountInfoString(ACCOUNT_COMPANY)," from ",_tWkD(dSu)," to ",_tWkD(aTm1[0])," = ", ((dSu - aTm1[0])/3600 > 4*24*3600),"h");
|
|
|
|
bool isOdd=false, isOK=false;
|
|
while(dSu>tmeEndCheck && !IsStopped() && maxOddSess >0)
|
|
{
|
|
|
|
|
|
//--- Skip Dec. and Jan. due to the many holidays and there is no change of DST
|
|
while(MoY(dSu)<2 || MoY(dSu)>11)
|
|
dSu -= WeekInSec;
|
|
|
|
//--- get the last bar before the weekend gap
|
|
b1 = CopyTime("EURUSD",PERIOD_H1,dSu,1,aTm1);
|
|
if(b1<0)
|
|
{
|
|
Print(" FAILED ",_tSu(dSu)," b1: ",b1," e:",_LastError);
|
|
continue;
|
|
}
|
|
|
|
//--- get the first bar after the weekend
|
|
b9 = CopyTime("EURUSD",PERIOD_H1,aTm1[0],dSu+3*24*3600,aTm9);
|
|
if(b9<3)
|
|
{
|
|
Print(" FAILED ",_tWkD(dSu+WeekInSec)," b9: ",b9," e:",_LastError);
|
|
continue;
|
|
}
|
|
|
|
//--- get the last bar before the next weekend
|
|
b1 = CopyTime("EURUSD",PERIOD_H1, dSu+WeekInSec,1,aTm1);
|
|
if(b1<1)
|
|
{
|
|
Print(" FAILED ",_tWkD(dSu+WeekInSec)," b1: ",b1," e:",_LastError);
|
|
continue;
|
|
}
|
|
|
|
//--- calc. the hours of the weekend gap and the following FX.-session
|
|
hD0 = int((aTm9[1] - aTm9[0])/3600) - 1; // -1 because th last h1 bar (e.g. 22:00) opens ~1h before the FX. session closes (e.g. 23:00)
|
|
hWk = int((aTm1[0] - aTm9[1])/3600) + 1; // +1 because th last h1 bar (e.g. 22:00) opens ~1h before the FX. session closes (e.g. 23:00)
|
|
|
|
string sAdd = StringFormat("OK 48 / 120 Month:% 3d USA DST == EU DST", MoY(aTm9[1]));
|
|
//--- print only if the weekend gap != 48h (e.g. Fr. 23:00 - Su. 23:00) or the FGX session != 120h (Su. 23:00 - Fr. 23:00 = 5*24=120) and NOT the current week
|
|
if((hD0!=48 || hWk!=120) && startCheck > aTm1[0])
|
|
{
|
|
sAdd = (hD0==48 && hWk==120)
|
|
? StringFormat("OK %2d / %3d Month:% 3d USA DST == EU DST", hD0,hWk, MoY(aTm9[1]))
|
|
: (hD0!=48 && hWk!=120) ? StringFormat("odd %2d / %3d Month:% 3d USA DST != EU DST", hD0,hWk, MoY(aTm9[1]))
|
|
: hD0!=48 ? StringFormat("odd %2d / %3d Month:% 3d USA winter, EU summer", hD0,hWk, MoY(aTm9[1]))
|
|
: StringFormat("odd %2d / %3d Month:% 3d USA summer, EU winter", hD0,hWk, MoY(aTm9[1]));
|
|
|
|
Print("odd Last QTS: ",_tWkD(aTm9[0]+3540)," nxt. Sess: ",_tWkD(aTm9[1])," - ",_tWkD(aTm1[0]+3540)," ",sAdd);
|
|
isOdd=true;
|
|
isOK=false;
|
|
if(hWk!=120)
|
|
{
|
|
nOdd++;
|
|
maxOddSess --;
|
|
}
|
|
isOK = false;
|
|
}
|
|
else
|
|
//Print("Check ",_tSu(dSu)," Last H1: ",_tWkD(aTm9[0])," FX-Session(h1): ",_tWkD(aTm9[1])," - ",_tWkD(aTm1[0]+3600)," Su.Gap:",hD0,"h Fx.Sess:",hWk,"h gap & sess. = OK");
|
|
if(!isOK)
|
|
{
|
|
Print("OK Last QTS: ",_tWkD(aTm9[0]+3540)," nxt. Sess: ",_tWkD(aTm9[1])," - ",_tWkD(aTm1[0]+3540)+" "+sAdd);
|
|
isOK = true;
|
|
}
|
|
|
|
//--- jump the next previous weekend
|
|
dSu -= WeekInSec;
|
|
|
|
}
|
|
|
|
Print("Done - last date checked: ", _tWkD(aTm1[0]),", ",nOdd," odd FOREX sessions (weeks) detected within ~",(int)(startCheck-aTm1[0])/(3600*24*365)," years");
|
|
return;
|
|
}
|
|
|