Synchronise Windows local time with the MT5 server - page 6

 
prostotrader:

Can someone explain why this code does not accurately synchronise time?

After all, the premarket receives a "fresh" quote, with the new server (exchange) time.

Try what I've got:

//+------------------------------------------------------------------+
//|                                                    Sync_Time.mq5 |
//|                                         Copyright 2016, Serj_Che |
//|                           https://www.mql5.com/ru/users/serj_che |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Serj_Che"
#property link      "https://www.mql5.com/ru/users/serj_che"
#property version   "1.00"

input bool info=true;
input int precision = 50;
//+------------------------------------------------------------------+
struct _SYSTEMTIME
  {
   short             year;
   short             mon;
   short             day_of_week;
   short             day;
   short             hour;
   short             min;
   short             sec;
   short             msc;
  };

_SYSTEMTIME loc_time;

#import "kernel32.dll"
void GetLocalTime(_SYSTEMTIME &sys_time);
bool SetLocalTime(_SYSTEMTIME &sys_time);
#import
//---
MqlTick tick;
MqlDateTime sv_time;
int tick_msc,ping,time_server,time_local,delta=0,mdelta[20],n=0;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   Comment("");
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Comment("");
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   loc_time.year=0;
   GetLocalTime(loc_time);
   if(loc_time.year>0)
     {
      if(!SymbolInfoTick(_Symbol,tick)) { Print("error SymbolInfoTick",GetLastError()); return; }
      ping=TerminalInfoInteger(TERMINAL_PING_LAST)/1000;
      tick_msc=int(tick.time_msc%1000);
      TimeToStruct(tick.time,sv_time);

      time_server=(sv_time.sec+sv_time.min*60)*1000+tick_msc;
      time_local=(loc_time.sec+loc_time.min*60)*1000+loc_time.msc;

      delta=AvgDelta(time_server-time_local);

      if(info) Comments();
      
      if(MathAbs(delta)>1000)
        {
         loc_time.sec=(short)sv_time.sec;
         loc_time.min=(short)sv_time.min;
         CorrectTime(loc_time);
         return;
        }
      if(delta>precision && loc_time.min<58)
        {
         loc_time.msc+=(short)delta;
         if(loc_time.msc>=1000) { loc_time.msc-=1000; loc_time.sec+=1; }
         if(loc_time.sec>=60) { loc_time.sec-=60; loc_time.min+=1; }
         CorrectTime(loc_time);
        }
      if(delta<-precision && loc_time.min>1)
        {
         loc_time.msc+=(short)delta;
         if(loc_time.msc<0) { loc_time.msc+=1000; loc_time.sec-=1; }
         if(loc_time.sec<0) { loc_time.sec+=60; loc_time.min-=1; }
         CorrectTime(loc_time);
        }
     }
   else
     {
      Print("error GetLocalTime");
     }
  }
//+------------------------------------------------------------------+
int AvgDelta(int d)
  {
   int avgd=0;
   mdelta[n]=d;
   n++; if(n>=20) n=0;
   for(int i=0;i<20;i++) avgd+=mdelta[i];
   return(avgd/20);
  }
//+------------------------------------------------------------------+
void CorrectTime(_SYSTEMTIME &ltime)
  {
   if(SetLocalTime(ltime))
     {
      ArrayInitialize(mdelta,0);
      Print("Local time sync -- is done, Sync min = ",ltime.min,
            " Sync sec = ",ltime.sec,"  delta ms = ",delta);
     }
   else Print("error SetLocalTime");
  }
//+------------------------------------------------------------------+
void Comments()
  {
   Comment(
           "\n time server: ",sv_time.hour,": ",sv_time.min,": ",sv_time.sec,": ",tick_msc,
           "\n time server: ",loc_time.hour,": ",loc_time.min,": ",loc_time.sec,": ",loc_time.msc,
           "\n ping : ",ping,
           "\n time_server : ",time_server,
           "\n time___local : ",time_local,
           "\n delta : ",delta,
           "\n min max delta: ",mdelta[ArrayMaximum(mdelta)]," : ",mdelta[ArrayMinimum(mdelta)],
           "");
  }
//+------------------------------------------------------------------+


Time fluctuates due to ping, server and terminal delays. But within -10; +10; milliseconds it works.

In the premarket ticks come too.

 
Sergey Chalyshev:

Try what I've got:



Time fluctuates due to ping, server and terminal delays. But within -10; +10; milliseconds it works.

In the premarket the ticks come too.

Thanks, I'll give it a try.

Added

Looks not bad, but.

1. If this code is inserted in a trading Expert Advisor, how to synchronize the correction between Expert Advisors, if

my Expert Advisor works on several futures?

2. If you put your code in a separate EA, there is no guarantee that the OnTick would come

into this symbol in the premarket (it may not come)?

3. Why is OnTick() better than OnBookEvent() in the premarket?

How is it "correct"

if(!SymbolInfoTick(_Symbol,tick)) { Print("error SymbolInfoTick",GetLastError()); return; }

than

if(CopyTicks(symbol,curr_tick,COPY_TICKS_INFO,0,1)==1)
 
prostotrader:

Thanks, I'll give it a try.

Added

It doesn't look bad, but

1. If this code is inserted in a trading Expert Advisor, how to synchronize the correction between Expert Advisors, if

my Expert Advisor works on several futures?

2. If you put your code in a separate EA, there is no guarantee that the OnTick would come

into this symbol in the premarket (may not come)?

The Expert Advisor should better be attached to a separate chart, the most liquid one, on two charts may interfere with each other.

When synchronization is better to remove, once a day synchronization should be enough. The clock of the broker, the exchange, or the computer cannot run or lag that much.

You can make the Expert Advisor delete itself when it synchronises.

 
Sergey Chalyshev:

It is better to put the advisor on a separate most liquid chart, two charts may interfere with each other.

When it synchronises it is better to remove it, once a day synchronisation should be enough. The clock of the broker, stock exchange or computer cannot run or lag so much.

We can make the Expert Advisor delete itself when it synchronizes.

And the third question?
 

3. Почему OnTick() лучше, чем OnBookEvent() в премаркет? 

The more "correct"

if(!SymbolInfoTick(_Symbol,tick)) {Print("errorSymbolInfoTick",GetLastError());return; }

not

if(CopyTicks(symbol,curr_tick,COPY_TICKS_INFO,0,1)==1)

as I've already explained, we can't get the time of change of the stick, such functionality doesn't exist in the terminal. The change of the cup occurs not only when Ask, Bid, Last are changed, respectively the time of OnBookEvent() is unknown.

you can only get the time of the tick.

OnTick() is no better than OnBookEvent(), it just doesn't work any other way.


 

From a neighbouring thread:

Forum on trading, automated trading systems and trading strategy testing

Sanction: Tslab + plaza 2 vs MT 5

Alexey Kozitsyn, 2017.01.17 12:02

You don't get it. I am aware of the tick structure, there are no complaints about it. The complaint is that in case of subscribing to update events, it is impossible to get the arrival time of this event, accordingly if I received ticks and then want to know the status of the cup - I cannot do this, as there is no arrival time of the cup! Synchronisation is impossible! Similarly with other stock indicators which I cited in the previous post.

And my question was when will the event arrival time of the cup + other stock indicators like OI be added.


 
Sergey Chalyshev:

I've already explained, we can't get the time of change of the cup, there is no such functionality in the terminal. The change of the cup does not happen only when Ask, Bid, Last are changed, respectively the time of OnBookEvent() is unknown.

you can only get the time of the tick.

OnTick() is no better than OnBookEvent(), you just can't do it any other way.


Sergei!

Look. A new quote has come and the market has changed, consequently, the OnBookEvent() event should be received,

which we simply use as an EVENT.

Then, it doesn't make any difference how you get information about the tick throughif(!SymbolInfoTick(_Symbol,tick)){Print("errorSymbolInfoTick",GetLastError());return; }

orif(CopyTicks(symbol,curr_tick,COPY_TICKS_INFO,0,1)==1)

But there is a huge difference in my approach and yours.

In my case, using EA on illiquid instrument (for example UUAH) you can add stacks of ALL futures and

