Strategy vault / Mean reversion
Reversal Trading Strategy Based on Stochastic RSI
This strategy is named "Reversal Trading Strategy Based on Stochastic RSI". It uses the Stochastic RSI indicator to identify overbought/oversold situations, entering reverse trades when extremes reverse. The…
This strategy is named "Reversal Trading Strategy Based on Stochastic RSI". It uses the Stochastic RSI indicator to identify overbought/oversold situations, entering reverse trades when extremes reverse.
The Stochastic RSI calculates the Stochastic oscillator on RSI values, generating K and D line signals that reflect overbought/oversold conditions in the RSI itself.
The trading logic is:
Calculate fast RSI to capture overbought/oversold.
Apply a weighted moving average on RSI to derive Stochastic RSI K-line signal.
When K-line crosses above its moving average, a buy signal is generated. When crossing below, a sell signal is generated.
Reversal signals near overbought or oversold extremes hint at reversal trade opportunities.
The advantage of this strategy is using Stochastic RSI to identify reversal points. But parameter combinations need optimization, and overtrading should be prevented. Stop loss is also essential.
In conclusion, Stochastic RSI is a common and useful way to determine reversal timing. But traders still need overall trend judgment to avoid buying tops and selling bottoms in retracements.
Parameters
| Name | Default | What it controls |
|---|---|---|
| v_input_1 | true | Use Heikin Ashi Candles in Algo Calculations |
| v_input_2 | true | From Month |
| v_input_3 | true | From Day |
| v_input_4 | 2021 | From Year |
| v_input_5 | 12 | Thru Month |
| v_input_6 | 30 | Thru Day |
| v_input_7 | 2021 | Thru Year |
| v_input_8 | true | Show Date Range |
| v_input_9_close | 0 | Source: close | high | low | open | hl2 | hlc3 | hlcc4 | ohlc4 |
| v_input_10 | 80 | TopBand |
| v_input_11 | 20 | LowBand |
| v_input_12 | 2 | RSI Length |
| v_input_13 | 50 | MA Length |
| v_input_14 | 5 | RSI MA Length |
| v_input_15 | 0 | MA Type: LRC | EMA | DEMA | TEMA | SMA | WMA | MF | VAMA | TMA | HMA | JMA | Kijun v2 | EDSMA | McGinley |
| v_input_16 | 0 | RSI MA Type: TMA | EMA | DEMA | TEMA | LRC | WMA | MF | VAMA | SMA | HMA | JMA | Kijun v2 | EDSMA | McGinley |
| v_input_17 | true | Kijun MOD Divider |
| v_input_18 | 3 | * Jurik (JMA) Only - Phase |
| v_input_19 | true | * Jurik (JMA) Only - Power |
| v_input_20 | 10 | * Volatility Adjusted (VAMA) Only - Volatility lookback length |
| v_input_21 | 0.8 | Modular Filter, General Filter Only - Beta |
| v_input_22 | false | Modular Filter Only - Feedback |
| v_input_23 | 0.5 | Modular Filter Only - Feedback Weighting |
| v_input_24 | 20 | EDSMA - Super Smoother Filter Length |
| v_input_25 | 0 | EDSMA - Super Smoother Filter Poles: 2 | 3 |
Source Pine Script
/*backtest
start: 2023-09-05 00:00:00
end: 2023-09-12 00:00:00
period: 5m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © MightyZinger
//@version=4
strategy(shorttitle="MZ SRSI",title="MightyZinger SRSI Strategy", overlay=false, pyramiding=1, calc_on_order_fills=true, calc_on_every_tick=true, default_qty_type=strategy.fixed, default_qty_value=5,commission_value=0.1)
//heiking ashi calculation
UseHAcandles = input(true, title="Use Heikin Ashi Candles in Algo Calculations")
////
// === /INPUTS ===
// === BASE FUNCTIONS ===
haClose = UseHAcandles ? security(heikinashi(syminfo.tickerid), timeframe.period, close) : close
haOpen = UseHAcandles ? security(heikinashi(syminfo.tickerid), timeframe.period, open) : open
haHigh = UseHAcandles ? security(heikinashi(syminfo.tickerid), timeframe.period, high) : high
haLow = UseHAcandles ? security(heikinashi(syminfo.tickerid), timeframe.period, low) : low
//Backtest dates
fromMonth = input(defval = 1, title = "From Month", type = input.integer, minval = 1, maxval = 12)
fromDay = input(defval = 1, title = "From Day", type = input.integer, minval = 1, maxval = 31)
fromYear = input(defval = 2021, title = "From Year", type = input.integer, minval = 1970)
thruMonth = input(defval = 12, title = "Thru Month", type = input.integer, minval = 1, maxval = 12)
thruDay = input(defval = 30, title = "Thru Day", type = input.integer, minval = 1, maxval = 31)
thruYear = input(defval = 2021, title = "Thru Year", type = input.integer, minval = 1970)
showDate = input(defval = true, title = "Show Date Range", type = input.bool)
start = timestamp(fromYear, fromMonth, fromDay, 00, 00) // backtest start window
finish = timestamp(thruYear, thruMonth, thruDay, 23, 59) // backtest finish window
window() => true // create function "within window of time"
src = UseHAcandles ? haClose : input(close, title="Source")
TopBand = input(80, step=0.01)
LowBand = input(20, step=0.01)
lengthRSI = input(2, minval=1,title="RSI Length")
lengthMA = input(50, minval=1,title="MA Length")
lengthRSI_MA= input(5, minval=1,title="RSI MA Length")
//RSI Source
maType = input(title="MA Type", type=input.string, defval="LRC", options=["SMA","EMA","DEMA","TEMA","LRC","WMA","MF","VAMA","TMA","HMA", "JMA", "Kijun v2", "EDSMA","McGinley"])
rsiMaType = input(title="RSI MA Type", type=input.string, defval="TMA", options=["SMA","EMA","DEMA","TEMA","LRC","WMA","MF","VAMA","TMA","HMA", "JMA", "Kijun v2", "EDSMA","McGinley"])
//MA Function
// Pre-reqs
//
tema(src, len) =>
ema1 = ema(src, len)
ema2 = ema(ema1, len)
ema3 = ema(ema2, len)
(3 * ema1) - (3 * ema2) + ema3
kidiv = input(defval=1,maxval=4, title="Kijun MOD Divider")
jurik_phase = input(title="* Jurik (JMA) Only - Phase", type=input.integer, defval=3)
jurik_power = input(title="* Jurik (JMA) Only - Power", type=input.integer, defval=1)
volatility_lookback = input(10, title="* Volatility Adjusted (VAMA) Only - Volatility lookback length")
// MF
beta = input(0.8,minval=0,maxval=1,step=0.1, title="Modular Filter, General Filter Only - Beta")
feedback = input(false, title="Modular Filter Only - Feedback")
z = input(0.5,title="Modular Filter Only - Feedback Weighting",step=0.1, minval=0, maxval=1)
//EDSMA
ssfLength = input(title="EDSMA - Super Smoother Filter Length", type=input.integer, minval=1, defval=20)
ssfPoles = input(title="EDSMA - Super Smoother Filter Poles", type=input.integer, defval=2, options=[2, 3])
//----
// EDSMA
get2PoleSSF(src, length) =>
PI = 2 * asin(1)
arg = sqrt(2) * PI / length
a1 = exp(-arg)
b1 = 2 * a1 * cos(arg)
c2 = b1
c3 = -pow(a1, 2)
c1 = 1 - c2 - c3
ssf = 0.0
ssf := c1 * src + c2 * nz(ssf[1]) + c3 * nz(ssf[2])
get3PoleSSF(src, length) =>
PI = 2 * asin(1)
arg = PI / length
a1 = exp(-arg)
b1 = 2 * a1 * cos(1.738 * arg)
c1 = pow(a1, 2)
coef2 = b1 + c1
coef3 = -(c1 + b1 * c1)
coef4 = pow(c1, 2)
coef1 = 1 - coef2 - coef3 - coef4
ssf = 0.0
ssf := coef1 * src + coef2 * nz(ssf[1]) + coef3 * nz(ssf[2]) + coef4 * nz(ssf[3])
// MA Main function
ma(type, src, len) =>
float result = 0
if type=="TMA"
result := sma(sma(src, ceil(len / 2)), floor(len / 2) + 1)
if type=="MF"
ts=0.,b=0.,c=0.,os=0.
//----
alpha = 2/(len+1)
a = feedback ? z*src + (1-z)*nz(ts[1],src) : src
//----
b := a > alpha*a+(1-alpha)*nz(b[1],a) ? a : alpha*a+(1-alpha)*nz(b[1],a)
c := a < alpha*a+(1-alpha)*nz(c[1],a) ? a : alpha*a+(1-alpha)*nz(c[1],a)
os := a == b ? 1 : a == c ? 0 : os[1]
//----
upper = beta*b+(1-beta)*c
lower = beta*c+(1-beta)*b
ts := os*upper+(1-os)*lower
result := ts
if type=="LRC"
result := linreg(src, len, 0)
if type=="SMA" // Simple
result := sma(src, len)
if type=="EMA" // Exponential
result := ema(src, len)
if type=="DEMA" // Double Exponential
e = ema(src, len)
result := 2 * e - ema(e, len)
if type=="TEMA" // Triple Exponential
e = ema(src, len)
result := 3 * (e - ema(e, len)) + ema(ema(e, len), len)
if type=="WMA" // Weighted
result := wma(src, len)
if type=="VAMA" // Volatility Adjusted
/// Copyright © 2019 to present, Joris Duyck (JD)
mid=ema(src,len)
dev=src-mid
vol_up=highest(dev,volatility_lookback)
vol_down=lowest(dev,volatility_lookback)
result := mid+avg(vol_up,vol_down)
if type=="HMA" // Hull
result := wma(2 * wma(src, len / 2) - wma(src, len), round(sqrt(len)))
if type=="JMA" // Jurik
/// Copyright © 2018 Alex Orekhov (everget)
/// Copyright © 2017 Jurik Research and Consulting.
phaseRatio = jurik_phase < -100 ? 0.5 : jurik_phase > 100 ? 2.5 : jurik_phase / 100 + 1.5
beta = 0.45 * (len - 1) / (0.45 * (len - 1) + 2)
alpha = pow(beta, jurik_power)
jma = 0.0
e0 = 0.0
e0 := (1 - alpha) * src + alpha * nz(e0[1])
e1 = 0.0
e1 := (src - e0) * (1 - beta) + beta * nz(e1[1])
e2 = 0.0
e2 := (e0 + phaseRatio * e1 - nz(jma[1])) * pow(1 - alpha, 2) + pow(alpha, 2) * nz(e2[1])
jma := e2 + nz(jma[1])
result := jma
if type=="Kijun v2"
kijun = avg(lowest(len), highest(len))//, (open + close)/2)
conversionLine = avg(lowest(len/kidiv), highest(len/kidiv))
delta = (kijun + conversionLine)/2
result :=delta
if type=="McGinley"
mg = 0.0
mg := na(mg[1]) ? ema(src, len) : mg[1] + (src - mg[1]) / (len * pow(src/mg[1], 4))
result :=mg
if type=="EDSMA"
zeros = src - nz(src[2])
avgZeros = (zeros + zeros[1]) / 2
// Ehlers Super Smoother Filter
ssf = ssfPoles == 2
? get2PoleSSF(avgZeros, ssfLength)
: get3PoleSSF(avgZeros, ssfLength)
// Rescale filter in terms of Standard Deviations
stdev = stdev(ssf, len)
scaledFilter = stdev != 0
? ssf / stdev
: 0
alpha = 5 * abs(scaledFilter) / len
edsma = 0.0
edsma := alpha * src + (1 - alpha) * nz(edsma[1])
result := edsma
result
//Indicator
hline(TopBand, color=color.red,linestyle=hline.style_dotted, linewidth=2)
hline(LowBand, color=color.green, linestyle=hline.style_dashed, linewidth=2)
// RSI Definition
rsiSource = ma(maType, src , lengthMA)
frsi = rsi(rsiSource, lengthRSI)
fsma = ma(rsiMaType, frsi , lengthRSI_MA)
plot(frsi,title='frsi', color= color.lime, linewidth=3)
fsmaColor=color.new(color.red, 80)
plot(fsma,title='fsma', color= fsmaColor , linewidth=3, style=plot.style_area)
//Background
bgcolor(frsi > fsma ? color.lime : color.orange, 80)
longcondition = crossover (frsi , fsma)
shortcondition = crossunder(frsi , fsma)
////////////////////////////////
//if (longcondition)
// strategy.entry("BUY", strategy.long, when = window())
//if (shortcondition)
// strategy.close("SELL", strategy.short, when = window())
strategy.entry(id="long", long = true, when = longcondition and window())
strategy.close("long", when = shortcondition and window())Published by ChaoZhang on the FMZ strategy square · last modified 2023-09-13. Collected in the Quant Trading Vault. Unvalidated research: re-test with your own data and costs before trusting it.
Build this with AgenKit
A spec is not a trading system. Paste this into your coding agent and AgenKit runs a specialist team — architecture, test-first build, risk gates, review — with paper trading on by default.
/agenkit build a production-grade trading bot with a backtest engine, risk controls and paper trading by default from strategies/Reversal-Trading-Strategy-Based-on-Stochastic-RSI.md- npx agenkit install engineering-kit in your project
- Paste the command into your agent and approve each phase
- Get tests, backtest, risk controls and a paper-trading switch
Understand it first
Before you run this, read the lesson behind the idea and how to backtest it honestly. Specs like this one are the survivors of an unknown number of trials; deflate their results accordingly.
Related specs
- Market Cypher Wave B Automated Trading StrategyPine Script · Mean reversion · 1h
- Multi Indicator Trend Reversal Trading StrategyPine Script · Mean reversion · 1h
- Advanced 15 Minute Chart Trading Signal StrategyPine Script · Mean reversion · 3h
- Dynamic Adaptive Multi Timeframe Trend Following and Range Reversal Hybrid StrategyPine Script · Mean reversion · 2d
- Oma and Apollo Dual Rail Trading StrategyPine Script · Mean reversion · 5m
- 3EMA with Stochastic RSI StrategyPine Script · Mean reversion · 1h