Strategi Breakout Tren Overfit yang Ekstrim

Penulis:ChaoZhang, Tanggal: 2023-09-28
Tag:

Ringkasan

Strategi ini bertujuan untuk menangkap tren kuat di pasar cryptocurrency dengan menggunakan beberapa saluran dan moving average untuk mengidentifikasi sinyal tren, dan menggabungkan indikator volume untuk menyaring breakout palsu sambil secara adaptif menghentikan kerugian untuk mengunci keuntungan, memungkinkan keuntungan untuk dibuat di pasar tren.

Prinsip Strategi

Strategi ini menggunakan kombinasi saluran cepat, saluran lambat dan rata-rata bergerak cepat untuk mengidentifikasi tren. Parameter saluran cepat lebih sensitif untuk menangkap fluktuasi harga jangka pendek; Parameter saluran lambat lebih moderat untuk menilai tren utama; Parameter rata-rata bergerak cepat berada di antara, menghasilkan sinyal perdagangan ketika memecahkan saluran.

Secara khusus, pertama-tama menghitung rel atas dan bawah saluran cepat, dan rata-rata bergerak. Ketika harga menembus rel atas, jika rel bawah saluran lambat juga di atas rata-rata bergerak, sinyal panjang dihasilkan; sebaliknya, ketika menembus rel bawah, ia memeriksa apakah rel atas saluran lambat di bawah rata-rata bergerak, menghasilkan sinyal pendek.

Selain itu, ia mendeteksi pola K-line, yang mengharuskan beberapa K-line disusun secara berurutan untuk menyaring breakout palsu; dan menghitung indikator tingkat perubahan harga untuk menentukan apakah telah memasuki konsolidasi untuk menghindari kesempatan pembalikan yang hilang; dan menggabungkan indikator volume untuk memastikan volume mengikuti harga pada saat breakout.

Untuk stop loss, strategi ini menggunakan stop loss adaptif. Berdasarkan volatilitas baru-baru ini, secara dinamis menyesuaikan persentase stop loss. Hal ini memungkinkan mengunci sebagian besar keuntungan tren sebanyak mungkin sambil memastikan stop loss yang efektif.

Analisis Keuntungan

Keuntungan terbesar dari strategi ini adalah bahwa kriteria untuk menghasilkan sinyal perdagangan relatif ketat, yang dapat secara efektif menyaring keluar non-trend false breakout dan benar-benar menangkap titik balik dalam tren pasar.

  1. Kombinasi dari beberapa saluran dan rata-rata bergerak memiliki kriteria yang lebih ketat dan dapat mengurangi kemungkinan penilaian yang salah.

  2. K-line sequence validation menghindari sinyal yang salah dari satu K-line yang menyimpang.

  3. Menggabungkan indikator tingkat perubahan harga dapat menentukan apakah telah memasuki konsolidasi untuk menghindari kesempatan pembalikan yang hilang.

  4. Menambahkan penilaian indikator volume memastikan sinyal hanya dihasilkan ketika volume mengikuti harga, menghindari pecah yang tidak efektif.

  5. Mekanisme stop loss adaptif dapat memaksimalkan penguncian keuntungan tren sambil memastikan stop loss.

Jadi secara umum, strategi ini memiliki karakteristik konfigurasi yang dioptimalkan, pengambilan keputusan yang bijaksana, stop loss adaptif, membuatnya sangat cocok untuk menangkap peluang tren.

Analisis Risiko

Meskipun strategi ini telah melakukan banyak optimasi dalam menyaring terobosan palsu dan menangkap tren, masih ada beberapa risiko yang perlu diperhatikan:

  1. Pengaturan parameter yang kompleks dapat menyebabkan perbedaan besar antara kombinasi parameter, yang membutuhkan pengujian ekstensif untuk menemukan parameter optimal, jika tidak dapat menghasilkan terlalu banyak sinyal palsu.

  2. Ketika kesenjangan antara rata-rata bergerak cepat dan saluran terlalu kecil, cenderung menghasilkan entri dan keluar yang sering, yang tidak kondusif untuk melacak tren secara terus menerus.

  3. Perhitungan persentase stop loss dalam mekanisme stop loss adaptif didasarkan pada standar deviasi sederhana, yang dapat menyebabkan stop loss yang tidak cukup dalam kondisi pasar yang ekstrem.

  4. Hal ini sangat bergantung pada indikator teknis dan mungkin gagal menanggapi perubahan fundamental yang besar.

  5. Sebagai tren yang mengikuti strategi, ia berkinerja buruk di pasar yang bergolak.

Untuk mengendalikan risiko ini, langkah-langkah berikut direkomendasikan:

  1. Lakukan backtesting yang cukup untuk menentukan kombinasi parameter yang optimal, atau pertimbangkan untuk menggunakan pembelajaran mesin untuk optimasi parameter.

  2. Secara sederhana memperluas interval saluran, memperpanjang periode rata-rata bergerak untuk mengurangi entri yang tidak perlu.

  3. Pertimbangkan untuk memperkenalkan model volatilitas yang lebih maju seperti metode hedge fund.

  4. Rujuk informasi dasar secara tepat waktu untuk menghindari perdagangan yang murni teknis.

  5. Tingkatkan penilaian pada kondisi pasar dan hentikan perdagangan di pasar yang bergolak.

Optimalisasi

Strategi dapat dioptimalkan lebih lanjut dengan cara berikut:

  1. Memperkenalkan algoritma pembelajaran mesin untuk mencapai optimasi parameter otomatis, dengan merekam kinerja parameter di lingkungan pasar yang berbeda untuk membangun tabel pencarian untuk optimasi dinamis.

  2. Tambahkan penilaian pada kondisi pasar, seperti menambahkan modul untuk menentukan apakah pasar sedang tren atau bergolak, dan jeda perdagangan di pasar bergolak untuk menghindari kerugian yang tidak perlu.

  3. Mengoptimalkan strategi stop loss, seperti trailing stop loss, stop loss proporsional dll.

  4. Menggabungkan faktor fundamental untuk mengirim peringatan ketika peristiwa fundamental utama terjadi, menghindari kerugian berdasarkan indikator teknis saja.

  5. Melakukan optimalisasi portofolio, menggabungkan strategi ini dengan strategi lain yang tidak terkait untuk lebih mendiversifikasi risiko.

  6. Memperkenalkan kerangka perdagangan kuantitatif untuk eksekusi sinyal otomatis dan kontrol risiko yang ketat.

Kesimpulan

Singkatnya, strategi ini sangat cocok untuk menangkap peluang tren di pasar cryptocurrency. Ini menggunakan beberapa saluran dan moving average untuk menghasilkan sinyal perdagangan, dan secara efektif menyaring kebisingan breakout palsu dan berhasil mengunci keuntungan tren. Tapi optimasi parameter, metode stop loss, penilaian keadaan pasar dll masih membutuhkan perhatian. Dengan perbaikan terus-menerus, ini memiliki potensi untuk pengembalian investasi yang stabil. Ini memberikan contoh yang bagus untuk desain strategi kuantitatif.


/*backtest
start: 2022-09-21 00:00:00
end: 2023-09-27 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
strategy("Extremely Overfit", overlay=true, commission_type=strategy.commission.percent, commission_value=.16, default_qty_type=strategy.percent_of_equity, default_qty_value=100, pyramiding = 1)
price = close

goLong = input(title="go long?", type=input.bool, defval=true)
goShort = input(title="go short?", type=input.bool, defval=true)
//trendRestrict = input(title="basic trend restriction?", type=input.bool, defval=false)
dynamicRestrict = true //input(title="dynamic trend restriction?", type=input.bool, defval=true)
longtrendimpt = true //input(title="additional weight on long-term trends?", type=input.bool, defval=true)
volRestrict = true //input(title="volume restriction?", type=input.bool, defval=true)
conservativeClose = false //input(title="conservative order closing?", type=input.bool, defval=false)

Restrictiveness = input ( -40,step=10,title ="Restrictiveness (higher = make fewer trades)")
volatilityImportance = 3.2 //input( 3.2, step = 0.1, minval = 0)
fastChannelLength = input( 6 )
fastChannelMargin = input ( 3.2, step = 0.1, minval = 0)
slowChannelLength = input ( 6, step = 1, minval = 0)
slowChannelMargin = input ( 1.5, step = 0.1, minval = 0)
fastHMAlength = input (4, step = 1, minval = 0)
stopLoss = input( 3, step = 0.1, minval = 0)
//altClosePeriod = input( 27, step = 1, minval = 1)
//altCloseFactor = input( 4.9, step = 0.1)
stopLossFlexibility = 50 //input(50, step=10, title="effect of volatility on SL?")
volumeMAlength = 14 //input ( 14, step = 1, minval = 1)
volumeVolatilityCutoff = 3.8 // ( 3.8, step = 1, minval = 0)
trendSensitivity = 3.8 //input ( 3.8, step = 0.1)
obvLookback = 10 //input(10, step = 10, minval = 10)
obvCorrThreshold = 0.89 //input(0.89, step = 0.01)
ROClength = 80 //input( 80, step = 10)
ROCcutoff = 5.6 //input( 5.6, step=0.1)

trendRestrict = false
//trendLookback = input ( 360, step = 10, minval = 10)
//longTrendLookback = input(720, step = 10, minval = 10)
//longTrendImportance = input(1.5, step = 0.05)
trendLookback = 360
longTrendLookback = 720
longTrendImportance = 1.5

//conservativeness = input( 2.4, step = 0.1)
conservativeness = 0
//trendPower = input( 0, step=1)
trendPower = 0
//conservativenessLookback = input( 650, step = 10, minval = 0)
conservativenessLookback = 10
//consAffectFactor = input( 0.85,step=0.01)
consAffectFactor = 0.85
//volatilityLookback = input(50, step=1, minval=2)
volatilityLookback = int(50)
recentVol = stdev(price,volatilityLookback)/sqrt(volatilityLookback)

//price channel

fastChannel = ema(price, fastChannelLength)
fastChannelUB = fastChannel * (1 + (float(fastChannelMargin) / 1000)) + (recentVol * (float(volatilityImportance) * (1 + (Restrictiveness/100))))
fastChannelLB = fastChannel * (1 - (float(fastChannelMargin) / 1000)) - (recentVol * (float(volatilityImportance) * (1 + (Restrictiveness/100))))
fchU = ((fastChannelUB < open) and (fastChannelUB < close))
fchL = ((fastChannelLB > open) and (fastChannelLB > close))
//plot(fastChannelUB)
//plot(fastChannelLB)

//slow channel
//slowChannelLBmargin = input ( 2, step = 0.1, minval = 0 )
slowChannel = ema(ema(price,slowChannelLength),slowChannelLength)
slowChannelUB = slowChannel * (1 + (float(slowChannelMargin) / 2000)) + (recentVol * (float(volatilityImportance) * (1 + (Restrictiveness/100))))
slowChannelLB = slowChannel * (1 - (float(slowChannelMargin) / 2000)) - (recentVol * (float(volatilityImportance) * (1 + (Restrictiveness/100))))
schU = ((slowChannelUB < close))
schL = ((slowChannelLB > close))
cschU = (((slowChannelUB * (1 + conservativeness)) < close))
cschL = (((slowChannelUB * (1 - conservativeness)) > close))
//plot(slowChannel,color = #00FF00)
//plot(slowChannelUB,color = #00FF00)
//plot(slowChannelLB,color = #00FF00)


fastHMA = hma(price,fastHMAlength)
fastAboveUB = (fastHMA > slowChannelUB)
fastBelowLB = (fastHMA < slowChannelLB)
//plot(fastHMA, color = 	#FF0000, linewidth = 2)

//consecutive candles
//consecutiveCandlesReq = input(1, step = 1, minval = 1, maxval = 4)
consecutiveCandlesReq = 1
consecutiveBullReq = float(consecutiveCandlesReq)
consecutiveBearReq = float(consecutiveCandlesReq)
cbull = ((close[0] > close[1]) and (consecutiveBullReq == 1)) or (((close[0] > close[1]) and (close[1] > close[2])) and consecutiveBullReq == 2) or (((close[0] > close[1]) and (close[1] > close[2]) and (close[2] > close[3])) and consecutiveBullReq == 3) or (((close[0] > close[1]) and (close[1] > close[2]) and (close[2] > close[3]) and (close[3] > close[4])) and consecutiveBullReq == 4)
cbear = ((close[0] < close[1]) and (consecutiveBearReq == 1)) or (((close[0] < close[1]) and (close[1] < close[2])) and consecutiveBearReq == 2) or (((close[0] < close[1]) and (close[1] < close[2]) and (close[2] < close[3])) and consecutiveBearReq == 3) or (((close[0] < close[1]) and (close[1] < close[2]) and (close[2] < close[3]) and (close[3] < close[4])) and consecutiveBearReq == 4)

//trend detection
//trendCutoff = input(0, step = 0.1)
trendCutoff = 0
trendDetectionPct = float(trendCutoff/100)
trendVal = float((close[0] - close[trendLookback])/close[0])
trendUp = (trendVal > (0 + trendDetectionPct))
trendDown = (trendVal < (0 - trendDetectionPct))
//plot(trendVal+36.5,linewidth=2)

// peak indicators
peakHigh = ((fastHMA > fastChannelUB) and (fastChannelLB > slowChannelUB))
peakLow = ((fastHMA < fastChannelLB) and (fastChannelUB < slowChannelLB))
TpeakHigh = (fastHMA > fastChannelUB) and (fastChannelUB > slowChannelUB)
TpeakLow = (fastHMA < fastChannelUB) and (fastChannelLB < slowChannelLB)
//TpeakHigh = (fastHMA > fastChannelUB) and (fastChannelLB > avg(slowChannelUB,slowChannelLB))
//TpeakLow = (fastHMA < fastChannelUB) and (fastChannelUB < avg(slowChannelLB,slowChannelUB))
//TpeakHigh = ((crossover(fastHMA,fastChannelUB)) and (fastChannelLB > slowChannelUB))
//TpeakLow = ((crossover(fastChannelLB,fastHMA)) and (fastChannelUB < slowChannelLB))
//TpeakHigh = (fastHMA > (fastChannelUB * (1 + (trendPower/800)))) and (fastChannelUB > (slowChannelUB * (1 + (trendPower/800))))
//TpeakLow = (fastHMA < (fastChannelUB * (1 - (trendPower/800)))) and (fastChannelLB < (slowChannelLB * (1 - (trendPower/800))))
//TpeakHigh = (fastHMA > (fastChannelUB * (1 + (trendPower/800)))) and (avg(fastChannelUB,fastChannelLB) > (slowChannelUB * (1 + (trendPower/800))))
//TpeakLow = (fastHMA < (fastChannelUB * (1 - (trendPower/800)))) and (avg(fastChannelLB,fastChannelUB) < (slowChannelLB * (1 - (trendPower/800))))
//plot(fastChannelUB * (1 + (trendPower/700)), color=#FF69B4)

// and for closing...
closeLong = (crossover(fastHMA,fastChannelUB) and (fastChannelLB > slowChannelUB))
closeShort = (crossover(fastChannelLB,fastHMA) and (fastChannelUB < slowChannelLB))
//closeLong = (crossover(fastHMA,fastChannelUB) and (fastChannelLB > slowChannelUB)) or (roc(price,altClosePeriod) > altCloseFactor)
//closeShort = (crossover(fastChannelLB,fastHMA) and (fastChannelUB < slowChannelLB))  or (roc(price,altClosePeriod) < (altCloseFactor) * -1)
//closeLong = (crossover(fastHMA,fastChannelUB) and (fastChannelLB > slowChannelUB)) or (((price - fastChannelUB) > (altCloseFactor * abs(((fastChannelUB - fastChannelLB)/2) - ((slowChannelUB - slowChannelLB)/2)))) and (fastChannelLB > slowChannelUB))
//closeShort = (crossover(fastChannelLB,fastHMA) and (fastChannelUB < slowChannelLB)) or (((fastChannelLB - price) > (altCloseFactor * abs(((fastChannelUB - fastChannelLB)/2) - ((slowChannelUB - slowChannelLB)/2)))) and (fastChannelUB < slowChannelLB))
//closeLong = crossover(fastHMA,fastChannelUB) and ((fastChannelLB[0] - fastChannelLB[1]) < (slowChannelUB[0] - slowChannelUB[1]))
//closeShort = crossover(fastChannelLB,fastHMA) and ((fastChannelUB[0] - fastChannelUB[1]) > (slowChannelLB[0] - slowChannelLB[1]))


//stop-loss
priceDev = stdev(price,trendLookback) * (1 + stopLossFlexibility/5)
stopLossMod = stopLoss * (1 + (priceDev/price))
//longStopPrice  = strategy.position_avg_price * (1 - (stopLoss/100))
//shortStopPrice = strategy.position_avg_price * (1 + (stopLoss/100))
longStopPrice  = strategy.position_avg_price * (1 - (stopLossMod/100))
shortStopPrice = strategy.position_avg_price * (1 + (stopLossMod/100))


// volume
volumeMA = ema(volume,volumeMAlength)
volumeDecrease = ((not volRestrict ) or (volumeMA[0] < ema(volumeMA[1] * (1 - (volumeVolatilityCutoff/100)),5)))
volumeCutoff = ema(volumeMA[1] * (1 - (volumeVolatilityCutoff/100)),5)
//plot(volumeMA)
//plot(volumeCutoff)

// detect volatility
//trendinessLookback = input ( 600, step = 10, minval = 0)
trendinessLookback = trendLookback
trendiness = (stdev(price,trendinessLookback)/price) * (1 - (Restrictiveness/100))
longtermTrend = ((price - price[longTrendLookback])/price)
//dynamicTrendDetected = (dynamicRestrict and (abs(trendiness * 100) < trendSensitivity))
dynamicTrendDetected = (longtrendimpt and (dynamicRestrict and (abs(trendiness * 100) < (trendSensitivity+(longtermTrend * longTrendImportance))))) or (not longtrendimpt and ((dynamicRestrict and (abs(trendiness * 100) < trendSensitivity))))

// adapt conservativeness to volatility

//consVal = sma(((stdev(price,conservativenessLookback))/price)*100,25)
consVal = sma(((stdev(price,conservativenessLookback))/price)*100,25)
cVnorm = sma(avg(consVal,3),60)
cVal = consVal - cVnorm

//conservativenessMod = conservativeness * (cVal * consAffectFactor)
conservativenessMod = conservativeness * (consVal * consAffectFactor)
//plot(consVal,linewidth=4)
//plot(cVnorm,color = #00FF00)
//plot(cVal,linewidth=2)

// ROC cutoff (for CLOSING)
//rocCloseLong = (ema(roc(price,ROClength),10) > ROCcutoff)
//rocCloseShort = (ema(roc(price,ROClength),10) < (ROCcutoff * -1))
ROCval = roc(price,ROClength)
ROCema = ema(ROCval,30)
ROCabs = abs(ROCema)
ROCallow = ROCabs < ROCcutoff
ROCallowLong = (ROCabs < ROCcutoff)  or ((ROCabs >= ROCcutoff) and ((fastChannelLB < slowChannelLB) and (fastHMA < fastChannelLB)))
ROCallowShort = (ROCabs < ROCcutoff) or ((ROCabs >= ROCcutoff) and ((fastChannelUB > slowChannelUB) and (fastHMA > fastChannelUB)))
//plot(ROCallow)

// obv
evidence_obv = (correlation(price,obv[0],obvLookback))
obvAllow = evidence_obv > obvCorrThreshold


//if (not na(vrsi))
if trendRestrict or dynamicTrendDetected
    //if (strategy.position_size == 0)
    if not (strategy.position_size < 0)
        if trendUp
        	//if cbear and schL and fchL and trendUp and goLong
        	if cbear and TpeakLow and volumeDecrease and ROCallow and goLong and obvAllow
        	//if cbear and peakLow and rocHigh and volumeDecrease and goLong
        		strategy.entry("Long", strategy.long, comment="Long")
    if not (strategy.position_size > 0)
        if trendDown
        	//if cbull and schU and fchU and trendDown and goShort
        	if cbull and TpeakHigh and volumeDecrease and ROCallow and goShort and obvAllow
        	//if cbull and peakHigh and rocLow and volumeDecrease and goShort
        		strategy.entry("Short", strategy.short, comment="Short")
else
    //if (strategy.position_size == 0)
    if not (strategy.position_size < 0)
        //if cbear and peakLow and goLong
    	//if cbear and peakLow and volumeDecrease and ROCallow and goLong
    	if TpeakLow and goLong and obvAllow
    		strategy.entry("Long", strategy.long, comment="Long")
    if not (strategy.position_size > 0)
        //if cbull and peakHigh and goShort
    	//if cbull and peakHigh and volumeDecrease and ROCallow and goShort
    	if TpeakHigh and goShort and obvAllow
    		strategy.entry("Short", strategy.short, comment="Short")

if conservativeClose
    //pkHigh = ((fastHMA > fastChannelUB) and (fastChannelUB > (slowChannelUB * (1 + conservativeness/1000))))
    //pkLow = ((fastHMA < fastChannelLB) and (fastChannelLB < (slowChannelLB * (1 - conservativeness/1000))))
    //pkHigh = ((fastHMA > fastChannelUB) and (fastChannelUB > (slowChannelUB * (1 + conservativenessMod/1000))))
    //pkLow = ((fastHMA < fastChannelLB) and (fastChannelLB < (slowChannelLB * (1 - conservativenessMod/1000))))
    pkHigh = ((fastHMA > fastChannelUB) and (fastChannelUB > (slowChannelUB * (1 + ((conservativenessMod/1000) * (1 - Restrictiveness/100))))))
    pkLow = ((fastHMA < fastChannelLB) and (fastChannelLB < (slowChannelLB * (1 - ((conservativenessMod/1000) * (1 - Restrictiveness/100))))))
    
    if (strategy.position_size > 0)
        //if fastAboveUB
        //if pkHigh and closeLong
        if closeLong
    		strategy.close("Long", comment="closeLong")
    if (strategy.position_size < 0)
        //if fastBelowLB
        //if pkLow and closeShort
        if closeShort
    		strategy.close("Short", comment="closeShort")
else
    if (strategy.position_size > 0)
        //if fastAboveUB
        if peakHigh
    		strategy.close("Long", comment="closeLong")
    if (strategy.position_size < 0)
        //if fastBelowLB
        if peakLow
    		strategy.close("Short", comment="closeShort")

if (strategy.position_size > 0)
    strategy.exit(id="Long", stop=longStopPrice, comment="stopLong")

if (strategy.position_size < 0)
    strategy.exit(id="Short", stop=shortStopPrice, comment="stopShort")
//plot(strategy.equity, title="equity", color=color.red, linewidth=2, style=plot.style_areabr)












Lebih banyak