Calculating Relative Strenght Index

Do you need a programmer? Make an order to let the developer find you!
110
2016.06.22 02:03

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]

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
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?

4476
2016.06.22 08:36

Set array as series after copying.

```      datetime time[];
int size = CopyTime(Symbol(),0, istart, tocopy, time);
ArraySetAsSeries(time,true);
```
110
2016.06.22 13:32
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;
}```

4476
2016.06.22 15:47

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;
}```
/