MQL5Book/Scripts/p4/TimeSummer.mq5
super.admin 1c8e83ce31 convert
2025-05-30 16:09:41 +02:00

194 lines
16 KiB
MQL5

//+------------------------------------------------------------------+
//| TimeSummer.mq5 |
//| Copyright 2021, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "..\..\Include\PRTF.mqh"
#include "..\..\Include\DateTime.mqh"
#include <TimeZoneInfo.mqh>
//+------------------------------------------------------------------+
//| Server time zone and DST information |
//+------------------------------------------------------------------+
struct ServerTime
{
int offsetGMT; // time zone offset in seconds against UTC/GMT
int offsetDST; // DST correction in seconds (included in offsetGMT)
bool supportDST; // DST changes are detected in the quotes
string description; // textual explanation of result
};
//+------------------------------------------------------------------+
//| Estimate server time zone and DST mode from H1 quotes history |
//+------------------------------------------------------------------+
ServerTime ServerTimeZone(const string symbol = NULL)
{
const int year = 365 * 24 * 60 * 60;
datetime array[];
if(PRTF(CopyTime(symbol, PERIOD_H1, TimeCurrent() - year, TimeCurrent(), array)) > 0)
{
// approx. 6000 bars should be acquired here
const int n = ArraySize(array);
PrintFormat("Got %d H1 bars, ~%d days", n, n / 24);
int hours[24] = {};
int current = 0;
for(int i = 0; i < n; ++i)
{
const ENUM_DAY_OF_WEEK weekday = TimeDayOfWeek(array[i]);
// skip all days except Sunday and Monday
if(weekday > MONDAY) continue;
// lets analyze the first H1 bar of the trading week
// find out an hour for the first bar after weekend
current = _TimeHour();
// collect stats for opening hours
hours[current]++;
// now skip 2 days to check next week
i += 48;
}
Print("Week opening hours stats:");
ArrayPrint(hours);
if(hours[current] <= 52 / 4)
{
// TODO: refine results using previous weeks
Print("Extraordinary week detected");
}
// find most often time shift
int max = ArrayMaximum(hours);
// now check if a secondary time shift was also happened
hours[max] = 0;
int sub = ArrayMaximum(hours);
// result variable init
ServerTime st = {};
int DST = 0;
// winter/summer periods are not equal!
// summer time can be 8 months per year
// 52 is the full year in weeks
if(hours[sub] > 52 / 4) // DST is supported
{
if(current == max || current == sub)
{
if(current == MathMin(max, sub))
DST = fabs(max - sub); // DST is enabled now
}
st.supportDST = true;
}
current += 2 + DST; // +2 to get UTC offset
// NB. when DST is enabled, time is shifted forward in the time zone,
// but for outside it is looked like the time is shifted back
// (everything in this time zone is happened earlier for others)
// so to get standard time of the zone we need to add DST
current %= 24;
// time zones are in the range [UTC-12,UTC+12]
if(current > 12) current = current - 24;
current += DST; // if DST is enabled it's shown in offsetGMT according to MT5 rules
st.description = StringFormat("Server time offset: UTC%+d, including DST%+d", current, DST);
st.offsetGMT = -current * 3600;
st.offsetDST = -DST * 3600;
return st;
}
ServerTime empty = {-INT_MAX, -INT_MAX, false};
return empty;
}
#define HOUR 3600
#define DAY (24 * HOUR)
#define WEEK 7
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
datetime GetBarTime(const datetime time, const bool NextBar = false, string Symb = NULL, const ENUM_TIMEFRAMES TimeFrame = PERIOD_M1)
{
if (Symb == NULL)
Symb = _Symbol;
return(iTime(Symb, TimeFrame, iBarShift(Symb, TimeFrame, time) - (NextBar ? 1 : 0)));
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
datetime GetTimeDayOfWeek(const int Shift = 0, const ENUM_DAY_OF_WEEK Day = SUNDAY)
{
const datetime Res = TimeCurrent() / DAY * DAY;
return(Res - (((WEEK + (TimeDayOfWeek(Res) - Day)) % WEEK) + Shift * WEEK) * DAY);
}
// Аналог по серверному времени - https://www.mql5.com/ru/docs/dateandtime/timegmtoffset
// Работает для FOREX-символов, когда M1-история доступна за ближайшую неделю
int TimeServerGMTOffset( void )
{
const datetime Sunday = GetTimeDayOfWeek();
return(((int)MathRound((double)MathMin(Sunday - DAY - GetBarTime(Sunday), Sunday + DAY - GetBarTime(Sunday, true)) / HOUR) - 3) * HOUR);
}
// Аналог по серверному времени - https://www.mql5.com/ru/docs/dateandtime/timegmt
// Работает для FOREX-символов, когда M1-история доступна за ближайшую неделю
datetime TimeServerGMT(void)
{
return(TimeCurrent() + TimeServerGMTOffset());
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//PRTF(TimeLocal());
PRTF(TimeCurrent());
//PRTF(TimeTradeServer());
PRTF(TimeGMT());
PRTF(TimeGMTOffset());
PRTF(TimeDaylightSavings());
ServerTime st = ServerTimeZone();
Print(st.description);
Print("ServerGMTOffset: ", st.offsetGMT);
Print("ServerTimeDaylightSavings: ", st.offsetDST);
Print("\n\n");
//---
//PRTF(TimeLocal());
PRTF(TimeCurrent());
//PRTF(TimeTradeServer());
PRTF(TimeGMT());
PRTF(TimeServerGMT());
Print("\n\n");
CTimeZoneInfo my_time(ZONE_ID_BROKER);
ENUM_ZONE_ID id = ZONE_ID_UTC;
PRTF(my_time.GetCurrentTimeForPlace(ZONE_ID_BROKER));
PRTF(my_time.GetCurrentTimeForPlace(ZONE_ID_UTC));
PRTF(my_time.GetCurrentTimeForPlace(ZONE_ID_LOCAL));
PRTF(my_time.ConvertTimeForPlace(TimeGMT(), ZONE_ID_UTC, ZONE_ID_BROKER));
PRTF(my_time.TimeLocal());
PRTF(my_time.TimeUTC());
PRTF(my_time.IsDaylightSavingTime(TimeCurrent() - PeriodSeconds(PERIOD_MN1) * 7, ZONE_ID_BROKER));
PRTF(my_time.IsDaylightSavingTime(TimeCurrent() - PeriodSeconds(PERIOD_MN1) * 7, ZONE_ID_UTC));
//datetime localtime = CTimeZoneInfo::GetCurrentTimeForPlace(id);
//datetime converted = CTimeZoneInfo::ConvertTimeForPlace(localtime, id, ZONE_ID_BROKER);
//PrintFormat("%-49s | %s", CTimeZoneInfo::FormatTimeForPlace(localtime, id), CTimeZoneInfo::FormatTimeForPlace(converted, ZONE_ID_BROKER));
}
//+------------------------------------------------------------------+
/*
example output MQ Demo
(WARNING: TimeGMT != ServerGMT,
because TimeGMT() - TimeCurrent() gives 3 hours difference,
whereas ServerGMTOffset is 2 hours difference;
probably DST is enabled all year round)
TimeLocal()=2021.09.09 22:06:17 / ok
TimeCurrent()=2021.09.09 22:06:10 / ok
TimeTradeServer()=2021.09.09 22:06:17 / ok
TimeGMT()=2021.09.09 19:06:17 / ok
TimeGMTOffset()=-10800 / ok
TimeDaylightSavings()=0 / ok
CopyTime(symbol,PERIOD_H1,TimeCurrent()-year,TimeCurrent(),array)=6207 / ok
Got 6207 H1 bars, ~258 days
Week opening hours stats:
52 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Server time offset: UTC+2, including DST+0
ServerGMTOffset: -7200
ServerTimeDaylightSavings: 0
*/
//+------------------------------------------------------------------+