Inconsistent iBarShift() return values within Startegy Tester

 

Hello to All,

I am seeing inconsistent results using iBarShift() within the Strategy Tester that I cannot explain.

This problem arose whilst using a library that works very well for more current dates but is reporting incorrect results for earlier historical dates. Unfortunately my specific use case for the library requires me to use for dates as far back as 2007. Which is where I have encountered the problem.

On investigation, I believe the problem may be the behaviour of the iBarShift() function in the Strategy Tester.

The Broker Historical Data

The iBarShift() function in my use case specifically queries the history of the XAUUSD symbol on H1 timeframe.

Looking at the historical XAUUSD bar data for this particular broker I have the following:

++XAUUSD Bar History.png++

For this broker the earliest bar for XAUUSD is 2010.06.15 00:00.

iBarshift Test Harness

I have created the following test harness to reproduce the problem.

//+------------------------------------------------------------------+
//|                                               Test_iBarShift.mq5 |
//|                                        Copyright © 2021, A Scott |
//|                                                                  |
//| Program to test iBarShift()                                      |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, Arnold Scott"
#property version   "1.00"

//+------------------------------------------------------------------+
//| Definitions                                                      |
//+------------------------------------------------------------------+
#define DAY 24*3600

//+------------------------------------------------------------------+
//| Input Parameters                                                 |
//+------------------------------------------------------------------+
input string inp_symbol           = "XAUUSD";       // Symbol for iBarShift()
input ENUM_TIMEFRAMES inp_period  = PERIOD_H1;      // Period for iBarShift()

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
  EventSetTimer(DAY); 
  return (INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert Timer function                                            |
//+------------------------------------------------------------------+
void OnTimer()
{
  datetime tts = TimeTradeServer();
  int barindex = iBarShift(inp_symbol, inp_period, tts, false);

  PrintFormat("iBarShift(%s, %s, %s, false) = %i",
               inp_symbol,
               StringSubstr(EnumToString(inp_period), 7),
               TimeToString(tts),
               barindex);
}


I have run the test harness with the following parameters in the Strategy Tester

++ StrategyTesterFrom2010-06-13.png++

The following journal log is produced.

++JournalLogFrom2010-06-13.png ++

What I would have expected here was the iBarShift (XAUUSD, H1, 2010.06.14 00:00, false) would returned -1 and all the other dates would have returned 0.

Now, when I run the test harness from a starting date where I know there is history, so for example 2010.06.15, just 2 days later from the original starting date of 2010.06.13 I get the following

++ StrategyTester2010-06-15.png ++

I get the following journal log

++ JournalLog2010-06-15.png ++

Now the iBarShift() dates that previously returned -1, now return the 0 value I would have expected  because they exist in the XAUUSD history.

Interpretation of the result

From what I am seeing it looks as though if I run iBarShift() for a date prior to the start of a symbols history it looks to somehow affect subsequent calls to iBarShift() where history does exist.

Conclusion

Looking for assistance in understanding what is happening here.

Have I coded a bug in my program here?

Do I have a misunderstanding on how iBarShift() is supposed to work?

I am aware of posts highlighting problems accessing history within the Strategy Tester due to its limitation on how much history it retrieves before the start date of the test but this does not feel like it is related. I could be wrong.

Is this a recognised issue with using iBarShift() within the Strategy Tester that I have not found in my research?

I did take a look at posts related to  problem with ibarshift getting values from higher timeframes in strategy tester - Real Account - MQL4 and MetaTrader 4 - MQL4 programming forum (mql5.com) however this looked to be related to Multi Time Frame Indicators which are not involved with this particular test or the library. I am not backtesting an indicator or manually adding the multi-timeframe indicator onto the backtesting chart for the EA.

It's the inconsistency of the iBarShift() return values for the same dates across the 2 simple test runs earlier that has me particularly confused.


Workaround

I may have a workaround for my particular use case that I am testing now which I do not like but am I hoping I am missing something here in the use of the iBarShift() function within the Strategy Tester so the functionality can be implemented properly.

Thanks for any assistance or light that can be thrown on this.

Arn

 

I never encounter any issue using iBarShift, but it's also true that I never started a backtest few bars after the very beginning of my history.

For obvious reasons, it's mandatory to start all your test with enough history data before your start date.

Try to start just 1 month later, is the issue still there?

 
Fabio Cavalloni #:

I never encounter any issue using iBarShift, but it's also true that I never started a backtest few bars after the very beginning of my history.

For obvious reasons, it's mandatory to start all your test with enough history data before your start date.

Try to start just 1 month later, is the issue still there?

Holy Smokes Fabio ... thanks for such a quick response. Was actually still editing the post trying to embed images. Did not realize the post had actually published while I was updating it.

To answer your question. Yes. the iBarShift() function does behave correctly when the Strategy Tester is started a month later which is what I would have expected.

I do think you are right Fabio. The Strategy Tester will enforce that there is history before the start date for the symbol it is being executed on. If this is not the case then the Strategy Tester will not execute the test at all reporting a "history cache build error". 

If I run the Strategy Tester using the XAUUSD symbol (instead of EURUSD) with a start date before the start of the XAUUSD history data then the Strategy Tester does indeed stop the execution of the test. 

However, in the test above I am executing the Strategy Tester using the EURUSD symbol which has plenty of history with this broker. In this case the Strategy Tester proceeds with the test and execute the iBarShift() function using the XAUUSD symbol (which is what I want it to do).

It is the inconsistent result of iBarShift() call to XAUUSD within the OnTimer() event that has me confused.

It is because the Strategy Tester continues to process the test and execute the iBarShift() for XAUUSD that I would have expected a -1 for bars not in the XAUUSD history and 0 for current bars it does find in XAUUSD history.

The reason why this is an issue in my use case is that if I say have an array of 10 dates that I want to process within the Strategy Tester. The first date is before the XAUUSD history date and the other 9 are valid. Once iBarShift() correctly reports an error with the first date (which is before XAUUSD history). It will also then proceed to incorrectly report an error with the other 9 dates even though the dates are fine. The preference being it reports an error with the first date but correctly processes the other dates.

Thank you for the suggestion Fabio. The Strategy Tester behaviour would have made a lot more sense to me if it just failed completely rather than continue running but report inconsistent iBarShift() values.

Happy to be corrected here if I am misunderstanding something here with the use of the iBarShift() function within the Strategy Tester.

 
Don't try to use any price (or indicator) or server related functions in OnInit (or on load or in OnTimer before you've received a tick), as there may be no connection/chart yet:
  1. Terminal starts.
  2. Indicators/EAs are loaded. Static and globally declared variables are initialized. (Do not depend on a specific order.)
  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. A new tick is received, OnCalculate/OnTick is called. Now TickValue, TimeCurrent, account information and prices are valid.
 
William Roeder #:
Don't try to use any price (or indicator) or server related functions in OnInit (or on load or in OnTimer before you've received a tick), as there may be no connection/chart yet:
  1. Terminal starts.
  2. Indicators/EAs are loaded. Static and globally declared variables are initialized. (Do not depend on a specific order.)
  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. A new tick is received, OnCalculate/OnTick is called. Now TickValue, TimeCurrent, account information and prices are valid.

Thanks William.

When looking into this I also thought I might be doing something wrong with the OnInit() or OnTimer() events in this test code.

So I did code a quick test version without using OnInit() or OnTimer() to check whether iBarShift() exhibited the same behaviour in the Strategy Tester but unfortunately it gave me the same results.


//+------------------------------------------------------------------+
//|                                      Test_iBarShift_OnTick().mq5 |
//|                                        Copyright © 2020, A Scott |
//|                                                                  |
//| Program to test iBarShift()                                      |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, Arnold Scott"
#property version   "1.00"

//+------------------------------------------------------------------+
//| Input Parameters                                                 |
//+------------------------------------------------------------------+
input string inp_symbol           = "XAUUSD";        // Symbol for iBarShift()
input ENUM_TIMEFRAMES inp_period  = PERIOD_H1;       // Period for iBarShift()

//+------------------------------------------------------------------+
//| Time macros                                                      |
//+------------------------------------------------------------------+
datetime  g_time[];

//+------------------------------------------------------------------+
//| OnTick function                                            |
//+------------------------------------------------------------------+
void OnTick()
{

  if (!BarIsNew())            return;

  datetime tts = TimeTradeServer();
  int barindex = iBarShift(inp_symbol, inp_period, tts, false);

  PrintFormat("iBarShift(%s, %s, %s, false) = %i",
               inp_symbol,
               StringSubstr(EnumToString(inp_period), 7),
               TimeToString(tts),
               barindex);
}

//+------------------------------------------------------------------+
//| BarIsNew() function                                             |
//+------------------------------------------------------------------+
bool BarIsNew()
{
    CopyTime(Symbol(), Period(),0,2,g_time);

    static datetime lastTime = 0;

    bool barIsNew = false;
    if (g_time[0] > lastTime)
    {
        if (lastTime != 0) barIsNew = true;
        lastTime = g_time[0];
    }

    return (barIsNew);
}