Синхронизация локального времени Windows с сервером МТ5 - страница 6

 
prostotrader:

Кто-нибудь может пояснить, почему этот код не точно синхронизиоует время?

Ведь в премаркет приходит "свежая" котировка, с новым временем сервера(биржи).

 Попробуй то что у меня получилось:

//+------------------------------------------------------------------+
//|                                                    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)],
           "");
  }
//+------------------------------------------------------------------+


 

Время плавает из за пинга, задержек сервера и терминала. Но в пределах -10; +10; миллисекунд получается синхронизировать. 

В премаркет тики тоже приходят. 

 
Sergey Chalyshev:

 Попробуй то что у меня получилось:



 

Время плавает из за пинга, задержек сервера и терминала. Но в пределах -10; +10; миллисекунд получается синхронизировать. 

В премаркет тики тоже приходят. 

Спасибо, попробую.

Добавлено

Выглядит не плохо, но

1. Если этот код вставить в торгового эксперта, то как синхронизировать коррекцию между экспертами, если

этот эксперт работает на нескольких фьючерсах?

2. Если поместить твой код в отдельного эксперта, то где гарантия, что OnTick придёт имеено

в этот символ в премаркет (может и не прийти)? 

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

Чем "правильнее"

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

нежели

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


 

 
prostotrader:

Спасибо, попробую.

Добавлено

Выглядит не плохо, но

1. Если этот код вставить в торгового эксперта, то как синхронизировать коррекцию между экспертами, если

этот эксперт работает на нескольких фьючерсах?

2. Если поместить твой код в отдельного эксперта, то где гарантия, что OnTick придёт имеено

в этот символ в премаркет (может и не прийти)? 

Советник лучше повесить на отдельный график наиболее ликвидный, на двух графиках могут мешать друг другу.

Когда синхронизируется лучше удалить, раз в сутки синхронизировать достаточно должно быть. Не могут же часы брокера, биржи или компьютера так сильно бежать или отставать.

Можно сделать чтобы советник сам удалялся когда синхронизируется.

 
Sergey Chalyshev:

Советник лучше повесить на отдельный график наиболее ликвидный, на двух графиках могут мешать друг другу.

Когда синхронизируется лучше удалить, раз в сутки синхронизировать достаточно должно быть. Не могут же часы брокера, биржи или компьютера так сильно бежать или отставать.

Можно сделать чтобы советник сам удалялся когда синхронизируется.

А третий вопрос?
 

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

Чем "правильнее"

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

нежели

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

я же объяснял уже, мы не можем получить время изменения стакана, такого функционала нет в терминале. Изменения стакана происходит не только когда изменяется Ask, Bid, Last, соответственно и время OnBookEvent() неизвестно. 

можно получить только время тика. 

OnTick() не лучше, чем OnBookEvent(), просто по другому не получится. 


 

из соседней ветки:

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Сантимент: Tslab + plaza 2 против MT 5

Alexey Kozitsyn, 2017.01.17 12:02

Вы не поняли. Я в курсе структуры тика, к ней претензий нет. Претензии есть к тому, что в случае подписки на события обновления стакана, невозможно получить время прихода этого события, соответственно если я получил тики, а затем хочу узнать состояние стакана - я не могу этого сделать, т.к. времени прихода стакана нет! Синхронизацию провести невозможно! Аналогично с другими биржевыми показателями, которые привел в предыдущем посте.

И мой вопрос заключался в том, когда будет добавлено время прихода события стакана + других биржевых показателей, таких как ОИ. 


 
Sergey Chalyshev:

я же объяснял уже, мы не можем получить время изменения стакана, такого функционала нет в терминале. Изменения стакана происходит не только когда изменяется Ask, Bid, Last, соответственно и время OnBookEvent() неизвестно. 

можно получить только время тика. 

OnTick() не лучше, чем OnBookEvent(), просто по другому не получится. 


Серёж!

Смотри. Пришла новая котировка, стакан изменился, следовательно должно прийти событие OnBookEvent(),

которое мы просто используем как СОБЫТИЕ. 

Затем, нет никакой разницы как ты получаешь инфу о тике через if(!SymbolInfoTick(_Symbol,tick)) { Print("error SymbolInfoTick",GetLastError()); return; }

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

Но разница в моём подходе и твоём огромная.

В моём случае, используя эксперта на малоликвидном инструменте (например UUAH) ты можешь добавить стаканы ВСЕХ фьючерсов и

ГАРАНТИРОВАННО получишь тик в премаркет, не думая о работе других экспертов в терминале. 

Т.е все новые котировки будут "идти" в отдельный советник. 

Добавлено

который будет "заниматься" только синхронизацией, не мешая никому. 

 
//+------------------------------------------------------------------+
//|                                              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;
     }
  }
//+------------------------------------------------------------------+
 

Вот только, сегодня, после 10-00 (синхронихация была в премаркет)

локальное время отличалось от времени в Обзоре рынка на 7 сек.  :(

 
prostotrader:

Серёж!

Смотри. Пришла новая котировка, стакан изменился, следовательно должно прийти событие OnBookEvent(),

которое мы просто используем как СОБЫТИЕ. 

Затем, нет никакой разницы как ты получаешь инфу о тике через if(!SymbolInfoTick(_Symbol,tick)) { Print("error SymbolInfoTick",GetLastError()); return; }

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

Но разница в моём подходе и твоём огромная.

В моём случае, используя эксперта на малоликвидном инструменте (например UUAH) ты можешь добавить стаканы ВСЕХ фьючерсов и

ГАРАНТИРОВАННО получишь тик в премаркет, не думая о работе других экспертов в терминале. 

Т.е все новые котировки будут "идти" в отдельный советник. 

Добавлено

который будет "заниматься" только синхронизацией, не мешая никому. 

Пришла новая котировка и стакан изменился это разные события. При изменении стакана если добавлена (убрана) заявка выше ask или ниже bid, событие OnBookEvent() приходит, но это не новая котировка и в историю тиков она не попадает, следовательно и последнее известное время сервера не меняется. 

Блин не знаю как еще объяснить, прикалываешься? )) 

Причина обращения: