Strategi ini bertujuan untuk menangkap trend yang kuat di pasaran mata wang kripto dengan menggunakan pelbagai saluran dan purata bergerak untuk mengenal pasti isyarat trend, dan menggabungkan penunjuk jumlah untuk menapis pecah palsu sambil secara adaptif menghentikan kerugian untuk mengunci keuntungan, yang membolehkan keuntungan dibuat di pasaran yang sedang berkembang.
Strategi ini menggunakan gabungan saluran pantas, saluran perlahan dan purata bergerak pantas untuk mengenal pasti trend. Parameter saluran pantas lebih sensitif untuk menangkap turun naik harga jangka pendek; parameter saluran perlahan lebih sederhana untuk menilai trend utama; parameter purata bergerak pantas berada di antara, menghasilkan isyarat perdagangan apabila ia menembusi saluran.
Secara khusus, ia mula-mula mengira rel atas dan bawah saluran pantas, dan purata bergerak. Apabila harga menembusi rel atas, jika rel bawah saluran perlahan juga di atas purata bergerak, isyarat panjang dihasilkan; sebaliknya, apabila ia menembusi rel bawah, ia memeriksa sama ada rel atas saluran perlahan di bawah purata bergerak, menghasilkan isyarat pendek.
Di samping itu, ia mengesan corak K-line, yang memerlukan beberapa K-line disusun secara berurutan untuk menapis pecah palsu; dan mengira penunjuk kadar perubahan harga untuk menentukan sama ada ia telah memasuki penyatuan untuk mengelakkan peluang pembalikan yang hilang; dan menggabungkan penunjuk jumlah untuk memastikan jumlah mengikuti harga pada pecah.
Untuk stop loss, strategi ini menggunakan stop loss adaptif. Berdasarkan turun naik baru-baru ini, ia secara dinamik menyesuaikan peratusan stop loss. Ini membolehkan mengunci sebanyak mungkin keuntungan trend sambil memastikan stop loss yang berkesan.
Kelebihan terbesar strategi ini adalah bahawa kriteria untuk menghasilkan isyarat perdagangan agak ketat, yang dapat menapis secara berkesan pecah palsu bukan trend dan benar-benar menangkap titik perubahan dalam trend pasaran.
Gabungan pelbagai saluran dan purata bergerak mempunyai kriteria yang lebih ketat dan boleh mengurangkan kebarangkalian penilaian yang salah.
K-line urutan pengesahan mengelakkan isyarat yang salah dari satu K-line yang menyimpang.
Memasukkan penunjuk kadar perubahan harga boleh menentukan sama ada ia telah memasuki penyatuan untuk mengelakkan peluang pembalikan yang hilang.
Menambah pertimbangan penunjuk jumlah memastikan isyarat dihasilkan hanya apabila jumlah mengikuti harga, mengelakkan pecah yang tidak berkesan.
Mekanisme stop loss adaptif boleh memaksimumkan kunci keuntungan trend sambil memastikan stop loss.
Jadi secara umum, strategi ini mempunyai ciri-ciri konfigurasi yang optimum, membuat keputusan yang bijak, stop loss adaptif, menjadikannya sangat sesuai untuk menangkap peluang trend.
Walaupun strategi ini telah melakukan banyak pengoptimuman dalam menapis pecah palsu dan menangkap trend, masih ada beberapa risiko yang perlu diperhatikan:
Tetapan parameter yang kompleks boleh membawa kepada perbezaan besar antara kombinasi parameter, yang memerlukan ujian yang luas untuk mencari parameter optimum, jika tidak, ia mungkin menghasilkan terlalu banyak isyarat palsu.
Apabila jurang antara purata bergerak pantas dan saluran terlalu kecil, ia cenderung menghasilkan entri dan keluar yang kerap, yang tidak kondusif untuk mengesan trend yang berterusan.
Pengiraan peratusan stop loss dalam mekanisme stop loss adaptif bergantung kepada penyimpangan standard yang mudah, yang boleh menyebabkan stop loss yang tidak mencukupi dalam keadaan pasaran yang melampau.
Ia sangat bergantung kepada penunjuk teknikal dan mungkin tidak dapat bertindak balas terhadap perubahan asas yang besar.
Sebagai trend yang mengikuti strategi, ia kurang berprestasi di pasaran bergelombang.
Untuk mengawal risiko ini, langkah-langkah berikut disyorkan:
Lakukan pengujian belakang yang mencukupi untuk menentukan kombinasi parameter yang optimum, atau pertimbangkan menggunakan pembelajaran mesin untuk pengoptimuman parameter.
Secara sederhana meluaskan selang saluran, memanjangkan tempoh purata bergerak untuk mengurangkan entri yang tidak perlu.
Pertimbangkan untuk memperkenalkan model turun naik yang lebih maju seperti kaedah dana lindung nilai.
Rujuk maklumat asas dengan tepat pada masanya untuk mengelakkan perdagangan yang murni teknikal.
Tingkatkan penilaian terhadap keadaan pasaran dan hentikan perdagangan di pasaran yang bergelora.
Strategi ini boleh dioptimumkan lagi dengan cara berikut:
Memperkenalkan algoritma pembelajaran mesin untuk mencapai pengoptimuman parameter automatik, dengan merekodkan prestasi parameter dalam persekitaran pasaran yang berbeza untuk membina jadual carian untuk pengoptimuman dinamik.
Tambah penilaian mengenai keadaan pasaran, seperti menambah modul untuk menentukan sama ada pasaran adalah trend atau bergelombang, dan hentikan perdagangan di pasaran bergelombang untuk mengelakkan kerugian yang tidak perlu.
Mengoptimumkan strategi stop loss, seperti trailing stop loss, stop loss proporsional dan lain-lain
Memasukkan faktor asas untuk menghantar amaran apabila peristiwa asas utama berlaku, mengelakkan kerugian berdasarkan indikator teknikal semata-mata.
Melakukan pengoptimuman portfolio, menggabungkan strategi ini dengan strategi lain yang tidak berkaitan untuk lebih mempelbagaikan risiko.
Memperkenalkan rangka kerja perdagangan kuantitatif untuk pelaksanaan isyarat automatik dan kawalan risiko yang ketat.
Ringkasnya, strategi ini sangat sesuai untuk menangkap peluang trend di pasaran mata wang kripto. Ia menggunakan pelbagai saluran dan purata bergerak untuk menjana isyarat perdagangan, dan berkesan menapis bunyi pecah palsu dan berjaya mengunci keuntungan trend. Tetapi pengoptimuman parameter, kaedah berhenti kerugian, penilaian keadaan pasaran dll masih memerlukan perhatian. Dengan peningkatan berterusan, ia berpotensi untuk pulangan pelaburan yang stabil. Ia memberikan contoh yang baik untuk reka bentuk 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)