Strategi pembalikan pelacakan dua saluran

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

img

Gambaran umum

Dual Channel Tracking Reversal adalah strategi trading reversal yang menggabungkan Bollinger Bands, Keltner Channels, dan indikator momentum.

Logika Strategi

  1. Menghitung band tengah, atas dan bawah untuk Bollinger Bands

    • Band tengah menggunakan SMA dekat
    • Band atas dan bawah adalah band tengah ± kelipatan standar deviasi yang dapat disesuaikan
  2. Menghitung band tengah, atas dan bawah untuk saluran Keltner

    • Band tengah menggunakan SMA dekat
    • Band atas dan bawah adalah band tengah ± ganda ATR yang dapat disesuaikan
  3. Tentukan apakah Bollinger Bands berada di dalam Saluran Keltner

    • Memperset pada saat BB bawah > KC bawah dan BB atas < KC atas
    • Menekuk off jika tidak
  4. Hitung lereng regresi linier val dekat terhadap titik tengah BB dan KC

    • Val > 0 menunjukkan dekat meningkat, val < 0 berarti menurun
  5. Menghitung ROC dan EMA dari ROC untuk penutupan

    • Tentukan apakah tingkat perubahan melebihi ambang batas yang dapat disesuaikan
    • Di atas ambang batas menunjukkan tren yang ada
  6. Saat dipencet, lama saat val > 0 dan ROC melebihi ambang

    • Kebalikannya untuk pendek
  7. Tentukan kondisi stop loss dan take profit

Keuntungan

  1. Keakuratan yang ditingkatkan dengan menggabungkan sistem saluran ganda untuk pembalikan

  2. Hindari sinyal palsu menggunakan regresi linier dan tingkat perubahan

  3. Parameter yang dapat disesuaikan yang fleksibel untuk optimasi di seluruh produk

  4. Kontrol risiko yang efektif per perdagangan dengan stop loss/take profit

  5. Data backtest yang cukup untuk memvalidasi kelayakan strategi

Risiko dan Solusi

  1. Memperset tidak selalu mengarah pada pembalikan yang efektif

    • Mengoptimalkan parameter dan memperketat kriteria memeras
  2. Pencegahan palsu menghasilkan sinyal yang salah

    • Tambahkan regresi linier untuk menentukan arah tren
  3. Stop loss terlalu luas yang menyebabkan kerugian tunggal yang berlebihan

    • Optimalkan titik stop loss dan kontrol per kerugian perdagangan
  4. Periode pengujian yang tidak cukup

    • Memperluas pengujian ke lebih banyak periode untuk membuktikan kelayakan jangka panjang

Peluang Peningkatan

  1. Optimasi parameter untuk lebih banyak produk

  2. Tambahkan pembelajaran mesin untuk identifikasi dukungan / resistensi

  3. Masukkan perubahan volume untuk meningkatkan validitas breakout

  4. Melakukan analisis multi-frame waktu untuk persistensi tren

  5. Mengoptimalkan stop loss/take profit dinamis

Kesimpulan

Strategi Reversal Tracking Dual Channel menggunakan indikator seperti Bollinger Bands dan Keltner Channels untuk trading reversal. Dengan optimasi parameter, dapat diadaptasi ke berbagai produk untuk mengidentifikasi validitas breakout sampai batas tertentu.


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