[SERVICE DESK] Zamanlayıcıda kıdemli TF'nin zamanı alınırken hata oluştu!

 

Görev: göstergeyi başlatırken, zamanlayıcıdaki gerçek verileri alın: haftalık, günlük ve saatlik çubuğun açılış saati. Sonra bunları daha sonra kullanmak üzere global değişkenlere yazın. Mevcut TF M1'dir.

Gerçekleştirme: SeriesInfoInteger() işlevini kullanarak çubukların zamanını elde ederiz.

 #property version    "1.00"
#property strict
#property indicator_chart_window
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//--- Время открытия текущего часа, дня и недели
datetime _weekOpenTime = 0 ;
datetime _hourOpenTime = 0 ;
datetime _dayOpenTime= 0 ;
//--- Вести лог журнала
const bool inpFileLog= true ;
//--- Количество секунд в одном дне
const int SEC_PER_DAY= 86400 ;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit ()
  {
//--- Запускаем таймер
   if (! EventSetMillisecondTimer ( 20 ))
     {
       Print ( __FUNCTION__ , ": ОШИБКА #" , GetLastError (), ": таймер с частотой 20 ms не установлен!" );
       return ( INIT_FAILED );
     }
//--- Сбрасываем время открытия текущего часа, дня и недели
   _weekOpenTime= 0 ;
   _dayOpenTime = 0 ;
   _hourOpenTime= 0 ;
//---
   return ( INIT_SUCCEEDED );
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate ( const int rates_total,
                 const int prev_calculated,
                 const datetime &time[],
                 const double &open[],
                 const double &high[],
                 const double &low[],
                 const double &close[],
                 const long &tick_volume[],
                 const long &volume[],
                 const int &spread[])
  {

   return ( rates_total );
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer ()
  {
//--- Проверяем, записано ли время открытия текущей недели
   if (!CheckCurrentWeekOpenTime())                         // Если время не записано
       return ;                                                 // Выходим
//--- Проверяем, записано ли время открытия текущего дня
   if (!CheckCurrentDayOpenTime())                         // Если время не записано
       return ;                                                 // Выходим
//--- Проверяем, записано ли время открытия текущего часа
   if (!CheckCurrentHourOpenTime())                         // Если время не записано
       return ;                                                 // Выходим
  }
//+------------------------------------------------------------------+
//| Проверяем, записано ли время открытия текущей недели             |
//+------------------------------------------------------------------+
bool CheckCurrentWeekOpenTime()
  {
//--- Проверяем, записано ли время
   if (_weekOpenTime== 0 ) // Если время не записано
     {
       //--- Получаем время открытия недельного бара
       ResetLastError ();
       const datetime weekBarOpenTime=( datetime ) SeriesInfoInteger ( _Symbol , PERIOD_W1 , SERIES_LASTBAR_DATE );
       const int err= GetLastError ();
       //---
       if (inpFileLog)
        {
         Print ( __FILE__ , ": Время открытия недельного бара = " + TimeToString (weekBarOpenTime)+ ". Ошибка #" ,err);
         //Print( __FILE__,": Время открытия текущей недели через iTime = "+TimeToString( weekOpenTime2 )+". Ошибка #",err2 );
        }
       //ResetLastError();
       //const datetime weekBarOpenTime2 = iTime( _Symbol, PERIOD_W1, 0 );
       //const int err2 = GetLastError();
       //--- Проверяем, получено ли время открытия недельного бара
       if (weekBarOpenTime== 0 || err!= 0 ) // Если время бара не получено или история обновляется
         return ( false );                               // Возвращаем ложь
       //--- Запоминаем время открытия текущей недели (время открытия недельного бара - воскресенье)
      _weekOpenTime=weekBarOpenTime+SEC_PER_DAY;
       //const datetime weekOpenTime2 = weekBarOpenTime2+SEC_PER_DAY;
       //---
       if (inpFileLog)
        {
         Print ( __FILE__ , ": Актуальное время открытия текущей недели = " + TimeToString (_weekOpenTime)+ ". Ошибка #" ,err);
         //Print( __FILE__,": Время открытия текущей недели через iTime = "+TimeToString( weekOpenTime2 )+". Ошибка #",err2 );
        }
       //--- Возвращаем истину
       return ( true );
     }
//--- Время открытия недели ранее записано. Возвращаем истину
   return ( true );
  }
//+------------------------------------------------------------------+
//| Проверяем, записано ли время открытия текущего дня                  |
//+------------------------------------------------------------------+
bool CheckCurrentDayOpenTime()
  {
//--- Проверяем, записано ли время
   if (_dayOpenTime== 0 ) // Если время не записано
     {
       //--- Получаем время открытия дневного бара
       ResetLastError ();
       const datetime tempDayOpenTime=( datetime ) SeriesInfoInteger ( _Symbol , PERIOD_D1 , SERIES_LASTBAR_DATE );
       const int err= GetLastError ();
       //ResetLastError();
       //const datetime dayOpenTime2 = iTime( _Symbol, PERIOD_D1, 0 );
       //const int err2 = GetLastError();
       //---
       if (inpFileLog)
        {
         Print ( __FILE__ , ": Время открытия текущего дня = " + TimeToString (tempDayOpenTime)+ ". Ошибка #" ,err);
         //Print( __FILE__,": Время открытия текущего дня iTime = "+TimeToString( dayOpenTime2 )+". Err2 #",err2 );
        }
       //--- Проверяем, получено ли время открытия дневного бара
       if (tempDayOpenTime== 0 || err!= 0 ) // Если время бара не получено
         return ( false );                                 // Возвращаем ложь
       //--- Сохраняем в глобальную переменную значение открытия текущего дня
      _dayOpenTime=tempDayOpenTime;
       //---
       if (inpFileLog)
        {
         Print ( __FILE__ , ": Актуальное время открытия текущего дня = " + TimeToString (_dayOpenTime)+ ". Ошибка #" ,err);
         //Print( __FILE__,": Время открытия текущей недели через iTime = "+TimeToString( weekOpenTime2 )+". Ошибка #",err2 );
        }
       //--- Возвращаем истину
       return ( true );
     }
//--- Время открытия дня ранее записано. Возвращаем истину
   return ( true );
  }
//+------------------------------------------------------------------+
//| Проверяем, записано ли время открытия текущего часа              |
//+------------------------------------------------------------------+
bool CheckCurrentHourOpenTime()
  {
//--- Проверяем, записано ли время
   if (_hourOpenTime== 0 ) // Если время не записано
     {
       //--- Получаем время открытия часового бара
       ResetLastError ();
       const datetime tempHourOpenTime=( datetime ) SeriesInfoInteger ( _Symbol , PERIOD_H1 , SERIES_LASTBAR_DATE );
       const int err= GetLastError ();
       //const datetime hourOpenTime2 = iTime( _Symbol, PERIOD_H1, 0 );
       //---
       if (inpFileLog)
        {
         Print ( __FILE__ , ": Время открытия текущего часа = " + TimeToString (tempHourOpenTime)+ ". Ошибка #" ,err);
         //Print( __FILE__,": Время открытия текущего часа iTime = "+TimeToString( hourOpenTime2 ) );
        }
       //--- Проверяем, получено ли время открытия часового бара
       if (tempHourOpenTime== 0 || err!= 0 ) // Если время бара не получено
         return ( false );                                 // Возвращаем ложь
       //---
      _hourOpenTime=tempHourOpenTime;
       //---
       if (inpFileLog)
        {
         Print ( __FILE__ , ": Актуальное время открытия текущего часа = " + TimeToString (_hourOpenTime)+ ". Ошибка #" ,err);
         //Print( __FILE__,": Время открытия текущего часа iTime = "+TimeToString( hourOpenTime2 ) );
        }
       //--- Возвращаем истину
       return ( true );
     }
//--- Время открытия часа ранее записано. Возвращаем истину
   return ( true );
  }

Sonuç: Sonuç olarak, eğer terminal birkaç saat boyunca ÇALIŞMIYORSA , örneğin, gece için kapatıldıysa, ilk (günlük) başlatıldığında aşağıdaki sonucu alırız:

 2018.09 . 21 11 : 11 : 27.306 test_isNewDayInTimer USDCHF.e,M1: test_isNewDayInTimer.mq4: Актуальное время открытия текущего часа = 2018.09 . 20 16 : 00 . Ошибка # 0
2018.09 . 21 11 : 11 : 27.306 test_isNewDayInTimer USDCHF.e,M1: test_isNewDayInTimer.mq4: Время открытия текущего часа = 2018.09 . 20 16 : 00 . Ошибка # 0
2018.09 . 21 11 : 11 : 27.280 test_isNewDayInTimer USDCHF.e,M1: test_isNewDayInTimer.mq4: Время открытия текущего часа = 2018.09 . 20 16 : 00 . Ошибка # 4066
2018.09 . 21 11 : 11 : 27.279 test_isNewDayInTimer USDCHF.e,M1: test_isNewDayInTimer.mq4: Актуальное время открытия текущего дня = 2018.09 . 20 00 : 00 . Ошибка # 0
2018.09 . 21 11 : 11 : 27.279 test_isNewDayInTimer USDCHF.e,M1: test_isNewDayInTimer.mq4: Время открытия текущего дня = 2018.09 . 20 00 : 00 . Ошибка # 0
2018.09 . 21 11 : 11 : 27.265 test_isNewDayInTimer USDCHF.e,M1: test_isNewDayInTimer.mq4: Время открытия текущего дня = 2018.09 . 20 00 : 00 . Ошибка # 4066
2018.09 . 21 11 : 11 : 27.264 test_isNewDayInTimer USDCHF.e,M1: test_isNewDayInTimer.mq4: Актуальное время открытия текущей недели = 2018.09 . 17 00 : 00 . Ошибка # 0
2018.09 . 21 11 : 11 : 27.264 test_isNewDayInTimer USDCHF.e,M1: test_isNewDayInTimer.mq4: Время открытия недельного бара = 2018.09 . 16 00 : 00 . Ошибка # 0
2018.09 . 21 11 : 11 : 27.233 test_isNewDayInTimer USDCHF.e,M1: test_isNewDayInTimer.mq4: Время открытия недельного бара = 2018.09 . 16 00 : 00 . Ошибка # 4066
2018.09 . 21 11 : 11 : 27.066 test_isNewDayInTimer USDCHF.e,M1: initialized
2018.09 . 21 11 : 11 : 27.055 Custom indicator test_isNewDayInTimer USDCHF.e,M1: loaded successfully

Gördüğünüz gibi, veri alma zamanı 2018.09.21 11:11 ve bu sefer için günün açık zamanını = 2018.09.20 (2018.09.21 olmasına rağmen) ve açık zamanını alıyoruz. saat = 2018.09.20 16:00 (2018.09 .21 11:00 olmasına rağmen). Ayrıca, terminal tarafından döndürülen zaman, son kez kapatıldığı andaki veriden başka bir şey değildir. Onlar. veriler, terminalin kapatılmış olmasına bakılmaksızın önbelleğe alınır ve döndürülür. Ve anlıyorum ki, veriler güncellenene kadar her seferinde #4066 hatası (güncelleme durumunda istenen geçmiş veriler) döndürülürse, ancak hayır, döndürülen ERROR verileridir! Bu hata yalnızca bir kez döndürülür ve ardından - istediğiniz gibi yaşayın. Bu açık bir önbelleğe alma hatası. Geliştiricilerden ( @Slava ) buna dikkat etmelerini rica ediyorum!

Tekrarlıyorum. Zamanlayıcıda talep ederseniz hatalı veriler görünür!

Terminal sürümü: x64, 1090.

 
4066 hatası MTF hindileri için tipik bir sorundur, terminal diğer TF'lerden veri yüklemedi, diğer TF'lerin veri bütünlüğünü kontrol etmek gerekiyor.
 
Vitaly Gorbunov :
4066 hatası MTF hindileri için tipik bir sorundur, terminal diğer TF'lerden veri yüklemedi, diğer TF'lerin veri bütünlüğünü kontrol etmek gerekiyor.

Tavsiye vermeden önce koda ve yazdıklarıma daha yakından bakın.

Kodun hata kontrolü ve boş veri kontrolü vardır. Ve bir fonksiyon hatasız yanlış veri döndürdüğünde, bu bir hatadır!

 
Alexey Kozitsyn :

Tavsiye vermeden önce koda ve yazdıklarıma daha yakından bakın.

Kodun hata kontrolü ve boş veri kontrolü vardır. Ve bir fonksiyon hatasız yanlış veri döndürdüğünde, bu bir hatadır!

Belki bir şeyi kaçırdım, örneğin CheckCurrentHourOpenTime () prosedüründe geçmişin bütünlüğünü nerede kontrol ettiğinizi gösterin.
 
Vitaly Gorbunov :
Belki bir şeyi kaçırdım, örneğin CheckCurrentHourOpenTime () prosedüründe geçmişin bütünlüğünü nerede kontrol ettiğinizi gösterin.

Tarihin bütünlüğünden ne anlıyorsunuz?

Geçmiş değerleri alınırken hata kontrolü yapıldığından bahsediyorum. Her fonksiyonda bir kontrol var. İşte burada:

 //--- Проверяем, получено ли время открытия часового бара
       if (tempHourOpenTime== 0 || err!= 0 ) // Если время бара не получено
         return ( false );                                 // Возвращаем ложь

Onlar. boş bir değer veya bir hata alınırsa, zaman global değişkene yazılmaz. Sizce bu yeterli değil mi?

Sonuç olarak, SeriesInfoInteger() işlevi önce bir hata döndürür, ancak sonraki çalıştırmada - HAYIR! Üstelik doğru değeri de döndürmez!
 

SeriesInfoInteger() yalnızca belirli bir istekle ilgili bilgileri döndürür, bu durumda tarihte bilinen son çubuğun açılış zamanını sembol ve nokta ile döndürmeyi istiyoruz. Burada bir hata yok, ki o an aşırıydı, sonra iade etti. Şimdi büyük bir bilgisayara gideceğim ve size geçmişin bütünlüğünü nasıl kontrol edebileceğinizi göstereceğim.

 
Vitaly Gorbunov :

SeriesInfoInteger() yalnızca belirli bir istekle ilgili bilgileri döndürür, bu durumda tarihte bilinen son çubuğun açılış zamanını sembol ve nokta ile döndürmeyi istiyoruz. Burada bir hata yok, ki o an aşırıydı, sonra iade etti. Şimdi büyük bir bilgisayara gideceğim ve size geçmişin bütünlüğünü nasıl kontrol edebileceğinizi göstereceğim.

Ne demek hata yok? Ve neden o zaman "sol" hata kodları veriyor. Tarihin yanlış olduğu yerde doğru olduğunu söylüyor...

 
Alexey Kozitsyn :

Ne demek hata yok? Ve neden o zaman "sol" hata kodları veriyor. Tarihin yanlış olduğu yerde doğru olduğunu söylüyor...

Bir kez daha, bu işlev geçmişin bütünlüğünü kontrol etmez! İçinde bulabildiği bilgileri geri verir. Belirli bir durumda, terminalin kapatıldığı anda talep edilen saatlik bir bar buldu. Hikayenin geri kalanı henüz yüklenmedi.

 

Belirli bir TF'nin geçmişinin tamamen değiştirildiğini kontrol etmek için işlevi kullanmak yeterlidir:

 bool IsTFDataReady( ENUM_TIMEFRAMES eTF)
{
   ResetLastError ();
   iTime ( NULL , eTF, 1 );
   return GetLastError () == ERR_NO_ERROR ;
}

İşlev false döndürürse, istenen TF'deki veriler eksiktir. Aksi takdirde, tamamlayın.

 
Vitaly Gorbunov :

Bir kez daha, bu işlev geçmişin bütünlüğünü kontrol etmez! İçinde bulabildiği bilgileri geri verir. Belirli bir durumda, terminalin kapatıldığı anda talep edilen saatlik bir bar buldu. Hikayenin geri kalanı henüz yüklenmedi.

Tekrar. Bu hiçbir yerde bahsedilmiyor. Bu ilk. İkincisi, neden önce 4066 hata kodunu gösterip sonra değil de yanlış yönlendiriyor?

 
Ihor Herasko :

Belirli bir TF'nin geçmişinin tamamen değiştirildiğini kontrol etmek için işlevi kullanmak yeterlidir:

İşlev false döndürürse, istenen TF'deki veriler eksiktir. Aksi takdirde, tamamlayın.

Zamanlayıcıyı kontrol ettiniz mi? Yorumladığım satırları görüyor musun? Bu işlevi kontrol ettim, hiç hata göstermedi ve ayrıca yanlış veriler gösterdi. Tekrar kontrol edeceğim.

Neden: