Files
strategies/布林带突破交易策略Bollinger-Band-Breakout-Trading-Strategy.md
2024-03-03 22:27:55 +08:00

189 lines
6.5 KiB
Markdown

> Name
布林带突破交易策略Bollinger-Band-Breakout-Trading-Strategy
> Author
ChaoZhang
> Strategy Description
[trans]
本策略通过判断价格对布林带通道的突破情况进行交易。该策略属于通道突破类策略的一种,旨在捕捉价格突破通道形成的趋势交易机会。
策略原理:
1. 计算布林带通道,中轨为n日简单移动均线,上下轨为中轨之上下若干倍标准差。
2. 当价格从上向下突破下轨时,进行短仓入场。当价格从下向上突破上轨时,进行多仓入场。
3. 设置止损线为相反方向轨线之外,进行风险控制。
4. 根据最大回撤情况调整通道带宽,优化参数。
5. 结合交易量过滤判断,避免虚假突破。
该策略的优势:
1. 突破通道可有效判断趋势转折点。
2. 布林带参数优化简单实际,不易过优化。
3. 结合交易量可过滤假突破,提高质量。
该策略的风险:
1. 布林带滞后问题较突出,可能错过最佳入场点。
2. 突破后容易出现反转,须设置合理止损。
3. 优化中追求低频交易可能错失机会。
总之,该策略通过判断布林带的突破情况进行交易,是一种典型的通道突破策略。Relative 简单的规则有利于参数优化,但滞后及止损设置问题仍需警惕,始能获得长期稳定收益。
||
This strategy trades the price breakout of Bollinger Bands. It aims to capture trend opportunities from channel breakouts.
Strategy Logic:
1. Calculate Bollinger Bands with n-period moving average as midline and volatility bands above and below.
2. Enter short when price breaks down below lower band. Enter long when breaking above upper band.
3. Set stops outside opposite band for risk control.
4. Adjust band width based on max drawdown for parameter optimization.
5. Add volume filter to avoid false breakouts.
Advantages:
1. Breaking bands effectively identifies trend turns.
2. Bollinger parameter optimization is simple and practical.
3. Volume filter improves quality by avoiding falseouts.
Risks:
1. Lagging bands may miss best entry timing.
2. Post-breakout reversals are common, requiring reasonable stops.
3. Seeking low-frequency trades in optimization can miss opportunities.
In summary, this is a typical channel breakout strategy trading Bollinger breaks. The relatively simple rules benefit optimization but lag and stop placement issues remain that impact long-term steady gains.
[/trans]
> Strategy Arguments
|Argument|Default|Description|
|----|----|----|
|v_input_1|40|Length|
|v_input_2|3|R|
|v_input_3|false|Auto Adjust R|
|v_input_4|0.02|Step in R|
|v_input_5|2000|Base Year|
|v_input_6|120|Volume Threadhold|
|v_input_7|true|Include Long|
|v_input_8|true|Include Short|
|v_input_9|true|Enable Position Sizing|
> Source (PineScript)
``` pinescript
/*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)
```
> Detail
https://www.fmz.com/strategy/426504
> Last Modified
2023-09-12 16:23:12