Need help coding RSI

  • Thread starter Thread starter alikim
  • Start date Start date
  • Watchers Watchers 3

alikim

Newbie
Dec 27, 2024
2
0
1
36
I wrote this function, it works, but the value doesn't match what MT4 shows me. What am I doing wrong?

MQL4:
void CalcRSI(int period, bool output = true) {
   int startDate = 2 * period;
   double gains[];
   double losses[];
   ArrayResize(gains, startDate + 1);
   ArrayResize(losses, startDate + 1);
 
   for (int i = startDate; i >= 0; i--) {
      double diff = Close[i] - Close[i + 1];
      gains[i] = diff > 0 ? diff : 0.0;
      losses[i] = diff > 0 ? 0.0 : -diff;
   }
 
   double avrGain = 0.0;
   double avrLoss = 0.0;
 
   // initial average
   for (int i = startDate; i > startDate - period; i--) {
      avrGain += gains[i];
      avrLoss += losses[i];
   }
   avrGain /= period;
   avrLoss /= period;
 
   // Wilder's smoothing
   for (int i = startDate - period; i >= 0; i--) {
      avrGain = (avrGain * (period - 1) + gains[i]) / period;
      avrLoss = (avrLoss * (period - 1) + losses[i]) / period;
   }
 
   double rs = avrGain / avrLoss;
   double rsi = 100 - (100 / (1 + rs));
 
   if(output) {
      Alert(StringFormat("RSI(%d): %.2f", period, rsi));
   }
}
 
Last edited by a moderator:
This might help:

void CalcRSI(int period, bool output = true) {
int startDate = period;
double gains[], losses[];
ArrayResize(gains, period);
ArrayResize(losses, period);

// Calculate the gains and losses for the period
for (int i = startDate; i > 0; i--) {
double diff = Close - Close[i + 1];
gains[i - 1] = diff > 0 ? diff : 0.0;
losses[i - 1] = diff < 0 ? -diff : 0.0;
}

// Calculate the initial average gain and loss
double avrGain = 0.0;
double avrLoss = 0.0;
for (int i = 0; i < period; i++) {
avrGain += gains;
avrLoss += losses;
}
avrGain /= period;
avrLoss /= period;

// Wilder's smoothing method for subsequent periods
for (int i = startDate; i < Bars - 1; i++) {
double diff = Close - Close[i + 1];
double gain = diff > 0 ? diff : 0.0;
double loss = diff < 0 ? -diff : 0.0;

avrGain = (avrGain * (period - 1) + gain) / period;
avrLoss = (avrLoss * (period - 1) + loss) / period;
}

// Calculate RS and RSI
double rs = (avrLoss == 0) ? 100 : avrGain / avrLoss; // Prevent division by zero
double rsi = 100 - (100 / (1 + rs));

if (output) {
Alert(StringFormat("RSI(%d): %.2f", period, rsi));
}
}
 
This might help:

void CalcRSI(int period, bool output = true) {
int startDate = period;
double gains[], losses[];
ArrayResize(gains, period);
ArrayResize(losses, period);

// Calculate the gains and losses for the period
for (int i = startDate; i > 0; i--) {
double diff = Close - Close[i + 1];
gains[i - 1] = diff > 0 ? diff : 0.0;
losses[i - 1] = diff < 0 ? -diff : 0.0;
}

// Calculate the initial average gain and loss
double avrGain = 0.0;
double avrLoss = 0.0;
for (int i = 0; i < period; i++) {
avrGain += gains;
avrLoss += losses;
}
avrGain /= period;
avrLoss /= period;

// Wilder's smoothing method for subsequent periods
for (int i = startDate; i < Bars - 1; i++) {
double diff = Close - Close[i + 1];
double gain = diff > 0 ? diff : 0.0;
double loss = diff < 0 ? -diff : 0.0;

avrGain = (avrGain * (period - 1) + gain) / period;
avrLoss = (avrLoss * (period - 1) + loss) / period;
}

// Calculate RS and RSI
double rs = (avrLoss == 0) ? 100 : avrGain / avrLoss; // Prevent division by zero
double rsi = 100 - (100 / (1 + rs));

if (output) {
Alert(StringFormat("RSI(%d): %.2f", period, rsi));
}
}
Please use code highlighting. Otherwise, it becomes garbled.
 
I wrote this function, it works, but the value doesn't match what MT4 shows me. What am I doing wrong?

MQL4:
void CalcRSI(int period, bool output = true) {
   int startDate = 2 * period;
   double gains[];
   double losses[];
   ArrayResize(gains, startDate + 1);
   ArrayResize(losses, startDate + 1);
 
   for (int i = startDate; i >= 0; i--) {
      double diff = Close[i] - Close[i + 1];
      gains[i] = diff > 0 ? diff : 0.0;
      losses[i] = diff > 0 ? 0.0 : -diff;
   }
 
   double avrGain = 0.0;
   double avrLoss = 0.0;
 
   // initial average
   for (int i = startDate; i > startDate - period; i--) {
      avrGain += gains[i];
      avrLoss += losses[i];
   }
   avrGain /= period;
   avrLoss /= period;
 
   // Wilder's smoothing
   for (int i = startDate - period; i >= 0; i--) {
      avrGain = (avrGain * (period - 1) + gains[i]) / period;
      avrLoss = (avrLoss * (period - 1) + losses[i]) / period;
   }
 
   double rs = avrGain / avrLoss;
   double rsi = 100 - (100 / (1 + rs));
 
   if(output) {
      Alert(StringFormat("RSI(%d): %.2f", period, rsi));
   }
}
What are you expecting it to match?
 
I almost solved it, basically added one day in the first line:
Code:
int startDate = 2 * period + 1;
now it looks like this (cyan lines), compared to in-built RSI (blue lines):

1735390174856.png

my wild guess, since it differs at the beginning, where initial average is calculated, maybe MT4 calculates initial value also using Wilder's smoothing, and not as average. Another reason might be that startDate is rather 2 or 3 days shorter, haven't had time to run tests yet.
 
I almost solved it, basically added one day in the first line:
Code:
int startDate = 2 * period + 1;
now it looks like this (cyan lines), compared to in-built RSI (blue lines):

View attachment 30885

my wild guess, since it differs at the beginning, where initial average is calculated, maybe MT4 calculates initial value also using Wilder's smoothing, and not as average. Another reason might be that startDate is rather 2 or 3 days shorter, haven't had time to run tests yet.
That's because Wilder's smoothing carries over previous values well beyond the period's length. Start calculating from the data's beginning and you'll get the same result as the MT4 built-in RSI. I also recommend checking the RSI.mq4 source code in the Indicators folder - it shows how MetaQuotes calculates this indicator.
 
  • 👍
Reactions: alikim
MQL4:
void CalcRSI(int period, bool output = true) {
   int startDate = period;
   double gains[], losses[];
   ArrayResize(gains, period);
   ArrayResize(losses, period);
 
   // Calculate the gains and losses for the period
   for (int i = startDate; i > 0; i--) {
      double diff = Close[i] - Close[i + 1];
      gains[i - 1] = diff > 0 ? diff : 0.0;
      losses[i - 1] = diff < 0 ? -diff : 0.0;
   }
 
   // Calculate the initial average gain and loss
   double avrGain = 0.0;
   double avrLoss = 0.0;
   for (int i = 0; i < period; i++) {
      avrGain += gains[i];
      avrLoss += losses[i];
   }
   avrGain /= period;
   avrLoss /= period;
 
   // Wilder's smoothing method for subsequent periods
   for (int i = startDate; i < Bars - 1; i++) {
      double diff = Close[i] - Close[i + 1];
      double gain = diff > 0 ? diff : 0.0;
      double loss = diff < 0 ? -diff : 0.0;
 
      avrGain = (avrGain * (period - 1) + gain) / period;
      avrLoss = (avrLoss * (period - 1) + loss) / period;
   }
 
   // Calculate RS and RSI
   double rs = (avrLoss == 0) ? 100 : avrGain / avrLoss; // Prevent division by zero
   double rsi = 100 - (100 / (1 + rs));
 
   if (output) {
      Alert(StringFormat("RSI(%d): %.2f", period, rsi));
   }
}
Post automatically merged:

Please use code highlighting. Otherwise, it becomes garbled.
Got it, thanks.
 
  • 👍
Reactions: Enivid