Esta é uma estratégia de tendência baseada no canal de preços construído com médias móveis duplas.
A estratégia de canal de preço médio móvel dupla usa EMA rápida e EMA lenta para construir o canal de preços. A EMA rápida tem um parâmetro de 89 períodos e a EMA lenta tem um parâmetro de 200 períodos. Ao mesmo tempo, três EMAs baseadas em preço alto, preço baixo e preço próximo são usadas para construir o intervalo do canal. O trilho superior e o trilho inferior do canal são EMA de preço alto de 34 períodos e EMA de preço baixo, respectivamente.
Quando a EMA rápida está acima da EMA lenta e o preço está abaixo do trilho inferior, ela é determinada como uma tendência ascendente.
Durante uma tendência ascendente, a estratégia abrirá posições curtas quando a inversão da tendência for identificada.
Além disso, a estratégia tem uma função de stop loss de trailing.
A maior vantagem desta estratégia é que usa o canal de preço médio móvel duplo para determinar a tendência de preços, combinado com negociação de reversão para evitar perseguir altos e vender baixos.
Outras vantagens incluem: grande espaço de otimização de parâmetros que pode ser ajustado para diferentes produtos e ciclos; atualização em tempo real do preço de stop loss com baixo risco operacional.
O principal risco desta estratégia é que a eficácia da identificação de sinais de reversão pode não ser ideal e podem ocorrer erros de julgamento.
Além disso, a configuração de pontos de stop loss também é muito crítica. Se o ponto de stop loss for muito alto, o stop loss pode não ser decisivo o suficiente. Se o ponto de stop loss for muito baixo, pode haver situações de stop loss excessivas. Isso precisa ser ajustado de acordo com produtos específicos.
Por último, os problemas de dados também podem conduzir ao fracasso da estratégia. É necessário assegurar que sejam utilizados dados históricos credíveis, contínuos e suficientes para o backtesting e a verificação das negociações em tempo real da estratégia.
Os principais domínios de otimização desta estratégia incluem:
Os períodos da EMA rápida e da EMA lenta podem ser otimizados testando diferentes combinações de parâmetros para determinar o efeito
Os parâmetros dos trilhos superior e inferior do canal de preços também podem ser ajustados para encontrar parâmetros de ciclo mais adequados
A definição dos pontos de stop loss é crítica e pode ser otimizada através do teste de diferentes parâmetros
Teste se a introdução de outros indicadores para determinar a inversão da tendência pode melhorar o desempenho das negociações
O processo geral de operação desta estratégia é razoável e suave. Ele usa o canal de média móvel dupla para determinar a direção da tendência para a negociação, e tem um stop loss para bloquear os lucros. Através da otimização de parâmetros e otimização do gerenciamento de riscos, esta estratégia pode se tornar uma estratégia de negociação quantitativa eficiente.
/*backtest start: 2023-12-01 00:00:00 end: 2023-12-31 23:59:59 period: 1h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=4 strategy("Trend trader Strategy", overlay=true) //f you want to trade shallower Pullbacks for quicker scalps, try reducing the // PAC and EMA combination lengths for example: // * 21 PAC and 55, 144, 377 for fast, medium, slow EMAs // * 13 PAC and 34, 89, 233 for fast, medium, slow EMAs // - Each alert should be evaluated on it's own merits, the alerts are designed to highlight possible // scalping trades from Pullback recoveries around the PAC. fromDay = input(defval = 1, title = "From Day", minval = 1, maxval = 31) fromMonth = input(defval = 6, title = "From Month", minval = 1, maxval = 12) fromYear = input(defval = 2020, title = "From Year", minval = 1970) // To Date Inputs toDay = input(defval = 1, title = "To Day", minval = 1, maxval = 31) toMonth = input(defval = 12, title = "To Month", minval = 1, maxval = 12) toYear = input(defval = 2020, title = "To Year", minval = 1970) isMon() => dayofweek(time('D')) == dayofweek.monday isTue() => dayofweek(time('D')) == dayofweek.tuesday isWed() => dayofweek(time('D')) == dayofweek.wednesday isThu() => dayofweek(time('D')) == dayofweek.thursday isFri() => dayofweek(time('D')) == dayofweek.friday // Calculate start/end date and time condition DST = 1 //day light saving for usa //--- Europe London = iff(DST==0,"0000-0900","0100-1000") //--- America NewYork = iff(DST==0,"0400-1400","0500-1500") //--- Pacific Sydney = iff(DST==0,"1300-2200","1400-2300") //--- Asia Tokyo = iff(DST==0,"1500-2400","1600-0100") customTime =iff(DST==0,"2300-1500","2400-1600") customTime2 =iff(DST==0,"0800-1500","0900-1600") //-- Time In Range timeinrange(res, sess) => time(res, sess) != 0 london = timeinrange(timeframe.period, London) newyork = timeinrange(timeframe.period, NewYork) c_time = timeinrange(timeframe.period,customTime) c_time2 = timeinrange(timeframe.period,customTime2) startDate = timestamp(fromYear, fromMonth, fromDay, 00, 00) finishDate = timestamp(toYear, toMonth, toDay, 00, 00) time_cond = time >= startDate and time <= finishDate and (london or newyork) // === INPUTS === HiLoLen = input(34, minval=2, title="High Low PAC channel Length") fastEMAlength = input(89, minval=2) mediumEMAlength = input(200, minval=2) slowEMAlength = input(600, minval=2) ShowFastEMA = input(false) ShowMediumEMA = input(false) ShowSlowEMA = input(false) ShowHHLL = input(false) ShowFractals = input(false) filterBW = input(false, title="Show Ideal Fractals Only") ShowBarColor = input(true, title="Show coloured Bars around PAC") ShowBuySell = input(false, title="Show Buy/Sell Alert Arrows") Lookback = input(3, minval=1, title="Pullback Lookback for PAC Cross Check") DelayArrow = input(false, title="Show Alert Arrows Only on Closed Candles") Delay = DelayArrow ? 1 : 0 ShowTrendBGcolor= input(true) UseHAcandles = input(false, title="Use Heikin Ashi Candles in Algo Calculations") // // === /INPUTS === // === BASE FUNCTIONS === haClose = UseHAcandles ? security(heikinashi(syminfo.tickerid), timeframe.period, close) : close haOpen = UseHAcandles ? security(heikinashi(syminfo.tickerid), timeframe.period, open) : open haHigh = UseHAcandles ? security(heikinashi(syminfo.tickerid), timeframe.period, high) : high haLow = UseHAcandles ? security(heikinashi(syminfo.tickerid), timeframe.period, low) : low // ||--- Fractal Recognition Functions: ---------------------------------------------------------------|| isRegularFractal(mode) => ret = mode == 1 ? high[4] < high[3] and high[3] < high[2] and high[2] > high[1] and high[1] > high[0] : mode == -1 ? low[4] > low[3] and low[3] > low[2] and low[2] < low[1] and low[1] < low[0] : false ret isBWFractal(mode) => ret = mode == 1 ? high[4] < high[2] and high[3] <= high[2] and high[2] >= high[1] and high[2] > high[0] : mode == -1 ? low[4] > low[2] and low[3] >= low[2] and low[2] <= low[1] and low[2] < low[0] : false ret // ||-----------------------------------------------------------------------------------------------------|| // // === /BASE FUNCTIONS === // === SERIES SETUP === // // ||--- Setup Moving Averages and PAC channel: // ||-----------------------------------------------------------------------------------------------------|| fastEMA = ema(haClose, fastEMAlength) mediumEMA = ema(haClose, mediumEMAlength) slowEMA = ema(haClose, slowEMAlength) pacC = ema(haClose, HiLoLen) pacL = ema(haLow, HiLoLen) pacU = ema(haHigh, HiLoLen) TrendDirection = fastEMA > mediumEMA and pacL > mediumEMA ? 1 : fastEMA < mediumEMA and pacU < mediumEMA ? -1 : 0 // ||--- Fractal Recognition: // ||-----------------------------------------------------------------------------------------------------|| filteredtopf = filterBW ? isRegularFractal(1) : isBWFractal(1) filteredbotf = filterBW ? isRegularFractal(-1) : isBWFractal(-1) // ||-----------------------------------------------------------------------------------------------------|| // ||--- Higher Highs, Lower Highs, Higher Lows, Lower Lows -------------------------------------------|| valuewhen_H0 = valuewhen(filteredtopf == true, high[2], 0) valuewhen_H1 = valuewhen(filteredtopf == true, high[2], 1) valuewhen_H2 = valuewhen(filteredtopf == true, high[2], 2) // higherhigh = filteredtopf == false ? false : valuewhen_H1 < valuewhen_H0 and valuewhen_H2 < valuewhen_H0 lowerhigh = filteredtopf == false ? false : valuewhen_H1 > valuewhen_H0 and valuewhen_H2 > valuewhen_H0 valuewhen_L0 = valuewhen(filteredbotf == true, low[2], 0) valuewhen_L1 = valuewhen(filteredbotf == true, low[2], 1) valuewhen_L2 = valuewhen(filteredbotf == true, low[2], 2) // higherlow = filteredbotf == false ? false : valuewhen_L1 < valuewhen_L0 and valuewhen_L2 < valuewhen_L0 lowerlow = filteredbotf == false ? false : valuewhen_L1 > valuewhen_L0 and valuewhen_L2 > valuewhen_L0 // // === /SERIES === // // === PLOTTING === // // Plot the Price Action Channel (PAC) base on EMA high,low and close L = plot(pacL, color=color.gray, linewidth=1, title="High PAC EMA", transp=50) U = plot(pacU, color=color.gray, linewidth=1, title="Low PAC EMA", transp=50) C = plot(pacC, color=color.red, linewidth=2, title="Close PAC EMA", transp=0) fill(L, U, color=color.gray, transp=90, title="Fill HiLo PAC") // Colour bars according to the close position relative to the PAC selected. BARcolor = haClose > pacU ? color.blue : haClose < pacL ? color.red : color.gray barcolor(ShowBarColor ? BARcolor : na, title="Bar Colours") // BGcolor = TrendDirection == 1 ? color.green : TrendDirection == -1 ? color.red : color.yellow bgcolor(ShowTrendBGcolor ? BGcolor : na, transp=90, title="Trend BG Color") // STEP 1: // Configure trail stop level with input options (optional) longTrailPerc = input(title="Trail Long Loss (%)", type=input.float, minval=0.0, step=0.05, defval=0.1) * 0.01 shortTrailPerc = input(title="Trail Short Loss (%)", type=input.float, minval=0.0, step=0.05, defval=0.1) * 0.01 atrRange = input(14, title="ATR Range", type=input.integer) buyStop = input(2, title="* ATR Buy SL", type=input.float) sellStop = input(1, title="* ATR Sell SL", type=input.float) targetATR = input(1, title="* ATR TP1", type=input.float) moveToEntryFigure = input(0.5, title=" move to entry in % towards target", type=input.float) showMove = input(true, title="Show Move to Entry points") showMoveBuycol = showMove ? color.lime : na showMoveSellcol = showMove ? color.lime : na // Plots buyStopp = plot(close - atr(atrRange) * buyStop, title="Buy SL", style=plot.style_stepline, color=color.red, transp=75, linewidth=3) sellStopp = plot(close + atr(atrRange) * sellStop, title="Sell SL", style=plot.style_stepline, color=color.red, transp=75, linewidth=3) buyTP1 = plot(close + atr(atrRange) * targetATR, title="Buy TP", style=plot.style_cross, color=color.lime, transp=75, linewidth=3) sellTP1 = plot(close - atr(atrRange) * targetATR, title="Sell TP", style=plot.style_cross, color=color.lime, transp=75, linewidth=3) buyMove = plot(close + atr(atrRange) * targetATR * moveToEntryFigure, title="Buy Move to Entry", style=plot.style_cross, color=showMoveBuycol, transp=75, linewidth=3) sellMove = plot(close - atr(atrRange) * targetATR * moveToEntryFigure, title="Sell Move to Entry", style=plot.style_cross, color=showMoveSellcol, transp=75, linewidth=3) if barstate.isconfirmed if(BGcolor==color.red and BGcolor[1]==color.yellow and c_time ) strategy.entry("short", strategy.short, comment="short", alert_message='short') strategy.cancel("long") if(BGcolor==color.green and BGcolor[1]==color.yellow and c_time ) strategy.entry("long", strategy.long, comment="long", alert_message = 'long') strategy.cancel("short") // STEP 2: // Determine trail stop loss prices longStopPrice = 0.0, shortStopPrice = 0.0 longStopPrice := if (strategy.position_size > 0) stopValue = close * (1 - longTrailPerc) max(stopValue, longStopPrice[1]) else 0 shortStopPrice := if (strategy.position_size < 0) stopValue = close * (1 + shortTrailPerc) min(stopValue, shortStopPrice[1]) else 999999 // Plot stop loss values for confirmation plot(series=(strategy.position_size > 0) ? longStopPrice : na, color=color.fuchsia, style=plot.style_cross, linewidth=2, title="Long Trail Stop") plot(series=(strategy.position_size < 0) ? shortStopPrice : na, color=color.fuchsia, style=plot.style_cross, linewidth=2, title="Short Trail Stop") // STEP 3: // Submit exit orders for trail stop loss price //if (strategy.position_size > 0) // strategy.exit("XL TRL STP","long", stop=longStopPrice) //if (strategy.position_size < 0) // strategy.exit("XS TRL STP","short", stop=shortStopPrice) tp=input(0.0032,type=input.float, title="tp") sl=input(0.001,type=input.float, title="sl") //strategy.close("long", when= tp/2,qty_percent = 50) //strategy.exit("longtp/sl","long",profit=tp, loss=sl, stop=longStopPrice, alert_message='closelong') //strategy.exit("shorttp/sl","short",profit=tp, loss=sl, stop=shortStopPrice, alert_message='closeshort') //tpatrlong= close + atr(atrRange) * targetATR //slatrlong= close - atr(atrRange) * buyStop //strategy.exit("longtp/sl","long",profit=tp, loss=sl, alert_message='closelong') //strategy.exit("shorttp/sl","short",profit=tp, loss=sl, alert_message='closeshort') strategy.exit("closelong", "long" , profit = close * tp / syminfo.mintick, loss = close * sl / syminfo.mintick, alert_message = "closelong") strategy.exit("closeshort", "short" , profit = close * tp / syminfo.mintick, loss = close * sl / syminfo.mintick, alert_message = "closeshort") if(BGcolor==color.yellow or not c_time) strategy.close("short", comment="time or yellow", alert_message='closeshort') strategy.close("long", comment="time or yellow", alert_message='closelong')