Inconsistent results when using iTime()

 

Hi,


Ok so I have an issue with my EA that I use as a screener / setup alerter.


Here’s how it works: I set it up on any chart, M5 TF, and it scans through a predefined number of pairs (which corresponds to my watchlist).

For each pair, in the example I give it gives the low of the last couple of bars.


The issue that I have, is the every now and then, the value of the last bar is incorrect. This is due to the fact that for some reason, the Time[0] of that pair is not the same as the one on which the EA is attached.


So for example, on a M5 chart, let’s say Time[0] (the current bar) is 14:50. As the EA scans through each pair, it should have the same time throughout. Most of the time it does, but sometimes the iTime(*,0,5) of a certain pair will show 14:45 instead. Like, it hasn’t switched to the new bar, which is strange?


It messes up my calculations, because for example the value of iLow(1) will actually correspond to the value of Low[2] of the specific pair. Again, only happens every now and then, most of the time the Time and values are correct.

#property strict

datetime runOnce; //Run once per bar
datetime tempTime; //Used to compare current bar

string PairList ="EURAUD.,GBPUSD."; //The watchlist, simplified here to 2 pairs. Must correspond to the way the pairs are listed on the broker, it could be EURAUD, or EURAUD.r for example.

int OnInit(){return(INIT_SUCCEEDED);}
void OnDeinit(const int reason){}

void OnTick()
  {
   if(runOnce!=Time[0]) //Run once per bar
     {
     tempTime=Time[0]; //Set the time of the current bar
     string pairs[]; // An array to get strings of pairs
     int k=StringSplit(PairList,44,pairs); //Seperate each pair from the array
      
      if(k>0)
        {        
         for(int i=0;i<k;i++) //for each pair in the pairlist
           {
           datetime compareTime = iTime(pairs[i],0,0); //this is the time for each specific pair, should correspond to Time[0] of that pair.
           if(compareTime!=tempTime) //Time[0] of the current chart should be the same as Time[0] of the pair we're currently looking at.
               {
               Alert("DIFFERENT TIME FOUND: " + pairs[i]);
               Alert("Time: " + TimeToStr(compareTime));
               Sleep(5000); //Here, I've tried to time out in case no ticks came through the new bar. Changes nothing.
               }
           
           //Here the EA would get some metrics on each pair, like in this example the last low value.
           Alert("Pair: " + pairs[i]);
           Alert("Current open: " + iOpen(pairs[i],0,0));
           Alert("Previous low: " + iLow(pairs[i],0,1));
           Alert("Low before that: " + iLow(pairs[i],0,2));           
          
           }
         runOnce=Time[0];  
         }         
     }
  }



I’ve tried resolving that issue thinking it might be that no ticks have gone through that pair, with a Sleep() function in a While loop. But it doesn’t work, the loop just keeps going throughout the bar, meaning the value of iTime doesn’t change.

Thanks for any idea as to what could be wrong here.
 
Barraka:

As the EA scans through each pair, it should have the same time throughout. Most of the time it does, but sometimes the iTime(*,0,5) of a certain pair will show 14:45 instead. Like, it hasn’t switched to the new bar, which is strange?

  1. Not strange. A new bar starts when a new tick comes in.

    You assume every bar every exists — they don't. What if there are no ticks during a specific candle period? There can be minutes between ticks during the Asian session, think M1 chart. Larger charts, think weekend, market holiday (country and broker specific.) requires knowledge of when your broker stops and starts (not necessary the same as the market.)
              "Free-of-Holes" Charts - MQL4 Articles 20 June 2006
              No candle if open = close ? - MQL4 programming forum 2010.06.06

  2. On MT4: Unless the chart is that specific symbol(s)/TF(s) referenced, you must handle 4066/4073 errors before accessing candle/indicator values.
              Download history in MQL4 EA - Forex Calendar - MQL4 programming forum - Page 3 #26 № 4 2019.05.20

 
William Roeder:
  1. Not strange. A new bar starts when a new tick comes in.

    You assume every bar every exists — they don't. What if there are no ticks during a specific candle period? There can be minutes between ticks during the Asian session, think M1 chart. Larger charts, think weekend, market holiday (country and broker specific.) requires knowledge of when your broker stops and starts (not necessary the same as the market.)
              "Free-of-Holes" Charts - MQL4 Articles 20 June 2006
              No candle if open = close ? - MQL4 programming forum 2010.06.06

  2. On MT4: Unless the chart is that specific symbol(s)/TF(s) referenced, you must handle 4066/4073 errors before accessing candle/indicator values.
              Download history in MQL4 EA - Forex Calendar - MQL4 programming forum - Page 3 #26 № 4 2019.05.20

Thank you for your input.

Was not aware of errors 4066/4073. 

I had a feeling it was something to do with ticks not having come through, but I thought my Sleep(5000) function would fix it. In another implementation of the code, I had a While loop that ran Sleep(5000) until the value of iTime() was the same value as Time[]. It never happened, and the loop would run until the next bar. Maybe I'm getting confused as to how the Sleep function works, but I thought that after the 5 seconds interval, if new ticks had come through on that pair, I would get iTime()==Time[]. ?


Started reading those links. Seems like I would need something like:

while(!download_history(...){ Sleep(1000); RefreshRates(); }


Which makes me think, maybe in my While loop I just needed a RefreshRates(), will try that.


Quick question while I'm at it: In one of your code snippet, you have:

ResetLastError();
   datetime other = iTime(symbol, period, 0);
   if(_LastError == 0)  return true;
   if(_LastError != ERR_HISTORY_WILL_UPDATED){...}

Is the value of _LastError set as soon as the variable "other" is defined? And, shouldn't the 2nd condition be if(_LastError== ERR_HISTORY_WILL_UPDATED)? I mean, it's that specific error we're looking for, right?


Overall, from what I understand I should try something like:

bool condition = false;

while (!condition)
   {
   ResetLastError();
   datetime other = iTime(symbol, period, 0);
   if(_LastError == 0)  condition = true;
   if(_LastError == ERR_HISTORY_WILL_UPDATED)
      {
      Print("Still updating...");
      Sleep(5000);
      RefreshRates();
      }
   if(_LastError == ERR_NO_HISTORY_DATA   )
      {
      Print("No history...");
      Sleep(5000);
      RefreshRates();
      }
   }
 
Barraka: Overall, from what I understand I should try something like:

Was

if(!download_history(symbol, period)) return;
too simple for you?
 
William Roeder:

Was

to simple for you?


That would work nicely, but it skips the current bar / pair, I want it to wait for the tick so it can proceed to other calculations.


I've tested another implementation of the while loop, and this version works for me. Indeed, like I was saying previously I was missing RefreshRates() in my previous attempt.

Here's what it looks like, I don't directly check for error 4066/4073, but indirectly it does the job:

datetime compareTime = iTime(pairs[i],0,0);
           while(compareTime!=tempTime) 
               {
               Sleep(5000);
               RefreshRates();
               compareTime = iTime(pairs[i],0,0);
               }


Thanks for your help :)

 
Barraka: That would work nicely, but it skips the current bar / pair, I want it to wait for the tick so it can proceed to other calculations.

The return only skips one tick. Fix your broken code.

Reason: