La idea central de esta estrategia es hacer que el ciclo de suavización del RSI sea dinámico, ajustándose automáticamente según la correlación entre el precio y la dinámica, lo que mejora la utilidad del RSI.
La estrategia primero calcula la dinámica de los precios, y luego calcula el coeficiente de correlación entre el precio y la dinámica. Cuando el coeficiente de correlación es cercano a 1, el precio y la dinámica están altamente correlacionados positivamente; cuando el coeficiente de correlación es cercano a 1, el precio y la dinámica están altamente correlacionados negativamente.
La longitud de los ciclos suavizados del RSI se puede ajustar según la correlación entre el precio y la dinámica. Cuando la correlación es alta, se usa un ciclo RSI más corto; cuando la correlación es baja, se usa un ciclo RSI más largo.
En concreto, esta estrategia establece la longitud del ciclo RSI en un rango de 20 a 50 por defecto. Después de calcular los coeficientes relacionados con el precio y la dinámica, el coeficiente correspondiente se mapea a este rango de 20 a 50 mediante el método de mapeo lineal como la longitud del ciclo de suavizado final del RSI.
Esto permite ajustar automáticamente los parámetros del indicador RSI en función de las condiciones del mercado, utilizando un RSI más corto cuando los cambios de precio y los cambios de dinámica están fuertemente relacionados, lo que lo hace más sensible; y un RSI más largo cuando la correlación no es fuerte, para reducir el impacto del ruido en la señal.
La estrategia vale la pena aprender la idea de ajustar dinámicamente el ciclo de suavización del RSI, pero en la implementación concreta hay mucho espacio para mejorar. La clave es encontrar los factores decisivos que afectan la elección de los parámetros del RSI y convertirlos en indicadores cuantificables. Al mismo tiempo, no depender completamente de los modelos, también es necesario optimizar el rango de parámetros en función de la experiencia y la retroalimentación.
/*backtest
start: 2023-09-06 00:00:00
end: 2023-10-06 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=5
strategy("Dynamic RSI Momentum", "DRM Strategy", process_orders_on_close = true, default_qty_type = strategy.percent_of_equity, default_qty_value = 50 )
// +++++++++++++++++++++
// ++ INPUT ++
// +++++++++++++++++++++
// Momentum
len = input.int(10, "Momentum Length", 1, group = "Dynamic RSI Momentum")
src = input.source(close, "Source", group = "Dynamic RSI Momentum")
min_rsi = input.int(20, "Min RSI", group = "Dynamic RSI Momentum")
max_rsi = input.int(50, "Max RSI", group = "Dynamic RSI Momentum")
upLvl = input.float(70, "OverBought", 0, 100, group = "Dynamic RSI Momentum")
dnLvl = input.float(30, "OverSold", 0, 100, group = "Dynamic RSI Momentum")
// +++++++++++++++++++++
// ++ CALCULATION ++
// +++++++++++++++++++++
// RMA Function
rmaFun(src, len) =>
sma = ta.sma(src, len)
alpha = 1/len
sum = 0.0
sum := na(sum[1]) ? sma : alpha * src + (1 - alpha) * nz(sum[1])
// RSI Function
rsiFun(src, len) =>
100 - 100 / (1 + rmaFun(src - src[1] > 0 ? src - src[1] : 0, len) /
rmaFun(src[1] - src > 0 ? src[1] - src : 0, len))
// Momentum
momVal = src - src[len]
// Calculation Price vs Momentum
corr = ta.correlation(src, momVal, len)
corr := corr > 1 or corr < -1 ? float(na) : corr
rsiLen = 0
rsiLen := int(min_rsi + nz(math.round((1 - corr) * (max_rsi-min_rsi) / 2, 0), 0))
rsiMom = rsiFun(src, rsiLen)
// +++++++++++++++++++++
// ++ STRATEGY ++
// +++++++++++++++++++++
long = ta.crossover(rsiMom, dnLvl)
short = ta.crossunder(rsiMom, upLvl)
// +++> Long <+++++
if long and not na(rsiMom)
strategy.entry("Long", strategy.long)
// +++> Short <+++++
if short and not na(rsiMom)
strategy.entry("Short", strategy.short)
// +++++++++++++++++++++
// ++ PLOT ++
// +++++++++++++++++++++
plot(rsiMom, "Dynamic RSI Momentum", rsiMom < dnLvl ? color.green : rsiMom > upLvl ? color.red : color.yellow)
hline(50, "Mid Line", color.gray)
upperLine = hline(upLvl, "Upper Line", color.gray)
lowerLine = hline(dnLvl, "Lower Line", color.gray)
fill(upperLine, lowerLine, color.new(color.purple, 90), "Background Fill")