Chiến lược đảo ngược theo dõi hai kênh

Tác giả:ChaoZhang, Ngày: 2023-11-02 16:31:50
Tags:

img

Tổng quan

Chiến lược đảo ngược theo dõi kênh kép là một chiến lược giao dịch đảo ngược kết hợp các dải Bollinger, kênh Keltner và các chỉ số động lực. Nó xác định các vùng nén giá thông qua sự tổng hợp các dải Bollinger và kênh Keltner, và sử dụng các chỉ số động lực để xác định các tín hiệu đảo ngược để vào và ra.

Chiến lược logic

  1. Tính toán các dải giữa, trên và dưới cho các dải Bollinger

    • Dải giữa sử dụng SMA của gần
    • Các dải trên và dưới là dải giữa ± gấp đôi độ lệch chuẩn có thể điều chỉnh
  2. Tính toán các dải giữa, trên và dưới cho Keltner kênh

    • Dải giữa sử dụng SMA của gần
    • Các dải trên và dưới là dải giữa ± nhiều lần ATR có thể điều chỉnh
  3. Xác định xem các dải Bollinger có nằm bên trong các kênh Keltner không

    • Nén khi BB dưới > KC dưới và BB trên < KC trên
    • Nếu không, hãy rút lui đi.
  4. Tính toán đường cong khúc nghiêng val của gần với BB và KC giữa điểm

    • Val > 0 cho thấy gần đang gia tăng, val < 0 có nghĩa là giảm
  5. Tính toán ROC và EMA của ROC để đóng

    • Xác định xem tỷ lệ thay đổi có vượt quá ngưỡng điều chỉnh không
    • Trên ngưỡng cho thấy xu hướng hiện tại
  6. Khi ép, dài khi val > 0 và ROC vượt quá ngưỡng

    • Ngược lại là ngắn.
  7. Đặt các điều kiện dừng lỗ và lấy lợi nhuận

Ưu điểm

  1. Cải thiện độ chính xác bằng cách kết hợp hệ thống kênh kép để đảo ngược

  2. Tránh tín hiệu sai bằng cách sử dụng hồi quy tuyến tính và tỷ lệ thay đổi

  3. Các thông số điều chỉnh linh hoạt để tối ưu hóa trên các sản phẩm

  4. Kiểm soát rủi ro hiệu quả cho mỗi giao dịch với lệnh dừng lỗ/lấy lợi nhuận

  5. Dữ liệu backtest đủ để xác nhận tính khả thi của chiến lược

Rủi ro và giải pháp

  1. Nén không phải lúc nào cũng dẫn đến đảo ngược hiệu quả

    • Tối ưu hóa các tham số và thắt chặt các tiêu chí ép
  2. Những sự đột phá giả tạo ra các tín hiệu sai

    • Thêm hồi quy tuyến tính để xác định hướng xu hướng
  3. Stop loss quá rộng dẫn đến lỗ đơn quá lớn

    • Tối ưu hóa điểm dừng lỗ và kiểm soát mỗi lỗ giao dịch
  4. Thời gian thử nghiệm không đủ

    • Mở rộng thử nghiệm ra nhiều thời gian hơn để chứng minh khả năng sống lâu dài

Cơ hội gia tăng

  1. Tối ưu hóa tham số cho nhiều sản phẩm hơn

  2. Thêm máy học để xác định hỗ trợ / kháng cự

  3. Tích hợp thay đổi khối lượng để cải thiện tính hợp lệ của việc phá vỡ

  4. Thực hiện phân tích nhiều khung thời gian cho sự bền vững của xu hướng

  5. Tối ưu hóa stop loss / take profit năng động

Kết luận

Chiến lược đảo ngược theo dõi kênh kép sử dụng các chỉ số như Bollinger Bands và Keltner Channels để giao dịch đảo ngược. Với tối ưu hóa tham số, nó có thể được điều chỉnh trên các sản phẩm khác nhau để xác định tính hợp lệ của việc phá vỡ ở một mức độ nào đó.


/*backtest
start: 2023-10-02 00:00:00
end: 2023-11-01 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
// Credit for the initial Squeeze Momentum code to LazyBear, rate of change code is from Kiasaki
strategy("Squeeze X BF 🚀", overlay=false, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.0)

/////////////// Time Frame ///////////////
testStartYear = input(2012, "Backtest Start Year") 
testStartMonth = input(1, "Backtest Start Month")
testStartDay = input(1, "Backtest Start Day")
testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay, 0, 0)

testStopYear = input(2019, "Backtest Stop Year")
testStopMonth = input(12, "Backtest Stop Month")
testStopDay = input(31, "Backtest Stop Day")
testPeriodStop = timestamp(testStopYear,testStopMonth,testStopDay, 0, 0)

testPeriod() => true

/////////////// Squeeeeze ///////////////
length = input(20, title="BB Length")
mult = input(2.0,title="BB MultFactor")
lengthKC=input(22, title="KC Length")
multKC = input(1.5, title="KC MultFactor")
 
useTrueRange = input(true, title="Use TrueRange (KC)")
 
// Calculate BB
source = close
basis = sma(source, length)
dev = mult * stdev(source, length)
upperBB = basis + dev
lowerBB = basis - dev

// Calculate KC
ma = sma(source, lengthKC)
range = useTrueRange ? tr : (high - low)
rangema = sma(range, lengthKC)
upperKC = ma + rangema * multKC
lowerKC = ma - rangema * multKC

sqzOn  = (lowerBB > lowerKC) and (upperBB < upperKC)
sqzOff = (lowerBB < lowerKC) and (upperBB > upperKC)
noSqz  = (sqzOn == false) and (sqzOff == false)

val = linreg(source - avg(avg(highest(high, lengthKC), lowest(low, lengthKC)),sma(close,lengthKC)), lengthKC,0)

///////////// Rate Of Change ///////////// 
roclength = input(30, minval=1), pcntChange = input(7, minval=1)
roc = 100 * (source - source[roclength]) / source[roclength]
emaroc = ema(roc, roclength / 2)
isMoving() => emaroc > (pcntChange / 2) or emaroc < (0 - (pcntChange / 2))

/////////////// Strategy ///////////////
long = val > 0 and isMoving()
short = val < 0 and isMoving()

last_long = 0.0
last_short = 0.0
last_long := long ? time : nz(last_long[1])
last_short := short ? time : nz(last_short[1])

long_signal = crossover(last_long, last_short)
short_signal = crossover(last_short, last_long)

last_open_long_signal = 0.0
last_open_short_signal = 0.0
last_open_long_signal := long_signal ? open : nz(last_open_long_signal[1])
last_open_short_signal := short_signal ? open : nz(last_open_short_signal[1])

last_long_signal = 0.0
last_short_signal = 0.0
last_long_signal := long_signal ? time : nz(last_long_signal[1])
last_short_signal := short_signal ? time : nz(last_short_signal[1])

in_long_signal = last_long_signal > last_short_signal
in_short_signal = last_short_signal > last_long_signal

last_high = 0.0
last_low = 0.0
last_high := not in_long_signal ? na : in_long_signal and (na(last_high[1]) or high > nz(last_high[1])) ? high : nz(last_high[1])
last_low := not in_short_signal ? na : in_short_signal and (na(last_low[1]) or low < nz(last_low[1])) ? low : nz(last_low[1])

sl_inp = input(100.0, title='Stop Loss %') / 100
tp_inp = input(5000.0, title='Take Profit %') / 100
 
take_level_l = strategy.position_avg_price * (1 + tp_inp)
take_level_s = strategy.position_avg_price * (1 - tp_inp)

since_longEntry = barssince(last_open_long_signal != last_open_long_signal[1]) 
since_shortEntry = barssince(last_open_short_signal != last_open_short_signal[1]) 

slLong = in_long_signal ? strategy.position_avg_price * (1 - sl_inp) : na
slShort = strategy.position_avg_price * (1 + sl_inp)
long_sl = in_long_signal ? slLong : na
short_sl = in_short_signal ? slShort : na

/////////////// Execution ///////////////
if testPeriod()
    strategy.entry("Long",  strategy.long, when=long)
    strategy.entry("Short", strategy.short, when=short)
    strategy.exit("Long Ex", "Long", stop=long_sl, limit=take_level_l, when=since_longEntry > 0)
    strategy.exit("Short Ex", "Short", stop=short_sl, limit=take_level_s, when=since_shortEntry > 0)
    
/////////////// Plotting ///////////////
bcolor = iff(val > 0, iff(val > nz(val[1]), color.lime, color.green), iff(val < nz(val[1]), color.red, color.maroon))
plot(val, color=bcolor, linewidth=4)
bgcolor(not isMoving() ? color.white : long ? color.lime : short ? color.red : na, transp=70)
bgcolor(long_signal ? color.lime : short_signal ? color.red : na, transp=50)
hline(0, color = color.white)

Thêm nữa