Stochastic Relative Strength Index (STOCHRSI)¶
The Stochastic RSI is a momentum oscillator that applies the Stochastic formula to RSI values rather than price. It measures the level of RSI relative to its high-low range over a set period, making it more sensitive than standard RSI. StochRSI oscillates between 0 and 100, providing early signals for overbought and oversold conditions.
Usage¶
require 'sqa/tai'
prices = [44.34, 44.09, 44.15, 43.61, 44.33, 44.83,
45.10, 45.42, 45.84, 46.08, 46.03, 46.41,
46.22, 45.64, 46.21, 46.25, 46.08, 46.46,
46.55, 47.03, 47.28, 47.61, 48.12, 48.21]
# Calculate Stochastic RSI (returns two arrays)
fastk, fastd = SQA::TAI.stochrsi(prices, period: 14)
puts "FastK: #{fastk.last.round(2)}"
puts "FastD: #{fastd.last.round(2)}"
Parameters¶
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
prices |
Array | Yes | - | Array of price values |
period |
Integer | No | 14 | RSI period for calculation |
fastk_period |
Integer | No | 5 | Period for FastK calculation |
fastd_period |
Integer | No | 3 | Period for FastD (signal line) |
fastd_ma_type |
Integer | No | 0 | Moving average type for FastD (0=SMA) |
Returns¶
Returns two arrays: 1. FastK - The Stochastic calculation applied to RSI values 2. FastD - Signal line (moving average of FastK)
Both values range from 0 to 100.
Formula¶
1. Calculate RSI over specified period
2. FastK = 100 × (RSI - Lowest RSI) / (Highest RSI - Lowest RSI)
3. FastD = Moving Average of FastK
Interpretation¶
| Value | Interpretation |
|---|---|
| 80-100 | Overbought - potential sell signal |
| 20-80 | Neutral zone |
| 0-20 | Oversold - potential buy signal |
Note: Array elements should be ordered from oldest to newest (chronological order)
Key Characteristics: - More sensitive than standard RSI - Generates earlier signals - More prone to false signals in ranging markets - FastK/FastD crossovers provide additional confirmation
Example: Basic StochRSI Strategy¶
prices = load_historical_prices('AAPL')
fastk, fastd = SQA::TAI.stochrsi(prices, period: 14)
k = fastk.last
d = fastd.last
if k < 20 && d < 20
puts "Oversold: FastK=#{k.round(2)}, FastD=#{d.round(2)}"
if k > d
puts "Bullish crossover in oversold zone - BUY signal"
end
elsif k > 80 && d > 80
puts "Overbought: FastK=#{k.round(2)}, FastD=#{d.round(2)}"
if k < d
puts "Bearish crossover in overbought zone - SELL signal"
end
end
Example: StochRSI Crossovers¶
prices = load_historical_prices('TSLA')
fastk, fastd = SQA::TAI.stochrsi(prices, period: 14)
# Detect crossovers
if fastk[-2] < fastd[-2] && fastk[-1] > fastd[-1]
zone = case fastk[-1]
when 0...20 then "oversold"
when 20...80 then "neutral"
else "overbought"
end
puts "Bullish crossover in #{zone} zone"
puts "FastK crossed above FastD at #{fastk[-1].round(2)}"
if fastk[-1] < 20
puts "Strong BUY signal - oversold crossover"
else
puts "Moderate BUY signal"
end
elsif fastk[-2] > fastd[-2] && fastk[-1] < fastd[-1]
zone = case fastk[-1]
when 0...20 then "oversold"
when 20...80 then "neutral"
else "overbought"
end
puts "Bearish crossover in #{zone} zone"
puts "FastK crossed below FastD at #{fastk[-1].round(2)}"
if fastk[-1] > 80
puts "Strong SELL signal - overbought crossover"
else
puts "Moderate SELL signal"
end
end
Example: StochRSI Extremes¶
prices = load_historical_prices('NVDA')
fastk, fastd = SQA::TAI.stochrsi(prices, period: 14)
# Count consecutive bars in extreme zones
oversold_bars = 0
overbought_bars = 0
fastk.last(10).each do |value|
next if value.nil?
oversold_bars += 1 if value < 20
overbought_bars += 1 if value > 80
end
if oversold_bars >= 3
puts "StochRSI oversold for #{oversold_bars} consecutive bars"
puts "High probability of reversal to upside"
puts "Wait for FastK to cross above 20 for confirmation"
elsif overbought_bars >= 3
puts "StochRSI overbought for #{overbought_bars} consecutive bars"
puts "High probability of reversal to downside"
puts "Wait for FastK to cross below 80 for confirmation"
end
Example: StochRSI with Trend Filter¶
prices = load_historical_prices('MSFT')
fastk, fastd = SQA::TAI.stochrsi(prices, period: 14)
ema_50 = SQA::TAI.ema(prices, period: 50)
ema_200 = SQA::TAI.ema(prices, period: 200)
current_price = prices.last
k = fastk.last
d = fastd.last
# Determine trend
trend = if current_price > ema_50.last && ema_50.last > ema_200.last
:strong_uptrend
elsif current_price > ema_50.last
:uptrend
elsif current_price < ema_50.last && ema_50.last < ema_200.last
:strong_downtrend
else
:downtrend
end
puts <<~OUTPUT
Trend: #{trend}
Price: #{current_price.round(2)}
StochRSI FastK: #{k.round(2)}
StochRSI FastD: #{d.round(2)}
OUTPUT
case trend
when :strong_uptrend, :uptrend
# Only look for oversold buy signals in uptrend
if k < 20 && fastk[-2] < fastd[-2] && fastk[-1] > fastd[-1]
puts "#{trend.to_s.upcase} + Oversold StochRSI crossover = Strong BUY"
end
when :strong_downtrend, :downtrend
# Only look for overbought sell signals in downtrend
if k > 80 && fastk[-2] > fastd[-2] && fastk[-1] < fastd[-1]
puts "#{trend.to_s.upcase} + Overbought StochRSI crossover = Strong SELL"
end
end
Example: StochRSI Divergence¶
prices = load_historical_prices('AMZN')
fastk, fastd = SQA::TAI.stochrsi(prices, period: 14)
# Find recent highs
price_high_1 = prices[-40..-20].max
price_high_2 = prices[-19..-1].max
stoch_high_1 = fastk[-40..-20].compact.max
stoch_high_2 = fastk[-19..-1].compact.max
# Bearish divergence: price higher high, StochRSI lower high
if price_high_2 > price_high_1 && stoch_high_2 < stoch_high_1
puts "Bearish Divergence detected!"
puts "Price higher high: #{price_high_1.round(2)} -> #{price_high_2.round(2)}"
puts "StochRSI lower high: #{stoch_high_1.round(2)} -> #{stoch_high_2.round(2)}"
puts "Potential reversal to downside"
end
# Find recent lows
price_low_1 = prices[-40..-20].min
price_low_2 = prices[-19..-1].min
stoch_low_1 = fastk[-40..-20].compact.min
stoch_low_2 = fastk[-19..-1].compact.min
# Bullish divergence: price lower low, StochRSI higher low
if price_low_2 < price_low_1 && stoch_low_2 > stoch_low_1
puts "Bullish Divergence detected!"
puts "Price lower low: #{price_low_1.round(2)} -> #{price_low_2.round(2)}"
puts "StochRSI higher low: #{stoch_low_1.round(2)} -> #{stoch_low_2.round(2)}"
puts "Potential reversal to upside"
end
Example: StochRSI with RSI Confirmation¶
prices = load_historical_prices('GOOGL')
# Calculate both indicators
fastk, fastd = SQA::TAI.stochrsi(prices, period: 14)
rsi = SQA::TAI.rsi(prices, period: 14)
k = fastk.last
d = fastd.last
rsi_value = rsi.last
puts <<~OUTPUT
StochRSI FastK: #{k.round(2)}
StochRSI FastD: #{d.round(2)}
RSI: #{rsi_value.round(2)}
OUTPUT
# Strong signals when both indicators agree
if k < 20 && rsi_value < 30
puts "Both StochRSI and RSI oversold - Very Strong BUY signal"
if fastk[-2] < fastd[-2] && fastk[-1] > fastd[-1]
puts "StochRSI crossover adds confirmation"
end
elsif k > 80 && rsi_value > 70
puts "Both StochRSI and RSI overbought - Very Strong SELL signal"
if fastk[-2] > fastd[-2] && fastk[-1] < fastd[-1]
puts "StochRSI crossover adds confirmation"
end
elsif k < 20 && rsi_value > 50
puts "StochRSI oversold but RSI neutral - Wait for RSI confirmation"
elsif k > 80 && rsi_value < 50
puts "StochRSI overbought but RSI neutral - Wait for RSI confirmation"
end
Example: Multiple Timeframe StochRSI¶
# Assuming you have different timeframe data
daily_prices = load_historical_prices('AAPL', timeframe: 'daily')
hourly_prices = load_historical_prices('AAPL', timeframe: 'hourly')
daily_k, daily_d = SQA::TAI.stochrsi(daily_prices, period: 14)
hourly_k, hourly_d = SQA::TAI.stochrsi(hourly_prices, period: 14)
puts <<~OUTPUT
Daily StochRSI: K=#{daily_k.last.round(2)}, D=#{daily_d.last.round(2)}
Hourly StochRSI: K=#{hourly_k.last.round(2)}, D=#{hourly_d.last.round(2)}
OUTPUT
# Strongest signals when both timeframes align
if daily_k.last < 30 && hourly_k.last < 20
puts "Multi-timeframe oversold alignment - Strong buy setup"
if hourly_k[-2] < hourly_d[-2] && hourly_k[-1] > hourly_d[-1]
puts "Hourly crossover triggers entry"
end
elsif daily_k.last > 70 && hourly_k.last > 80
puts "Multi-timeframe overbought alignment - Strong sell setup"
if hourly_k[-2] > hourly_d[-2] && hourly_k[-1] < hourly_d[-1]
puts "Hourly crossover triggers entry"
end
end
Trading Strategies¶
1. Overbought/Oversold Extremes¶
- Buy when StochRSI drops below 20 (oversold)
- Sell when StochRSI rises above 80 (overbought)
- More sensitive than regular RSI
- Best in trending markets
2. FastK/FastD Crossovers¶
- Buy when FastK crosses above FastD (especially in oversold zone)
- Sell when FastK crosses below FastD (especially in overbought zone)
- Most reliable crossovers occur near extremes
- Confirm with price action
3. Divergence Trading¶
- Bullish divergence: Price makes lower low, StochRSI makes higher low
- Bearish divergence: Price makes higher high, StochRSI makes lower high
- Powerful reversal signals
- Requires patience for setup
4. Zero-Line Rejection¶
- Buy when StochRSI bounces off 0-10 level without full reversal
- Sell when StochRSI bounces off 90-100 level without full reversal
- Indicates strong momentum continuation
5. Midline Cross¶
- Buy when StochRSI crosses above 50 from below
- Sell when StochRSI crosses below 50 from above
- Indicates momentum shift
Advanced Techniques¶
1. StochRSI Range Adjustment¶
Adjust overbought/oversold levels based on market conditions: - Strong bull market: Use 85/25 instead of 80/20 - Strong bear market: Use 75/15 instead of 80/20 - Volatile markets: Use 90/10 for fewer, stronger signals
2. Multiple Confirmations¶
Wait for multiple signals before entering: - StochRSI extreme + crossover - StochRSI extreme + divergence + crossover - StochRSI + RSI agreement
3. Time-Based Filters¶
Count bars in extreme zones: - 3+ bars oversold = stronger reversal signal - 3+ bars overbought = stronger reversal signal
StochRSI vs RSI vs Stochastic¶
prices = load_historical_prices('META')
high, low, close = load_ohlc_data('META')
# Calculate all three
stoch_rsi_k, stoch_rsi_d = SQA::TAI.stochrsi(prices, period: 14)
rsi = SQA::TAI.rsi(prices, period: 14)
stoch_k, stoch_d = SQA::TAI.stoch(high, low, close)
puts <<~COMPARISON
=== Indicator Comparison ===
StochRSI K: #{stoch_rsi_k.last.round(2)} (most sensitive)
RSI: #{rsi.last.round(2)} (moderate)
Stochastic: #{stoch_k.last.round(2)} (price-based)
StochRSI measures RSI momentum
RSI measures price momentum
Stochastic measures price position in range
COMPARISON
# All three oversold = strongest buy signal
if stoch_rsi_k.last < 20 && rsi.last < 30 && stoch_k.last < 20
puts "\nAll three indicators oversold - MAXIMUM BUY SIGNAL"
elsif stoch_rsi_k.last > 80 && rsi.last > 70 && stoch_k.last > 80
puts "\nAll three indicators overbought - MAXIMUM SELL SIGNAL"
end
Common Settings¶
| Setting | RSI Period | FastK | FastD | Use Case |
|---|---|---|---|---|
| Standard | 14 | 5 | 3 | Balanced approach |
| Sensitive | 14 | 3 | 3 | Quick signals |
| Smooth | 14 | 7 | 5 | Fewer false signals |
| Long-term | 21 | 8 | 5 | Position trading |
Advantages and Limitations¶
Advantages¶
- More sensitive than standard RSI
- Provides earlier signals
- Combines benefits of RSI and Stochastic
- Excellent for timing entries/exits
- Works well with trend filters
Limitations¶
- More prone to false signals
- Can whipsaw in ranging markets
- May signal reversals too early
- Requires confirmation from other indicators
- Not suitable as standalone indicator
Best Practices¶
- Use with Trend Filter: Only take signals aligned with the major trend
- Wait for Extremes: Focus on signals in overbought (>80) or oversold (<20) zones
- Confirm with Crossovers: Wait for FastK/FastD crossover for stronger confirmation
- Check Multiple Timeframes: Align signals across timeframes
- Combine with Volume: Stronger signals when accompanied by volume confirmation
- Set Realistic Targets: StochRSI is for timing, not for predicting magnitude
- Use Stop Losses: Protect against false signals with appropriate stops
Related Indicators¶
- RSI - Base indicator for StochRSI calculation
- Stochastic - Original Stochastic formula
- MACD - Complementary momentum indicator
- MFI - Volume-weighted RSI variant