Relative Strength Index (RSI)
I. What is RSI
The Relative Strength Index (RSI) is one of the most widely used momentum oscillators in technical analysis. It measures the speed and magnitude of price changes by comparing the extent of upward and downward movements over a given period, thereby determining whether an asset is overbought or oversold.
Historical Background
RSI was first introduced by American technical analysis pioneer J. Welles Wilder Jr. in 1978 in his classic book New Concepts in Technical Trading Systems. Wilder also invented ATR, ADX, Parabolic SAR, and several other indicators still widely used today. Due to its elegant logic and strong practical utility, RSI quickly became a standard indicator on all major trading platforms.
Indicator Classification
- Type: Oscillator, displayed in a separate panel
- Category: Momentum
- Default Parameters: Period , data source is Close price
- Value Range: 0 — 100
- Short-term: RSI(7) or RSI(9) — sensitive signals, suitable for short-term trading
- Standard: RSI(14) — Wilder’s recommended default, balancing sensitivity and stability
- Long-term: RSI(21) or RSI(25) — fewer but more reliable signals
II. Mathematical Principles and Calculation
Core Formulas
RSI is calculated in two steps: first compute the Relative Strength (RS), then normalize it to the 0-100 range.
Step 1: Calculate price changes
Separate gains and losses:
- Gain:
- Loss:
Step 2: Calculate average gains/losses using Wilder Smoothing (SMMA)
The initial calculation (at period ) uses a simple average:
Subsequent values use Wilder’s recursive smoothing (equivalent to EMA with ):
Step 3: Calculate RS and RSI
Equivalent form:
Step-by-Step Calculation Logic
- Calculate daily price changes
- Separate positive and negative changes: gains as positive values, losses as absolute values
- Initialize: compute simple averages of gains and losses for the first periods
- Recursive smoothing: update each subsequent period using Wilder’s smoothing formula
- RS = Average Gain / Average Loss
- RSI = 100 - 100/(1+RS)
Wilder Smoothing (SMMA) assigns gradually decaying weights to historical data, making RSI values more stable and less prone to sharp jumps from single-day extreme movements. This smoothing method is equivalent to an EMA with a period of .
III. Python Implementation
import numpy as np
import pandas as pd
def rsi(close: pd.Series, period: int = 14) -> pd.Series:
"""
Calculate the Relative Strength Index (RSI) using Wilder Smoothing
Parameters
----------
close : pd.Series
Close price series
period : int
Calculation period, default 14
Returns
-------
pd.Series
RSI values (0-100)
"""
delta = close.diff()
gain = delta.where(delta > 0, 0.0)
loss = (-delta).where(delta < 0, 0.0)
# First average uses simple mean
avg_gain = gain.copy()
avg_loss = loss.copy()
avg_gain.iloc[:period] = np.nan
avg_loss.iloc[:period] = np.nan
avg_gain.iloc[period] = gain.iloc[1:period + 1].mean()
avg_loss.iloc[period] = loss.iloc[1:period + 1].mean()
# Wilder recursive smoothing
for i in range(period + 1, len(close)):
avg_gain.iloc[i] = (avg_gain.iloc[i - 1] * (period - 1) + gain.iloc[i]) / period
avg_loss.iloc[i] = (avg_loss.iloc[i - 1] * (period - 1) + loss.iloc[i]) / period
rs = avg_gain / avg_loss
rsi_values = 100 - 100 / (1 + rs)
return rsi_values
# ========== Usage Example ==========
if __name__ == "__main__":
np.random.seed(42)
dates = pd.date_range("2024-01-01", periods=120, freq="D")
price = 100 + np.cumsum(np.random.randn(120) * 1.5)
df = pd.DataFrame({
"date": dates,
"open": price + np.random.randn(120) * 0.3,
"high": price + np.abs(np.random.randn(120) * 0.8),
"low": price - np.abs(np.random.randn(120) * 0.8),
"close": price,
"volume": np.random.randint(1000, 10000, size=120),
})
df.set_index("date", inplace=True)
# Calculate RSI
df["RSI_14"] = rsi(df["close"], period=14)
# Generate overbought/oversold signals
df["signal"] = np.where(
df["RSI_14"] > 70, -1, # Overbought -> Sell signal
np.where(df["RSI_14"] < 30, 1, 0) # Oversold -> Buy signal
)
print("=== RSI Results (last 15 rows) ===")
print(df[["close", "RSI_14", "signal"]].tail(15).to_string())
print("\n=== Overbought/Oversold Signal Points ===")
signals = df[df["signal"] != 0]
print(signals[["close", "RSI_14", "signal"]].to_string())
IV. Problems the Indicator Solves
1. Overbought / Oversold Detection
The most classic use of RSI is identifying extreme price conditions:
| Zone | Condition | Meaning |
|---|---|---|
| Overbought | RSI > 70 | Excessive short-term gains, potential pullback |
| Oversold | RSI < 30 | Excessive short-term losses, potential bounce |
| Neutral | 30 <= RSI <= 70 | No extreme signal |
In strong trending markets, RSI can remain in overbought or oversold territory for extended periods. Trading against the trend based solely on overbought/oversold readings can lead to significant losses. Consider combining with trend indicators (such as ADX) to confirm whether the market is trending.
2. Divergence Signals
Divergence is one of RSI’s most valuable signals:
- Bearish Divergence: Price makes a new high, but RSI fails to make a new high — upward momentum is weakening, potential top
- Bullish Divergence: Price makes a new low, but RSI fails to make a new low — downward momentum is weakening, potential bottom
3. Centerline Crossover
- RSI crosses above 50 — upward momentum is strengthening, bullish
- RSI crosses below 50 — downward momentum is strengthening, bearish
4. Failure Swing
Wilder considered the “failure swing” to be RSI’s most reliable signal:
- Top Failure Swing: RSI breaks above 70, pulls back, fails to break above 70 again on the next rally, then breaks below the prior low — sell
- Bottom Failure Swing: RSI breaks below 30, bounces, fails to break below 30 again on the next decline, then breaks above the prior high — buy
V. Advantages, Disadvantages, and Use Cases
Advantages
| Advantage | Description |
|---|---|
| Clear boundaries | Fixed 0-100 range with intuitive overbought/oversold thresholds |
| Leading nature | Divergence signals often precede price reversals |
| Universality | Applicable to stocks, futures, forex, cryptocurrencies, and all markets |
| Computationally efficient | Recursive formula enables very fast real-time calculation |
Disadvantages
| Disadvantage | Description |
|---|---|
| False signals in trends | RSI can stay in overbought/oversold zones during strong trends, invalidating reversal signals |
| Parameter sensitive | Different RSI periods produce significantly different signals; requires tuning per market |
| Single dimension | Based solely on price change magnitude; ignores volume and other information |
| Saturation problem | RSI becomes stuck at high or low levels in extreme market conditions, losing reference value |
Use Cases
- Range-bound markets: RSI performs best in sideways, oscillating markets with high overbought/oversold signal accuracy
- Divergence detection: Finding reversal opportunities at the end of trends
- Filter: Combined with trend indicators, e.g., “only go long when RSI < 40 and price is above the 200-day moving average”
Comparison with Related Indicators
| Comparison | RSI | Stochastic | CCI |
|---|---|---|---|
| Value Range | 0-100 | 0-100 | Unbounded |
| Sensitivity | Medium | High | High |
| Best Timeframe | Medium to long | Short | Medium |
| Price Data | Close only | H/L/C | H/L/C |
- Multi-timeframe confirmation: Observe both daily RSI(14) and weekly RSI(14) simultaneously; signals are more reliable when both align.
- Dynamic thresholds: In bull markets, raise the overbought threshold to 80 and lower oversold to 40; reverse in bear markets.
- Combine with volume: RSI divergence + declining volume = stronger reversal signal.
- Avoid using alone: RSI works best as a confirmation tool, not the sole entry signal.