[SERVICE DESK] 타이머에서 시니어 TF의 시간을 가져오는 동안 오류가 발생했습니다!

 

작업: 표시기를 시작할 때 타이머의 실제 데이터를 가져옵니다: 주간, 일별 및 시간별 막대의 여는 시간. 그런 다음 나중에 사용할 수 있도록 전역 변수에 씁니다. 현재 TF는 M1입니다.

구현: 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(업데이트 상태에서 요청된 기록 데이터)이 반환될 때마다 데이터가 업데이트될 때마다 반환되지만 아니요, 반환되는 것은 오류 데이터라는 것을 이해합니다! 이 오류는 한 번만 반환된 다음 원하는 대로 실행됩니다. 명백한 캐싱 오류입니다. 개발자들( @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 );                                 // Возвращаем ложь

저것들. null 값이나 오류가 수신되면 시간이 전역 변수 에 기록되지 않습니다. 이것으로 충분하지 않다고 생각하십니까?

결론은 SeriesInfoInteger() 함수가 먼저 오류를 반환하지만 다음 실행에서는 - 아니요! 또한 올바른 값을 반환하지 않습니다!
 

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의 데이터가 불완전한 것입니다. 그렇지 않으면 완료합니다.

타이머는 확인하셨나요? 내 주석 줄을 참조하십시오? 이 기능을 확인했는데 오류가 전혀 표시되지 않고 잘못된 데이터도 표시되었습니다. 다시 확인하겠습니다.