Error ERR_CALENDAR_TIMEOUT in CalendarValueHistory when passing more than 1 month interval

 

CalendarValueHistory function times out if a period longer than one month is passed to it. I noticed this issue on b5327. Previously, this issue didn't exist, and the function returned all calendar events for the entire period.


   MqlCalendarValue Values[];
   datetime from = TimeCurrent ()- 30 * 24 * 60 * 60 ;
   CalendarValueHistory (Values, from, 0 , NULL , NULL ); // Returns aprox 5000 events in less 70ms 
   Print ( ArraySize (Values));
   Print ( GetLastError ());
  
  
   MqlCalendarValue Values[];
   datetime from = TimeCurrent ()- 31 * 24 * 60 * 60 ;
   CalendarValueHistory (Values, from, 0 , NULL , NULL );   // Timeout error 5401 – ERR_CALENDAR_TIMEOUT after aprox. 50 sec 
   Print ( ArraySize (Values));
   Print ( GetLastError ());  

What could be the problem and how to fix it?

 
I never get this error but sometimes I get the too many requests error. Might be a broker issue? Also I think using 0 in the third parameter will try and load all events in the future which who knows how well that works. Would recommend just preloading it by a day or so and only checking every new M1 bar (with a retry mechanism in case it doesn't work). If you are trying to get it to work inside the strategy tester (because CalendarValue functions do not work natively inside the strategy tester) then you need to write a script that saves the Calendar events into a csv or binary file and then read them to the EA during the backtest. 
 
Casey Courtney # :
I never get this error but sometimes I get the too many requests error. Might be a broker issue? Also I think using 0 in the third parameter will try and load all events in the future which who knows how well that works. Would recommend just preloading it by a day or so and only checking every new M1 bar (with a retry mechanism in case it doesn't work). If you are trying to get it to work inside the strategy tester (because CalendarValue functions do not work natively inside the strategy tester) then you need to write a script that saves the Calendar events into a csv or binary file and then read them to the EA during the backtest. 
I'm using the CalendarValueHistory(Values, 0, 0, NULL, NULL) call to save all events to a file. This method worked a few months ago, but stopped working after new release (I guess). I tested it on three different brokers, as well as on different servers and terminals. Now it times out everywhere if I call it with a period longer than a month.
 

CalendarValueHistory function times out if a period longer than one month is passed to it. I noticed this issue on b5327. Previously, this issue didn't exist, and the function returned all calendar events for the entire period.

MqlCalendarValue Values[];
datetime from = TimeCurrent ()- 30 * 24 * 60 * 60 ;
CalendarValueHistory (Values, from, 0 , NULL , NULL ); // Returns aprox 5000 events in less 70ms 
Print ( ArraySize (Values));
Print ( GetLastError ());
MqlCalendarValue Values[];
datetime from = TimeCurrent ()- 31 * 24 * 60 * 60 ;
CalendarValueHistory (Values, from, 0 , NULL , NULL );   // Timeout error 5401ERR_CALENDAR_TIMEOUT after aprox. 50 sec 
Print ( ArraySize (Values));
Print ( GetLastError ());

What could be the problem and how to fix it?
---
Here's a workaround that automatically splits requests into 30-day chunks:
//+------------------------------------------------------------------+
//|                                        CalendarValueHistory Fix  |
//|                                      Workaround for b5327 bug    |
//+------------------------------------------------------------------+
// Wrapper function to retrieve calendar data with automatic chunking
bool GetCalendarValueHistory(MqlCalendarValue &values[], 
                            datetime from_date, 
                            datetime to_date = 0,
                            string country_code = NULL,
                            string currency_code = NULL,
                            int chunk_days = 30)
{
   ArrayFree(values);
   // If to_date is 0, use current time
   if(to_date == 0)
      to_date = TimeCurrent();
   // Validate dates
   if(from_date >= to_date)
   {
      Print("Error: from_date must be earlier than to_date");
      return false;
   }
   // Calculate total period
   int total_days = (int)((to_date - from_date) / (24 * 60 * 60));
   Print("Retrieving calendar data for ", total_days, " days (", 
         TimeToString(from_date), " to ", TimeToString(to_date), ")");
   // If period is within safe limit, retrieve directly
   if(total_days <= chunk_days)
   {
      bool result = CalendarValueHistory(values, from_date, to_date, 
                                        country_code, currency_code);
      if(result)
      {
         Print("Retrieved ", ArraySize(values), " calendar events");
         return true;
      }
      else
      {
         Print("CalendarValueHistory error: ", GetLastError());
         return false;
      }
   }
   // Period too long - retrieve in chunks
   Print("Period exceeds ", chunk_days, " days. Using chunked retrieval...");
   int total_events = 0;
   int chunks_processed = 0;
   datetime chunk_start = from_date;
   while(chunk_start < to_date)
   {
      // Calculate chunk end (either chunk_days ahead or to_date, whichever is earlier)
      datetime chunk_end = chunk_start + chunk_days * 24 * 60 * 60;
      if(chunk_end > to_date)
         chunk_end = to_date;
      // Retrieve chunk
      MqlCalendarValue chunk_values[];
      bool chunk_result = CalendarValueHistory(chunk_values, chunk_start, chunk_end,
                                               country_code, currency_code);
      if(!chunk_result)
      {
         int error = GetLastError();
         Print("Error retrieving chunk ", chunks_processed + 1, 
               " (", TimeToString(chunk_start), " to ", TimeToString(chunk_end), 
               "): Error ", error);
         // If we already have some data, return partial success
         if(total_events > 0)
         {
            Print("Partial data retrieved: ", total_events, " events from ", 
                  chunks_processed, " chunks");
            return true;
         }
         return false;
      }
      // Append chunk to main array
      int chunk_size = ArraySize(chunk_values);
      if(chunk_size > 0)
      {
         int old_size = ArraySize(values);
         ArrayResize(values, old_size + chunk_size);
         ArrayCopy(values, chunk_values, old_size, 0, chunk_size);
         total_events += chunk_size;
      }
      chunks_processed++;
      Print("Chunk ", chunks_processed, ": Retrieved ", chunk_size, 
            " events (Total: ", total_events, ")");
      // Move to next chunk
      chunk_start = chunk_end;
      // Small delay to avoid overwhelming the server
      Sleep(10);
   }
   Print("Successfully retrieved ", total_events, " calendar events in ", 
         chunks_processed, " chunks");
   return true;
}
//+------------------------------------------------------------------+
//| Example usage                                                     |
//+------------------------------------------------------------------+
void OnStart()
{
   // Example: Retrieve last 90 days of calendar data
   MqlCalendarValue values[];
   datetime from = TimeCurrent() - 90 * 24 * 60 * 60; // 90 days ago
   if(GetCalendarValueHistory(values, from))
   {
      Print("Total events: ", ArraySize(values));
   }
   else
   {
      Print("Failed to retrieve calendar data");
   }
}

Usage:
// Simply replace your original code with:
MqlCalendarValue Values[];
datetime from = TimeCurrent() - 90 * 24 * 60 * 60;  // 90 days - works now!
if(GetCalendarValueHistory(Values, from))
{
   Print("Retrieved ", ArraySize(Values), " events");
}
 
PEDRO JOAQUIM GONCALVES GOMES #CalendarValueHistory function times out if a period longer than one month is passed to it. I noticed this issue on b5327. Previously, this issue didn't exist, and the function returned all calendar events for the entire period.

Thank you. I've created same workaround already. I'm looking for cause of this problem. It worked well few month ago. So, smth's changed.

Do you have the same problem?

 
PEDRO JOAQUIM GONCALVES GOMES #:

CalendarValueHistory function times out if a period longer than one month is passed to it. I noticed this issue on b5327. Previously, this issue didn't exist, and the function returned all calendar events for the entire period.


Sleep doesn't work in indicators. You will be required to use a wait-loop if you need the delay.
 

Here a more concise and non-noisy version of the original implementation, including a define to inline-replace the original MQL-API function:

(Just typed, not compiled or tested)


EDIT: Fixed a loop control error


//+------------------------------------------------------------------+
//| CalendarValueHistory()                                           |
//|                                      Workaround for b5327 bug    |
//| Original post : https://www.mql5.com/en/forum/496980&nbsp;            | 
//+------------------------------------------------------------------+
// Wrapper function to retrieve calendar data with automatic chunking
const int mqlbug_CalendarValueHistory(  MqlCalendarValue&   values[], 
                                        const datetime      from_date, 
                                        const datetime      _to_date        = NULL,
                                        const string        country_code    = NULL,
                                        const string        currency_code   = NULL,
                                        const int           chunk_days      = 7)
{
    // Local init

        const datetime      to_date             = (_to_date == NULL) ? ::TimeCurrent() : _to_date;
        datetime            chunk_start         = from_date;
        datetime            chunk_end           = MathMin(chunk_start + (chunk_days * 84600), to_date);
        bool                err                 = (_LastError != ERR_SUCCESS) || (from_date >= to_date);
        MqlCalendarValue    chunk_values[];
        ArrayFree(values);


    // Perform auto-chunking

        do
        {
            // Retrieve chunk
            err |= (!err) && !CalendarValueHistory(chunk_values, chunk_start, chunk_end, country_code, currency_code);

            // Append chunk to main array
            err |= (!err) && (ArrayCopy(values, chunk_values, ArraySize(values), NULL, ArraySize(chunk_values)) < 1);

            // Calculate chunk end (either chunk_days ahead or to_date, whichever is earlier)
            chunk_start = chunk_end;
            chunk_end  += chunk_days * 84600;
            chunk_end   = MathMin(chunk_end, to_date);
        }
        while( (!err)
            && (chunk_start < to_date) );

    // Return
    return(!err ? ArraySize(values) : -1);
}

#define CalendarValueHistory mqlbug_CalendarValueHistory

EDIT:

Updated return value to be in line with MQL-API
 
I just do something like this: 
CalendarValueHistory(values, D'2014.1.01', TimeCurrent());
// other stuff to save economic data to a file that I later read but don't really want to share on the forum
it does hit me with a too many requests issue if I go back further than 2002 
 
Casey Courtney #:
I just do something like this:  it does hit me with a too many requests issue if I go back further than 2002 
You need to be aware, in case you re using the workaround-function, or any other way of delaying your calls, indicators do not execute Sleep() function. - Yo uwill need to use a wait-loop to achieve something similar. - But this is very discouraged, as it blocks the shared thread on the chart.
 
Dominik Egert #:
You need to be aware, in case you re using the workaround-function, or any other way of delaying your calls, indicators do not execute Sleep() function. - Yo uwill need to use a wait-loop to achieve something similar. - But this is very discouraged, as it blocks the shared thread on the chart.
I don't use sleep in any of my EAs or indicators and I the only delay when I save calendar data is when its writing it all to a csv file. None of the code in this thread is really similar to what I do 
 
Dominik Egert # :

Here a more concise and non-noisy version of the original implementation, including a define to inline-replace the original MQL-API function:

(Just typed, not compiled or tested)


EDIT: Fixed a loop control error


Thank you for the universal wrapper. Do you think this is really a bug in b5327 or is it a new behavior that will limit calls with long periods?