Calculating Relative Strength index for 2 Moving Averages's Difference New comment (passing Array into Function)

 

Hi all, 

I am writing an indi on 2 Moving Average-cross and compute the Relative Strength Index (RSI) on the difference between these MAs. Basically it will measure the oscillation of the "Difference" between MovingAverage1 and MovingAverage2 (MaDiffRS). The codes is as below. The idea is to compute the 2 MAs and when the counter i pass over the RS's period (InpTIMEFRAME_RS).

I got stuck at getting the MaDiffRS at it return no value on the terminal. Can you check and advise what is wrong.  I believe it may be caused by passing the MaLine1Buffer and MaLine2Buffer arrays into the function MAValidatorChk incorrectly but not sure.

Main part of the indicator:

int start()
{

int counted_bars=IndicatorCounted();
if(counted_bars<0)return(-1);
if(counted_bars>0)counted_bars--;
int limit=Bars-counted_bars; //limit = new bar added into chart after indi dropped on chart
int InpTIMEFRAME_RS = MathMax(InpTIMEFRAME1,InpTIMEFRAME2);
if(counted_bars==0) limit-=InpTIMEFRAME_RS;

for(int i=0;i<limit;i++)
{
MaLine1Buffer[i] = iMA(NULL,InpTIMEFRAME1,adjustedMA1, InpMAShift1,InpMAMethod1,PRICE_CLOSE,i);
MaLine2Buffer[i] = iMA(NULL,InpTIMEFRAME2,adjustedMA2, InpMAShift2,InpMAMethod2,PRICE_CLOSE,i);
if(limit>=InpTIMEFRAME_RS && i>=InpTIMEFRAME_RS)
   {
   MaRSBuffer[i] = MAValidatorChk(InpMAPeriod_RS, MaLine1Buffer, InpTIMEFRAME1, InpMAPeriod1, MaLine2Buffer, InpTIMEFRAME2, InpMAPeriod2);
   }
   else MaRSBuffer[i]=0;
}

//--- return value of prev_calculated for next call
return(0);

}


double MAValidatorChk(int CalPeriod, double &InpMA1_array[], int Ma1_TF, int Ma1_period, double &InpMA2_array[], int Ma2_TF, int Ma2_period)
  {
      //from <40 [Oversold](buy only)
      //from 40-49 [Downtrend](Sell and buy) 
      //from 50-56 [Sideway] (No trading)
      //from 56-65 [Uptrend] (Buy)
      //from 69> [Overbought] (Sell only)
    //declare array to hold the last 100 value of MAs
       double MADiff_array[], MAPosDiff_array[], MANegDiff_array[];
       double MA1_array[], MA2_array[];
         
       ArrayResize(MADiff_array,CalPeriod);
       ArrayResize(MA1_array,CalPeriod);
       ArrayResize(MA2_array,CalPeriod);
       ArrayResize(MAPosDiff_array,CalPeriod);
       ArrayResize(MANegDiff_array,CalPeriod);
       for(int i=0;i<CalPeriod-1;i++)
        {
           //get value of MAh1 and MAh4 value 
            MA1_array[i] = InpMA1_array[i]; 
            MA2_array[i] = InpMA2_array[i]; 
             MADiff_array[i] = NormalizeDouble(MA1_array[i] - MA2_array[i],4);
             
          //pass the square MADiff_array value to MANegative and Positive array base on their value
          if(MADiff_array[i]<0)MANegDiff_array[i] =  1;
            else MANegDiff_array[i] = 0.0;
          if(MADiff_array[i]>0)MAPosDiff_array[i] =  1;
            else MAPosDiff_array[i] = 0.0;  
          //ArraySetAsSeries(MANegDiff_array,true);
          //ArraySetAsSeries(MAPosDiff_array,true);
          }
       //Compute the average 
       double AverageNegMADiff = NormalizeDouble(ArrayAverage(MANegDiff_array),4);
       double AveragePosMADiff =  NormalizeDouble(ArrayAverage(MAPosDiff_array),4);
       double MAdiffRS = NormalizeDouble(100-(100/(1+AveragePosMADiff/AverageNegMADiff)),2);
       //int NegPosRS_d;
       //if(NegPosRS  <0.9 || NegPosRS >1.1
       //function return 0 for uptrend (AveragePosMADiff > AverageNegMADiff) or downtrend(AveragePosMADiff < AverageNegMADiff)
       //if(AveragePosMADiff > AverageNegMADiff)result=1;
       //else if(AveragePosMADiff < AverageNegMADiff)result = -1;
       //else if(AveragePosMADiff = AverageNegMADiff) result=0;
       //  else GetLastError();
       return(MAdiffRS);
   }
   
   double ArrayAverage(double& array[])
   {
      double summation = 0; 
      for (int iArray = ArraySize(array) - 1; iArray >= 0; iArray--) summation += array[iArray];
      double average =    summation / ArraySize(array);
      if(average!=0)return(average);
      else 
         {
         Print("Error !!!", GetLastError());
         return(0);
         }
   }
   
 //+------------------------------------------------------------------+

void MaAdjuster(int anchorPeriod, int number)
{
if(anchorPeriod==PERIOD_H1)
{
switch(number) //convert to daily MA
{
case PERIOD_M1:MyMAMultiplier=60;break;
case PERIOD_M5:MyMAMultiplier=12;break;
case PERIOD_M15:MyMAMultiplier=4;break;
case PERIOD_M30:MyMAMultiplier=2;break;
case PERIOD_H1:MyMAMultiplier=1;break;
case PERIOD_H4:MyMAMultiplier=0.25;break;
case PERIOD_D1:MyMAMultiplier=0.042;break;
}
}
if(anchorPeriod==PERIOD_H4)
{
switch(number) //convert to daily MA
{
case PERIOD_M1:MyMAMultiplier=240;break;
case PERIOD_M5:MyMAMultiplier=48;break;
case PERIOD_M15:MyMAMultiplier=16;break;
case PERIOD_M30:MyMAMultiplier=8;break;
case PERIOD_H1:MyMAMultiplier=4;break;
case PERIOD_H4:MyMAMultiplier=1;break;
case PERIOD_D1:MyMAMultiplier=0.1667;break;
}
}
if(anchorPeriod==PERIOD_D1)
{
switch(number) //convert to daily MA
{
case PERIOD_M1:MyMAMultiplier=3600;break;
case PERIOD_M5:MyMAMultiplier=288;break;
case PERIOD_M15:MyMAMultiplier=96;break;
case PERIOD_M30:MyMAMultiplier=48;break;
case PERIOD_H1:MyMAMultiplier=24;break;
case PERIOD_H4:MyMAMultiplier=6;break;
case PERIOD_D1:MyMAMultiplier=1;break;
}
}
}

string tf2txt(int tf)
{
if(tf==PERIOD_M1) return("M1");
if(tf==PERIOD_M5) return("M5");
if(tf==PERIOD_M15) return("M15");
if(tf==PERIOD_M30) return("M30");
if(tf==PERIOD_H1) return("H1");
if(tf==PERIOD_H4) return("H4");
if(tf==PERIOD_D1) return("D1");
if(tf==PERIOD_W1) return("W1");
if(tf==PERIOD_MN1) return("MN1");
//----
return("??");
}


Extern part:

#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 Red
#property indicator_color2 clrAliceBlue
#property indicator_color2 clrGold

//--- indicator parameters
// MA line 1
extern int InpMAPeriod1=21; // Period
extern ENUM_TIMEFRAMES InpTIMEFRAME1=PERIOD_H4; //Anchor Timeframe
extern int InpMAShift1=0; // Shift
input ENUM_MA_METHOD InpMAMethod1=MODE_EMA; // Method

// MA line 1
extern int InpMAPeriod2=5; // Period
extern ENUM_TIMEFRAMES InpTIMEFRAME2=PERIOD_H4; //Anchor Timeframe
extern int InpMAShift2=0; // Shift
input ENUM_MA_METHOD InpMAMethod2=MODE_EMA; // Method

int InpMAPeriod_RS=30; // Period 

int adjustedMA1, adjustedMA2;
//--- indicator buffer

double MaLine1Buffer[], MaLine2Buffer[], MaRSBuffer[];
//Array to computing MaDiff
double MaDiff[];

double MyMAMultiplier;

Initialize part:

int OnInit(void)
{

int period = Period() ; //capture the timeframe of the chart use InpTIMEFRAME
MaAdjuster(InpTIMEFRAME1, period); //call the MaAdjuster function, sending the number of period() to the function
MaAdjuster(InpTIMEFRAME2, period); //call the MaAdjuster function, sending the number of period() to the function

adjustedMA1 = NormalizeDouble(InpMAPeriod1*MyMAMultiplier,0); //convert the number of candle base on selected TIMEFRAMES
adjustedMA2 = NormalizeDouble(InpMAPeriod2*MyMAMultiplier,0); //convert the number of candle base on selected TIMEFRAMES

int InpTIMEFRAME_RS = MathMax(InpTIMEFRAME1,InpTIMEFRAME2);
int draw_begin=adjustedMA1-1;
if(InpMAMethod1==MODE_EMA || InpMAMethod2==MODE_EMA) draw_begin=0;

//--- indicator short name
  IndiShortName(InpMAMethod1);
  IndiShortName(InpMAMethod2);

//--- check for input
if(InpMAPeriod1<2 || InpMAPeriod2<2)
return(INIT_FAILED);
//--- indicator buffers mapping and drawings
SetIndexBuffer(0,MaLine1Buffer);
SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,2);
SetIndexShift(0,InpMAShift1);
SetIndexDrawBegin(0,draw_begin);
SetIndexLabel(0,"AutoAdj-Ma1"+tf2txt(InpTIMEFRAME1));

SetIndexBuffer(1,MaLine2Buffer);
SetIndexStyle(1,DRAW_LINE,STYLE_SOLID,2);
SetIndexShift(1,InpMAShift2);
SetIndexDrawBegin(1,draw_begin);
SetIndexLabel(1,"AutoAdj-Ma2"+tf2txt(InpTIMEFRAME2));

SetIndexBuffer(2,MaRSBuffer);
SetIndexStyle(2,DRAW_LINE,STYLE_SOLID,2);
SetIndexDrawBegin(2,draw_begin);
SetIndexLabel(2,"AutoAdj-MaRS"+tf2txt(InpTIMEFRAME_RS));


//--- initialization done
return(INIT_SUCCEEDED);
}
Relative Strength Index (RSI)
Relative Strength Index (RSI)
  • www.mql5.com
The Relative Strength Index technical indicator (RSI) is a price-following oscillator that ranges between 0 and 100. When Wilder introduced the Relative Strength Index, he recommended using a 14-day RSI.. Since then, the 9-day and 25-day Relative Strength Index indicators have also gained popularity. A popular method of analyzing the RSI is to...
 

I hope to be grasping correctly what you're trying to achieve. If we understand the standard version of the RSI as the

"ratio of the rolling n-period averages of the up-moves vs. down-moves of the close price, adjusted to a 0-100 scale",

then what you're probably trying instead is the

"ratio of the rolling n-period averages of the positive vs. negative MA changes, adjusted to a 0-100 scale"

Am I summarizing correctly so far? And why not? I think it's an interesting idea.

What I think is strange though in this context is, that you only count the up-moves and down-moves of the MA (via assigning ones and zeros) instead of taking the actual quantitative value, which would resemble more the usual concept of the RSI

       for(int i=0;i<CalPeriod-1;i++) // this only makes sense if the index [CalPeriod-1] stands for the unfinished current candle, that you want to exclude from the calculation [which may be the case]
        {
           //get value of MAh1 and MAh4 value 
            MA1_array[i] = InpMA1_array[i]; 
            MA2_array[i] = InpMA2_array[i]; 
             MADiff_array[i] = NormalizeDouble(MA1_array[i] - MA2_array[i],4);
             
          //pass the MADiff_array value to MANegative and Positive array base on their value
          MAPosDiff_array[i]=MathMax(0,MA1_array[i]-MA2_array[i]);
          MANegDiff_array[i]=MathMax(0,MA2_array[i]-MA1_array[i]);

          //ArraySetAsSeries(MANegDiff_array,true);
          //ArraySetAsSeries(MAPosDiff_array,true);
          }
       //Compute the average 
       double AverageNegMADiff = NormalizeDouble(ArrayAverage(MANegDiff_array),4);
       double AveragePosMADiff =  NormalizeDouble(ArrayAverage(MAPosDiff_array),4);
       double MAdiffRS = NormalizeDouble(100-(100/(1+AveragePosMADiff/AverageNegMADiff)),2);
........
........

[I didn't look through all the rest of the code]

 
Chris70:

I hope to be grasping correctly what you're trying to achieve. If we understand the standard version of the RSI as the

"ratio of the rolling n-period averages of the up-moves vs. down-moves of the close price, adjusted to a 0-100 scale",

then what you're probably trying instead is the

"ratio of the rolling n-period averages of the positive vs. negative MA changes, adjusted to a 0-100 scale"

Am I summarizing correctly so far? And why not? I think it's an interesting idea.

What I think is strange though in this context is, that you only count the up-moves and down-moves of the MA (via assigning ones and zeros) instead of taking the actual quantitative value, which would resemble more the usual concept of the RSI

[I didn't look through all the rest of the code]

Thanks @Chris70 for your comment. Your understanding is indeed correct. I have opted back to actual quantitative value as per your suggestion (dummy {0.1} is initially chosen to reduce the small value change bias, but the 0-100 scale have actually cover for that).

Update: I have overcome the indicator display problem and now get the indicator worked as expected. I also add the 'trending' component into the MaRS to identify the trend up/ trend down of the MaRS (i.e. comparing the current value of MaRS with the average value of MaRS of the last x bars). The only problem I have is that the indicator seems taking a long time to load whenever I drop it on the chart. Can any one take a look at my code and suggest any optimization to help my indicator load faster. Thanks

Andre