本策略是一个基于多种移动平均线交叉信号的量化交易系统。它融合了七种不同类型的移动平均线指标,包括简单移动平均线(SMA)、指数移动平均线(EMA)、加权移动平均线(WMA)、成交量加权移动平均线(VWMA)、赫尔移动平均线(HMA)、平滑移动平均线(RMA)和阿诺德勒古斯移动平均线(ALMA)。策略支持两线或三线交叉系统,并可根据市场情况灵活选择做多和做空。
策略的核心逻辑是通过观察不同周期移动平均线之间的交叉关系来判断市场趋势。当快速移动平均线向上穿越慢速移动平均线时,产生做多信号;反之则产生做空信号。系统提供了两种入场方式:一是基于移动平均线的直接交叉,二是基于收盘价相对于移动平均线的位置关系。三线系统则通过引入中期移动平均线,增加了信号的可靠性和稳定性。
该策略是一个全面的趋势跟踪系统,通过融合多种移动平均线指标和灵活的参数设置,为交易者提供了一个可靠的量化交易框架。虽然存在一定的滞后性,但通过合理的参数优化和风险控制措施,策略仍然具有较好的实用价值。建议交易者在实盘中根据具体市场特点进行针对性优化。
/*backtest
start: 2019-12-23 08:00:00
end: 2025-01-04 08:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=5
strategy("Cruce de Medias Total", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=100,max_bars_back=1000)
// Parámetros de entrada
periodo_rapida = input.int(50, title="Periodos para media rápida", minval=1)
periodo_lenta = input.int(200, title="Periodos para media lenta", minval=1)
// Selección del tipo de media móvil
tipo_de_media = input.string(title="Elige el tipo de media móvil", defval="Simple sma", options=["Simple sma", "Exponencial ema", "Ponderada wma", "Volumen ponderada vwma", "Hull hma", "Media suavizada rma", "Media de Arnaud Legoux alma"])
// Posibilidad de estrategia con cruce de tres medias móviles
tres_medias = input.bool(false, title="Estrategia con cruce de 3 medias móviles")
periodo_media = input.int(100, title="Periodos para media media", minval=1)
// Opción de operar en corto
permitir_corto = input.bool(false, title="Permitir operaciones en corto")
// Opción de cuando comprar
cuando_comprar = input.string(title="Cuando comprar", defval="Cruce de medias", options=["Vela anterior cierra por encima de las medias", "Cruce de medias"])
// Opción de cuando vender
cuando_vender = input.string(title="Cuando vender", defval="Cruce de medias", options=["Vela anterior cierra por debajo de las medias", "Cruce de medias"])
float media_mov_rapida = na
float media_mov_media = na
float media_mov_lenta = na
// Definición de las medias móviles
if tipo_de_media == "Simple sma"
media_mov_rapida := ta.sma(close, periodo_rapida)
media_mov_media := ta.sma(close, periodo_media)
media_mov_lenta := ta.sma(close, periodo_lenta)
else if tipo_de_media == "Exponencial ema"
media_mov_rapida := ta.ema(close, periodo_rapida)
media_mov_media := ta.ema(close, periodo_media)
media_mov_lenta := ta.ema(close, periodo_lenta)
else if tipo_de_media == "Ponderada wma"
media_mov_rapida := ta.wma(close, periodo_rapida)
media_mov_media := ta.wma(close, periodo_media)
media_mov_lenta := ta.wma(close, periodo_lenta)
else if tipo_de_media == "Volumen ponderada vwma"
media_mov_rapida := ta.vwma(close, periodo_rapida)
media_mov_media := ta.vwma(close, periodo_media)
media_mov_lenta := ta.vwma(close, periodo_lenta)
else if tipo_de_media == "Hull hma"
media_mov_rapida := ta.hma(close, periodo_rapida)
media_mov_media := ta.hma(close, periodo_media)
media_mov_lenta := ta.hma(close, periodo_lenta)
else if tipo_de_media == "Media suavizada rma"
media_mov_rapida := ta.rma(close, periodo_rapida)
media_mov_media := ta.rma(close, periodo_media)
media_mov_lenta := ta.rma(close, periodo_lenta)
else if tipo_de_media == "Media de Arnaud Legoux alma"
offset = input.int(0, title="Desfase para ALMA", minval=-100, maxval=100)
sigma = input.float(6, title="Sigma para ALMA", minval=0.1, maxval=10)
media_mov_rapida := ta.alma(close, periodo_rapida, offset, sigma)
media_mov_media := ta.alma(close, periodo_media, offset, sigma)
media_mov_lenta := ta.alma(close, periodo_lenta, offset, sigma)
// Graficar las medias móviles en el gráfico
plot_rapida = plot(media_mov_rapida, color=color.green, linewidth=2, title="Media Móvil Rápida")
plot_media = plot(tres_medias ? media_mov_media : na, color=color.blue, linewidth=2, title="Media Móvil Media")
plot_lenta = plot(media_mov_lenta, color=color.red, linewidth=2, title="Media Móvil Lenta")
// Rellenar el área entre las medias móviles con color condicionado
fill(plot_rapida, plot_lenta, media_mov_rapida > media_mov_lenta ? color.new(color.green, 90) : color.new(color.red, 90), title="Relleno entre Medias")
// Lógica de la estrategia para cruce de medias
comprado = strategy.position_size > 0 // Verifica si ya hay una posición abierta
vendido = strategy.position_size < 0
if not comprado // Solo compra si no hay una posición abierta
if tres_medias and cuando_comprar == "Cruce de medias"
if media_mov_rapida > media_mov_media and media_mov_media > media_mov_lenta
strategy.entry("Largo", strategy.long)
label.new(bar_index, low, "Largo", style=label.style_label_up, color=color.green, textcolor=color.white)
else if not tres_medias and cuando_comprar == "Cruce de medias"
if ta.crossover(media_mov_rapida, media_mov_lenta)
strategy.entry("Largo", strategy.long)
label.new(bar_index, low, "Largo", style=label.style_label_up, color=color.green, textcolor=color.white)
else if tres_medias and cuando_comprar == "Vela anterior cierra por encima de las medias"
if close[1] > media_mov_rapida and close[1] > media_mov_media and close[1] > media_mov_lenta
strategy.entry("Largo", strategy.long)
label.new(bar_index, low, "Largo", style=label.style_label_up, color=color.green, textcolor=color.white)
else if not tres_medias and cuando_comprar == "Vela anterior cierra por encima de las medias"
if close[1] > media_mov_rapida and close[1] > media_mov_lenta
strategy.entry("Largo", strategy.long)
label.new(bar_index, low, "Largo", style=label.style_label_up, color=color.green, textcolor=color.white)
// Condición de cierre de la posición
if comprado
if tres_medias and cuando_vender == "Cruce de medias"
if media_mov_rapida < media_mov_media and media_mov_media < media_mov_lenta
strategy.close("Largo")
label.new(bar_index, high, "Cierre Largo", style=label.style_label_down, color=color.red, textcolor=color.white)
else if not tres_medias and cuando_vender == "Cruce de medias"
if ta.crossunder(media_mov_rapida, media_mov_lenta)
strategy.close("Largo")
label.new(bar_index, high, "Cierre Largo", style=label.style_label_down, color=color.red, textcolor=color.white)
else if tres_medias and cuando_vender == "Vela anterior cierra por debajo de las medias"
if close[1] < media_mov_rapida and close[1] < media_mov_media and close[1] < media_mov_lenta
strategy.close("Largo")
label.new(bar_index, high, "Cierre Largo", style=label.style_label_down, color=color.red, textcolor=color.white)
else if not tres_medias and cuando_vender == "Vela anterior cierra por debajo de las medias"
if close[1] < media_mov_rapida and close[1] < media_mov_lenta
strategy.close("Largo")
label.new(bar_index, high, "Cierre Largo", style=label.style_label_down, color=color.red, textcolor=color.white)
// Condición de entrar en corto
if not vendido and permitir_corto
if tres_medias
if media_mov_rapida < media_mov_media and media_mov_media < media_mov_lenta
strategy.entry("Short", strategy.short)
label.new(bar_index, low, "Short", style=label.style_label_up, color=color.blue, textcolor=color.white)
else
if ta.crossunder(media_mov_rapida, media_mov_lenta)
strategy.entry("Short", strategy.short)
label.new(bar_index, low, "Short", style=label.style_label_up, color=color.blue, textcolor=color.white)
// Condición de cierre de posición corta
if vendido
if tres_medias
if media_mov_rapida > media_mov_media and media_mov_media > media_mov_lenta
strategy.close("Short")
label.new(bar_index, high, "Cierre Short", style=label.style_label_down, color=color.purple, textcolor=color.white)
else
if ta.crossover(media_mov_rapida, media_mov_lenta)
strategy.close("Short")
label.new(bar_index, high, "Cierre Short", style=label.style_label_down, color=color.purple, textcolor=color.white)