La estrategia de doble EMA Crossover es una estrategia de seguimiento de tendencias comúnmente utilizada. Utiliza dos líneas EMA con períodos diferentes y genera señales de compra cuando la EMA de período más corto cruza la EMA de período más largo y señales de venta cuando ocurre lo contrario, con el fin de capturar los cambios de tendencia.
La lógica central de esta estrategia se basa en los principios de la cruz de oro y la cruz de muerte de las líneas EMA. La EMA puede suavizar los datos de precios de manera efectiva e indicar la dirección de la tendencia. La EMA de período más corto responde más rápidamente a los cambios de precios, mientras que la EMA de período más largo es menos sensible al ruido y refleja la tendencia a largo plazo. Cuando la EMA de período más corto cruza la EMA de período más largo, se considera una señal de que el impulso al alza se está fortaleciendo. Cuando sucede lo contrario, indica una aceleración del impulso a la baja.
Específicamente, esta estrategia utiliza los parámetros de longitud1 y longitud2 para establecer los períodos de dos líneas EMA. demaVal1 es el período de longitud1 y demaVal2 es el período de longitud2.
demaVal1 = EMA(close, length1)
demaVal2 = EMA(close, length2)
Cuando demaVal1 cruza demaVal2, se genera la señal de compra demaCrossover. Cuando sucede lo contrario, se genera la señal de venta demaCrossunder. La estrategia envía órdenes de negociación basadas en estas dos señales.
Las ventajas de esta estrategia incluyen:
También hay algunos riesgos asociados con esta estrategia:
Sobre la base de los riesgos mencionados anteriormente, se podrían optimizar los siguientes aspectos:
En conclusión, la Estrategia Dual EMA Crossover es un sistema simple pero práctico de seguimiento de tendencias. Al heredar las teorías maduras del análisis EMA y con el ajuste adecuado de parámetros y mejoras de la condición del filtro, se puede aplicar al comercio de tendencias en diferentes instrumentos con buenas perspectivas de aplicación.
/*backtest start: 2022-11-29 00:00:00 end: 2023-12-05 00:00:00 period: 1d basePeriod: 1h 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/ // © zeguela //@version=4 strategy(title="ZEGUELA DEMABOT", commission_value=0.063, commission_type=strategy.commission.percent, initial_capital=100, default_qty_value=90, default_qty_type=strategy.percent_of_equity, overlay=true, process_orders_on_close=true) // Step 1. Script settings // Input options srcData = input(title="Source Data", type=input.source, defval=close) // Length settings len1 = input(title="Length DEMA #1", type=input.integer, defval=8, minval=1) len2 = input(title="Length DEMA #2", type=input.integer, defval=24, minval=0) len3 = input(title="Length DEMA #3", type=input.integer, defval=0, minval=0) // Step 2. Calculate indicator values // Function that calculates the DEMA DEMA(series, length) => if (length > 0) emaValue = ema(series, length) 2 * emaValue - ema(emaValue, length) else na // Calculate the DEMA values demaVal1 = DEMA(srcData, len1) demaVal2 = DEMA(srcData, len2) demaVal3 = DEMA(srcData, len3) // Step 3. Determine indicator signals // See if there's a DEMA crossover demaCrossover = if (len2 > 0) and (len3 > 0) crossover(demaVal1, demaVal2) and (demaVal3 > demaVal3[1]) else if (len2 > 0) and (len3 == 0) crossover(demaVal1, demaVal2) else if (len3 > 0) and (len2 == 0) crossover(demaVal1, demaVal3) else crossover(close, demaVal1) // Check if there's a DEMA crossunder demaCrossunder = if (len2 > 0) and (len3 > 0) crossunder(demaVal1, demaVal2) and (demaVal3 < demaVal3[1]) else if (len2 > 0) and (len3 == 0) crossunder(demaVal1, demaVal2) else if (len3 > 0) and (len2 == 0) crossunder(demaVal1, demaVal3) else crossunder(close, demaVal1) // Step 4. Output indicator data // Plot DEMAs on the chart plot(series=demaVal1, color=color.green, linewidth=2, title="DEMA #1") plot(series=demaVal2, color=color.red, linewidth=2, title="DEMA #2") plot(series=demaVal3, color=color.fuchsia, linewidth=2, title="DEMA #3") //TRAILING STOP CODE a = input(title="Usar Trailing Stop?", type=input.bool, defval=false) stopPerlong = input(9.0, title='Stop Loss Long %', type=input.float, group="Stop Loss & Take Profit Settings") / 100 stopPershort = input(6.0, title='Stop Loss Short %', type=input.float, group="Stop Loss & Take Profit Settings") / 100 take1Perlong = input(25.0, title='Take Profit Long % 1', type=input.float, group="Stop Loss & Take Profit Settings") / 100 take1Pershort = input(6.0, title='Take Profit Short % 1', type=input.float, group="Stop Loss & Take Profit Settings") / 100 // Determine stop loss price longStopPrice = strategy.position_avg_price * (1 - stopPerlong) shortStopPrice = strategy.position_avg_price * (1 + stopPershort) longTake1Price = strategy.position_avg_price * (1 + take1Perlong) shortTake1Price = strategy.position_avg_price * (1 - take1Pershort) // Determine trail stop loss prices longStopPriceTrail = 0.0 longStopPriceTrail := if (strategy.position_size > 0) stopValue = close * (1 - stopPerlong) max(stopValue, longStopPriceTrail[1]) else 0 // Determine trailing short price shortStopPriceTrail = 0.0 shortStopPriceTrail := if (strategy.position_size < 0) stopValue = close * (1 + stopPershort) min(stopValue, shortStopPriceTrail[1]) else 999999 //calcular qual stop usar longStop = a ? longStopPriceTrail : longStopPrice shortStop = a ? shortStopPriceTrail : shortStopPrice //calcula o valor do stop e TP pra lançar no alerta longStopEntrada = close * (1 - stopPerlong) shortStopEntrada = close * (1 + stopPershort) longTPEntrada = close * (1 + take1Perlong) shortTPEntrada = close * (1 - take1Pershort) //armazena o preço de entrada e valor do SL e TP price_entryL = 0.0 price_entryL := na(price_entryL) ? na : price_entryL[1] price_entryS = 0.0 price_entryS := na(price_entryS) ? na : price_entryS[1] stopL = 0.0 stopL := na(stopL) ? na : stopL[1] stopS = 0.0 stopS := na(stopS) ? na : stopS[1] takeL = 0.0 takeL := na(takeL) ? na : takeL[1] takeS = 0.0 takeS := na(takeS) ? na : takeS[1] if (demaCrossover) price_entryL := close stopL := close * (1 - stopPerlong) takeL := close * (1 + take1Perlong) if (demaCrossunder) price_entryS := close stopS := close * (1 + stopPershort) takeS := close * (1 - take1Pershort) resultadoL = ((close - price_entryL)/price_entryL) * 100 resultadoLexit = "(SL = 1% e TP = 0,5%)" resultadoS = ((price_entryS - close)/price_entryS) * 100 resultadoSexit = "(SL = 1% e TP = 0,5)%" // Make input options that configure backtest date range _startDate = input(title="Start Date", type=input.integer, defval=1, minval=1, maxval=31, group="BackTest Period") _startMonth = input(title="Start Month", type=input.integer, defval=1, minval=1, maxval=12, group="BackTest Period") _startYear = input(title="Start Year", type=input.integer, defval=2018, minval=1800, maxval=2100, group="BackTest Period") _endDate = input(title="End Date", type=input.integer, defval=31, minval=1, maxval=31, group="BackTest Period") _endMonth = input(title="End Month", type=input.integer, defval=12, minval=1, maxval=12, group="BackTest Period") _endYear = input(title="End Year", type=input.integer, defval=2031, minval=1800, maxval=2100, group="BackTest Period") // Look if the close time of the current bar // falls inside the date range _inDateRange = (time >= timestamp(syminfo.timezone, _startYear, _startMonth, _startDate, 0, 0)) and (time < timestamp(syminfo.timezone, _endYear, _endMonth, _endDate, 0, 0)) //Alert configuration _alertMessageOpenLong="OpenLong" _alertMessageCloseLong="CloseLong" _alertmessageExitLong="ExitLong - TP/SL" _alertMessageOpenShort="OpenShort" _alertMessageCloseShort="CloseShort" _alertMessageExitShort="ExitShort - TP/SL" if (_inDateRange) //ENTER SOME SETUP TRADES FOR TSL EXAMPLE if (demaCrossover) strategy.entry("LONG", strategy.long, comment = _alertMessageOpenLong) if (demaCrossunder) strategy.entry("SHORT", strategy.short, comment = _alertMessageOpenShort) //EXIT TRADE @ TSL if strategy.position_size > 0 strategy.exit("TP/SL", "LONG", stop=longStop, limit=longTake1Price, comment=_alertmessageExitLong, alert_message=_alertmessageExitLong) if strategy.position_size < 0 strategy.exit("TP/SL", "SHORT", stop=shortStop, limit=shortTake1Price, comment =_alertMessageExitShort, alert_message=_alertMessageExitShort) //Look & Feel - Plot stop loss and take profit areas p1=plot(strategy.position_avg_price, color=color.blue, style=plot.style_linebr, linewidth=1, title="Preço de entrada") p2=plot(series=strategy.position_size > 0 ? longStop : na, color=color.red, style=plot.style_linebr, linewidth=1, title="Long Stop") p3=plot(series=strategy.position_size > 0 ? longTake1Price : na, color=color.green, style=plot.style_linebr, linewidth=1, title="Long TP") p4=plot(series=strategy.position_size < 0 ? shortStop : na, color=color.red, style=plot.style_linebr, linewidth=1, title="Short Stop") p5=plot(series=strategy.position_size < 0 ? shortTake1Price : na, color=color.green, style=plot.style_linebr, linewidth=1, title="Short TP") fill(p1, p2, color=color.red) fill(p1, p3, color=color.green) fill(p1, p4, color=color.red) fill(p1, p5, color=color.green) // Insert label with value stopLossOnLong = "Stop Loss = " + tostring(longStop) stopLossOnShort = "Stop Loss = " + tostring(shortStop) takeprofitOnLong = "Take Profit = " + tostring(longTake1Price) takeprofitOnShort = "Take Profit = " + tostring(shortTake1Price) precoentrada = "Entrada = " + tostring(strategy.position_avg_price) var label FinalLabelpriceL = na var label FinalLabelpriceS = na var label slFinalLabelL = na var label slFinalLabelS = na var label slFinalLabelTPL = na var label slFinalLabelTPS = na //Draw entry and stop loss lines and labels if strategy.position_size > 0 //write the price above the end of the stoploss line slFinalLabelL := label.new(bar_index, longStop, stopLossOnLong, style=label.style_none, size=size.normal, textcolor=color.red) slFinalLabelTPL := label.new(bar_index, longTake1Price, takeprofitOnLong, style=label.style_none, size=size.normal, textcolor=color.green) FinalLabelpriceL := label.new(bar_index, strategy.position_avg_price, precoentrada, style=label.style_none, size=size.normal, textcolor=color.blue) // Delete previous label when there is a consecutive new high, as there's no line plot in that case. if strategy.position_size > 0[1] label.delete(slFinalLabelL[1]) label.delete(slFinalLabelTPL[1]) label.delete(FinalLabelpriceL[1]) if strategy.position_size < 0 //write the price above the end of the stoploss line slFinalLabelS := label.new(bar_index, shortStop, stopLossOnShort, style=label.style_none, size=size.normal, textcolor=color.red) slFinalLabelTPS := label.new(bar_index, shortTake1Price, takeprofitOnShort, style=label.style_none, size=size.normal, textcolor=color.green) FinalLabelpriceS := label.new(bar_index, strategy.position_avg_price, precoentrada, style=label.style_none, size=size.normal, textcolor=color.blue) // Delete previous label when there is a consecutive new high, as there's no line plot in that case. if strategy.position_size < 0[1] label.delete(slFinalLabelS[1]) label.delete(slFinalLabelTPS[1]) label.delete(FinalLabelpriceS[1]) // Exit open market position when date range ends if (not _inDateRange) strategy.close_all()