Problem with iCustom+CopyBuffer on Strategy Tester

 

Hello!

I'm using the last version of MT5 (build 1881) and I'm having some troubles in strategy tester with a custom indicator with 7 buffers. The indicator works perfectly when I put it in the chart and works fine too when I put it in an EA and runs the advisor in real time mode. When I run the EA in strategy tester with the custom indicator, the CopyBuffer method copy the first buffer to all other buffers.

This is the EA code (Print returns the same value to all buffers):

#include <Trade/Trade.mqh>
#include <../Include/CheckHistory2.mqh>
#include <../Include/Posicao.mqh>
#include <../Include/NewBar/lib_cisnewbar.mqh>

// Bibliotecas
CTrade trade;
CisNewBar current_chart;

//Objetos
Posicao *posicao;

// Parâmetros de stop
double pivot[], res1[], res2[], res3[], sup1[], sup2[], sup3[]; 
// Manipuladores de indicadores
int ressupHandler;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   PositionSelect(_Symbol);
   posicao = new Posicao();
   
   ressupHandler = iCustom(_Symbol, _Period, "Resistance_Support_H", 0.8, 1.0, 1.618, PERIOD_D1); 
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
   {   
   PositionSelect(_Symbol);  

   CopyBuffer(ressupHandler, 0, 0, 1, sup1);
   CopyBuffer(ressupHandler, 1, 0, 1, res1);
   CopyBuffer(ressupHandler, 2, 0, 1, sup2);
   CopyBuffer(ressupHandler, 3, 0, 1, res2);
   CopyBuffer(ressupHandler, 4, 0, 1, sup3);
   CopyBuffer(ressupHandler, 5, 0, 1, res3);
   CopyBuffer(ressupHandler, 6, 0, 1, pivot); 
   
   Print("Níveis: "+sup3[0]+" "+sup2[0]+" "+sup1[0]+" "+pivot[0]+" "+res1[0]+" "+res2[0]+" "+res3[0]);
   } 

This is the Custom Indicator code:

#property strict

#property indicator_chart_window
#property indicator_buffers 7
#property indicator_plots   7
//--- plot Support
#property indicator_label1  "S1"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrGreen
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot Resistance
#property indicator_label2  "R1"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- plot Support
#property indicator_label3  "S2"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrGreen
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1
//--- plot Resistance
#property indicator_label4  "R2"
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrRed
#property indicator_style4  STYLE_SOLID
#property indicator_width4  1
//--- plot Support
#property indicator_label5  "S3"
#property indicator_type5   DRAW_LINE
#property indicator_color5  clrGreen
#property indicator_style5  STYLE_SOLID
#property indicator_width5  1
//--- plot Resistance
#property indicator_label6  "R3"
#property indicator_type6   DRAW_LINE
#property indicator_color6  clrRed
#property indicator_style6  STYLE_SOLID
#property indicator_width6  1
//--- plot Resistance
#property indicator_label7  "Mediana"
#property indicator_type7   DRAW_LINE
#property indicator_color7  clrBlue
#property indicator_style7  STYLE_SOLID
#property indicator_width7  1
//--- input parameters
input double               K_Fibo_1=0.8;
input double               K_Fibo_2=1.0;
input double               K_Fibo_3=1.618;
input ENUM_TIMEFRAMES      Period_TF=PERIOD_D1;
//--- indicator buffers
double         buffer1[];
double         buffer2[];
double         buffer3[];
double         buffer4[];
double         buffer5[];
double         buffer6[];
double         buffer7[];
datetime time_tf[];
double high_tf[];
double low_tf[];
int bars_tf=0;
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,buffer1,INDICATOR_DATA);
   SetIndexBuffer(1,buffer2,INDICATOR_DATA);
   SetIndexBuffer(2,buffer3,INDICATOR_DATA);
   SetIndexBuffer(3,buffer4,INDICATOR_DATA);
   SetIndexBuffer(4,buffer5,INDICATOR_DATA);
   SetIndexBuffer(5,buffer6,INDICATOR_DATA);
   SetIndexBuffer(6,buffer7,INDICATOR_DATA);

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   int limit=prev_calculated;
   if(limit>0)limit--;

   int bar=Bars(_Symbol,Period_TF);
   if(bars_tf==0 || bar>bars_tf)array_copy(bar);

   f1(0.5,limit,rates_total,time,buffer7,buffer7);
   f1(K_Fibo_1,limit,rates_total,time,buffer1,buffer2);
   f1(K_Fibo_2,limit,rates_total,time,buffer3,buffer4);
   f1(K_Fibo_3,limit,rates_total,time,buffer5,buffer6);

   return(rates_total);
  }
//+------------------------------------------------------------------+
void f1(double k_fibo,int q,int r,const datetime &time_[],double &b1[],double &b2[])
  {
   for(int w=q;w<r && !_StopFlag;w++)
     {
      int b=f2(time_[w]);//find the time of the current bar in the array of the higher
      double h=high_tf[b];//get the high
      double l=low_tf[b];//get the low
      double hl=h-l;//find the movement range
      b1[w]=h-hl*k_fibo;//add the calculated value to the support buffer
      b2[w]=l+hl*k_fibo;//add the calculated value to the resistance buffer
     }
  }
//+------------------------------------------------------------------+
int f2(datetime t_)
  {
   int b_=ArrayBsearch(time_tf,t_);//find a bar using a standard search in sorted arrays
   if(time_tf[b_]>t_)b_--;//if the time of the nearest bar of a higher timeframe is returned, we will reduce it by 1
   return(MathMax(0,b_-1));//do not forget to return a bars taking into account the minimum limit
  }
//+------------------------------------------------------------------+
void array_copy(int b_)
  {
   ArrayResize(time_tf,b_);//changing the buffer size for our data
   ArrayResize(high_tf,b_);
   ArrayResize(low_tf,b_);

   int total=b_-bars_tf;//calculate the required data copying

   CopyTime(_Symbol,Period_TF,0,total,time_tf);//copy missing data to the array
   CopyHigh(_Symbol,Period_TF,0,total,high_tf);
   CopyLow(_Symbol,Period_TF,0,total,low_tf);

   bars_tf=b_;//remember the array size and the amount of data
  }
//+------------------------------------------------------------------+

This is the image of the visualization mode. The buffers are loaded just in the bars before the start test date.


If I call the iCustom method in OnTick, the returned values are correct, but the EA run slowly. If I add other default indicators like iBands and iADX, the buffers are seted correctly.

 

I was searching in https://www.mql5.com/en/articles/239 and found this explanation:


The Calculation of Indicators During Testing

In the real-time mode, the indicator values ​​are calculated at every tick. The Strategy Tester adopted a cost-effective model for calculating indicators - indicators are recalculated only immediately before the running of the EA. It means that the recalculation of the indicators is done before the call of the OnTick(), OnTrade() and OnTimer() functions.

It does not matter whether or not there is a call for the indicator in a specific event handler, all of the indicators, the handles of which were created by the iCustom() or IndicatorCreate() functions will be recalculated before calling the event handler.

Consequently, when testing in the "Every tick" mode, the calculation of the indicators takes place before the call of OnTick() function.

If the timer is on in the EA, using the EventSetTimer() function, then the indicators will be recalculated before each call of the OnTimer() handler. Therefore, the testing time can be greatly increased with the use of an indicators, written in a non-optimal way.


If the indicator is recalculated only before the EA running, how do I test EA with custom indicators?

The Fundamentals of Testing in MetaTrader 5
The Fundamentals of Testing in MetaTrader 5
  • www.mql5.com
The idea of ​​automated trading is appealing by the fact that the trading robot can work non-stop for 24 hours a day, seven days a week. The robot does not get tired, doubtful or scared, it's is totally free from any psychological problems. It is sufficient enough to clearly formalize the trading rules and implement them in the algorithms, and...
Reason: