Reverse_RSI_Bands/improvements.md
Alex David Hernandez Maturrano 922b5bdf7b Updated improvements.md
2026-08-12 23:24:28 -03:00

4.8 KiB

Reverse RSI Bands

This document details the mathematical and architectural corrections applied to the original MQL5 implementation of the Reverse RSI indicator: Free download of the 'Reverse_Engineering_RSI' indicator by 'Scriptor' for MetaTrader 5 in the MQL5 Code Base, 2018.07.09.


1. Core Enhancements

The objective of the Reverse RSI indicator is to plot the exact price levels where the Relative Strength Index (RSI) would reach specific thresholds (like 70 for overbought and 30 for oversold).

Feature Original Code (Reverse_Engineering_RSI.mq5) Corrected Code (Reverse_RSI_Bands.mq5)
Target RSI Level Dynamic (uses a Moving Average of the current RSI). Fixed/Static (uses user-defined levels, default 70 and 30).
Smoothing Method MT5 Library EMA on Buffers (2N-1 period approximation). Exact Wilder Smoothing recursive implementation.
Temporal Alignment Uses current bar averages (i), creating a feedback loop. Uses previous bar averages (i-1 or i+1 in series) for true lookahead.
Plot Count 1 Line (Dynamic "Fair Value" line). 2 Bands (Overbought crimson band and Oversold green band).
Initialization Seed None (starts with raw value, causing persistent offsets). Simple Moving Average (SMA) of the first window (identical to standard RSI).

2. Detailed Technical & Mathematical Corrections

2.1 Fixed Target RSI Levels vs. Dynamic Smoothing (The Purpose Gap)

  • Original Issue: The original code used a moving average of the actual RSI as its target (RSI_MA = BufferAvgRSI[i]). This calculated the price needed to keep the RSI at its average line, resulting in a single "fair value" band. It failed to answer the primary trading question: "At what price will my RSI hit the 70 overbought level?"
  • Correction: We replaced the dynamic target with user-configurable levels (InpObLevel and InpOsLevel). The code now calculates and plots the two distinct boundaries corresponding to these target RSI values.

2.2 Correcting the Temporal Lookahead (Preventing Self-Contamination)

  • Original Issue: The original formula used BufferAvgUP[i] and BufferAvgDN[i] (the smoothed values for the current bar) to solve for the current bar's target price. Since the current bar's averages already include the current bar's price change, this created a logical contradiction and contaminated the mathematical deduction.
  • Correction: To find the price at bar i that results in target RSI T, we must compute using the state of the indicator before bar i was formed. The calculations now correctly extract the preceding bar's state (BufferAvgU[i-1] and BufferAvgD[i-1] in normal indexing order):
    AU_0 = AvgU_{i-1} \times (N-1)
    AD_0 = AvgD_{i-1} \times (N-1)

2.3 Eliminating Initialization Offsets (Wilder Smoothing vs. EMA)

  • Original Issue: Standard MQL5 iRSI initializes its average gain/loss buffers with a Simple Moving Average (SMA) over the first N bars. The original code used ExponentialMAOnBuffer to smooth gains/losses. Since ExponentialMAOnBuffer initializes using the first raw buffer value without an SMA seed, it created a permanent offset that decayed slowly but never reached zero.
  • Correction: We implemented a manual loop for the Wilder Smoothing that calculates an SMA for the first N bars to establish an exact matching seed, then switches to the recursive Wilder calculation:
    AvgU_i = AvgU_{i-1} \times (1 - \alpha) + UP_i \times \alpha
    Where \alpha = 1/N. This matches the standard RSI internal state perfectly.

3. Mathematical Verification

For any bar i, we want the target price P_i to result in RSI_i = T (where T is the target level). Let RS = T / (100 - T). We want:

\frac{AvgU_i}{AvgD_i} = RS

Substituting the recursive Wilder formulas:

\frac{AU_0 + U_i}{AD_0 + D_i} = RS \implies AU_0 + U_i = RS \times (AD_0 + D_i)

Where U_i and D_i are the current bar gains/losses, and AU_0, AD_0 are the decay-adjusted sums from the previous bar.

Case 1: Positive Price Change (P_i \ge P_{i-1})

Here, U_i = P_i - P_{i-1} and D_i = 0.

AU_0 + (P_i - P_{i-1}) = RS \times AD_0
P_i = P_{i-1} + \underbrace{RS \times AD_0 - AU_0}_{x}

This is valid if the price change is positive, i.e., x \ge 0.

Case 2: Negative Price Change (P_i < P_{i-1})

Here, U_i = 0 and D_i = P_{i-1} - P_i.

AU_0 = RS \times (AD_0 + P_{i-1} - P_i)
P_{i-1} - P_i = \frac{AU_0}{RS} - AD_0
P_i = P_{i-1} + AD_0 - \frac{AU_0}{RS} = P_{i-1} + x \times \frac{100 - T}{T}

This is valid if the price change is negative, which occurs exactly when x < 0.

The implementation in Reverse_RSI_Bands.mq5 implements this piecewise logic with 100% mathematical precision.