La estrategia de ruptura de impulso es una estrategia de seguimiento de tendencias que rastrea el impulso del mercado. Combina múltiples indicadores para juzgar si el mercado está actualmente en una tendencia al alza o a la baja, y abre posiciones largas cuando se rompen los niveles de resistencia clave y abre posiciones cortas cuando se rompen los niveles de soporte clave.
Esta estrategia utiliza principalmente los canales de Donchian de múltiples marcos de tiempo para determinar las tendencias del mercado y los niveles clave de precios. Específicamente, cuando los precios rompen el carril superior del canal de Donchian a más largo plazo, como 40 días, se juzga como una tendencia alcista. Junto con filtros adicionales como nuevos máximos dentro del año y la alineación de promedios móviles, se activan señales largas. Cuando los precios rompen por debajo del carril inferior del canal de Donchian a más largo plazo, se juzga como una tendencia bajista. Junto con filtros como nuevos mínimos dentro del año, se activan señales cortas.
La estrategia proporciona dos opciones para las posiciones de salida: línea de invalidación fija y pérdida de parada posterior. La línea de invalidación fija utiliza el tren inferior / superior de un canal de Donchian más corto, como 20 días. La pérdida de parada posterior calcula una línea de parada de pérdida dinámica cada día basada en los valores ATR. Ambos métodos pueden controlar los riesgos de manera efectiva.
Esta estrategia combina el juicio de tendencia y las operaciones de ruptura, que pueden capturar eficazmente las oportunidades direccionales a corto plazo en el mercado. En comparación con indicadores únicos, utiliza múltiples filtros que pueden filtrar algunas rupturas falsas y mejorar la calidad de las señales de entrada. Además, la aplicación de estrategias de stop loss también mejora su resiliencia y puede controlar eficazmente las pérdidas incluso si el mercado retrocede brevemente.
El principal riesgo de esta estrategia es que los precios pueden fluctuar violentamente, lo que desencadena pérdidas de parada en las posiciones de salida. Si los precios se invierten rápidamente después, las oportunidades podrían perderse. Además, el uso de múltiples filtros también puede filtrar algunas oportunidades y reducir la frecuencia de las operaciones.
Para reducir los riesgos, los múltiplos de ATR se pueden ajustar o los intervalos del canal de Donchian se pueden ampliar para disminuir la probabilidad de que se produzca un stop loss.
Esta estrategia puede optimizarse en los siguientes aspectos:
Mediante la prueba de diferentes parámetros, se puede encontrar la combinación óptima para equilibrar riesgos y rendimientos.
Esta estrategia combina múltiples indicadores para determinar la dirección de la tendencia y desencadena operaciones en los niveles clave de ruptura. Su mecanismo de stop loss también lo hace resistente a los riesgos. Al optimizar los parámetros, se pueden lograr retornos excedentes estables.
/*backtest start: 2024-01-23 00:00:00 end: 2024-02-22 00:00:00 period: 1h basePeriod: 15m 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/ // © HeWhoMustNotBeNamed //@version=4 strategy("BuyHigh-SellLow Strategy", overlay=true, initial_capital = 10000, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, commission_type = strategy.commission.percent, pyramiding = 1, commission_value = 0.01, calc_on_order_fills = true) donchianEntryLength = input(40, step=10) donchianExitLength = input(20, step=10) considerNewLongTermHighLows = input(true) shortHighLowPeriod = input(120, step=10) longHighLowPeriod = input(180, step=10) considerMAAlignment = input(true) MAType = input(title="Moving Average Type", defval="ema", options=["ema", "sma", "hma", "rma", "vwma", "wma"]) LookbackPeriod = input(40, minval=10,step=10) atrLength = input(22) atrMult = input(4) exitStrategy = input(title="Exit Strategy", defval="tsl", options=["dc", "tsl"]) considerYearlyHighLow = input(true) backtestYears = input(10, minval=1, step=1) f_getMovingAverage(source, MAType, length)=> ma = sma(source, length) if(MAType == "ema") ma := ema(source,length) if(MAType == "hma") ma := hma(source,length) if(MAType == "rma") ma := rma(source,length) if(MAType == "vwma") ma := vwma(source,length) if(MAType == "wma") ma := wma(source,length) ma f_getTrailingStop(atr, atrMult)=> stop = close - atrMult*atr stop := strategy.position_size > 0 ? max(stop, stop[1]) : stop stop f_getMaAlignment(MAType, includePartiallyAligned)=> ma5 = f_getMovingAverage(close,MAType,5) ma10 = f_getMovingAverage(close,MAType,10) ma20 = f_getMovingAverage(close,MAType,20) ma30 = f_getMovingAverage(close,MAType,30) ma50 = f_getMovingAverage(close,MAType,50) ma100 = f_getMovingAverage(close,MAType,100) ma200 = f_getMovingAverage(close,MAType,200) upwardScore = 0 upwardScore := close > ma5? upwardScore+1:upwardScore upwardScore := ma5 > ma10? upwardScore+1:upwardScore upwardScore := ma10 > ma20? upwardScore+1:upwardScore upwardScore := ma20 > ma30? upwardScore+1:upwardScore upwardScore := ma30 > ma50? upwardScore+1:upwardScore upwardScore := ma50 > ma100? upwardScore+1:upwardScore upwardScore := ma100 > ma200? upwardScore+1:upwardScore upwards = close > ma5 and ma5 > ma10 and ma10 > ma20 and ma20 > ma30 and ma30 > ma50 and ma50 > ma100 and ma100 > ma200 downwards = close < ma5 and ma5 < ma10 and ma10 < ma20 and ma20 < ma30 and ma30 < ma50 and ma50 < ma100 and ma100 < ma200 upwards?1:downwards?-1:includePartiallyAligned ? (upwardScore > 5? 0.5: upwardScore < 2?-0.5:upwardScore>3?0.25:-0.25) : 0 //////////////////////////////////// Calculate new high low condition ////////////////////////////////////////////////// f_calculateNewHighLows(shortHighLowPeriod, longHighLowPeriod, considerNewLongTermHighLows)=> newHigh = highest(shortHighLowPeriod) == highest(longHighLowPeriod) or not considerNewLongTermHighLows newLow = lowest(shortHighLowPeriod) == lowest(longHighLowPeriod) or not considerNewLongTermHighLows [newHigh,newLow] //////////////////////////////////// Calculate Yearly High Low ////////////////////////////////////////////////// f_getYearlyHighLowCondition(considerYearlyHighLow)=> yhigh = security(syminfo.tickerid, '12M', high[1]) ylow = security(syminfo.tickerid, '12M', low[1]) yhighlast = yhigh[365] ylowlast = ylow[365] yhighllast = yhigh[2 * 365] ylowllast = ylow[2 * 365] yearlyTrendUp = na(yhigh)? true : na(yhighlast)? close > yhigh : na(yhighllast)? close > max(yhigh,yhighlast) : close > max(yhigh, min(yhighlast, yhighllast)) yearlyHighCondition = ( (na(yhigh) or na(yhighlast) ? true : (yhigh > yhighlast) ) and ( na(yhigh) or na(yhighllast) ? true : (yhigh > yhighllast))) or yearlyTrendUp or not considerYearlyHighLow yearlyTrendDown = na(ylow)? true : na(ylowlast)? close < ylow : na(ylowllast)? close < min(ylow,ylowlast) : close < min(ylow, max(ylowlast, ylowllast)) yearlyLowCondition = ( (na(ylow) or na(ylowlast) ? true : (ylow < ylowlast) ) and ( na(ylow) or na(ylowllast) ? true : (ylow < ylowllast))) or yearlyTrendDown or not considerYearlyHighLow label_x = time+(60*60*24*1000*1) [yearlyHighCondition,yearlyLowCondition] donchian(rangeLength)=> upper = highest(rangeLength) lower = lowest(rangeLength) middle = (upper+lower)/2 [middle, upper, lower] inDateRange = true [eMiddle, eUpper, eLower] = donchian(donchianEntryLength) [exMiddle, exUpper, exLower] = donchian(donchianExitLength) maAlignment = f_getMaAlignment(MAType, false) [yearlyHighCondition, yearlyLowCondition] = f_getYearlyHighLowCondition(considerYearlyHighLow) [newHigh,newLow] = f_calculateNewHighLows(shortHighLowPeriod, longHighLowPeriod, considerNewLongTermHighLows) maAlignmentLongCondition = highest(maAlignment, LookbackPeriod) == 1 or not considerMAAlignment atr = atr(atrLength) tsl = f_getTrailingStop(atr, atrMult) //U = plot(eUpper, title="Up", color=color.green, linewidth=2, style=plot.style_linebr) //D = plot(exLower, title="Ex Low", color=color.red, linewidth=2, style=plot.style_linebr) longCondition = crossover(close, eUpper[1]) and yearlyHighCondition and newHigh and maAlignmentLongCondition exitLongCondition = crossunder(close, exLower[1]) shortCondition = crossunder(close, eLower[1]) and yearlyLowCondition and newLow exitShortCondition = crossover(close, exUpper[1]) strategy.entry("Buy", strategy.long, when=longCondition and inDateRange, oca_name="oca_buy") strategy.exit("ExitBuyDC", "Buy", when=exitStrategy=='dc', stop=exLower) strategy.exit("ExitBuyTSL", "Buy", when=exitStrategy=='tsl', stop=tsl) plot(strategy.position_size > 0 ? (exitStrategy=='dc'?exLower:tsl) : na, title="Trailing Stop", color=color.red, linewidth=2, style=plot.style_linebr) //strategy.close("Buy", when=exitLongCondition)