Array Out of Range !!!

[Deleted]  

Dear Forum Members

please help me to get rid of "Array Out of Range" code for IndicatorClass ...

The code is picked up from a custom indicator on MQL5 Market.


//+----------------------------------------------------------------------------------------------------------+
//| defines
//+----------------------------------------------------------------------------------------------------------+
class FxCiVWMACD
  {
private:
  //--- class variable for parameters
    string              m_Symbol;             // Symbol
    ENUM_TIMEFRAMES     m_TimeFrame;          // Timeframe
    int                 m_MACDPeriod_Fast;    // 
    int                 m_MACDPeriod_Slow;    //
    int                 m_MACDPeriod_Signal;  //
  //--- variables and Method to calculate Volume Weighted MACD
    int                 m_BarStart;
    int                 m_BarCount;
    //double              m_OscMAUp[];
    //double              m_OscMADn[];
    //double              m_MACDMain[];
    //double              m_MACDSignal[];
    //bool                Calculate_VWMACD(void);
  //--- Instance of other Class(s)
    //CLog*             m_log;                // Logging

public:
  //--- Parametric Contstructor and default Destructor methods
           FxCiVWMACD(void);
          ~FxCiVWMACD(void);
    bool   Init_Params(string pSymbol,ENUM_TIMEFRAMES pTimeFrame,int pMACDPeriod_Fast,int pMACDPeriod_Slow,int pMACDPeriod_Signal);
  //--- Specific methods of Class FxCiVWMACD
    bool   Get_iVWMACD(double &VWMACDMain[],double &VWMACDSignal[],double &VWMACDOscillator[]);
  };
//+----------------------------------------------------------------------------------------------------------+
//| METHOD:       FxCiVWMACD()
//| APPLICATION:  'default constructor' method without parameters passed into the Class
//+----------------------------------------------------------------------------------------------------------+
FxCiVWMACD::FxCiVWMACD(void)
  {
    //---
  } // END Of FxCiVWMACD()
//+----------------------------------------------------------------------------------------------------------+
//| METHOD:       FxCiVWMACD()
//| APPLICATION:  default destructor method
//+----------------------------------------------------------------------------------------------------------+
FxCiVWMACD::~FxCiVWMACD(void)
  {
//---
  } // END Of ~FxCiVWMACD()
//+----------------------------------------------------------------------------------------------------------+
//| METHOD:       Init_Params()
//| APPLICATION:  Initialize PARAMETERs of Indicator with parameters passed into the Class
//+----------------------------------------------------------------------------------------------------------+
bool FxCiVWMACD::Init_Params(string pSymbol,ENUM_TIMEFRAMES pTimeFrame,int pMACDPeriod_Fast,
                             int pMACDPeriod_Slow,int pMACDPeriod_Signal)
  {
    m_Symbol            = pSymbol;
    m_TimeFrame         = pTimeFrame;
    m_MACDPeriod_Fast   = pMACDPeriod_Fast;
    m_MACDPeriod_Slow   = pMACDPeriod_Slow;
    m_MACDPeriod_Signal = pMACDPeriod_Signal;
    m_BarStart          = 0;
    m_BarCount          = 10;
    //m_log = CLog::GetLog();
  //---
    return(true);
  } // END Of Init_Params()
//+----------------------------------------------------------------------------------------------------------+
//| METHOD:       Get_VWMACD()
//| APPLICATION:  Calculate & Get Volume Weighted MACD values
//+----------------------------------------------------------------------------------------------------------+
bool FxCiVWMACD::Get_iVWMACD(double &MACD_Main[],double &MACD_Signal[],double &MACD_Oscillator[])
  {
    double VEMAs[][6];
    #define _nFastMA 0      // numerator Fast MA
    #define _dFastMA 1      // denominator Fast MA
    #define _EMAFast 2
    #define _nSlowMA 3      // numerator Slow MA
    #define _dSlowMA 4      // denominator Slow MA
    #define _EMASlow 5

    if(ArrayRange(VEMAs,0) != m_BarCount)
      ArrayResize(VEMAs,m_BarCount);
    ArrayResize(MACD_Main,m_BarCount+1);	// causing array out of range error
    ArrayResize(MACD_Signal,m_BarCount+1);
    ArrayResize(MACD_Oscillator,m_BarCount+1);
        
    double alphaFast   = 2.0/(1.0 + m_MACDPeriod_Fast);
    double alphaSlow   = 2.0/(1.0 + m_MACDPeriod_Slow);
    double alphaSignal = 2.0/(1.0 + m_MACDPeriod_Signal);

  //--- Main Loop to calculate VW MACD for 'n' bar count
    for (int i = m_BarStart; i < m_BarCount; i++)
      {
        double volume = (double)iVolume(m_Symbol,m_TimeFrame,i);  // for now use only Tick Volume
        double price  = iClose(m_Symbol,m_TimeFrame,i);           // for now use only Close Price
      //--- Calculate the First Index Value of EMA
        if(i < 2)
          {
            VEMAs[i][_nFastMA] = (volume * price);
            VEMAs[i][_dFastMA] = (volume);
            VEMAs[i][_nSlowMA] = (volume * price);
            VEMAs[i][_dSlowMA] = (volume);
            continue;
          }
      //--- Calculate the Remaining Index Values of EMA
        VEMAs[i][_nFastMA] = VEMAs[i-1][_nFastMA] + alphaFast *(volume * price - VEMAs[i-1][_nFastMA]);
        VEMAs[i][_dFastMA] = VEMAs[i-1][_dFastMA] + alphaFast *(volume         - VEMAs[i-1][_dFastMA]);
        VEMAs[i][_EMAFast] = VEMAs[i][_nFastMA] / VEMAs[i][_dFastMA];     // Fast EMA Array
        
        VEMAs[i][_nSlowMA] = VEMAs[i-1][_nSlowMA] + alphaSlow *(volume * price - VEMAs[i-1][_nSlowMA]);
        VEMAs[i][_dSlowMA] = VEMAs[i-1][_dSlowMA] + alphaSlow *(volume         - VEMAs[i-1][_dSlowMA]);
        VEMAs[i][_EMASlow] = VEMAs[i][_nSlowMA] / VEMAs[i][_dSlowMA];     // Slow EMA Array

        MACD_Main[i]       = VEMAs[i][_EMAFast] - VEMAs[i][_EMASlow];
        MACD_Signal[i]     = MACD_Signal[i-1] + alphaSignal * (MACD_Main[i] - MACD_Signal[i-1]);
        MACD_Oscillator[i] = MACD_Main[i] - MACD_Signal[i];
        //m_OscMADn[i]    = 0;
      } // END Of Main for..loop
  //---
    return(true);
  } // END Of method Calculate_VWMACD()
//+----------------------------------------------------------------------------------------------------------+
William Roeder  
  1. ArrayResize does not result in an out of range.

  2.     for (int i = m_BarStart; i < m_BarCount; i++)
          ⋮
            VEMAs[i][_nFastMA] = VEMAs[i-1][_nFastMA] + alphaFast *(volume * price - VEMAs[i-1][_nFastMA]);

    m_BarStart is zero. Therefor when i is zero [i-1] does not exist. That is your out of range.

  3.     double VEMAs[][6];
        #define _nFastMA 0      // numerator Fast MA
        #define _dFastMA 1      // denominator Fast MA
        #define _EMAFast 2
        #define _nSlowMA 3      // numerator Slow MA
        #define _dSlowMA 4      // denominator Slow MA
        #define _EMASlow 5
    This is bad style. A one dimension array of a struct would be better.
[Deleted]  
William Roeder:
  1. ArrayResize does not result in an out of range.

  2. m_BarStart is zero. Therefor when i is zero [i-1] does not exist. That is your out of range.

  3. This is bad style. A one dimension array of a struct would be better.

UPDATE: Traced the error in method call, I was trying to call two instances with same name. Array Out of Range is Sorted out. However, continues to get wrong values / results now.

Thanks William

There is an if..loop when i < 2, so VEMAs[i-1] should be processed only when i != 0, that is what I understand. Actually this is working well in the VWMACD Indicator I have downloaded from the Forum Market. The only difference in indicator he has used  LOOP as  "for (int i = (int)MathMax(prev_calculated-1,0); i < rates_total; i++)"

I have tried changing BarStart to 1 (from Zero), still out of range error continues.

Also I am not sure how to SetArrayAsSeries (multidimensional array) in Class, because in in Indicaor it is done automatically while in method / function we need to do with code.

" This is bad style. A one dimension array of a struct would be better." I remember seeing post on forum somewhere, I will be grateful if you can share the link here please.

    for (int i = m_BarStart; i < m_BarCount; i++)
      {
        double volume = (double)iVolume(m_Symbol,m_TimeFrame,i);  // for now use only Tick Volume
        double price  = iClose(m_Symbol,m_TimeFrame,i);           // for now use only Close Price
      //--- Calculate the First Index Value of EMA
        if(i < 2)
          {
            VEMAs[i][_nFastMA] = (volume * price);
            VEMAs[i][_dFastMA] = (volume);
            VEMAs[i][_nSlowMA] = (volume * price);
            VEMAs[i][_dSlowMA] = (volume);
            continue;
          }
      //--- Calculate the Remaining Index Values of EMA
        VEMAs[i][_nFastMA] = VEMAs[i-1][_nFastMA] + alphaFast *(volume * price - VEMAs[i-1][_nFastMA]);
Reason: