iCustom function doesn't work in my EA

 

Good morning,


I have used an indicator I have found on MQL5 (The Vortex indicator (VI+ and VI-) with moving average on the VI+ curve).

Now I am trying to build an EA using this indicator and I've used the ICustom function to create the handle in the expert advisor.

Unfortunately when I backtest the EA in the strategy tester the values that I read inside the backtest journal of the VI- (MinusVI) are completely wrong.

The problem is inside the indicator or inside the EA?

Here the code of the EA:

//+------------------------------------------------------------------+
//|                                                   SampleMQL5.mq5 |
//|                                             Copyright Riccardo |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Riccardo"
#property link      ""
#property version   "1.00"


int PLUSVIhandle = 0,            // Declaring variable to store PLUSVI handle
    MINUSVIhandle = 0,            // Declaring variable to store MINUSVI handle
    MASIGBUFFERhandle = 0;            // Declaring variable to store MOVING AVERAGE OF PLUSVI handle
    
MqlParam params[];      // Array for storing indicators parameters

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {

   
   
/*************************************************/
/*    method of calling indicators  with iCustom          */
/*************************************************/
   ResetLastError();
   PLUSVIhandle = iCustom(NULL,PERIOD_H1,"Downloaded\\Vortex_modified",
                          24         // Period
                          
                 );
   Print("PLUSVI = ",PLUSVIhandle,"  error =",GetLastError());
   ResetLastError();
   MINUSVIhandle = iCustom(NULL,PERIOD_H1,"Downloaded\\Vortex_modified",
                          24        // Period
                          
                 );
   Print("MINUSVI =",MINUSVIhandle,"  error =",GetLastError());
   ResetLastError();

   MASIGBUFFERhandle = iCustom(NULL,PERIOD_H1,"Downloaded\\Vortex_modified",
                          24,        // Step
                          10,
                          MODE_SMA          // Maximum
                 );
   Print("MOVING AVERAGE ON PLUSVI INDICATOR = ",MASIGBUFFERhandle,"  error =",GetLastError());
   

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- Release our indicator handles
   IndicatorRelease(PLUSVIhandle);
   IndicatorRelease(MINUSVIhandle);
   IndicatorRelease(MASIGBUFFERhandle);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

// Dynamic arrays to store indicators values
double _plusvi[],
       _minusvi[],
       _plusvimovingaverage[];

// Setting the indexing in arrays the same as in timeseries, i.e. array element with zero
// index will store the values of the last bar, with 1th index - the last but one, etc.
   ArraySetAsSeries(_plusvi, true);
   ArraySetAsSeries(_minusvi, true);
   ArraySetAsSeries(_plusvimovingaverage, true);

// Using indicators handles, let's copy the values of indicator
// buffers to arrays, specially prepared for this purpose
   if (CopyBuffer(PLUSVIhandle,0,0,40,_plusvi) < 0){Print("CopyBufferplusVI error =",GetLastError());}
   if (CopyBuffer(MINUSVIhandle,0,0,40,_minusvi) < 0){Print("CopyBufferminusVI error =",GetLastError());}
   if (CopyBuffer(MASIGBUFFERhandle,0,0,40,_plusvimovingaverage) < 0){Print("CopyBufferMovingaverageonPLUSVIindicator error =",GetLastError());}
      Print("MINUSVI = ",_minusvi[0]);}
 //  Print("PLUSVI = ",_plusvi[0]);

  
//+------------------------------------------------------------------+


And here the code of the Vortex Indicator modified :

