[SERVICE DESK]在获取计时器中的高级TF的时间时出错!

 

目标: 当启动指标时,在计时器中获取当前数据:周线、日线和小时线的开盘时间。然后把它们写在全局变量中,以便进一步使用。目前的时间框架是М1。

实施: 我们使用SeriesInfoInteger()函数获得条形图时间。

#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 );
  }

结果: 作为一个结果,如果终端持续运行了几个小时,例如,它关闭了一晚上,我们在它的第一次(一天)启动时得到这样的结果。

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

正如你所看到的,数据检索时间是2018.09.21 11:11,对于这个时间,我们得到一天的开放时间=2018.09.20(尽管它应该是2018.09.21),小时的开放时间=2018.09.20 16:00(尽管它应该是2018.09.21 11:00)。而终端返回的时间不过是它最后一次关闭时的数据。也就是说,无论终端是否被关闭,数据都会被缓存并返回。我明白,如果每次都返回错误#4066(请求的历史数据处于更新状态),直到数据被更新,但没有,返回的是ERROR数据!这个错误只返回一次,然后你就可以忍受它了。有一个明显的缓存错误。我请开发人员(@Slava)注意一下!我的意思是说,如果你想知道更多的信息,请联系我。

我重复一遍。如果在定时器中要求,将出现错误的数据!

终端版本: x64,1090。

 
所以4066的错误是MTF指数的典型问题,终端没有反馈其他TF的数据,你需要检查其他TF的数据的完整性。
 
Vitaly Gorbunov:
那么,错误4066是MTF用户的一个典型问题,终端没有抽到其他TF的数据,需要检查其他TF数据的完整性。

在给出建议之前,请仔细看看代码和我所写的内容。

该代码有一个错误检查和一个空数据检查。而当一个函数在没有错误的情况下返回不正确的数据时,它就是一个错误!

 
Alexey Kozitsyn:

在给出建议之前,请仔细看看代码和我所写的内容。

该代码有一个错误检查和一个空数据检查。而当一个函数在没有错误的情况下返回不正确的数据时,它就是一个错误!

也许我错过了什么,告诉我你在哪里检查历史的完整性,例如,在CheckCurrentHourOpenTime() 过程中
 
Vitaly Gorbunov:
也许我错过了什么,请告诉我你在哪里检查历史的完整性,例如,在CheckCurrentHourOpenTime() 过程中。

你说的故事完整性是什么意思?

我说的是,在检索历史值时有一个检查错误的功能。每项功能中都有一个检查。在这里,它是。

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

也就是说,如果收到零值或错误--时间不会被写入全局变量。你认为这还不够吗?

关键是SeriesInfoInteger()函数首先返回一个错误,但在下一次运行时却返回NO!而且它也没有返回正确的值!
 

SeriesInfoInteger()只返回某个查询的信息,在这种情况下,我们要求按符号和周期返回历史上最后一个已知的酒吧 开盘时间。这里没有错误,目前的最新情况就是它返回的内容。我将告诉你如何检查历史的完整性。

 
Vitaly Gorbunov:

SeriesInfoInteger()只返回某个查询的信息,在本例中,我们要求按符号和周期返回历史上最后一个已知的 开盘时间。这里没有错误,目前的最新情况就是它返回的内容。我将到个人电脑前,告诉你如何检查历史的完整性。

你是说这里没有错误!?那为什么它发出 "假 "的错误代码?它说历史上没有问题的地方是可以的...

 
Alexey Kozitsyn:

你说这里没有错误是什么意思!?那么,为什么它会发出 "假 "的错误代码?它说历史上没有问题的地方是可以的...

再一次,这个函数并不检查历史的完整性它返回它能在其中找到的信息。在这个特定的案例中,它找到了终端关闭时要求的小时条。其余的历史还没有被加载。

 

要检查一个给定的TF的历史是否完全分页,只需使用一个函数。

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

如果该函数返回false,说明所请求的TF的数据不完整。否则,它就是完整的。

 
Vitaly Gorbunov:

再说一次,这个功能并不检查故事的完整性!它返回它能够在其中找到的信息。在这种情况下,它找到了终端关闭时要求的小时条。其余的历史还没有被加载。

再一次。任何地方都没有提到这一点。这首先是。第二,那么为什么先是显示错误代码 4066,然后又不显示,这是个误导?

 
Ihor Herasko:

要检查一个给定的TF的历史是否完全分页,只需使用一个函数。

如果该函数返回false,则所请求的TF的数据不完整。否则,它就是完整的。

你在定时器中检查过吗?你看到我评论了几行了吗?我检查了这个函数,它根本没有显示任何错误,也显示了不正确的数据。我再检查一下。