Dual Channel Tracking Reversal Strategy

Penulis:ChaoZhang, Tarikh: 2023-11-02 16:31:50
Tag:

img

Ringkasan

Strategi Pembalikan Pengesanan Saluran Berganda adalah strategi perdagangan pembalikan yang menggabungkan Bollinger Band, Saluran Keltner, dan penunjuk momentum.

Logika Strategi

  1. Mengira jalur tengah, atas dan bawah untuk Bollinger Bands

    • Band tengah menggunakan SMA berdekatan
    • Garis atas dan bawah adalah jalur tengah ± kelipatan penyimpangan standard yang boleh diselaraskan
  2. Mengira pertengahan, atas dan bawah jalur untuk Saluran Keltner

    • Band tengah menggunakan SMA berdekatan
    • Band atas dan bawah adalah band tengah ± kelipatan ATR yang boleh diselaraskan
  3. Tentukan sama ada Bollinger Bands berada di dalam Saluran Keltner

    • Memeras apabila BB bawah > KC bawah dan BB atas < KC atas
    • Memeras off jika tidak
  4. Mengira lempeng regresi linear val penutupan terhadap titik tengah BB dan KC

    • Val > 0 menunjukkan penutupan meningkat, Val < 0 bermaksud penurunan
  5. Mengira ROC dan EMA ROC untuk penutupan

    • Menentukan sama ada kadar perubahan melebihi ambang yang boleh diselaraskan
    • Di atas ambang menunjukkan trend yang sedia ada
  6. Apabila dalam keadaan memerah, lama apabila val > 0 dan ROC melebihi ambang

    • Sebaliknya untuk pendek
  7. Tetapkan syarat stop loss dan mengambil keuntungan

Kelebihan

  1. Kecekapan yang lebih baik dengan menggabungkan sistem saluran dua untuk pembalikan

  2. Elakkan isyarat palsu menggunakan regresi linear dan kadar perubahan

  3. Parameter yang boleh diselaraskan yang fleksibel untuk pengoptimuman di seluruh produk

  4. Pengendalian risiko yang berkesan bagi setiap perdagangan dengan stop loss/take profit

  5. Data backtest yang mencukupi untuk mengesahkan daya maju strategi

Risiko dan Penyelesaian

  1. Memerah tidak selalu membawa kepada pembalikan yang berkesan

    • Mengoptimumkan parameter dan mengetatkan kriteria memerah
  2. Pembebasan palsu menghasilkan isyarat yang salah.

    • Tambah regresi linear untuk menentukan arah trend
  3. Stop loss terlalu luas yang membawa kepada kerugian tunggal yang berlebihan

    • Mengoptimumkan titik stop loss dan kawalan setiap kerugian perdagangan
  4. Tempoh ujian yang tidak mencukupi

    • Memperluas ujian ke dalam lebih banyak tempoh untuk membuktikan daya maju jangka panjang

Peluang Peningkatan

  1. Pengoptimuman parameter untuk lebih banyak produk

  2. Tambah pembelajaran mesin untuk pengenalan sokongan / rintangan

  3. Menggabungkan perubahan jumlah untuk meningkatkan kesahihan pecah

  4. Melakukan analisis jangka masa berbilang untuk kesinambungan trend

  5. Mengoptimumkan Stop Loss/Take Profit dinamik

Kesimpulan

Strategi Pembalikan Pengesanan Saluran Berganda menggunakan penunjuk seperti Bollinger Bands dan Saluran Keltner untuk perdagangan pembalikan. Dengan pengoptimuman parameter, ia boleh disesuaikan di seluruh produk yang berbeza untuk mengenal pasti kesahihan pecah hingga tahap tertentu. Tetapi perdagangan pembalikan masih membawa risiko yang melekat, memerlukan penggabungan pembelajaran mesin dan lain-lain untuk meningkatkan ketepatan untuk pulangan yang berlebihan yang stabil.


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

Lebih lanjut