//+------------------------------------------------------------------+
//|                              Vortex(barabashkakvn's edition).mq5 |
//|From the January 2010 issue of Technical Analysis of Stocks &     |
//|Commodities                                                       |
//+------------------------------------------------------------------+
#property  copyright "Copyright 2009 under Creative Commons BY-SA License by Neil D. Rosenthal"
#property  link      "http://creativecommons.org/licenses/by-sa/3.0/"
#property version   "1.000"
#property indicator_separate_window
#property indicator_buffers 10
#property indicator_plots 3
#property indicator_color1 clrChartreuse
#property indicator_type1  DRAW_LINE
#property indicator_color2 clrRed
#property indicator_type2  DRAW_LINE
#property indicator_color3 clrMediumOrchid
#property indicator_type3  DRAW_LINE
//--- Connect a function of averaging from the MovingAverages.mqh file
#include <MovingAverages.mqh>
//--- input parameters
input int      VI_Length=24;
input int sp=10;
input ENUM_MA_METHOD sm=MODE_SMA;
//--- indicator buffers 
double PlusVI[];        //VI+ : + Vortex Indicator buffer
double MinusVI[];       //VI- : - Vortex Indicator buffer
double PlusVM[];        //VM+ : + Vortex Movement buffer
double MinusVM[];       //VM- : - Vorext Movement buffer
double SumPlusVM[];     //Sum of VI_Length PlusVM values
double SumMinusVM[];    //Sum of VI_Length MinusVM values
double SumTR[];         //True Range buffer
double ExtTRBuffer[];   //ATR buffer
double ExtATRBuffer[];  //ATR calculation buffer
double MASigBuffer[];
//---
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,PlusVI,INDICATOR_DATA);
   SetIndexBuffer(1,MinusVI,INDICATOR_DATA);
   SetIndexBuffer(2,MASigBuffer,INDICATOR_DATA);
   
   PlotIndexSetString(0,PLOT_LABEL,"PlusVI("+VI_Length+")");
   PlotIndexSetString(1,PLOT_LABEL,"MinusVI("+VI_Length+")");
   PlotIndexSetString(2,PLOT_LABEL,"MA("+sp+")");
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,VI_Length);
   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,VI_Length);
   PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,sm);
   SetIndexBuffer(3,PlusVM,INDICATOR_CALCULATIONS);
   SetIndexBuffer(4,MinusVM,INDICATOR_CALCULATIONS);
   SetIndexBuffer(5,SumPlusVM,INDICATOR_CALCULATIONS);
   SetIndexBuffer(6,SumMinusVM,INDICATOR_CALCULATIONS);
   SetIndexBuffer(7,SumTR,INDICATOR_CALCULATIONS);
   SetIndexBuffer(8,ExtTRBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(9,ExtATRBuffer,INDICATOR_CALCULATIONS);
   IndicatorSetInteger(INDICATOR_DIGITS,Digits());
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
//---
   if(rates_total<VI_Length+1)
      return(0);
   int limit=prev_calculated-1;
   if(prev_calculated==0)
     {
      limit=0;
      //--- clear caching buffers
      for(int i=limit;i<rates_total;i++)
        {
         PlusVI[i]=0.0;
         MinusVI[i]=0.0;
         PlusVM[i]=0.0;
         MinusVM[i]=0.0;
         SumPlusVM[i]=0.0;
         SumMinusVM[i]=0.0;
         SumTR[i]=0.0;
         ExtTRBuffer[i]=0.0;
         ExtATRBuffer[i]=0.0;
         MASigBuffer[i]=0.0;
         
        }
      limit=VI_Length;
     }
   for(int i=limit;i<rates_total;i++) // left #0 ... n ... right #rates_total
     {
      //--- store the values of PlusVM and MinusVM
      PlusVM[i]=MathAbs(high[i]-low[i-1]);         // PlusVM = |Today's High - Yesterday's Low|
      MinusVM[i]=MathAbs(low[i]-high[i-1]);        // MinusVM = |Today's Low - Yesterday's High|
      //---
      ExtTRBuffer[i]=MathMax(high[i],close[i-1])-MathMin(low[i],close[i-1]);
      ExtATRBuffer[i]=ExtATRBuffer[i-1]+(ExtTRBuffer[i]-ExtTRBuffer[i-1])/1.0;
      //--- sum VI_Length values of PlusVM, MinusVM and the True Range
      for(int j=0; j<VI_Length; j++)
        {
         SumPlusVM[i]+=PlusVM[i-j];
         SumMinusVM[i]+=MinusVM[i-j];
         SumTR[i]+=ExtATRBuffer[i-j];              //Sum VI_Length values of the True Range by using a 1-period ATR
        }
      //--- draw the indicator
      PlusVI[i]=SumPlusVM[i]/SumTR[i];
      MinusVI[i]=SumMinusVM[i]/SumTR[i];
     }
     
     int begin2=VI_Length+sp-1;
     switch(sm)
     {
      case MODE_EMA:
         ExponentialMAOnBuffer(rates_total,prev_calculated,begin2,sp,PlusVI,MASigBuffer);
         break;
      case MODE_LWMA:
         LinearWeightedMAOnBuffer(rates_total,prev_calculated,begin2,sp,PlusVI,MASigBuffer);
         break;
      case MODE_SMA:
         SimpleMAOnBuffer(rates_total,prev_calculated,begin2,sp,PlusVI,MASigBuffer);
         break;
      case MODE_SMMA:
         SmoothedMAOnBuffer(rates_total,prev_calculated,begin2,sp,PlusVI,MASigBuffer);
         break;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
 

You need to read the CopyBuffer help more carefully (note the 'indicator buffer number')

int  CopyBuffer(
   int       indicator_handle,     // indicator handle
   int       buffer_num,           // indicator buffer number
   int       start_pos,            // start position
   int       count,                // amount to copy
   double    buffer[]              // target array to copy
   );


Now look into your Expert Advisor - you are requesting data everywhere from the indicator buffer '0':

   if(CopyBuffer(PLUSVIhandle,0,0,40,_plusvi) < 0)
     {
      Print("CopyBufferplusVI error =",GetLastError());
     }
   if(CopyBuffer(MINUSVIhandle,0,0,40,_minusvi) < 0)
     {
      Print("CopyBufferminusVI error =",GetLastError());
     }
   if(CopyBuffer(MASIGBUFFERhandle,0,0,40,_plusvimovingaverage) < 0)
     {
      Print("CopyBufferMovingaverageonPLUSVIindicator error =",GetLastError());
     }


...

Now look at the indicator code: each indicator buffer has its own number:

   SetIndexBuffer(0,PlusVI,INDICATOR_DATA);
   SetIndexBuffer(1,MinusVI,INDICATOR_DATA);
   SetIndexBuffer(2,MASigBuffer,INDICATOR_DATA);
Documentation on MQL5: Timeseries and Indicators Access / CopyBuffer
Documentation on MQL5: Timeseries and Indicators Access / CopyBuffer
  • www.mql5.com
Counting of elements of copied data (indicator buffer with the index buffer_num) from the starting position is performed from the present to the past, i.e., starting position of 0 means the current bar (indicator value for the current bar). When copying the yet unknown amount of data, it is recommended to use a dynamic array as a buffer[]...
 

Thanks Vladimir,

now it works almost perfectly.

I will pay more attention reading the function parameters but I am a newbie of MQL5.

As concerns the EA I have observed that there is a slight difference between the values on the chart of the indicators and the values inside the journal log of the backtester.

Obviously I have looked the same symbol and the values at the same time. The difference is only of 1/100% but anyway there is a difference. Politely could you have an answer to this?


Thanks a lot

Regards

Riccardo

 
Riccardo_1983 :


I don’t understand what this is about - you did not provide any information.

 
Vladimir Karputov:

I don’t understand what this is about - you did not provide any information.


Thanks Vladimir for your previous answer. It almost has solved my difficulties.

The problem is that I'Ve observed that there is a slight difference between the value read on the indicator chart and the value in the journal log of the backtester.I have checked that the time frame is the same , the symbol is the same, and the input is the same.


Thanks


Kind regards


Riccardo
 
Riccardo_1983 :


Thanks Vladimir for your previous answer. It almost has solved my difficulties.

The problem is that I'Ve observed that there is a slight difference between the value read on the indicator chart and the value in the journal log of the backtester .I have checked that the time frame is the same , the symbol is the same, and the input is the same.


Thanks


Kind regards


Riccardo

And again, just a picture and just text. Look at the situation from the other side: how can I read your thoughts? How do I know what you are doing? How can I know where you are clicking with the mouse? In the end, in the picture you did not select anything and did not describe anything.

If you want to hear the exact answer - take the trouble to ask a quality question :)

 

Here is the corrected code (you only need one handle - you don't need to create three identical handles)

//+------------------------------------------------------------------+
//|                                                   SampleMQL5.mq5 |
//|                                               Copyright Riccardo |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Riccardo"
#property link      ""
#property version   "1.00"
//---
int      handle_iCustom;      // variable for storing the handle of the iCustom indicator
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create handle of the indicator iCustom
   handle_iCustom=iCustom(Symbol(),PERIOD_H1,"Vortex_modified");
//--- if the handle is not created
   if(handle_iCustom==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code
      PrintFormat("Failed to create handle of the iCustom indicator for the symbol %s/%s, error code %d",
                  Symbol(),
                  EnumToString(PERIOD_H1),
                  GetLastError());
      //--- the indicator is stopped early
      return(INIT_FAILED);
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- release our indicator handles
   if(handle_iCustom!=INVALID_HANDLE)
      IndicatorRelease(handle_iCustom);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- dynamic arrays to store indicators values
   double _plusvi[],_minusvi[],_plusvimovingaverage[];
//--- setting the indexing in arrays the same as in timeseries, i.e. array element with zero
//--- index will store the values of the last bar, with 1th index - the last but one, etc.
   ArraySetAsSeries(_plusvi, true);
   ArraySetAsSeries(_minusvi, true);
   ArraySetAsSeries(_plusvimovingaverage, true);
//--- using indicators handles, let's copy the values of indicator
//--- buffers to arrays, specially prepared for this purpose
   ResetLastError();
   if(CopyBuffer(handle_iCustom,0,0,3,_plusvi) < 0)
      Print("CopyBufferplusVI error =",GetLastError());
   ResetLastError();
   if(CopyBuffer(handle_iCustom,1,0,3,_minusvi) < 0)
      Print("CopyBufferminusVI error =",GetLastError());
   ResetLastError();
   if(CopyBuffer(handle_iCustom,2,0,3,_plusvimovingaverage) < 0)
      Print("CopyBufferMovingaverageonPLUSVIindicator error =",GetLastError());
   Comment("PlusVI[1] = ",DoubleToString(_plusvi[1],Digits()),", PlusVI[0] = ",DoubleToString(_plusvi[0],Digits()),"\n",
           "MinusVI[1] = ",DoubleToString(_minusvi[1],Digits()),", MinusVI[0] = ",DoubleToString(_minusvi[0],Digits()),"\n",
           "MASigBuffer[1] = ",DoubleToString(_plusvimovingaverage[1],Digits()),", MASigBuffer[0] = ",DoubleToString(_plusvimovingaverage[0],Digits()));
  }
//+------------------------------------------------------------------+
Files:
Reason: