Array out of range for Value Zone

John.Doe
14

Hi,

I'm having an issue with the Array out of range for line (226,36).

The indicator handles are set the same with only the difference of PRICE_HIGH and PRICE_LOW.

Can someone point me to where the error is?

//+------------------------------------------------------------------+
//|                                                  Value_Zone2.mq5 |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers   6
#property indicator_plots     4
//---plot Fast MA color
#property indicator_label1 "Fast MA"
#property indicator_type1  DRAW_COLOR_LINE
#property indicator_color1 clrWhiteSmoke,clrGoldenrod,clrSteelBlue
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//---plot Slow MA color
#property indicator_label2 "Slow MA"
#property indicator_type2  DRAW_COLOR_LINE
#property indicator_color2 clrWhiteSmoke,clrGreen,clrRed
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
//--- plot Buy Zone
#property indicator_label3 "Buy Zone"
#property indicator_type3  DRAW_ARROW
#property indicator_color3 clrGreen
#property indicator_style3 STYLE_SOLID
#property indicator_width3 1
//--- plot Sell Zone
#property indicator_label4 "Sell Zone"
#property indicator_type4  DRAW_ARROW
#property indicator_color4 clrRed
#property indicator_style4 STYLE_SOLID
#property indicator_width4 1
//--- input parameters
input int                  Inp_SMA_period    =  42;
input int                  Inp_MA_shift      =  0;
input ENUM_MA_METHOD       Inp_MA_method     =  MODE_EMA;
input ENUM_APPLIED_PRICE   Inp_MA_app_price  =  PRICE_CLOSE;
      int                  Inp_FMA_Period    =  MathRound(Inp_SMA_period/2);  
