Chiến lược giao dịch Bollinger Band Breakout

Tác giả:ChaoZhang, Ngày: 2023-09-12 16:23:12
Tags:

Chiến lược này giao dịch sự đột phá giá của Bollinger Bands. Nó nhằm mục đích nắm bắt các cơ hội xu hướng từ sự đột phá kênh.

Chiến lược logic:

  1. Tính toán Bollinger Bands với đường trung bình động n giai đoạn như đường trung và các dải biến động trên và dưới.

  2. Nhập ngắn khi giá phá vỡ dưới dải dưới. Nhập dài khi phá vỡ trên dải trên.

  3. Đặt dừng bên ngoài dải đối diện để kiểm soát rủi ro.

  4. Điều chỉnh chiều rộng băng thông dựa trên tối đa drawdown để tối ưu hóa tham số.

  5. Thêm bộ lọc âm lượng để tránh các sự đột phá giả.

Ưu điểm:

  1. Việc phá vỡ các dải băng hiệu quả xác định các biến đổi xu hướng.

  2. Bollinger tối ưu hóa tham số là đơn giản và thực tế.

  3. Bộ lọc âm lượng cải thiện chất lượng bằng cách tránh nhầm lẫn.

Rủi ro:

  1. Các ban nhạc bị tụt lại có thể bỏ lỡ thời điểm tốt nhất.

  2. Sự đảo ngược sau khi đột quỵ là phổ biến, đòi hỏi phải dừng lại hợp lý.

  3. Tìm kiếm các giao dịch tần số thấp trong tối ưu hóa có thể bỏ lỡ cơ hội.

Tóm lại, đây là một chiến lược thoát kênh điển hình giao dịch Bollinger Breaks. Các quy tắc tương đối đơn giản có lợi cho tối ưu hóa nhưng các vấn đề về vị trí trì hoãn và dừng lại vẫn ảnh hưởng đến lợi nhuận ổn định dài hạn.


/*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)

Thêm nữa