Calculating Relative Strenght Index

 

Hello everyone!


I'm trying to calculate rsi in my dll:

        double rsi(int period, double *open, double *high, double *low, double *close,  int pos) {
                double nsum = 0.0, psum = 0.0, dif;
                for (int a = 1; a <= period; a++) {
                        dif = close[(pos - a)] - close[(pos - a) - 1];

                        if (dif > 0.0) psum += dif;
                        else nsum -= dif;
                }
                psum /= period;
                nsum /= period;
                if (nsum != 0.0) {
                        return 100.0 - (100.0 / (1.0 + psum / nsum));
                }
                
                if (psum != 0.0) {
                        return 100.0;
                }
                return 50.0;
        }

 

Using rsi function:

// dll
void __declspec(dllexport)  __stdcall SpPushCandles(long long *time, double *open, double *high, double *low, double *close, int size, int id, long long *volume)
{
        /* In some reasons, metatrader arrays (time, open, high etc...) are inverted. Here the newest price can be found in close[size -1] but in metatrader its close[0]
        ExportedTime[size - 1] == MetatraderTime[0], ExportedTime[0] == MetatraderTime[size - 1] */

        int pos = size - 1;
        double p = 0;
        for (int a = size - 1; a >= size - 300; a--) { 
                spchar n1(8);
                p = in::rsi(2, open, high, low, close, a); // close is only needed by default in rsi but I have bigger plans for it in future
                n1.adddouble(p);
                sid(id)->Object->Create(n1, time[a], close[a], time[a], close[a], 255, 0, 0, 9); // creating text on window what text contains the output number of my rsi so I could compare it to mt rsi.
        }
}

// MT
void OnChartEvent( const int id2, const long &lparam, const double &dparam, const string &sparam)
{

   if(id2==CHARTEVENT_CLICK)
   {
      ObjectsDeleteAll(0);
   
      datetime t = 0;
      double p = 0;
      int s = 0;
      ChartXYToTimePrice( 0, lparam, dparam, s, t, p);
      if( t > TimeCurrent() ) t = TimeCurrent();
     
      int tocopy = 4096; 
      int istart = iBarShift( Symbol(), 0, t, false );
      if(istart < 0) istart = 0;
      timeslide = istart;
      
      datetime time[];
      ArraySetAsSeries(time,true);
      int size = CopyTime(Symbol(),0, istart, tocopy, time);
      
      long volume[];
      ArraySetAsSeries(time,true);
      size = CopyTickVolume(Symbol(),0, istart, tocopy, volume);
     
      double open[];
      ArraySetAsSeries(open,true);
      CopyOpen(Symbol(),0, istart, tocopy, open);
      
      double high[];
      ArraySetAsSeries(high,true);
      CopyHigh(Symbol(),0, istart, tocopy, high);
      
      double low[];
      ArraySetAsSeries(low,true);
      CopyLow(Symbol(),0, istart, tocopy, low);
      
      double close[];
      ArraySetAsSeries(close,true);
      CopyClose(Symbol(),0, istart, tocopy, close);
      
      SpPushCandles(time, open, high, low, close, size, id, volume);
      
   }
}

The problem is that its not showing the numbers that Rsi(2) shows in metatrader.
What am i doing wrong?

 

Set array as series after copying.

      datetime time[];
      int size = CopyTime(Symbol(),0, istart, tocopy, time);
      ArraySetAsSeries(time,true);
 
I wonder why did I started using ArraySetSeries in wrong way ... 
Anyways, it appears that Rsi in mt is using different price avarage, guessing its EMA.

Here's a working source code for code in main post:
double rsi(int period, double *open, double *high, double *low, double *close,  int pos) {
double nsum = 0.0, psum = 0.0, dif;
for (int a = pos - 1024; a < pos + period; a++) { // indicator needs at least 1024+period candles in order to work because of the EMA
dif = close[a] - close[a - 1];

if (dif > 0.0) psum += dif;
else nsum -= dif;
}
psum /= period;
nsum /= period;

for (int a = (pos - 1024 ) + period; a <= pos; a++) {
dif = close[a] - close[a - 1];
psum = (psum * (period - 1) + (dif>0.0 ? dif : 0.0)) / period;
nsum = (nsum * (period - 1) + (dif<0.0 ? -dif : 0.0)) / period;

}

if (nsum != 0.0)
return 100.0 - 100.0 / (1 + psum / nsum);
else
{
if (psum != 0.0) return 100.0;
return 50.0;
}
return 50.0;
}

 

The first one is ok because you only need the previous values.

double rsi(int period,double *open,double *high,double *low,double *close,int pos) 
  {
   double nsum=0.0,psum=0.0,dif;
   static int prevpos=-1;
   if(prevpos<0)
     { 
      for(int a=period-1; a>=0; a--) 
        {
         dif=close[(pos+a)]-close[(pos+a)+1];
   
         if(dif>0.0) psum+=dif;
         else nsum-=dif;
        }
      psum /= period;
      nsum /= period;
     }

   static double prevnsum=0.0,prevpsum=0.0;
   dif = close[pos] - close[pos + 1];
   psum = (prevpsum * (period - 1) + (dif>0.0 ? dif : 0.0)) / period;
   nsum = (prevnsum * (period - 1) + (dif<0.0 ? -dif : 0.0)) / period;
   if(prevpos!=pos)
     {   
      prevpsum = psum;
      prevnsum = nsum;
      prevpos = pos;
     }

   if(nsum!=0.0) 
     {
      return 100.0 - (100.0 / (1.0 + psum / nsum));
     }

   if(psum!=0.0) 
     {
      return 100.0;
     }
   return 50.0;
  }
Reason: