本策略通过判断价格对布林带通道的突破情况进行交易。该策略属于通道突破类策略的一种,旨在捕捉价格突破通道形成的趋势交易机会。
策略原理:
计算布林带通道,中轨为n日简单移动均线,上下轨为中轨之上下若干倍标准差。
当价格从上向下突破下轨时,进行短仓入场。当价格从下向上突破上轨时,进行多仓入场。
设置止损线为相反方向轨线之外,进行风险控制。
根据最大回撤情况调整通道带宽,优化参数。
结合交易量过滤判断,避免虚假突破。
该策略的优势:
突破通道可有效判断趋势转折点。
布林带参数优化简单实际,不易过优化。
结合交易量可过滤假突破,提高质量。
该策略的风险:
布林带滞后问题较突出,可能错过最佳入场点。
突破后容易出现反转,须设置合理止损。
优化中追求低频交易可能错失机会。
总之,该策略通过判断布林带的突破情况进行交易,是一种典型的通道突破策略。Relative 简单的规则有利于参数优化,但滞后及止损设置问题仍需警惕,始能获得长期稳定收益。
/*backtest start: 2023-08-12 00:00:00 end: 2023-09-11 00:00:00 period: 2h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=2 // strategy("ChannelBreakOutStrategyV2.1", commission_type = "percent", commission_value = 0.1, calc_on_order_fills = true, overlay=true) length = input(title="Length", minval=1, maxval=1000, defval=40) maxR = input(title = "R", minval = 1.0, maxval = 10, defval = 3, step = 0.1) adoptR = input(title = "Auto Adjust R", defval = false) stepR = input(title = "Step in R", minval = 0.01, maxval = 0.1, step = 0.01, defval = 0.02) baseYear = input(title = "Base Year", minval = 2000, maxval = 2016, defval = 2000) volumeTh = input(title = "Volume Threadhold", minval = 100.0, maxval = 200, defval = 120, step = 5) hasLong = input(title = "Include Long", defval = true) hasShort = input(title = "Include Short", defval = true) usePositionSizing = input(title = "Enable Position Sizing", defval = true) getTrailStop(val, current) => s = val > 1.6 ? 0.8 : val >= 1.4 ? 0.85 : val >= 1.3 ? 0.9 : 0.93 s * current upBound = highest(high, length) downBound = lowest(low, length) hasVol = (volume / sma(volume, length) * 100 >= volumeTh) ? 1 : 0 hasPos = strategy.position_size != 0 ? 1 : 0 trailstop = atr(length) * 3 ptvalue = syminfo.pointvalue equity = strategy.openprofit > 0 ? strategy.equity - strategy.openprofit : strategy.equity curR = adoptR == false ? maxR : n == 0 ? maxR : hasPos == 1 ? curR[1] : (rising(equity,1) > 0? curR[1] + stepR : falling(equity, 1) > 0 ? curR[1] <= 2.0 ? 2.0 : curR[1] - stepR : curR[1]) contracts = usePositionSizing == false ? 20 : floor(equity / 100 * curR / (trailstop * ptvalue)) realbuystop = close - trailstop realsellstop = close + trailstop isPFst = (hasPos[1] == 0 and hasPos == 1) ? 1 : 0 isPOn = (hasPos[1] + hasPos == 2) ? 1 : 0 largestR = hasPos == 0 or isPFst == 1 ? -1 : nz(largestR[1]) < close ? close : largestR[1] pctRise = largestR / strategy.position_avg_price rbs = strategy.position_size <= 0 ? realbuystop : isPFst ? strategy.position_avg_price - trailstop : pctRise >= 1.3 ? getTrailStop(pctRise, largestR) : (isPOn and realbuystop > rbs[1] and close > close[1]) ? realbuystop : rbs[1] rss = strategy.position_size >= 0 ? realsellstop : isPFst ? strategy.position_avg_price + trailstop : (isPOn and realsellstop < rss[1] and close < close[1]) ? realsellstop : rss[1] isStart = na(rbs) or na(rss) ? 0 : 1 buyARun = close - open > 0 ? 0 : open - close sellARun = open - close > 0 ? 0 : close - open if (strategy.position_size > 0 and buyARun >= trailstop / 3 * 2 and pctRise < 1.3) strategy.close("buy") strategy.cancel("exit") if (strategy.position_size < 0 and sellARun >= trailstop / 3 * 2) strategy.close("sell") strategy.cancel("exit") strategy.cancel("buy") strategy.cancel("sell") conLong = hasLong == true and hasPos == 0 and year > baseYear and (isStart + hasVol) == 2 strategy.order("buy", strategy.long, qty = contracts, stop=upBound + syminfo.mintick * 5, comment="BUY", when = conLong) if (rbs > high) strategy.close("buy") strategy.exit("exit", "buy", stop = rbs, when = hasPos == 1 and isStart == 1) conShort = hasShort == true and hasPos == 0 and year > baseYear and (isStart + hasVol) == 2 strategy.order("sell", strategy.short, qty = contracts, stop=downBound - syminfo.mintick * 5, comment="SELL", when = conShort) if (rss < low) strategy.close("sell") strategy.exit("exit", "sell", stop = rss, when = hasPos == 1 and isStart == 1) plot(series = rbs, color=blue) plot(series = realbuystop, color=green) plot(series = rss, color=red) plot(series = realsellstop, color=yellow)