mql5/Scripts/Downloads/test_WeekendData.mq5
Princeec13 ecd22e8ddd
2025-08-10 17:43:21 -04:00

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 ; // hidden auxiliary variable: the Τ is a Greek character, so virtually no danger
int MoY(const datetime t) {TimeToStruct(t,);return(.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;
}