Chiến lược này được giao dịch bằng cách đánh giá sự phá vỡ của giá đối với kênh Brin. Chiến lược này thuộc loại chiến lược phá vỡ kênh, nhằm nắm bắt cơ hội giao dịch theo xu hướng được hình thành bởi các kênh phá vỡ giá.
Nguyên tắc chiến lược:
Tính toán đường băng Brin, đường trung tâm là đường trung bình di chuyển đơn giản trong n ngày, đường trên và đường dưới là đường trung tâm trên và dưới nhiều lần chênh lệch chuẩn.
Khi giá từ trên xuống đột phá xuống đường, hãy vào vị trí ngắn. Khi giá từ dưới xuống đột phá lên đường, hãy vào vị trí nhiều.
Đặt đường dừng bên ngoài đường ray theo hướng ngược lại để kiểm soát rủi ro.
Điều chỉnh băng thông kênh theo điều kiện rút lui tối đa, tối ưu hóa tham số.
Trong khi đó, các nhà phân tích cho rằng các giao dịch trên các sàn giao dịch khác có thể bị phá vỡ.
Những lợi thế của chiến lược này:
Bước đột phá có thể xác định hiệu quả các điểm thay đổi.
Tối ưu hóa tham số của Brin rất đơn giản và thực tế.
Kết hợp với khối lượng giao dịch có thể lọc các đột phá giả, nâng cao chất lượng.
Rủi ro của chiến lược này:
Brin có vấn đề về sự chậm trễ và có thể đã bỏ lỡ điểm xuất sắc nhất.
Sau khi phá vỡ, dễ bị đảo ngược, phải thiết lập dừng thiệt hại hợp lý.
Trong quá trình tối ưu hóa, việc theo đuổi giao dịch tần số thấp có thể làm mất cơ hội.
Tóm lại, chiến lược này giao dịch bằng cách đánh giá sự phá vỡ của Brin, một chiến lược phá vỡ kênh điển hình. Các quy tắc đơn giản tương đối có lợi cho việc tối ưu hóa các tham số, nhưng các vấn đề về thiết lập trễ và dừng lỗ vẫn cần phải cảnh giác để có được lợi nhuận ổn định lâu dài.
/*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)