it is GUARANTEED to obtain a tick in the premarket, without worrying about the work of other Expert Advisors in the terminal.

I.e. all new quotes will "go" into a separate EA.

Added by

The main thing is to keep the EA "in sync" without interfering with anyone else's work.

 
//+------------------------------------------------------------------+
//|                                              Time_sync_forts.mq5 |
//|                                      Copyright 2017 prostotrader |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017 prostotrader"
#property link      "https://www.mql5.com"
#property version   "1.01"
//---
struct _SYSTEMTIME
  {
   ushort            wYear;
   ushort            wMonth;
   ushort            wDayOfWeek;
   ushort            wDay;
   ushort            wHour;
   ushort            wMinute;
   ushort            wSecond;
   ushort            wMilliseconds;
  };

_SYSTEMTIME loc_time;

#import "kernel32.dll"
void GetLocalTime(_SYSTEMTIME &sys_time);
bool SetLocalTime(_SYSTEMTIME &sys_time);
#import
//---
bool     is_sync;
string   symb_rts;
string   symb_si;
string   symb_gold;
string   symb_br;
string   symb_gazr;
string   symb_sbrf;
datetime last_time;
//
input string BrInstr="BR-2.17"; //Brent
//+------------------------------------------------------------------+
//| Expert set second symbol function                                |
//+------------------------------------------------------------------+
string SetSecSymbol(const string a_symbol,const string prefix)
  {
   int str_tire=0;
   ushort let_symbol;
   int str_size=StringLen(a_symbol);

   for(int i=0; i<str_size; i++)
     {
      let_symbol=StringGetCharacter(a_symbol,i);

      if(let_symbol=='-')
        {
         str_tire=i;
         break;
        }
     }
   if(str_tire>0)
     {
      return(prefix + StringSubstr(a_symbol, str_tire, str_size - str_tire));
     }
   return("");
  }
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   last_time=TimeCurrent();
   is_sync=false;
   MarketBookAdd(Symbol());
//---  
   symb_rts=SetSecSymbol(Symbol(),"RTS");
   if(!SymbolSelect(symb_rts,true))
     {
      MessageBox(symb_rts+" not found in the Market watch!","Error",MB_OK|MB_ICONERROR);
      return(INIT_FAILED);
     }
   else MarketBookAdd(symb_rts);
//---  
   symb_si=SetSecSymbol(Symbol(),"Si");
   if(!SymbolSelect(symb_si,true))
     {
      MessageBox(symb_si+" not found in the Market watch!","Error",MB_OK|MB_ICONERROR);
      return(INIT_FAILED);
     }
   else MarketBookAdd(symb_si);
//---
   symb_gold=SetSecSymbol(Symbol(),"GOLD");
   if(!SymbolSelect(symb_gold,true))
     {
      MessageBox(symb_gold+" not found in the Market watch!","Error",MB_OK|MB_ICONERROR);
      return(INIT_FAILED);
     }
   else MarketBookAdd(symb_gold);
//---
   symb_gazr=SetSecSymbol(Symbol(),"GAZR");
   if(!SymbolSelect(symb_gazr,true))
     {
      MessageBox(symb_gazr+" not found in the Market watch!","Error",MB_OK|MB_ICONERROR);
      return(INIT_FAILED);
     }
   else MarketBookAdd(symb_gazr);
//---
   symb_sbrf=SetSecSymbol(Symbol(),"SBRF");
   if(!SymbolSelect(symb_sbrf,true))
     {
      MessageBox(symb_sbrf+" not found in the Market watch!","Error",MB_OK|MB_ICONERROR);
      return(INIT_FAILED);
     }
   else MarketBookAdd(symb_sbrf);
//---
   symb_br=BrInstr;
   if(!SymbolSelect(symb_br,true))
     {
      MessageBox(symb_br+" not found in the Market watch!","Error",MB_OK|MB_ICONERROR);
      return(INIT_FAILED);
     }
   else MarketBookAdd(symb_br);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   MarketBookRelease(Symbol());
   MarketBookRelease(symb_rts);
   MarketBookRelease(symb_br);
   MarketBookRelease(symb_si);
   MarketBookRelease(symb_gold);
   MarketBookRelease(symb_gazr);
   MarketBookRelease(symb_sbrf);
  }