//--- indicator buffers
double   MAFastBuffer[], MAFastBufferC[];
double   MASlowBuffer[], MASlowBufferC[];
double   MASlowBufferHigh[],MASlowBufferLow[];
double   BuyZoneBuffer[],SellZoneBuffer[];
//--- 
int   handle_iFMA;
int   handle_iSMA;
int   handle_iSMAHigh,handle_iSMALow;
int   bars_calculated   =  0;
bool  m_init_error      =  false; 
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MAFastBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,MAFastBufferC,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(2,MASlowBuffer,INDICATOR_DATA);
   SetIndexBuffer(3,MASlowBufferC,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(4,BuyZoneBuffer,INDICATOR_DATA);
   SetIndexBuffer(5,SellZoneBuffer,INDICATOR_DATA);
//--- setting a code from the Wingdings charset as the property of PLOT_ARROW
   PlotIndexSetInteger(2,PLOT_ARROW,241);
   PlotIndexSetInteger(3,PLOT_ARROW,242);
//--- set the vertical shift of arrows in pixels
   PlotIndexSetInteger(2,PLOT_ARROW_SHIFT,25);
   PlotIndexSetInteger(3,PLOT_ARROW_SHIFT,-25);
//--- set as an empty value 0.0
   PlotIndexSetDouble(2,PLOT_EMPTY_VALUE,EMPTY_VALUE);
   PlotIndexSetDouble(3,PLOT_EMPTY_VALUE,EMPTY_VALUE);   
//--- create handle of the indicator iFMA
   handle_iFMA=iMA(Symbol(),Period(),Inp_FMA_Period,Inp_MA_shift,Inp_MA_method,Inp_MA_app_price);
//--- if the handle is not created
   if(handle_iFMA==INVALID_HANDLE)
      {
      //--- tell about the failure and output the error code
      PrintFormat("Failed to create handle of the iMA indicator for the symbol %s/%s, error code %d",
                  Symbol(),
                  EnumToString(Period()),
                  GetLastError());
      //--- the indicator is stopped early
      m_init_error=true;
   return(INIT_SUCCEEDED);
      }
//--- create handle of the indicator iSMA
   handle_iSMA=iMA(Symbol(),Period(),Inp_SMA_period,Inp_MA_shift,Inp_MA_method,Inp_MA_app_price);
//--- if the handle is not created
   if(handle_iSMA==INVALID_HANDLE)
      {
      //--- tell about the failure and output the error code
      PrintFormat("Failed to create handle of the iMA indicator for the symbol %s/%s, error code %d",
                  Symbol(),
                  EnumToString(Period()),
                  GetLastError());
      //--- the indicator is stopped early
      m_init_error=true;
   return(INIT_SUCCEEDED);
      }  
//--- create handle of the indicator iSMA
   handle_iSMAHigh=iMA(Symbol(),Period(),Inp_SMA_period,Inp_MA_shift,Inp_MA_method,PRICE_HIGH);
//--- if the handle is not created
   if(handle_iSMAHigh==INVALID_HANDLE)
      {
      //--- tell about the failure and output the error code
      PrintFormat("Failed to create handle of the iMA indicator for the symbol %s/%s, error code %d",
                  Symbol(),
                  EnumToString(Period()),
                  GetLastError());
      //--- the indicator is stopped early
      m_init_error=true;
   return(INIT_SUCCEEDED);
      } 
      //--- create handle of the indicator iSMA
   handle_iSMALow=iMA(Symbol(),Period(),Inp_SMA_period,Inp_MA_shift,Inp_MA_method,PRICE_LOW);
//--- if the handle is not created
   if(handle_iSMALow==INVALID_HANDLE)
      {
      //--- tell about the failure and output the error code
      PrintFormat("Failed to create handle of the iMA indicator for the symbol %s/%s, error code %d",
                  Symbol(),
                  EnumToString(Period()),
                  GetLastError());
      //--- the indicator is stopped early
      m_init_error=true;
   return(INIT_SUCCEEDED);
      }        
//---
   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(m_init_error)
      return(0);
   if(rates_total<=Inp_SMA_period)
      return(0);   
//---
   int   values_to_copy;
//--- determine the number of values calculated in the indicator
   int calculated=BarsCalculated(handle_iSMA);
   if(calculated<=0)
      {
      PrintFormat("BarsCalculated() returned %d, error code %d",calculated,GetLastError());
      return(0);
      }
//--- if it is the first start of calculation of the indicator or if the number of values in the iMA indicator changed
//---or if it is necessary to calculated the indicator for two or more bars (it means something has changed in the price history)
   if(prev_calculated==0 || calculated!=bars_calculated || rates_total>prev_calculated+1)
   {
   //--- if the iMABuffer array is greater than the number of values in the iMA indicator for symbol/period, then we don't copy everything
   //--- otherwise, we copy less than the size of indicator buffers
   if(calculated>rates_total)
      values_to_copy=rates_total;
   else
      values_to_copy=calculated;
   }
   else
   {
   //--- it means that it's not the first time of the indicator calculation, and since the last call of OnCalculate()
   //--- for calculation not more than one bar is added
   values_to_copy=(rates_total-prev_calculated)+1;
   }
//--- fill the iMABuffer array with values of the Moving Average indicator
//--- if FillArrayFromBuffer returns false, it means the information is nor ready yet, quit operation
   if(!FillArrayFromBuffer(MAFastBuffer,Inp_MA_shift,handle_iFMA,values_to_copy))
      return(0); 
//--- fill the iMABuffer array with values of the Moving Average indicator
//--- if FillArrayFromBuffer returns false, it means the information is nor ready yet, quit operation
   if(!FillArrayFromBuffer(MASlowBuffer,Inp_MA_shift,handle_iSMA,values_to_copy))
      return(0);   
//--- fill the iMABuffer array with values of the Moving Average indicator
//--- if FillArrayFromBuffer returns false, it means the information is nor ready yet, quit operation
   if(!FillArrayFromBuffer(MASlowBufferHigh,Inp_MA_shift,handle_iSMAHigh,values_to_copy))
      return(0); 
      //--- fill the iMABuffer array with values of the Moving Average indicator
//--- if FillArrayFromBuffer returns false, it means the information is nor ready yet, quit operation
   if(!FillArrayFromBuffer(MASlowBufferLow,Inp_MA_shift,handle_iSMALow,values_to_copy))
      return(0);                        
//--- memorize the number of values in the Moving Average indicator
   bars_calculated=calculated;      
//--- main loop
   int limit=prev_calculated-1;
   if(prev_calculated==0)
      {
      limit=1;
      for(int i=0; i<limit; i++)
      {
      MAFastBufferC[i]=0.0;
      MASlowBufferC[i]=0.0;
      BuyZoneBuffer[0]=EMPTY_VALUE;
      SellZoneBuffer[0]=EMPTY_VALUE;
      }
      }   
   for(int i=limit; i<rates_total; i++)
   {
      BuyZoneBuffer[i]=EMPTY_VALUE;
      SellZoneBuffer[i]=EMPTY_VALUE;
      //--- defining the MA line Colors
      if(MAFastBuffer[i]>MAFastBuffer[i-1] && MAFastBuffer[i]>MASlowBuffer[i]){MAFastBufferC[i]=1;}
      else
         if(MAFastBuffer[i]<MAFastBuffer[i-1] && MAFastBuffer[i]<MASlowBuffer[i]){MAFastBufferC[i]=2;}
            else {MAFastBufferC[i]=0;}
      if(MASlowBuffer[i]>MASlowBuffer[i-1] && MAFastBuffer[i]>MASlowBuffer[i]){MASlowBufferC[i]=1;}
      else
         if(MASlowBuffer[i]<MASlowBuffer[i-1] && MAFastBuffer[i]<MASlowBuffer[i]){MASlowBufferC[i]=2;}      
            else {MASlowBufferC[i]=0;}  
      //--- defining the Value Zones      
      if((MAFastBufferC[i]==1 && MASlowBufferC[i]==1) &&                                                                                  //--- Price Action
         ((open[i]>MASlowBufferLow[i] && open[i]<MAFastBuffer[i]) || (close[i]>MASlowBufferLow[i] && close[i]<MAFastBuffer[i])))          //--- Value Zone Entry
         {
         BuyZoneBuffer[i]=low[i];
         }
      if((MAFastBufferC[i]==2 && MASlowBufferC[i]==2) &&                                                                                  //--- Price Action
         ((open[i]<MASlowBufferHigh[i] && open[i]>MAFastBuffer[i]) || (close[i]<MASlowBufferHigh[i] && close[i]>MAFastBuffer[i])))        //--- Value Zone Entry
         {
         SellZoneBuffer[i]=high[i];
         }         
   }   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Filling indicator buffers from the MA indicator                  |
//+------------------------------------------------------------------+
bool FillArrayFromBuffer(double &values[],   // indicator buffer of Moving Average values
                         int shift,          // shift
                         int ind_handle,     // handle of the iMA indicator
                         int amount          // number of copied values
                        )
{
//--- reset error code
   ResetLastError();
//--- fill a part of the iMABuffer array with values from the indicator buffer that has 0 index
   if(CopyBuffer(ind_handle,0,0,amount,values)<0)
      {
      //--- if the copying fails, tell the error code
      PrintFormat("Failed to copy data from the iMA indicator, error code %d",GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated
      return(false);
      }
//--- everything is fine
   return(true);
}
//+------------------------------------------------------------------+
//| Indicator deinitialization function                              |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(handle_iFMA!=INVALID_HANDLE)
   IndicatorRelease(handle_iFMA);
if(handle_iSMA!=INVALID_HANDLE)
   IndicatorRelease(handle_iSMA);
if(handle_iSMAHigh!=INVALID_HANDLE)
   IndicatorRelease(handle_iSMAHigh);
if(handle_iSMALow!=INVALID_HANDLE)
   IndicatorRelease(handle_iSMALow);   
}
//+------------------------------------------------------------------+

Thank you.

Regards,

JK

William Roeder
26008
William Roeder  
   int limit=prev_calculated-1;
   if(prev_calculated==0) {…}   
   for(int i=limit; i<rates_total; i++){
      BuyZoneBuffer[i]=EMPTY_VALUE;
First run, prev_calculated is zero, limit is minus one, i is minus one, array[-1] does not exist.
          How to do your lookbacks correctly #9#14 & #19
Vladimir Karputov
Moderator
273996

There are 6 indicator buffers declared, but in fact you have 8 arrays:

#property indicator_buffers   6
***
double   MAFastBuffer[], MAFastBufferC[];
double   MASlowBuffer[], MASlowBufferC[];
double   MASlowBufferHigh[],MASlowBufferLow[];
double   BuyZoneBuffer[],SellZoneBuffer[];
John.Doe
14
John.Doe  

Hi William, Vladimir,

Apologies for the oversight.


Managed to get it right by adding the additional 2 buffer.

Thanks for the enlightenment.


Regards,

JD