Stochastic RSI (StochRSI)
I. What is StochRSI
The Stochastic RSI (StochRSI) is a composite indicator created by applying the Stochastic Oscillator formula to RSI values (rather than to prices). It measures the relative position of RSI within its own range over a given period, thereby amplifying the signal sensitivity of RSI.
Historical Background
StochRSI was first introduced by Tushar Chande and Stanley Kroll in 1994 in their book The New Technical Trader. They observed that standard RSI often lingers between 30-70 without triggering overbought/oversold signals in many situations. By applying the Stochastic transformation to RSI, more frequent and timely trading signals can be generated.
Indicator Classification
- Type: Oscillator, displayed in a separate panel
- Category: Momentum — second-order derived indicator
- Default Parameters: RSI period , Stochastic period , %K smoothing , %D smoothing
- Value Range: 0 — 1 (or 0 — 100)
Standard RSI(14) typically oscillates within the 30-70 range and rarely reaches extreme values. StochRSI re-normalizes RSI values to the 0-1 range, distributing the indicator more evenly across its full range and significantly increasing the trigger frequency of overbought/oversold signals.
II. Mathematical Principles and Calculation
Core Formulas
Step 1: Calculate standard RSI
Where , using Wilder Smoothing (see RSI tutorial for details).
Step 2: Apply Stochastic transformation to RSI
Where:
- = lowest RSI value over the past periods
- = highest RSI value over the past periods
- = Stochastic lookback period (default 14)
Step 3: Calculate %K and %D
Step-by-Step Calculation Logic
- Calculate RSI(14): Using Wilder Smoothing
- Find RSI extremes: Highest and lowest RSI values over the past 14 periods
- Normalize: Map current RSI to the [0, 1] interval
- %K smoothing: Apply SMA(3) to StochRSI to get %K
- %D smoothing: Apply SMA(3) to %K to get %D
Mathematical Significance
StochRSI is essentially an “indicator of an indicator”:
- RSI measures price momentum (normalized first-order derivative)
- StochRSI measures the position of RSI momentum within its range (second-order information)
When StochRSI = 1, RSI is at its recent highest level; when StochRSI = 0, RSI is at its recent lowest level.
Raw StochRSI ranges from 0-1. Some platforms multiply it by 100 to display as 0-100. When using thresholds, note the correspondence: 0.8 corresponds to 80, 0.2 corresponds to 20.
III. Python Implementation
import numpy as np
import pandas as pd
def rsi(close: pd.Series, period: int = 14) -> pd.Series:
"""Calculate RSI using Wilder Smoothing"""
delta = close.diff()
gain = delta.where(delta > 0, 0.0)
loss = (-delta).where(delta < 0, 0.0)
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()
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
return 100 - 100 / (1 + rs)
def stoch_rsi(close: pd.Series,
rsi_period: int = 14,
stoch_period: int = 14,
k_smooth: int = 3,
d_smooth: int = 3) -> pd.DataFrame:
"""
Calculate Stochastic RSI
Parameters
----------
close : pd.Series
Close price series
rsi_period : int
RSI calculation period, default 14
stoch_period : int
Stochastic lookback period, default 14
k_smooth : int
%K smoothing period, default 3
d_smooth : int
%D smoothing period, default 3
Returns
-------
pd.DataFrame
DataFrame with StochRSI, %K, and %D columns
"""
rsi_values = rsi(close, rsi_period)
rsi_min = rsi_values.rolling(window=stoch_period, min_periods=stoch_period).min()
rsi_max = rsi_values.rolling(window=stoch_period, min_periods=stoch_period).max()
stoch_rsi_raw = (rsi_values - rsi_min) / (rsi_max - rsi_min)
k = stoch_rsi_raw.rolling(window=k_smooth, min_periods=k_smooth).mean()
d = k.rolling(window=d_smooth, min_periods=d_smooth).mean()
return pd.DataFrame({
"StochRSI": stoch_rsi_raw,
"K": k,
"D": d
}, index=close.index)
# ========== Usage Example ==========
if __name__ == "__main__":
np.random.seed(42)
dates = pd.date_range("2024-01-01", periods=150, freq="D")
price = 100 + np.cumsum(np.random.randn(150) * 1.2)
df = pd.DataFrame({
"date": dates,
"open": price + np.random.randn(150) * 0.3,
"high": price + np.abs(np.random.randn(150) * 0.8),
"low": price - np.abs(np.random.randn(150) * 0.8),
"close": price,
"volume": np.random.randint(1000, 10000, size=150),
})
df.set_index("date", inplace=True)
# Calculate StochRSI
result = stoch_rsi(df["close"])
df = pd.concat([df, result], axis=1)
print("=== StochRSI Results (last 15 rows) ===")
print(df[["close", "StochRSI", "K", "D"]].tail(15).to_string())
# Overbought/Oversold signals
df["signal"] = np.where(
(df["K"] > 0.8) & (df["D"] > 0.8), -1,
np.where((df["K"] < 0.2) & (df["D"] < 0.2), 1, 0)
)
signals = df[df["signal"] != 0]
print("\n=== Overbought/Oversold Signals ===")
print(signals[["close", "K", "D", "signal"]].head(15).to_string())
IV. Problems the Indicator Solves
1. Enhanced RSI Sensitivity
Standard RSI(14) spends most of its time drifting between 40-60, while StochRSI frequently reaches the extreme values of 0 and 1, providing more trading opportunities.
2. Overbought / Oversold Detection
| Zone | Condition | Meaning |
|---|---|---|
| Overbought | %K > 0.8 and %D > 0.8 | RSI is at a relatively high level recently |
| Oversold | %K < 0.2 and %D < 0.2 | RSI is at a relatively low level recently |
3. Crossover Signals
- %K crosses above %D (in oversold zone) — Buy signal
- %K crosses below %D (in overbought zone) — Sell signal
4. Short-Term Timing
Since StochRSI is more sensitive than RSI, it is particularly suited for precise entry timing after the trend direction has already been confirmed.
StochRSI has a high signal frequency but also significant noise; the false signal rate when used alone is high. It must be combined with trend filters and other confirmation tools.
V. Advantages, Disadvantages, and Use Cases
Advantages
| Advantage | Description |
|---|---|
| Extremely sensitive | Triggers signals far more frequently than standard RSI |
| Uniform distribution | More evenly distributed in the 0-1 range, making thresholds easier to set |
| Precise timing | Ideal for finding optimal entries after a trend is confirmed |
| Rich signals | Dual signal system of overbought/oversold + crossovers |
Disadvantages
| Disadvantage | Description |
|---|---|
| High noise | High sensitivity brings more false signals |
| Volatile | Jumps rapidly between 0 and 1, requires smoothing |
| Second-order derivative | As an indicator of an indicator, relationship to price is indirect |
| Many parameters | Four parameters require tuning, increasing overfitting risk |
Use Cases
- Intraday trading: High sensitivity suits short-cycle operations
- Entry timing: Use StochRSI to find precise entries after trend direction is confirmed
- Paired with trend indicators: Works best with MACD, ADX, and other trend indicators
Comparison with Related Indicators
| Comparison | StochRSI | RSI | Stochastic |
|---|---|---|---|
| Sensitivity | Very high | Medium | High |
| False signal rate | High | Low | Medium |
| Best timeframe | Short-term | Medium to long | Short-term |
| Data source | RSI values | Close price | H/L/C |
- Must pair with trend indicators: Using StochRSI alone produces too many false signals; combine with MACD or ADX.
- Smoothing parameters matter: The %K and %D smoothing periods (default 3) can be increased to reduce noise.
- Extreme value confirmation: When both %K and %D enter overbought/oversold territory simultaneously, the signal is more reliable than a single line.
- Suited for mean reversion strategies: In range-bound markets, StochRSI is an excellent reversal signal tool.