Different value from the indicator on the same day while debugging on historical data and running strategy tester.

 

Hello, I am testing ea using iCustom function to pull data from indicator. But I found some discrepancies in the data that indicator gave on the chart vs iCustom function on the same date. I thought that my ea had some bug and run the debugging on the same date and while running code step by step it gave me correct value on that particular date ( same as indicator on the chart window). But when I run strategy tester using the same ea values are differ from the indicator on the chart... I don't know why it is behaving like that. Actually, while debugging  all the values are identical to what indicator is giving, and while running strategy tester all the values are way off from what it should be. Is there some sort of buffer that I need to reset every time I call iCustom or something?


//+------------------------------------------------------------------+
//|                                             KalmanFilter-HedgeEA.mq5 |
//|                                                           suvroc |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "suvroc"
#property link      ""
#property version   "1.00"

#include <myFunctions.mqh>
#include <CustomOptimisation.mqh>
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
// GLOBAL VARS

sinput group                              "EA GENERAL SETTINGS"
input ulong                               MagicNumber             = 101;
input bool                                UseFillingPolicy        = false;
input ENUM_ORDER_TYPE_FILLING             FillingPolicy           = ORDER_FILLING_FOK;
input double                              minTrades               = 50.0;

sinput group                              "ATR SETTINGS";
input int                                 atrPeriod = 14;
input int                                 shiftAtr  = 0;

sinput group                              "1st CONFIRMATION INDICATOR PARAMETERS";

//--- enums
enum ENUM_MODE
  {
   MODE_RSI,   // RSI
   MODE_STO    // Stochastic
  };
//--- input parameters
input uint                 InpPeriod         =  9;             // Period
input uint                 InpPeriodSm       =  2;             // Smoothing
input ENUM_MODE            InpMode           =  MODE_RSI;      // Mode
input ENUM_MA_METHOD       InpMethod         =  MODE_SMA;      // Method
input ENUM_APPLIED_PRICE   InpAppliedPrice   =  PRICE_CLOSE;   // Applied price



double atrValue;
int atrHandle; 
int asoHandle;

string entrySignal;
string entrySignalConfirmation;
datetime    glTimeBarOpen;
   
//---
TCustomCriterionArray   *criterion_Ptr;
//---

int OnInit()
  {
//---
   glTimeBarOpen = D'1971.01.01 00:00';
   string indiPath = "ASO.ex5";
   atrHandle = iATR(_Symbol,PERIOD_CURRENT,atrPeriod);
   
   asoHandle = iCustom(_Symbol,PERIOD_CURRENT,indiPath, InpPeriod, InpPeriodSm,InpMode,InpMethod,InpAppliedPrice);
   if(asoHandle == INVALID_HANDLE)
     {
         Print("FAILED TO INIT DIDI INDEX INDICATOR");
         return (INVALID_HANDLE);
     }
   
   if (atrHandle == INVALID_HANDLE) 
   {
      Print("FAILED TO INIT ATR INDICATOR");
      return (INVALID_HANDLE);
   }
   
   
   //criterion_Ptr=new TCustomCriterionArray();
  // if(CheckPointer(criterion_Ptr)==POINTER_INVALID)
   //  {
   //   return(-1);
   //  }
   //criterion_Ptr.Add( new TSimpleCriterion( STAT_PROFIT ));
   //criterion_Ptr.Add( new TSimpleDivCriterion( STAT_BALANCE_DD ));
   //criterion_Ptr.Add( new TSimpleMinCriterion( STAT_TRADES, minTrades ));
   //criterion_Ptr.Add( new TBalanceSlopeCriterion(Symbol(),100000.0));
   //criterion_Ptr.Add(new TTSSFCriterion());
      
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
    //  if(CheckPointer(criterion_Ptr)==POINTER_DYNAMIC)
   //  {
   //   delete(criterion_Ptr);
   //  }
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
//+------------------------------------------------------------------+
//| 1. ATR                                         |
//+------------------------------------------------------------------+
   
   atrValue = NormalizeDouble(myAtr(atrHandle,shiftAtr),_Digits);
   Comment("ATR : ", atrValue);
   
//+------------------------------------------------------------------+
//| 2. TESTED INDICATOR                                              |
//+------------------------------------------------------------------+
      //--------------------//
   //  NEW BAR CONTROL   //
   //--------------------//
   datetime currTime = TimeCurrent(); 
   bool newBar = false;
   double   myBallance = AccountInfoDouble(ACCOUNT_BALANCE);
   double   contractSize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_CONTRACT_SIZE);
    //Print("current time : " + currTime);
   //Check for New Bar
   if(currTime == (iTime(Symbol(),PERIOD_CURRENT,0) + PeriodSeconds(PERIOD_M10) * 1))
   {
      newBar = true;
      glTimeBarOpen = iTime(Symbol(),PERIOD_CURRENT,0) + PeriodSeconds(PERIOD_M10) * 1;   
   }   
   
   if(newBar == true)
   {  
     
      //double myBuffer[];
      //CopyBuffer(didiHandle,2,0,2,myBuffer);
     // bool cross = DetectCrossover(myBuffer,2);
      //Print("DIDI SIGNAL : ", myBuffer[1]);
   //--------------------//
   //  TRADE ENTRY       //
   //--------------------//
      
      double   myLot = CalculatePositionSize(_Symbol, 0.02, (int)(atrValue * 1.5 / _Point));
      
            //-------------------------//
            //  1st CONFIRMATION       //
            //-------------------------//
      
      entrySignal = detectCrossover(asoHandle,0,1,glTimeBarOpen);
      Comment("EA #", MagicNumber, " | ",entrySignal, " 1st CI");
            //-------------------------//
            //  2nd CONFIRMATION       //
            //-------------------------//
      
      
      
      if((entrySignal == "LONG" || entrySignal == "SHORT") && CheckPlacedPositions(MagicNumber) == false)
      {
         
         ulong ticket = OpenTrades(entrySignal,MagicNumber,NormalizeDouble(myLot,2), UseFillingPolicy, FillingPolicy);  
         
         //SL & TP Trade Modification
         if(ticket > 0)
         {
            double stopLoss = CalculateStopLoss(entrySignal, atrValue * 1.5);
            double takeProfit = CalculateTakeProfit(entrySignal, atrValue);
            TradeModification(ticket,MagicNumber,stopLoss,takeProfit);         
         }
      }
      else if((entrySignal == "LONG" || entrySignal == "SHORT"))
       {
         Print(entrySignal + " without position check" );
       }
      else
        {
         Print(entrySignal);
        }
   //--------------------//
   //  TRADE EXIT       //
   //--------------------//            


              
      
   
   }
//+------------------------------------------------------------------+
//| 2. ORDER MANAGEMENT                                              |
//+------------------------------------------------------------------+

  }
//+------------------------------------------------------------------+
double  OnTester()
  {
   double   param=0.0;

//      Balance max + min Drawdown + Trades Number:
 //  if(CheckPointer(criterion_Ptr)!=POINTER_INVALID)
   //  {
   //   param=criterion_Ptr.GetCriterion();
    // }

   //return(param);
   double winTrades = TesterStatistics(STAT_PROFIT_TRADES);
   double lossTrades = TesterStatistics(STAT_LOSS_TRADES);
   double winLossPercent = (winTrades+lossTrades) > 0? winTrades / (winTrades+lossTrades) * 100.0 : 0;
   return (winLossPercent);
  }
//+------------------------------------------------------------------+
//|                 DETECT CROSSOVER                                 |
//+------------------------------------------------------------------+
string detectCrossover(int pHandle, int pSignalBuffer1, int pSignalBuffer2, const datetime time)
  {
   MqlDateTime dt;
   TimeToStruct(time,dt);
   double indicator1[];
   double indicator2[];

   CopyBuffer(pHandle,pSignalBuffer1,0,3,indicator1);
   CopyBuffer(pHandle,pSignalBuffer2,0,3,indicator2);
   ArraySetAsSeries(indicator1, true);
   ArraySetAsSeries(indicator2, true);
   if(indicator1[0] > indicator2[0] && (indicator1[1] <= indicator2[1]))// || (dt.day_of_week == 1 && indicator[1] > pCrossLine && indicator[2] <= pCrossLine )))
     {
      return  "LONG";

     }
   else
      if(indicator1[0] < indicator2[0] && (indicator1[1] >= indicator2[1])) // || (dt.day_of_week == 1 && indicator[1] < pCrossLine && indicator[2] >= pCrossLine)))
        {
         return  "SHORT";
        }
   return "NO TRADE - " + DoubleToString(indicator1[0]) + " | " + DoubleToString(indicator2[0])  + " | " + DoubleToString(dt.day_of_week) + " | " + DoubleToString(indicator1[1]) + " | " + DoubleToString(indicator2[1]);
  
  }

The Fundamentals of Testing in MetaTrader 5
The Fundamentals of Testing in MetaTrader 5
  • www.mql5.com
What are the differences between the three modes of testing in MetaTrader 5, and what should be particularly looked for? How does the testing of an EA, trading simultaneously on multiple instruments, take place? When and how are the indicator values calculated during testing, and how are the events handled? How to synchronize the bars from different instruments during testing in an "open prices only" mode? This article aims to provide answers to these and many other questions.
 
suvroc:

Hello, I am testing ea using iCustom function to pull data from indicator. But I found some discrepancies in the data that indicator gave on the chart vs iCustom function on the same date. I thought that my ea had some bug and run the debugging on the same date and while running code step by step it gave me correct value on that particular date ( same as indicator on the chart window). But when I run strategy tester using the same ea values are differ from the indicator on the chart... I don't know why it is behaving like that. Actually, while debugging  all the values are identical to what indicator is giving, and while running strategy tester all the values are way off from what it should be. Is there some sort of buffer that I need to reset every time I call iCustom or something?


What settings are you using for the strategy tester in debug and when Backtesting?
 
Dominik Egert #:
What settings are you using for the strategy tester in debug and when Backtesting?

without delay and on every tick - debug settings

zero latency, ideal execution  and on every tick - strategy tester

 

I found the reason and solution to my issue. To my embarrassment it all was written in a MQL5 help file :

Testing Trading Strategies

"The Calculation of Indicators During Testing

In the real-time mode, the indicator values are calculated at every tick.

In the Strategy Tester, indicators are calculated only when they are accessed for data, i.e. when indicator buffer values are requested. The only exceptions are custom indicators with the specified #property tester_everytick_calculate. In this case, recalculation is done on each tick.

In the visual testing mode, all indicators are unconditionally recalculated when a new tick arrives in order to be correctly displayed on the visual testing chart.

The indicator is calculated once per tick. All subsequent requests for indicator data do not lead to recalculation until a new tick arrives. Therefore, if the timer is enabled in an EA via the EventSetTimer() function, the indicator data is requested from the last tick before each call of the OnTimer() handler. If the indicator has not been calculated on the last tick yet, the calculations of the indicator values are launched. If the data has already been prepared, it is provided without a new recalculation.

Thus, all indicator calculations are performed in the most resource-saving manner — if the indicator has already been calculated at a given tick, its data is provided 'as is'. No recalculation is launched."

Solution to my issue was to modify my indicator by adding  #property tester_everytick_calculate .



 
suvroc #:

I found the reason and solution to my issue. To my embarrassment it all was written in a MQL5 help file :

Testing Trading Strategies

"The Calculation of Indicators During Testing

In the real-time mode, the indicator values are calculated at every tick.

In the Strategy Tester, indicators are calculated only when they are accessed for data, i.e. when indicator buffer values are requested. The only exceptions are custom indicators with the specified #property tester_everytick_calculate. In this case, recalculation is done on each tick.

In the visual testing mode, all indicators are unconditionally recalculated when a new tick arrives in order to be correctly displayed on the visual testing chart.

The indicator is calculated once per tick. All subsequent requests for indicator data do not lead to recalculation until a new tick arrives. Therefore, if the timer is enabled in an EA via the EventSetTimer() function, the indicator data is requested from the last tick before each call of the OnTimer() handler. If the indicator has not been calculated on the last tick yet, the calculations of the indicator values are launched. If the data has already been prepared, it is provided without a new recalculation.

Thus, all indicator calculations are performed in the most resource-saving manner — if the indicator has already been calculated at a given tick, its data is provided 'as is'. No recalculation is launched."

Solution to my issue was to modify my indicator by adding  #property tester_everytick_calculate .



Thanks for letting me know how you solved it. I will try it as you said.
Reason: