Chiến lược này nhằm mục đích nắm bắt các xu hướng mạnh trên thị trường tiền điện tử bằng cách sử dụng nhiều kênh và đường trung bình động để xác định các tín hiệu xu hướng, và kết hợp các chỉ số khối lượng để lọc các sự đột phá sai trong khi thích nghi ngăn chặn thua lỗ để khóa lợi nhuận, cho phép lợi nhuận được thực hiện trong các thị trường xu hướng.
Chiến lược này sử dụng sự kết hợp của kênh nhanh, kênh chậm và trung bình di chuyển nhanh để xác định xu hướng. Các thông số kênh nhanh nhạy cảm hơn để nắm bắt biến động giá ngắn hạn; các thông số kênh chậm ôn hòa hơn để đánh giá xu hướng chính; các thông số trung bình di chuyển nhanh nằm ở giữa, tạo ra các tín hiệu giao dịch khi nó phá vỡ kênh.
Cụ thể, nó đầu tiên tính toán các đường ray trên và dưới của kênh nhanh, và trung bình động. Khi giá vượt qua đường ray trên, nếu đường ray dưới của kênh chậm cũng vượt quá mức trung bình động, một tín hiệu dài sẽ được tạo ra; ngược lại, khi nó vượt qua đường ray dưới, nó kiểm tra xem đường ray trên của kênh chậm có dưới mức trung bình động không, tạo ra tín hiệu ngắn.
Ngoài ra, nó phát hiện mô hình đường K, yêu cầu nhiều đường K phải được sắp xếp theo trình tự để lọc các sự đột phá sai; và tính toán chỉ số tỷ lệ thay đổi giá để xác định xem nó đã tham gia hợp nhất để tránh bỏ lỡ cơ hội đảo ngược; và kết hợp các chỉ số khối lượng để đảm bảo khối lượng theo sau giá khi đột phá.
Đối với stop loss, chiến lược sử dụng stop loss thích nghi. Dựa trên sự biến động gần đây, nó điều chỉnh năng động tỷ lệ stoploss. Điều này cho phép khóa càng nhiều lợi nhuận xu hướng càng tốt trong khi đảm bảo stop loss hiệu quả.
Ưu điểm lớn nhất của chiến lược này là các tiêu chí để tạo ra tín hiệu giao dịch tương đối nghiêm ngặt, có thể lọc hiệu quả các breakout sai không theo xu hướng và thực sự nắm bắt các điểm chuyển đổi trong xu hướng thị trường.
Sự kết hợp của nhiều kênh và đường trung bình động có các tiêu chí nghiêm ngặt hơn và có thể làm giảm khả năng đánh giá sai.
Xác nhận trình tự K-line tránh các tín hiệu sai từ một K-line lệch.
Việc kết hợp chỉ số tỷ lệ thay đổi giá có thể xác định liệu nó đã gia nhập hợp nhất để tránh bỏ lỡ cơ hội đảo ngược.
Việc thêm đánh giá chỉ số khối lượng đảm bảo tín hiệu chỉ được tạo ra khi khối lượng theo sau giá, tránh sự đột phá không hiệu quả.
Cơ chế dừng lỗ thích nghi có thể tối đa hóa việc khóa lợi nhuận xu hướng trong khi đảm bảo dừng lỗ.
Vì vậy, nói chung, chiến lược này có các đặc điểm của cấu hình tối ưu, ra quyết định thận trọng, dừng lỗ thích nghi, làm cho nó rất phù hợp để nắm bắt các cơ hội xu hướng.
Mặc dù chiến lược này đã thực hiện rất nhiều tối ưu hóa trong việc lọc các sự đột phá giả và nắm bắt xu hướng, nhưng vẫn có một số rủi ro cần lưu ý:
Cài đặt tham số phức tạp có thể dẫn đến sự khác biệt lớn giữa các kết hợp tham số, đòi hỏi phải thử nghiệm rộng rãi để tìm các tham số tối ưu, nếu không có thể tạo ra quá nhiều tín hiệu sai.
Khi khoảng cách giữa trung bình động nhanh và kênh quá nhỏ, nó có xu hướng tạo ra các bước vào và ra thường xuyên, điều này không thuận lợi cho việc theo dõi xu hướng liên tục.
Tính toán tỷ lệ stop loss trong cơ chế stop loss thích nghi dựa trên độ lệch chuẩn đơn giản, có thể dẫn đến stop loss không đủ trong điều kiện thị trường cực đoan.
Nó phụ thuộc nhiều vào các chỉ số kỹ thuật và có thể không phản ứng với những thay đổi cơ bản lớn.
Là một xu hướng theo chiến lược, nó hoạt động kém hơn trong các thị trường hỗn loạn.
Để kiểm soát những rủi ro này, các biện pháp sau đây được khuyến cáo:
Thực hiện kiểm tra ngược đủ để xác định kết hợp tham số tối ưu, hoặc xem xét sử dụng máy học để tối ưu hóa tham số.
Giới hạn mở rộng khoảng thời gian kênh, kéo dài thời gian trung bình di chuyển để giảm các mục không cần thiết.
Xem xét việc giới thiệu các mô hình biến động tiên tiến hơn như phương pháp quỹ phòng hộ.
Liên hệ thông tin cơ bản kịp thời để tránh giao dịch kỹ thuật thuần túy.
Tăng sự phán đoán về tình trạng thị trường và tạm dừng giao dịch trong các thị trường hỗn loạn.
Chiến lược có thể được tối ưu hóa thêm theo các cách sau:
giới thiệu các thuật toán học máy để đạt được tối ưu hóa tham số tự động, bằng cách ghi lại hiệu suất tham số trong các môi trường thị trường khác nhau để xây dựng bảng tìm kiếm cho tối ưu hóa năng động.
Thêm phán đoán về tình trạng thị trường, chẳng hạn như thêm các mô-đun để xác định xem thị trường có xu hướng hay bất ổn, và tạm dừng giao dịch trong các thị trường bất ổn để tránh tổn thất không cần thiết.
Tối ưu hóa các chiến lược dừng lỗ, chẳng hạn như dừng lỗ sau, dừng lỗ tỷ lệ vv
Bao gồm các yếu tố cơ bản để gửi cảnh báo khi các sự kiện cơ bản lớn xảy ra, tránh tổn thất dựa trên chỉ số kỹ thuật.
Thực hiện tối ưu hóa danh mục đầu tư, kết hợp chiến lược này với các chiến lược không liên quan khác để đa dạng hóa rủi ro hơn nữa.
Đưa ra khuôn khổ giao dịch định lượng cho việc thực hiện tín hiệu tự động và kiểm soát rủi ro nghiêm ngặt.
Tóm lại, chiến lược này rất phù hợp để nắm bắt các cơ hội xu hướng trên thị trường tiền điện tử. Nó sử dụng nhiều kênh và trung bình động để tạo ra tín hiệu giao dịch, và lọc hiệu quả tiếng ồn đột phá sai và khóa thành công lợi nhuận xu hướng. Nhưng tối ưu hóa tham số, phương pháp dừng lỗ, đánh giá trạng thái thị trường vv vẫn cần chú ý. Với sự cải thiện liên tục, nó có tiềm năng cho lợi nhuận đầu tư ổn định. Nó cung cấp một ví dụ tuyệt vời cho thiết kế chiến lược định lượng.
/*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)