iBarShift problem - Time iteration from previous date to current date don't give correct shifts

 

Hello, 

I need help with this idea , i'm trying to create a on-chart multi-currency backtester , that iterate over time and symbols , and get the bar shift using iBarShift .

the problem is i'm getting inconsistent shift results , what i expected was to get the shifts in order from whatever start date until shift 0 .

but the iBarShift seems to give unordered results for ordered time iteration .

the other thing also is there are time jumps even if the data for that period is available and the iteration increase by 1 minute.

i tried also creating time RoundUp , but the same problem is faced.

here is my code :

//+------------------------------------------------------------------+
//|                                             TimeIteratorTest.mq4 |
//|                                              Baha Eddine Tahouri |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Baha Eddine Tahouri"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

extern datetime StartDate = D'2010.01.01';
int MinutesToIncrement = 1;
extern int StatusTimeIntervalUpdateMinutes = 1440;
datetime StatusLastTimeIncrementUpdate = 0;


string SymbolsList[3];

bool Init = false;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   SymbolsList[0] = "EURUSD";
   SymbolsList[1] = "NZDUSD";
   SymbolsList[2] = "GBPAUD";
   
   EventSetTimer(1);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   EventKillTimer();
//---
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---

if(Init == false)
{
   for(datetime CountedDatetime = StartDate; CountedDatetime <= iTime(_Symbol,PERIOD_M1,0); CountedDatetime += MinutesToIncrement * 60)
   {  
      if(ObjectFind(ChartID(),"STOP")>=0)
      {
         Comment("Backtest Stopped !");
          break;
      }
      
      if(CountedDatetime > StatusLastTimeIncrementUpdate + StatusTimeIntervalUpdateMinutes *60)
      {
         StatusLastTimeIncrementUpdate = CountedDatetime;
         
         Comment("Backtesting ... ",TimeToString(CountedDatetime,TIME_DATE|TIME_MINUTES));
      }
      
      for(int sym = 0; sym < ArraySize(SymbolsList); sym++)
      {
         string SYMBOL = SymbolsList[sym];
         
         int shift = iBarShift(SYMBOL, PERIOD_M1, RoundUpTime(CountedDatetime, PERIOD_M1));
         Print("DEBUG : " ,"shift = " , shift ," | Symbol : ",SYMBOL , " | Datetime : ", TimeToString(CountedDatetime,TIME_DATE|TIME_MINUTES));
      }
   }
   
Init = true;
}

//---
  }
//+------------------------------------------------------------------+
datetime RoundUpTime(datetime time, ENUM_TIMEFRAMES period) {
    long periodSeconds = PeriodSeconds(period);
    // Find the current bar start
    long remainder = time % periodSeconds;
    // Add time to move to the next bar start (rounding up)
    return (time - remainder + periodSeconds);
}


Results i got :



Any help would be appreciated  , Thanks

 
thanks for the reply , i think that's passed by default as false , specifying false did not change the behavior.
 
Baha Eddine Tahouri #:
thanks for the reply , i think that's passed by default as false , specifying false did not change the behavior.

I just realized that you have "mq4" in your code header.

This is the MT5 subforum, so I deleted my Post #1 regarding MQL5 code.

I stopped coding MQL4 years ago. Hopefully someone else can chime in to help you.

@Moderators, please move this thread to the MT4 subforum.

 
thanks for the reply , the same code can be used on MQL5 it's just been written on mq4 editor
 
Ryan is correct, use iBarShift(..., true) and add a check: if (shift == -1) continue;

This will force your loop to only process actual existing data and fix the inconsistent results you see in the logs. You are iterating through 2026.04.12, which was a Sunday.
 
Baha Eddine Tahouri #:
thanks for the reply , the same code can be used on MQL5 it's just been written on mq4 editor

You're welcome.

Not exactly the same (pun intended). I compiled an mq5 file today from the CodeBase that was missing an exact in iBarShift(), and the Compiler threw an error. I fixed it by adding the exact.

 
Use the CODE button (Alt-S) when inserting code.

A moderator corrected the formatting this time. Please format code properly in future; posts with improperly formatted code may be removed.

Three issues in your code:

1. RoundUpTime() is broken for aligned times

Your loop increments by exactly 60s, so CountedDatetime is always on a minute boundary. remainder = 0, so the function always adds a full extra minute — skipping every bar. Drop it, or use floor rounding:

datetime FloorTime(datetime time, ENUM_TIMEFRAMES period) {

long s = PeriodSeconds(period);

return (datetime)(time - time % s);

}

2. Decreasing shifts = correct behavior

Shift 0 is the current bar, higher = older. Iterating forward in time gives naturally decreasing shifts. Not a bug.

3. Different shifts per symbol = normal

EURUSD shift 25055 vs NZDUSD shift 2745 at the same datetime just means each symbol has a different amount of M1 history loaded. They're correct individually.

Better approach for multi-symbol iteration — iterate by shift, not by time:

for(int sym = 0; sym < ArraySize(SymbolsList); sym++) {

string symbol = SymbolsList[sym];

int startShift = iBarShift(symbol, PERIOD_M1, StartDate, false);

for(int shift = startShift; shift >= 0; shift--) {

datetime barTime = iTime(symbol, PERIOD_M1, shift);

// process here

}

}

Also ensure history is loaded before calling iBarShift on off-chart symbols:

if(iBars(symbol, PERIOD_M1) == 0) continue;
 

thanks for all of you , i will see what i can do , and get back when there is an update

 
   SymbolsList[0] = "EURUSD";
   SymbolsList[1] = "NZDUSD";
   SymbolsList[2] = "GBPAUD";

On MT4: Unless the current 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 - MQL4 programming forum - Page 3 #26.4 (2019)

 
Great , that helped a lot