RSI Code

 

Hi everybody

I wrote a mql4 program to get the RSI value in every tick. But now I have a problem and get different values. could you please help me to find out my mistake?

 

double get_RSI_value (double & price[][6], double period) {

   double tmp = 0.0;
   double Avg_Positive = 0.0;
   double Avg_Negative = 0.0;
   double sum_negative = 0.0;
   double sum_positive = 0.0;
   double RS = 0.0;
   double RSI = 0.0;

   for (int i = 1 ; i <= period ; i++) {
      tmp = price[i][4] - price[i-1][4];
      if (tmp >= 0) {
         sum_positive += tmp;
      } else {
         sum_negative = (-1 * tmp) + sum_negative;
         // sum_negative -= tmp;
      }
   }

   if (period < 2) return 0;

   Avg_Negative = sum_negative / period;
   Avg_Positive = sum_positive / period;

   if (Avg_Negative != 0.0) {
      RS = Avg_Positive / Avg_Negative;
      RSI = 100.0 - (100.0 / (1.0 + RS));
   }
   else {
      if(Avg_Positive != 0.0)
         RSI = 100.0;
      else
         RSI = 50.0;
   }

   return RSI;
}

 
Don't paste code
Play video
Please edit your post.
For large amounts of code, attach it.
 

Code placed in SRC mode. (updated)

please someone help, Why I get various value in compare with meta-trader RSI indicator?

 
nitro_man: Why I get various value in compare with meta-trader RSI indicator?
      tmp = price[i][4] - price[i-1][4];
Because you're computing it backwards. Change is Current Close minus Previous Close, not Current Close minus Future close.
 
WHRoeder:
nitro_man: Why I get various value in compare with meta-trader RSI indicator?
Because you're computing it backwards. Change is Current Close minus Previous Close, not Current Close minus Future close.

Thanks, But I double check the RSI indicator formula, that's correct. In this indicator we have: current close price - previous close price

I checked this on wikipedia too: https://en.wikipedia.org/wiki/Relative_strength_index 

 
nitro_man:

Hi everybody

I wrote a mql4 program to get the RSI value in every tick. But now I have a problem and get different values. could you please help me to find out my mistake?

 

period is an integer. The dynamic array should be resized before doing calculations.

double get_RSI_value (double & price[][6], int period) {

   double tmp = 0.0;
   double Avg_Positive = 0.0;
   double Avg_Negative = 0.0;
   double sum_negative = 0.0;
   double sum_positive = 0.0;
   double RS = 0.0;
   double RSI = 0.0;

   if (period < 2) return 0;
   
   ArrayResize(price,period);
   for (int i = 1 ; i <= period ; i++) {
      tmp = price[i][4] - price[i-1][4];
      if (tmp >= 0) {
         sum_positive += tmp;
      } else {
         sum_negative = (-1 * tmp) + sum_negative;
         // sum_negative -= tmp;
      }
   }


   Avg_Negative = sum_negative / period;
   Avg_Positive = sum_positive / period;

   if (Avg_Negative != 0.0) {
      RS = Avg_Positive / Avg_Negative;
      RSI = 100.0 - (100.0 / (1.0 + RS));
   }
   else {
      if(Avg_Positive != 0.0)
         RSI = 100.0;
      else
         RSI = 50.0;
   }

   return RSI;
}
 
pipPod:

period is an integer. The dynamic array is usually the last dimension and should be resized before doing calculations.

thanks dude, I checked that, I think the solution you said couldn't solve it but now I have much better results. I changed function to this:

 

double get_RSI (double period) {

   double tmp = 0.0;
   double Avg_Positive = 0.0;
   double Avg_Negative = 0.0;
   double sum_negative = 0.0;
   double sum_positive = 0.0;
   double RS = 0.0;
   double RSI = 0.0;
   
   double prices[][6];
   ArrayCopyRates(prices, NULL, 0);
   RefreshRates();
   
   for (int i = 0 ; i < period ; i++) {
      
      tmp = prices[i][4] - prices[i+1][4];     
      if (tmp >= 0) {
         sum_positive += tmp;
      } else {
         sum_negative -= tmp;
      }
   }
   
   if (period < 2) return 0;
   
   Avg_Negative = sum_negative / period;
   Avg_Positive = sum_positive / period;
   
   if (Avg_Negative != 0.0) {
      RS = Avg_Positive / Avg_Negative;
      RSI = 100.0 - (100.0 / (1.0 + RS));
   }
   else {
      if(Avg_Positive != 0.0)
         RSI = 100.0;
      else
         RSI = 50.0;
   }
   return RSI;
}
 

I did:

 

double prices[][6];
   ArrayCopyRates(prices, NULL, 0); 
RefreshRates(); 

   

I thinks I must refresh prices in the function and do refresh them before calculation. Am I right? 

 
nitro_man:

I did:

 

   

I thinks I must refresh prices in the function and do refresh them before calculation. Am I right? 

I don't think RefreshRates() is necessary, but you still have to make sure the right prices(indexes) are copied.
 
nitro_man: I double check the RSI indicator formula, that's correct. In this indicator we have: current close price - previous close price
      tmp = price[i][4] - price[i-1][4];
nitro_man: I changed function to this:
      tmp = prices[i][4] - prices[i+1][4];     
nitro_man: I did:
double prices[][6];
   ArrayCopyRates(prices, NULL, 0); 
  1. WHRoeder: Because you're computing it backwards. Change is Current Close minus Previous Close, not Current Close minus Future close.
    It is supposed to be the previous close price. That is what I said. But that is NOT what you were computing.
  2. RefreshRates is necessary only if you don't return from start, after sleep, or between multiple server calls to update Bid, Ask, Close[0], or OrderClosePrice() on open orders.

  3. If you change to the new ACR, your code would be self documenting as well as avoiding the large allocation/copy and convert elements that you are doing with the double version.
    MqlRates prices[];
       ArrayCopyRates(prices, NULL, 0); 
    :
         tmp = prices[i].close - prices[i+1].close;
    

 
WHRoeder:
nitro_man: I double check the RSI indicator formula, that's correct. In this indicator we have: current close price - previous close price
nitro_man: I changed function to this:
nitro_man: I did:
  1. WHRoeder: Because you're computing it backwards. Change is Current Close minus Previous Close, not Current Close minus Future close.
    It is supposed to be the previous close price. That is what I said. But that is NOT what you were computing.
  2. RefreshRates is necessary only if you don't return from start, after sleep, or between multiple server calls to update Bid, Ask, Close[0], or OrderClosePrice() on open orders.

  3. If you change to the new ACR, your code would be self documenting as well as avoiding the large allocation/copy and convert elements that you are doing with the double version.

thanks alot WHRoeder.

now I have this code with different RSI value in same time with RSI indicator :(

MqlRates prices[];
ArrayCopyRates(prices, NULL, 0); 
double RSI_value = get_RSI_value (prices, FA_Period);


double get_RSI_value (MqlRates & peices_arg[], double period) {

   double Avg_Positive = 0.0;
   double Avg_Negative = 0.0;
   double sum_negative = 0.0;
   double sum_positive = 0.0;
   double tmp = 0.0;
   double RS = 0.0;
   double RSI = 0.0;
   
   for (int i = 1 ; i <= period ; i++) {
      tmp = peices_arg[i].close - peices_arg[i+1].close;
      if (tmp >= 0) {
         sum_positive += tmp;
      } else {
         sum_negative -= tmp;
      }
   }
   
   if (period < 2) return 0;
   
   Avg_Negative = sum_negative / period;
   Avg_Positive = sum_positive / period;
   
   if (Avg_Negative != 0.0) {
      RS = Avg_Positive / Avg_Negative;
      RSI = 100.0 - (100.0 / (1.0 + RS));
   }
   else {
      if(Avg_Positive != 0.0)
         RSI = 100.0;
      else
         RSI = 50.0;
   }
   
   return RSI;
}

RSI indicator in meta trader software itself has a condition like this:

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[])
  {
   int    i,pos;
   double diff;
//---
   if(Bars<=InpRSIPeriod || InpRSIPeriod<2)
      return(0);
//--- counting from 0 to rates_total
   ArraySetAsSeries(ExtRSIBuffer,false);
   ArraySetAsSeries(ExtPosBuffer,false);
   ArraySetAsSeries(ExtNegBuffer,false);
   ArraySetAsSeries(close,false);
//--- preliminary calculations
   pos=prev_calculated-1;
   if(pos<=InpRSIPeriod)
     {
      //--- first RSIPeriod values of the indicator are not calculated
      ExtRSIBuffer[0]=0.0;
      ExtPosBuffer[0]=0.0;
      ExtNegBuffer[0]=0.0;
      double sump=0.0;
      double sumn=0.0;
      for(i=1; i<=InpRSIPeriod; i++)
        {
         ExtRSIBuffer[i]=0.0;
         ExtPosBuffer[i]=0.0;
         ExtNegBuffer[i]=0.0;
         diff=close[i]-close[i-1];
         if(diff>0)
            sump+=diff;
         else
            sumn-=diff;
        }
      //--- calculate first visible value
      ExtPosBuffer[InpRSIPeriod]=sump/InpRSIPeriod;
      ExtNegBuffer[InpRSIPeriod]=sumn/InpRSIPeriod;
      if(ExtNegBuffer[InpRSIPeriod]!=0.0)
         ExtRSIBuffer[InpRSIPeriod]=100.0-(100.0/(1.0+ExtPosBuffer[InpRSIPeriod]/ExtNegBuffer[InpRSIPeriod]));
      else
        {
         if(ExtPosBuffer[InpRSIPeriod]!=0.0)
            ExtRSIBuffer[InpRSIPeriod]=100.0;
         else
            ExtRSIBuffer[InpRSIPeriod]=50.0;
        }
      //--- prepare the position value for main calculation
      pos=InpRSIPeriod+1;
     }
//--- the main loop of calculations
   for(i=pos; i<rates_total && !IsStopped(); i++)
     {
      diff=close[i]-close[i-1];
      ExtPosBuffer[i]=(ExtPosBuffer[i-1]*(InpRSIPeriod-1)+(diff>0.0?diff:0.0))/InpRSIPeriod;
      ExtNegBuffer[i]=(ExtNegBuffer[i-1]*(InpRSIPeriod-1)+(diff<0.0?-diff:0.0))/InpRSIPeriod;
      if(ExtNegBuffer[i]!=0.0)
         ExtRSIBuffer[i]=100.0-100.0/(1+ExtPosBuffer[i]/ExtNegBuffer[i]);
      else
        {
         if(ExtPosBuffer[i]!=0.0)
            ExtRSIBuffer[i]=100.0;
         else
            ExtRSIBuffer[i]=50.0;
        }
     }
   return(rates_total);
}

what is "the main loop of calculations" part for?

I think this part is difference part.

Reason: