No documentation for "cannot refresh history [4073]"? How to properly handle this error?

 

I am using ChartOpen and then ChartApplyTemplate methods to execute an EA on a new chart from the current EA.

Sometimes (about 5% of all cases and it seems completely random) this newly executed EA throws an "cannot refresh history [4073]" error when initializing. Once this happens, the strategy becomes unusable - you can't access any series or info about the chart that it's running on. Also, if you afterwards put the EA again directly from the navigator on that same chart, it works.

I've tried to handle this error, look for any kind of documentation or info on this, but there's pretty much nothing.

What causes this error and how to handle it properly?

Here's an unsuccessful attempt that I made (once encountered, it would just loop infinitely, because the state won't change).

   datetime daytimes[];
   ArrayCopySeries(daytimes, MODE_TIME, Symbol(), Period());
   int timeTotal = 0;
   int error=GetLastError();
   if(error==4066 || error == 4073)
   {
      //once you get here, you are screwed
      //let's try it a few times, maybe the data will load
      while((error==4066 || error == 4073) && timeTotal <= 10000)
      {
         timeTotal += 100;
         Sleep(100);
         ArrayCopySeries(daytimes, MODE_TIME, Symbol(), Period());
         error=GetLastError(); //is it ok now? 
      }
      
      if(error==4066 || error == 4073)
      {
         return INIT_FAILED; //you will always end here
      }
      else
         //everything ok
   }
   else
      //no problem
 
6xfngb5dgfe6d:newly executed EA throws an "cannot refresh history [4073]" error when initializing.
  1. Why did you post your MT4 question in the Root / MT5 General section instead of the MQL4 section, (bottom of the Root page?)
              General rules and best pratices of the Forum. - General - MQL5 programming forum
    Next time post in the correct place. The moderators will likely move this thread there soon.

  2. Don't try to use any price or server related functions in OnInit as there may be no connection/chart yet:
    1. Terminal starts.
    2. indicators/EAs are loaded.
    3. OnInit is called.
    4. For indicators OnCalculate is called with any existing history.
    5. Human may have to enter password, connection to server begins.
    6. New history is received, OnCalculate called again.
    7. New tick is received, OnCalculate/OnTick is called. Now TickValue, TimeCurrent and prices are valid.

  3. On MT4: Unless the current chart is the specific pair/TF referenced, you must handle 4066/4073 errors.
              Download history in MQL4 EA - MQL4 and MetaTrader 4 - MQL4 programming forum

 

Thanks for your response and sorry about the wrong place, I'll keep that in mind next time.

I am, indeed, calling OnTick from OnInit. The reason I am doing that is because I need the EA to enter the trade immediately after it's dropped onto the chart. Without that, it just has to wait for the chart to move, which is definitely not what I want. Is there a better way of achieving it?

I also can't understand, why does it work sometimes. Shouldn't it fail every single time, because the chart isn't initialized?

 
6xfngb5dgfe6d:

Thanks for your response and sorry about the wrong place, I'll keep that in mind next time.

I am, indeed, calling OnTick from OnInit. The reason I am doing that is because I need the EA to enter the trade immediately after it's dropped onto the chart. Without that, it just has to wait for the chart to move, which is definitely not what I want. Is there a better way of achieving it?

I also can't understand, why does it work sometimes. Shouldn't it fail every single time, because the chart isn't initialized?


void TradeLogicFunc(){}

int OnInit()
{
   EventSetMillisecondTimer(1);
   return INIT_SUCCEEDED;
}

void OnTimer()
{
   TradeLogicFunc();
   EventKillTimer();
}
 
nicholishen:

Can I call OnTick instead of TradeLogicFunc() there?

 
6xfngb5dgfe6d:

Can I call OnTick instead of TradeLogicFunc() there?

No. Oninit needs to return successful.
 
nicholishen:
No. Oninit needs to return successful.

It will be if your timer declaration is just before "return INIT_SUCCEEDED", so I would answer yes, you can call OnTick() there.

 

Isn't OnTimer event running in a different thread?

 
Alain Verleyen:

It will be if your timer declaration is just before "return INIT_SUCCEEDED", so I would answer yes, you can call OnTick() there.


Yes, you are correct... I read too fast and didn't understand the question... I thought he was asking about calling OnTick from OnInit 

 

So to summarize this up:

To avoid error 4073 and also achieve immediate logic execution after initialization, one should use this code:

int OnInit()
{
   //init logic

   EventSetMillisecondTimer(1); //right before return
   return INIT_SUCCEEDED;
}

void OnTimer()
{
   OnTick();
   EventKillTimer();
}

void OnTick()
{
   //Logic here
}

Is this the best practice?

 

I wont try to catch this problem in OnInit!

  1. Check in OnInit() if you have everything you need - may be in a separate function
  2. If you haven't got everything
    a) in an EA repeat the call of that function with a Sleep() until..,
    b) in an indicator repeat the call of that function and return(0) from OnCalculate (the don't 'know' Sleep!) until...
Reason: