Estrategia de negociación cruzada de medias móviles dinámicas

El autor:¿ Qué pasa?, Fecha: 2023-11-13 10:27:54
Las etiquetas:

img

Resumen general

La idea clave de esta estrategia es construir múltiples promedios móviles basados en el indicador Ratio OCHL Averager de diferentes marcos de tiempo y generar señales comerciales basadas en el cruce.

Estrategia lógica

La estrategia utiliza dos indicadores de promedio de OCHL con diferentes marcos de tiempo como las líneas rápidas y lentas.

b = abs(close-open)/(high - low)
c = min(max(b, 0), 1)  
Ratio OCHL Averager = c*close + (1-c)*previous Ratio OCHL Averager

Aquí b representa el índice de movimiento de precios intradiario y c es el b normalizado. El Ratio OCHL Averager incorpora precios abiertos, cerrados, altos y bajos para construir el promedio móvil.

La estrategia establece un período más corto para la línea rápida y un período más largo para la línea lenta. Una señal de compra se genera cuando la línea rápida cruza por encima de la línea lenta, y una señal de venta cuando la línea rápida cruza por debajo. Captura la tendencia por la lógica de cruce de la media móvil.

Ventajas

  1. El Ratio OCHL Averager suaviza los datos de precios y filtra el ruido del mercado, lo que hace que la señal de negociación sea más confiable.

  2. El cruce de dos medias móviles combinado con diferentes plazos permite detectar mejor el inicio de una nueva tendencia.

  3. Los períodos de la línea rápida y lenta pueden ajustarse a las diferentes condiciones del mercado.

  4. La lógica de la estrategia es simple e intuitiva, fácil de entender e implementar.

  5. El stop loss y el take profit se pueden establecer de forma flexible para controlar los riesgos.

Los riesgos

  1. El cruce de la media móvil puede generar señales falsas excesivas y puede ser necesario utilizar otros indicadores técnicos para filtrar.

  2. Los períodos de la línea rápida y lenta deben elegirse razonablemente, de lo contrario pueden afectar al rendimiento de la estrategia.

  3. Se trata de una estrategia de seguimiento de tendencias no adecuada para el mercado de rango limitado.

  4. El stop loss y el take profit deben ajustarse adecuadamente para reducir las pérdidas y optimizar el nivel de ganancia.

Direcciones de optimización

  1. Considere combinar indicadores de impulso como MACD, KDJ para filtrar la señal y mejorar la calidad.

  2. Prueba diferentes combinaciones de períodos de línea rápida y lenta para encontrar los parámetros óptimos.

  3. Optimice el stop loss y tome ganancias basándose en los resultados de las pruebas de retroceso.

  4. Considere ajustar dinámicamente los parámetros en determinadas condiciones de mercado, por ejemplo, aumentar el período en un mercado de rango.

Conclusión

La estrategia tiene una lógica clara de usar cruce de promedio móvil rápido y lento para determinar la dirección de la tendencia. Es una estrategia de tendencia dinámica adecuada para la negociación a mediano plazo. Todavía hay mucho espacio para la optimización por ajuste de parámetros, filtración de señales, etc. En general, es una estrategia de negociación de tendencia flexible y práctica.


/*backtest
start: 2023-11-05 00:00:00
end: 2023-11-12 00:00:00
period: 3m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
strategy(title="[XC] Adaptive Strategy V3 - Ratio OCHL Averager no repaint",shorttitle="R_OHCL", overlay=true, currency=currency.EUR,initial_capital=10000,
     default_qty_value=100, default_qty_type=strategy.percent_of_equity , calc_on_every_tick=false, calc_on_order_fills=true)


//                  ╔═ SETTINGS                  ╗
//░░░░░░░░░░░░░░░░░ ╚════════════════════════════╝ ░░░░░░░░░░░░░░░░░░░░░░░░

strategy_1     = input ( defval=true   , type=input.bool    , title="STRATEGY 1? —>"      )
Recursive      = input(false)
RES201         = "Min",RES202= "D",RES203 = "W",RES204 = "M"

//++ Resolution 1 ++
inp_resolution1 = input(600, minval=1, title="Resolution Line 1")
restype1        = input ( defval="Min"  , type=input.string , title= "Resolution Line 1" , options=[ "Min","D","W","M"])
multiplier1     = restype1 == "Min" ? "" : restype1 == "D" ? "D" : restype1 == "W" ? "W" : "M"
resolution1     = tostring(inp_resolution1)+ multiplier1

//++ Resolution 2 ++
inp_resolution2 = input(1440, minval=1, title="Resolution Line 2")
restype2        = input ( defval="Min"  , type=input.string , title= "Resolution Line 2" , options=["Min","D","W","M"])
multiplier2     = restype2 == "Min" ? "" : restype2 == "D" ? "D" : restype2 == "W" ? "W" : "M"
resolution2     = tostring(inp_resolution2)+ multiplier2

StopLoss        = input(defval = 500 , title = "Stop Loss", minval = 0)
TakeProfit      = input(defval = 2500 , title = "Take Profit", minval = 0)
// === RISK MANAGEMENT VALUE PREP ===
// if an input is less than 1, assuming not wanted so we assign 'na' value to disable it.
useTakeProfit   = TakeProfit  >= 1 ? TakeProfit  : na
useStopLoss     = StopLoss    >= 1 ? StopLoss    : na


//                  ╔═ BACKTEST RANGE            ╗
//░░░░░░░░░░░░░░░░░ ╚════════════════════════════╝ ░░░░░░░░░░░░░░░░░░░░░░░░
line_breakBTR  = input ( defval = true   , type=input.bool   , title="BACKTEST RANGE —"      ) 
FromYear       = input ( defval = 2019, title = "From Year", minval = 2017)
FromMonth      = input ( defval = 1, title = "From Month", minval = 1, maxval = 12)
FromDay        = input ( defval = 2, title = "From Day", minval = 1, maxval = 31)
//FromHour     = input ( defval = 1, title = "From Hour", minval = 1, maxval = 24)
ToYear         = input ( defval = 9999, title = "To Year", minval = 2017)
//ToHour       = input ( defval = 0, title = "From Hour", minval = 0, maxval = 24)
ToMonth        = input ( defval = 1, title = "To Month", minval = 1, maxval = 12)
ToDay          = input ( defval = 1, title = "To Day", minval = 1, maxval = 31)

// === FUNCTION EXAMPLE ===
start     = timestamp(syminfo.timezone, FromYear, FromMonth, FromDay, 0, 00)  // backtest start window
finish    = timestamp(syminfo.timezone, ToYear  , ToMonth  , ToDay  , 0, 59)  // backtest finish window
window()  => time >= start and time <= finish ? true : false // create function "within window of time"

//                  ╔═ INDICATOR                 ╗
//░░░░░░░░░░░░░░░░░ ╚════════════════════════════╝ ░░░░░░░░░░░░░░░░░░░░░░░░

// "Ratio OCHL Averager" -> alexgrover / tradingview.com/script/RGAtOI6h-Ratio-OCHL-Averager-An-Alternative-to-VWAP/

rochla( res,Recursive)=>
    //Recursive = false
    H =  security(syminfo.tickerid,res,high[1],gaps = barmerge.gaps_off,  lookahead = barmerge.lookahead_on)
    L =  security(syminfo.tickerid,res,low[1] ,gaps = barmerge.gaps_off,  lookahead = barmerge.lookahead_on)
    d = 0.
    //----
    a = Recursive ? nz(d[1],open) : open
    b = abs(close-a)/(H - L)
    c = b > 1 ? 1 : b
    d := c*close+(1-c)*nz(d[1],close)



strat1_line1=rochla(resolution1,Recursive)
strat1_line2=rochla(resolution2,Recursive)

plot(strat1_line1, title="Ratio OCHL Averager 1", color=#DAA520,linewidth=2,transp=0)
plot(strat1_line2, title="Ratio OCHL Averager 2", color=#B22222,linewidth=2,transp=0)



//                  ╔═ STRATEGY 1                ╗
//░░░░░░░░░░░░░░░░░ ╚════════════════════════════╝ ░░░░░░░░░░░░░░░░░░░░░░░░

trading_strat1_line1 = strategy_1 == 1    ? strat1_line1   : na
trading_strat1_line2 = strategy_1 == 1    ? strat1_line2   : na

longCross  = crossunder (trading_strat1_line2, trading_strat1_line1) ? true : false
shortCross = crossover  (trading_strat1_line2, trading_strat1_line1) ? true : false

plot( longCross  ? trading_strat1_line1 : na , title = "Long"  , color=color.aqua, style=plot.style_circles, linewidth=5, offset= 0)
plot( shortCross ? trading_strat1_line2 : na , title = "Short" , color=color.red , style=plot.style_circles, linewidth=5, offset= 0)



//                  ╔═ Backtest 1                ╗
//░░░░░░░░░░░░░░░░░ ╚════════════════════════════╝ ░░░░░░░░░░░░░░░░░░░░░░░░


strategy.exit("close",loss = useStopLoss, profit = useTakeProfit)

if longCross  and window() and strategy_1 == 1 
    strategy.entry("Go Long", strategy.long)
if shortCross and window() and strategy_1 == 1 
    strategy.entry("Go Short", strategy.short)

//end

Más.