History data and error 4066

 

Hello,

Is there any safe method to check if history is current after error 4066?.

THX!!

 
ArrayCopySeries - MQL4 Documentation states
If data are copied from another chart with different symbol and/or timeframe, it is possible that the necessary data will lack. In this case, error ERR_HISTORY_WILL_UPDATED (4066 - requested history data under updating) will be placed into the last_error variable, and there will be necessary to retry copying after a certain period of time.
And shows an example.
So I wrote this.
/** Starts and waits for a download of chart history.
 * In Technical Indicator Functions - MQL4 Documentation][TIF3] it states:
 * > If data (symbol name and/or timeframe differ from the current ones) are
 * > requested from another chart, the situation is possible that the
 * > corresponding chart was not opened in the client terminal and the
 * > necessary data must be requested from the server. In this case, error
 * > `ERR_HISTORY_WILL_UPDATED` (4066 - the requested history data are under
 * > updating) will be placed in the last_error variable, and and there will
 * > be necessary to retry \[the operation] after a certain period of time.
 *
 * The [ArrayCopySeries][ACS] example tests array[0] against server time.
 * [ACS]: https://docs.mql4.com/array/arraycopyseries
 * [TIF3]: https://docs.mql4.com/en/indicators
 *
 * Note: you _only_ get 4066 once. Subsequent calls (\::ArrayCopyRates and
 * apparently \::ArrayCopySeries) silently succeed but the data is bogus
 * until the download completes. These calls should have been synchronous,
 * but then they couldn't be used in indicators.
 */
bool  download_history(
         ENUM_TIMEFRAMES   period=PERIOD_CURRENT,  ///< The standard timeframe.
         string            msg=__FUNSIG__          ///< Debug.
         SYMBOL            symbol=THIS_SYMBOL      /**< The symbol required.*/){
   if(symbol == THIS_SYMBOL)     symbol = _Symbol;
   if(period == PERIOD_CURRENT)  period = _Period;
   ResetLastError();
   datetime other = iTime(symbol, period, 0);
   if(_LastError == 0)  return true;
   if(_LastError != ERR_HISTORY_WILL_UPDATED){
      AssertFailure(StringFormat("%s: iTime(%s,%i) Failed: %i",
                                 msg, symbol, period, _LastError) );
      return false;
   }
   datetime today = DateOfDay();
   for(int i = 0;i < 15; i++){
      Sleep(1000);
      ResetLastError();
      other = iTime(symbol, period, 0);
      if(today == DateOfDay(other)){   RefreshRates();   return true;   }
   }
   AssertFailure(StringFormat("%s: iTime(%s,%i) Failed: %i (15 secs)",
                              msg, symbol, period, _LastError) );
   return false;
}
 
#define HR2400 PERIOD_D1 * 60    // 86400 = 24 * 3600
int      TimeOfDay(datetime when=0){      if(when == 0)  when = TimeCurrent();
                                          return( when % HR2400 );            }
datetime DateOfDay(datetime when=0){      if(when == 0)  when = TimeCurrent();
                                          return( when - TimeOfDay(when) );   }
//datetime Tomorrow( datetime when=0){      if(when == 0)  when = TimeCurrent();
//                                          return(DateOfDay(when) + HR2400);   }
//datetime Yesterday(datetime when=0){      if(when == 0)  when = TimeCurrent();
//   int iD1 = iBarShift(NULL, PERIOD_D1, DateOfDay(when) - 1);
//                                       return( iTime(NULL, PERIOD_D1, iD1) ); }
 
whroeder1:
ArrayCopySeries - MQL4 Documentation states And shows an example.
So I wrote this.
Sleep() is not executed in indicators.
 

I tend to use OnTimer() with a simple flag in OnTick() / OnCalculate() to be compatible with both.

Although I believe OnTimer() wasn't an option back in 2015 

 
honest_knave:

I tend to use OnTimer() with a simple flag in OnTick() / OnCalculate() to be compatible with both.

Although I believe OnTimer() wasn't an option back in 2015 

OnTimer was available since 2014.
 
Ovo Cz:
OnTimer was available since 2014.

I stand corrected! 

I guess it was a build 600 thing.

 
Alain Verleyen: Sleep() is not executed in indicators.
True. In another thread I posted a variation of download_history that didn't have the internal wait, but immediately returned false. Thus the calls would be:
In indicators
int OnCalculate(...){
   if(!download_history(...) return prev_calculated;
   :
Return and wait for the next tick and retry.
In EAs
void OnTick(){
   while(!download_history(...){ Sleep(1000); RefreshRates(); }
   :
 
whroeder1:
True. In another thread I posted a variation of download_history that didn't have the internal wait, but immediately returned false. Thus the calls would be:
In indicators
int OnCalculate(...){
   if(!download_history(...) return prev_calculated;
   :
Return and wait for the next tick and retry.
In EAs
void OnTick(){
   while(!download_history(...){ Sleep(1000); RefreshRates(); }
   :
Yes. I didn't notice it was an old post.
Reason: