Oscillator Average always set's to 0 for certain values

 

Hi,


Was hoping someone else could tell me why my oscillator has 0 values at the more recent index positions.

The code essentially creates a bunch of RSI's of different periods. Then aims to create a multi length average.

Yet for some reason the values plot to 0 in the more recent candles. I cannot figure out why.


Code:

//+------------------------------------------------------------------+
//|                                             Multi_Period_RSI.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//////////////////////////////////////////////////////////////////////
#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 100
#property indicator_level1 30
#property indicator_level2 70
#property indicator_levelcolor clrWhite
#property indicator_levelstyle STYLE_DOT
#property indicator_buffers 10
#property indicator_plots   4

//--- plot Period - 10
#property indicator_label1  "10"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrPink
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot Period - 14
#property indicator_label2  "14"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- plot Period - 21
#property indicator_label3  "21"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrDodgerBlue
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1
//--- plot Average
#property indicator_label4  "Average"
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrGold
#property indicator_style4  STYLE_SOLID
#property indicator_width4  3
//--- input parameters

input int   inpPeriod1    = 10;             // RSI 1 Period
input int   inpPeriod2    = 14;             // RSI 2 Period
input int   inpPeriod3    = 21;             // RSI 3  Period

// Buffers for short term RSI
double    ShortRSIBuffer[];
double    ExtShortPosBuffer[];
double    ExtShortNegBuffer[];

// Buffers for medium term RSI
double    MediumRSIBuffer[];
double    ExtMediumPosBuffer[];
double    ExtMediumNegBuffer[];

// Buffers for long term RSI
double    LongRSIBuffer[];
double    ExtLongPosBuffer[];
double    ExtLongNegBuffer[];

//--- Average RSI Indicator Buffer
double    ExtRSIBuffer[];

// Price Buffers

double    Prices[];

int       ExtShortPeriodRSI;
int       ExtMediumPeriodRSI;
int       ExtLongPeriodRSI;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- check for input
   if(inpPeriod1<1 || inpPeriod2<1 || inpPeriod3<1)
     {
      ExtShortPeriodRSI  = 10;
      ExtMediumPeriodRSI = 14;
      ExtLongPeriodRSI   = 21;
      PrintFormat("Incorrect value for input variables InpPeriodRSI = %d || %d || %d. Indicator will use value %d || %d || %d for calculations.",
                  inpPeriod1,inpPeriod2,inpPeriod3,ExtShortPeriodRSI,ExtMediumPeriodRSI,ExtLongPeriodRSI);
     }
   else
     {
      ExtShortPeriodRSI=inpPeriod1;
      ExtMediumPeriodRSI=inpPeriod2;
      ExtLongPeriodRSI=inpPeriod3;
     }

//--- indicator buffers mapping

   SetIndexBuffer(0,ShortRSIBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,ExtShortPosBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(2,ExtShortNegBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,MediumRSIBuffer,INDICATOR_DATA);
   SetIndexBuffer(4,ExtMediumPosBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(5,ExtMediumNegBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(6,LongRSIBuffer,INDICATOR_DATA);
   SetIndexBuffer(7,ExtLongPosBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(8,ExtLongNegBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(9,ExtRSIBuffer,INDICATOR_DATA);

//--- set accuracy
   IndicatorSetInteger(INDICATOR_DIGITS,2);
   IndicatorSetInteger(INDICATOR_DIGITS,2);
   IndicatorSetInteger(INDICATOR_DIGITS,2);
   IndicatorSetInteger(INDICATOR_DIGITS,2);
//--- sets first bar from what index will be drawn
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ExtShortPeriodRSI);
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ExtMediumPeriodRSI);
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ExtLongPeriodRSI);

//--- name for DataWindow and indicator subwindow label
   IndicatorSetString(INDICATOR_SHORTNAME,"RSI("+string(ExtShortPeriodRSI)+")");
   IndicatorSetString(INDICATOR_SHORTNAME,"RSI("+string(ExtMediumPeriodRSI)+")");
   IndicatorSetString(INDICATOR_SHORTNAME,"RSI("+string(ExtLongPeriodRSI)+")");
   
   ArraySetAsSeries(ShortRSIBuffer,true);
   ArraySetAsSeries(ExtShortPosBuffer,true);
   ArraySetAsSeries(ExtShortNegBuffer,true);
   ArraySetAsSeries(MediumRSIBuffer,true);
   ArraySetAsSeries(ExtMediumPosBuffer,true);
   ArraySetAsSeries(ExtMediumNegBuffer,true);
   ArraySetAsSeries(LongRSIBuffer,true);
   ArraySetAsSeries(ExtLongPosBuffer,true);
   ArraySetAsSeries(ExtLongNegBuffer,true);
   ArraySetAsSeries(ExtRSIBuffer,true);

  }
//+------------------------------------------------------------------+
//| Relative Strength Index                                          |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
   if(rates_total<=ExtShortPeriodRSI || rates_total<=ExtMediumPeriodRSI || rates_total<=ExtLongPeriodRSI)
      return(0);
//--- preliminary calculations

   ArrayResize(Prices,rates_total);
   for(int i = 0; i <= rates_total ; i++){
      Prices[i] = price[i];
   }

   CreateRsiBuffers(prev_calculated, rates_total,ShortRSIBuffer,ExtShortPosBuffer,ExtShortNegBuffer,ExtShortPeriodRSI);
   CreateRsiBuffers(prev_calculated, rates_total,MediumRSIBuffer,ExtMediumPosBuffer,ExtMediumNegBuffer,ExtMediumPeriodRSI);
   CreateRsiBuffers(prev_calculated, rates_total,LongRSIBuffer,ExtLongPosBuffer,ExtLongNegBuffer,ExtLongPeriodRSI);
   CreateAverageRsiBuffer(prev_calculated,ExtRSIBuffer);
//--- OnCalculate done. Return new prev_calculated.
   return(rates_total);
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+

void CreateRsiBuffers(int pre_calculated, int bars_total ,double &MainBuffer[],double &PosBuffer[],double &NegBuffer[],int RsiPeriod){
   int pos=pre_calculated-1;
   int rates_total = bars_total;
   if(!rates_total > 0) return;
   if(pos<=RsiPeriod)
     {
      double sum_pos=0.0;
      double sum_neg=0.0;
      //--- first RSIPeriod values of the indicator are not calculated
      MainBuffer[0]=0.0;
      PosBuffer[0]=0.0;
      NegBuffer[0]=0.0;
      for(int i=1; i<=RsiPeriod; i++)
        {
         MainBuffer[i]=0.0;
         PosBuffer[i]=0.0;
         NegBuffer[i]=0.0;
         double diff=Prices[i]-Prices[i-1];
         sum_pos+=(diff>0?diff:0);
         sum_neg+=(diff<0?-diff:0);
        }
      //--- calculate first visible value
      PosBuffer[RsiPeriod]=sum_pos/RsiPeriod;
      NegBuffer[RsiPeriod]=sum_neg/RsiPeriod;
      if(NegBuffer[RsiPeriod]!=0.0)
         MainBuffer[RsiPeriod]=100.0-(100.0/(1.0+PosBuffer[RsiPeriod]/NegBuffer[RsiPeriod]));
      else
        {
         if(PosBuffer[RsiPeriod]!=0.0)
            MainBuffer[RsiPeriod]=100.0;
         else
            MainBuffer[RsiPeriod]=50.0;
        }
      //--- prepare the position value for main calculation
      pos=RsiPeriod+1;
     }
//--- the main loop of calculations
   for(int i=pos; i<rates_total && !IsStopped(); i++)
     {
      double diff=Prices[i]-Prices[i-1];
      PosBuffer[i]=(PosBuffer[i-1]*(RsiPeriod-1)+(diff>0.0?diff:0.0))/RsiPeriod;
      NegBuffer[i]=(NegBuffer[i-1]*(RsiPeriod-1)+(diff<0.0?-diff:0.0))/RsiPeriod;
      if(NegBuffer[i]!=0.0)
         MainBuffer[i]=100.0-100.0/(1+PosBuffer[i]/NegBuffer[i]);
      else
        {
         if(NegBuffer[i]!=0.0)
            MainBuffer[i]=100.0;
         else
            MainBuffer[i]=50.0;
        }
     }
}

void CreateAverageRsiBuffer(int total_bars,double &MainBuffer[]){
      if(!total_bars > 0) return;
      int buffer_size = ArraySize(ShortRSIBuffer) + ArraySize(MediumRSIBuffer) + ArraySize(LongRSIBuffer);
      if(buffer_size % 3 == 0){
         double average;
         for(int i = buffer_size - 1;i >= 0;i--){
            average = (ShortRSIBuffer[i] + MediumRSIBuffer[i] + LongRSIBuffer[i]) / 3;
            ExtRSIBuffer[i] = average;
         }
      }
}


Side note - The reason for not creating standard handles is due to the fact that I am unable to create a handle for the average plot.


Thanks