[Erro em obter o tempo do TF sênior no temporizador!

 

Objetivo: Ao iniciar o indicador, obter os dados atuais no cronômetro: o horário de abertura da barra semanal, diária e horária. Em seguida, escreva-as em variáveis globais para uso posterior. O cronograma atual é М1.

Implementação: Obtemos os tempos de barra usando a função 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 );
  }

Resultado: Como resultado, se o terminal ÚLTIMO funcionasse por várias horas, por exemplo, se estivesse desligado durante a noite, obtemos tal resultado em seu primeiro (um dia) início:

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

Como você pode ver, o tempo de recuperação de dados é 2018.09.21 11:11, e para essa hora recebemos o horário de abertura do dia = 2018.09.20 (embora deva ser 2018.09.21) e o horário de abertura da hora = 2018.09.20 16:00 (embora deva ser 2018.09.21 11:00). E o tempo devolvido pelo terminal não é nada além dos dados no momento em que ele foi fechado pela última vez. Isto é, os dados são armazenados em cache e devolvidos independentemente do fato de que o terminal tenha sido desligado. E entendo se o erro #4066 seria devolvido toda vez (dados históricos solicitados em estado de atualização) até que os dados sejam atualizados, mas não, são os dados ERROR que são devolvidos! Este erro só é devolvido uma vez e então você pode viver com ele. Há um claro erro de cache. Peço aos desenvolvedores(@Slava) que prestem atenção a isso!

Repito. Os dados errôneos aparecerão se forem solicitados no temporizador!

Versão terminal: x64, 1090.

 
Portanto, o erro 4066 é um problema típico dos índices MTF, o terminal não alimentou os dados de outros TFs, a integridade dos dados de outros TFs precisa ser verificada.
 
Vitaly Gorbunov:
Portanto, o erro 4066 é um problema típico dos usuários de MTF, o terminal não bombeou os dados de outros TFs que precisam verificar a integridade de outros dados de TFs.

Veja mais de perto o código e o que eu escrevi antes de dar conselhos.

O código tem uma verificação de erros e uma verificação de dados vazios. E quando uma função retorna dados incorretos sem um erro, é um erro!

 
Alexey Kozitsyn:

Veja mais de perto o código e o que eu escrevi antes de dar conselhos.

O código tem uma verificação de erros e uma verificação de dados vazios. E quando uma função retorna dados incorretos sem um erro, é um erro!

Talvez eu tenha perdido algo, mostre-me onde você verifica a integridade da história, por exemplo, no procedimentoCheckCurrentHourOpenTime()
 
Vitaly Gorbunov:
Talvez eu tenha perdido algo e me mostre onde você verifica a integridade da história, por exemplo, no procedimentoCheckCurrentHourOpenTime()

O que você quer dizer com integridade da história?

Estou falando do fato de que há uma verificação de erros quando se recuperam valores históricos. Há um cheque em cada função. Aqui está:

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

Isto é, se for recebido um valor zero ou erro - o tempo não é escrito em variável global. Você acha que não é suficiente?

A questão é que a função SeriesInfoInteger() primeiro retorna um erro, mas na próxima execução ela retorna NÃO! E também não retorna o valor correto!
 

SeriesInfoInteger() retorna apenas informações para uma determinada consulta, neste caso estamos pedindo para retornar o último tempo conhecido de abertura de bar na história por símbolo e período. Não há erro aqui, o que era o mais recente no momento é o que retornou. Mostrarei a você como verificar a integridade da história.

 
Vitaly Gorbunov:

SeriesInfoInteger() retorna apenas informações para uma determinada consulta, neste caso estamos pedindo para retornar o último tempo conhecido de abertura de bar na história por símbolo e período. Não há erro aqui, o que era o mais recente no momento é o que retornou. Chegarei ao PC e lhe mostrarei como verificar a integridade do histórico.

Você quer dizer que não há erro aqui!? Então por que está dando códigos de erro "falsos"? Diz que a história está bem onde não está...

 
Alexey Kozitsyn:

O que você quer dizer com "não há erro aqui"? Então por que está dando códigos de erro "falsos"? Diz que a história está bem onde não está...

Mais uma vez, esta função não verifica a integridade da história! Ele retorna as informações que poderia encontrar nele. Neste caso em particular, encontrou a barra de horas que foi solicitada quando o terminal foi desligado. O resto da história ainda não foi carregada.

 

Para verificar se o histórico de um determinado TF está paginando completamente, basta usar uma função:

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

Se a função retornar falso, os dados para o TF solicitado estão incompletos. Caso contrário, está completo.

 
Vitaly Gorbunov:

Mais uma vez, esta função não verifica a integridade da história! Ela retorna as informações que conseguiu encontrar nela. Neste caso, encontrou a barra de horas que foi solicitada quando o terminal foi desligado. O resto da história ainda não foi carregada.

Mais uma vez. Não é mencionado em nenhum lugar. Isso é o primeiro de tudo. Em segundo lugar, então por que é enganador mostrar primeiro o código de erro 4066 e depois não?

 
Ihor Herasko:

Para verificar se o histórico de um determinado TF está paginando completamente, basta usar uma função:

Se a função retornar falso, os dados para o TF solicitado estão incompletos. Caso contrário, está completo.

Você já verificou no temporizador? Você vê que eu comentei linhas? Eu verifiquei esta função, ela não mostrava nenhum erro e também mostrava dados incorretos. Vou verificar novamente.

Razão: