该策略是基于双均线构建价格通道,使用通道范围来判断价格趋势方向,并设定止损追踪来锁定利润的趋势追踪策略。
双均线价格通道策略使用快速EMA和慢速EMA构建价格通道。快速EMA参数为89周期,慢速EMA参数为200周期。同时使用基于高价、低价、收盘价的三条均线构建价格通道范围。通道上轨线和下轨线分别为34周期的高价EMA和低价EMA。
当快速EMA在慢速EMA之上且价格低于下轨时,判断为上涨趋势;当快速EMA在慢速EMA之下且价格高于上轨时,判断为下跌趋势。
在上涨趋势时,策略会在确定趋势反转的时候做空;在下跌趋势时,策略会在确定趋势反转的时候做多。
此外,策略带有止损追踪功能。持仓后会实时更新追踪止损价格,实现利润的锁定。
该策略最大的优势在于利用双均线构建价格通道判断价格趋势,再结合反转做单,避免追高杀跌。同时带有移动止损追踪功能,可以锁定利润,降低亏损风险。
其他优势还有:参数优化空间大,可以针对不同品种和周期进行调整parameter;实时更新止损价格,操作风险低。
该策略主要的风险在于反转信号判定的效果不好,可能出现误判。这时就要优化参数,确保确定趋势反转的效果。
此外,止损点设置也很关键。止损点过大可能出现不够果断止损的情况;止损点过小可能出现过度止损的情况。这需要根据具体品种来调整。
最后,数据问题也可能导致策略失效。要确保使用的是可信、连续、充分的历史数据来回测和实盘验证策略。
该策略的优化主要集中在以下几个方面:
快速EMA和慢速EMA的周期可以进行优化,设置不同的参数组合来判断效果
价格通道的上下轨参数也可以调整,寻找更合适的周期参数
止损点的设置很关键,可以测试不同参数来优化止损策略
可以测试是否引入其他指标来确定趋势反转,提高做单效果
本策略整体运作流程合理顺畅,利用双均线通道判断趋势方向做单,并带有移动止损来锁定利润,是一款较为稳定的趋势追踪策略。通过参数优化和风控设置的优化,该策略可以成为高效的量化交易策略之一。
/*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')