//+------------------------------------------------------------------+
//| Expert Convert To Time function                                  |
//+------------------------------------------------------------------+
bool ConvertToTime(const long n_value,_SYSTEMTIME  &a_time)
  {
   a_time.wMilliseconds=ushort(n_value%1000);
   ulong new_time=ulong(double(n_value)/1000);
   MqlDateTime cur_time = {0};
   TimeToStruct(datetime(new_time),cur_time);
   if(cur_time.year>0)
     {
      a_time.wDay=ushort(cur_time.day);
      a_time.wDayOfWeek=ushort(cur_time.day_of_week);
      a_time.wHour=ushort(cur_time.hour);
      a_time.wMinute= ushort(cur_time.min);
      a_time.wMonth = ushort(cur_time.mon);
      a_time.wSecond= ushort(cur_time.sec);
      a_time.wYear=ushort(cur_time.year);
      return(true);
     }
   return(false);
  }  
//+------------------------------------------------------------------+
//| Expert On book event function                                    |
//+------------------------------------------------------------------+
void OnBookEvent(const string &symbol)
  {
   loc_time.wYear=0;
   GetLocalTime(loc_time);
   if(loc_time.wYear>0)
     {
      if((loc_time.wHour==9) && (loc_time.wMinute>=50) && (loc_time.wMinute<=59))
        {
         MqlTick curr_tick[1];
         if(CopyTicks(symbol,curr_tick,COPY_TICKS_INFO,0,1)==1)
           {
            MqlDateTime sv_time;
            TimeToStruct(curr_tick[0].time,sv_time);
            if(!is_sync)
              {
               if((loc_time.wDayOfWeek==ushort(sv_time.day_of_week)) &&
                  (loc_time.wHour==ushort(sv_time.hour)))
                 {
                  long last_ping=long(NormalizeDouble((double(TerminalInfoInteger(TERMINAL_PING_LAST))/1000)/2,0));
                  long mls_time=long(curr_tick[0].time_msc%1000);
                  if((mls_time+last_ping)>999)
                    {
                     mls_time=long(curr_tick[0].time_msc)+last_ping;
                     if(!ConvertToTime(mls_time, loc_time)) return;
                    }
                  else
                    {
                     loc_time.wMinute = ushort(sv_time.min);
                     loc_time.wSecond = ushort(sv_time.sec);
                     loc_time.wMilliseconds=ushort(mls_time);
                    }
                  if(SetLocalTime(loc_time))
                    {
                     is_sync=true;
                     Print("Local time sync is done. Symbol = ", symbol, " Sync min = ", loc_time.wMinute,
                           " Sync sec = ", loc_time.wSecond, " Sync ms = ", loc_time.wMilliseconds);
                    }
                 }
              }
           }
        }
      else is_sync=false;
     }
  }
//+------------------------------------------------------------------+
 

Only, today, after 10:00 (synchronisation was in pre-market)

local time differed from the time in the Market Watch by 7 sec. :(

 
prostotrader:

Sergei!

Look. A new quote has come, the market has changed, therefore the OnBookEvent() event must be received,

which we simply use as EVENT.

Then, it doesn't make any difference how you get information about the tick throughif(!SymbolInfoTick(_Symbol,tick)){Print("errorSymbolInfoTick",GetLastError());return; }

orif(CopyTicks(symbol,curr_tick,COPY_TICKS_INFO,0,1)==1)

But there is a huge difference in my approach and yours.

In my case, using EA on illiquid instrument (for example UUAH) you can add stacks of ALL futures and

it is GUARANTEED to obtain a tick in the premarket, without worrying about the work of other Expert Advisors in the terminal.

I.e. all new quotes will "go" into a separate EA.

Added by

It will "deal" only with synchronization and will not interfere with anyone else's work.

A new quote has come and the market depth has changed - these are different events. If a bid or offer higher or lower than ask is added (removed), the OnBookEvent() event occurs but it is not a new quote and it does not get to the tick history and therefore the last known server time does not change.

I don't know how else to explain it, are you kidding? ))