Download history in MQL4 EA - page 4

 
William Roeder:

Any candle related function does that. The test is for the error and not to continue until download completes.

I came across this thread when I was trying to load TF data for a chart running an EA, so I could get iATR(100) on various TFs even if there was no data loaded.

bool DownloadHistory(int period=0, string symbol="")
{
        string fn = __FUNCTION__ + "()";

        if (symbol == "")       symbol = Symbol();
        if (period == 0)        period = Period();
        
        for (int i=0; i < 5; i++)
        {
                ResetLastError();
                datetime other = iTime(symbol, period, 0);
                if (_LastError == 0  &&  other != 0)
                        return(true);
                if (_LastError != ERR_HISTORY_WILL_UPDATED  &&  _LastError != ERR_NO_HISTORY_DATA)
                        Debug(1, fn, "iTime(" + symbol + ", " + period + ", 0) Failed. Error = " + _LastError);
                else    // we need to wait for it to load
                        Sleep(500);
        }
        return(false);
}

It seemed to work pretty well, running it on 28 charts, except I kept getting an error on AUDNZD only when it tried to load H4 data, which was odd because the chart was on H4.  Eventually I just used the home key to load more and it went away.

But using the iTime() function only loads the minimal which appears to be 120.1 KB.  I wondered if anyone had a method for MT4 to make it load all data (like holding the 'Home' key) or a certain amount of data.

Substituting a variuable 'bar' for zero, I tried this:

int bar = iBars(NULL, 30);
while (true)
{
        bar = bar + iBars(NULL, PERIOD_M30);
        DownloadHistory(PERIOD_M30 , Symbol(), bar);
}       

But it only resulted in a error 4051.  Anyone ever figure a way to load 'X' bars of data, or to load all?

 
Derk Wehler:

I came across this thread when I was trying to load TF data for a chart running an EA, so I could get iATR(100) on various TFs even if there was no data loaded.

It seemed to work pretty well, running it on 28 charts, except I kept getting an error on AUDNZD only when it tried to load H4 data, which was odd because the chart was on H4.  Eventually I just used the home key to load more and it went away.

But using the iTime() function only loads the minimal which appears to be 120.1 KB.  I wondered if anyone had a method for MT4 to make it load all data (like holding the 'Home' key) or a certain amount of data.

Substituting a variuable 'bar' for zero, I tried this:

But it only resulted in a error 4051.  Anyone ever figure a way to load 'X' bars of data, or to load all?

Don't answer all-at-once.  I'm very patient.

 
Derk Wehler: Anyone ever figure a way to load 'X' bars of data, or to load all?
If you don't have any history, here's how you can get all available from your broker. Otherwise, you will have to download history from elsewhere.
 
William Roeder:
If you don't have any history, here's how you can get all available from your broker. Otherwise, you will have to download history from elsewhere.

William:

Thank you for the response.  The link you sent seems to be a manual method.  I was attempting to find a way to do it programmatically.

But that's still a pretty good trick for manually getting it :-)

 

Hi All,

I've been encountering the 4073 error trying to copy rates for minute data in the past. 

I can copy rates 1-3 days in the past but no further. I have confirmed that I have minute data going back some months. 

The EA setup to test this is below - Thank you to William and others who have got me this far.

#property copyright "Copyright 2021, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
int day = 0;

#define HR2400 (PERIOD_D1 * 60)    // 86400 = 24 * 3600
#define SYMBOL string
#define THIS_SYMBOL ""




bool     download_history(ENUM_TIMEFRAMES period=PERIOD_CURRENT){
   return download_history(_Symbol, period);
}

bool     download_history(SYMBOL symbol, ENUM_TIMEFRAMES period=PERIOD_CURRENT){
   if(period == PERIOD_CURRENT)  period = (ENUM_TIMEFRAMES)_Period;
   ResetLastError();    datetime other = iTime(symbol, period, 0);
   if(_LastError == 0 && other != 0)   return true;
   if(_LastError != ERR_HISTORY_WILL_UPDATED
   && _LastError != ERR_NO_HISTORY_DATA
     )   PrintFormat("iTime(%s,%i) Failed: %i", symbol, period, _LastError);
   return false;
}

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
  
  
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
      if(TimeDayOfWeek(TimeCurrent()) != day)
      {
         day = TimeDayOfWeek(TimeCurrent());
         while(!download_history(PERIOD_M1) ){ Sleep(1000); RefreshRates(); }

         datetime start_time = TimeCurrent() - 2*PERIOD_D1*60;
         datetime end_time = TimeCurrent() - 1*PERIOD_D1*60;

         Print("Set times - start: ", start_time, " stop: ", end_time);
         
         // Get rates of smaller periods within the session
         MqlRates rates[];
         
         int num_rates = CopyRates(Symbol(), PERIOD_M1, start_time, end_time, rates);
            
         Print("Num rates = ", num_rates);
         if(num_rates == -1)
         {
            Print("Error Code = ",GetLastError()); 
            ResetLastError();
         }
      }
  }
//+------------------------------------------------------------------+


In its current state, the CopyRates function does not throw an error (with or without calling the download_history function).

If I change the start and end times to be 12 and 11 days in the past (for example), I then get 4073 errors.

         datetime start_time = TimeCurrent() - 12*PERIOD_D1*60;
         datetime end_time = TimeCurrent() - 11*PERIOD_D1*60;


Can someone please point out what I may be doing wrong?

On a live MT4 account, what limit might I find on how far back I could download minute data? I'm just looking for an approximation here.


Thanks!

 

I have worked something out - the EA currently is getting loaded with all bars within the timeframe that I've chosen to run it over PLUS an extra 1001 bars before the start of my testing timeframe. 

I confirmed this by seeing that the below code prints 1001 bars for the first tick of every back test irrespective of when in history I start the backtest.

Print("iBars = ", iBars(NULL, 0));

This is good news. Because now I just need to work out how to stretch the historical data that the EA is loaded with to be something more like 100,000 bars before the start of my testing timeframe. 

Of course, this doesn't guarantee that I will get access to this data when I'm running live... that's a scary thought.

 
William Roeder #:
  1. Why are you using current? That will always be correct. It's purpose is to get other symbols/TFs.

  2. Correct.

  3. Had to go to my sources. Originally had HR2400 86400. Changed it sometime to the above which broke it. Equal precedence, left to right: dt % PERIOD_D1 * 60 not equal to dt % (PERIOD_D1 * 60).

  4. Wouldn't have been a problem if you had used the corrected version which doesn't use TimeOfDay(). Try this:
bool     download_history(ENUM_TIMEFRAMES period=PERIOD_CURRENT){
   return download_history(_Symbol, period);
}
bool     download_history(SYMBOL symbol, ENUM_TIMEFRAMES period=PERIOD_CURRENT){
   if(period == PERIOD_CURRENT)  period = (ENUM_TIMEFRAMES)_Period;
   ResetLastError();    datetime other = iTime(symbol, period, 0);
   if(_LastError == 0 && other != 0)   return true;
   if(_LastError != ERR_HISTORY_WILL_UPDATED
   && _LastError != ERR_NO_HISTORY_DATA
     )   PrintFormat("iTime(%s,%i) Failed: %i", symbol, period, _LastError);
   return false;
}

This block of code has been a great help, thanks @William Roeder.

 
William Roeder # :
  1. Why are you using current? That will always be correct. It's purpose is to get other symbols/TFs.

  2. Correct.

  3. Had to go to my sources. Originally had HR2400 86400 . Changed it sometime to the above which broke it. Equal precedence, left to right: dt % PERIOD_D1 * 60 not equal to dt % (PERIOD_D1 * 60) .

  4. Wouldn't have been a problem if you had used the corrected version which doesn't use TimeOfDay() . Try this:

I have unfortunately used this code with no success. I am trying in the strategy tester in m15 TF to get the High and Low of the daily bar, but I get the 4051 error. Has anyone been able to solve it?

 

Hello!

My indicator does all its job in OnInit. How can I make indicator wait for MT4 to finish downloading missing history first, or is it impossible in this case?

 
Botan626 #: Hello! My indicator does all its job in OnInit. How can I make indicator wait for MT4 to finish downloading missing history first, or is it impossible in this case?

Putting everything in OnInit() is not the correct way to code an Indicator. You should start there. If you use the OnCalculate() you can more easily know when data is available and when there are updates to that data.

Reason: