Chiến lược này được đặt tên là RSI_OTT-TP / SL. Nó kết hợp chỉ số RSI và dải OTT để xác định các tín hiệu giao dịch, thuộc về các chiến lược theo xu hướng. Chiến lược đánh giá hướng xu hướng thị trường thông qua chỉ số RSI và sử dụng dải OTT để xác định các điểm nhập cụ thể. Nó cũng cho phép người dùng đặt tỷ lệ lấy lợi nhuận và dừng lỗ để khóa lợi nhuận hoặc tránh thua lỗ tự động.
Chiến lược này sử dụng các chỉ số RSI và OTT để xác định xu hướng và điểm nhập cảnh.
Chỉ số RSI được sử dụng để đánh giá hướng xu hướng tổng thể. Chỉ số RSI có thể cho thấy thị trường có bị mua quá mức hay bán quá mức không. RSI vượt trên mức mua quá mức là tín hiệu mua, trong khi vượt dưới mức bán quá mức là tín hiệu bán. Độ dài mặc định của chỉ số RSI là 6, mức mua quá mức là 50 và mức bán quá mức cũng là 50 trong chiến lược này.
Các dải OTT được sử dụng để phát hiện các điểm nhập. Chúng là các dải được hình thành dựa trên chỉ số tỷ lệ biến động (VAR). Khi giá vượt qua dải dưới lên, đó là tín hiệu mua. Khi giá vượt qua dải trên xuống, đó là tín hiệu bán.
Sau khi xác định xu hướng và xác nhận điểm nhập cảnh, chiến lược này sẽ mở các vị trí dài hoặc ngắn khi giá vượt qua dải OTT.
Chiến lược sẽ đóng các vị trí tự động khi giá lấy lợi nhuận hoặc dừng lỗ được chạm vào.
Chiến lược cũng cho phép giao dịch chỉ dài, chỉ ngắn hoặc cả hai hướng.
Kết hợp các băng tần RSI và OTT có thể tìm ra các điểm nhập cảnh có xác suất cao dưới sự đánh giá xu hướng chính xác.
Các băng tần OTT sử dụng chỉ số động lực và rất nhạy cảm với biến động giá, có thể phát hiện các điểm chuyển đổi sớm.
Các chức năng lấy lợi nhuận và dừng lỗ giúp khóa lợi nhuận và hạn chế lỗ trước khi chúng mở rộng, có lợi cho kiểm soát rủi ro.
Cấu trúc mã là rõ ràng với đủ các bình luận, dễ hiểu và sửa đổi.
Các tham số chiến lược có thể được điều chỉnh linh hoạt thông qua giao diện để thích nghi với môi trường thị trường khác nhau.
RSI có sự chậm phát hành và có thể bỏ lỡ các điểm đảo ngược xu hướng, dẫn đến tổn thất không cần thiết.
Các băng tần OTT cũng có thể tạo ra tín hiệu sai.
Các thiết lập lấy lợi nhuận và dừng lỗ không chính xác sẽ ảnh hưởng đến hiệu suất chiến lược.
Chiến lược chỉ được kiểm tra lại trên một sản phẩm duy nhất. Các thông số nên được tối ưu hóa riêng cho các sản phẩm khác nhau trong giao dịch trực tiếp.
Cửa sổ thời gian backtest ngắn và có thể không xác nhận đầy đủ hiệu quả của chiến lược.
Xem xét thêm các chỉ số khác để lọc, chẳng hạn như MACD, KD vv để giảm các mục nhập sai.
Phạm vi lấy lợi nhuận và dừng lỗ có thể được điều chỉnh năng động dựa trên biến động.
Tối ưu hóa tham số nghiên cứu cho các sản phẩm khác nhau để thiết lập các tiêu chí lựa chọn tham số.
Hãy thử các phương pháp học máy để tối ưu hóa các thông số chiến lược một cách năng động.
Thêm xác nhận khối lượng để tránh đột phá sai. Chỉ số khối lượng cũng có thể được sử dụng để xác định xu hướng.
Xem xét sử dụng sự thâm nhập của MA như là dừng lỗ thay vì chỉ đơn giản là tỷ lệ dừng lỗ.
Tóm lại, đây là một chiến lược theo xu hướng điển hình. Đầu tiên nó đánh giá hướng xu hướng thông qua RSI, sau đó sử dụng các băng tần OTT để hỗ trợ xác định các điểm vào cụ thể, và cuối cùng thiết lập lấy lợi nhuận và dừng lỗ để khóa lợi nhuận và kiểm soát rủi ro. Những lợi thế của chiến lược này là sự kết hợp chỉ số đơn giản và hiệu quả và kết quả backtest tốt. Nhưng cũng có một số rủi ro như RSI lag và tín hiệu sai băng tần OTT. Điều này đòi hỏi chúng ta tối ưu hóa các tham số một cách cẩn thận trong giao dịch trực tiếp, và thêm các chỉ số kỹ thuật khác để xác nhận để cải thiện sự ổn định của chiến lược. Với tối ưu hóa và xác minh liên tục, chiến lược này có thể trở thành một chiến lược theo xu hướng mẫu rất thực tế.
/*backtest start: 2023-09-08 00:00:00 end: 2023-10-08 00:00:00 period: 2h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © BigCoinHunter //@version=5 strategy(title="RSI_OTT-TP/SL", overlay=true, pyramiding=0, default_qty_type=strategy.percent_of_equity, default_qty_value=100, initial_capital=1000, currency=currency.USD, commission_value=0.05, commission_type=strategy.commission.percent, process_orders_on_close=true) //----------- get the user inputs -------------- //---------- RSI ------------- price = input(close, title="Source") RSIlength = input.int(defval=6,title="RSI Length") RSIoverSold = input.int(defval=50, title="RSI OverSold", minval=1) RSIoverBought = input.int(defval=50, title="RSI OverBought", minval=1) //------- OTT Bands ---------------- src = close length=input.int(defval=1, title="OTT Period", minval=1) percent=input.float(defval=5, title="OTT Percent", step=0.1, minval=0.001) mav = input.string(title="OTT MA Type", defval="VAR", options=["SMA", "EMA", "WMA", "TMA", "VAR", "WWMA", "ZLEMA", "TSF"]) ottUpperPercent = input.float(title="OTT Upper Line Coeff", defval=0.01, minval = 0.001, step=0.001) ottLowerPercent = input.float(title="OTT Lower Line Coeff", defval=0.01, minval = 0.001, step=0.001) Var_Func(src,length)=> valpha=2/(length+1) vud1=src>src[1] ? src-src[1] : 0 vdd1=src<src[1] ? src[1]-src : 0 vUD=math.sum(vud1,9) vDD=math.sum(vdd1,9) vCMO=nz((vUD-vDD)/(vUD+vDD)) VAR=0.0 VAR:=nz(valpha*math.abs(vCMO)*src)+(1-valpha*math.abs(vCMO))*nz(VAR[1]) VAR=Var_Func(src,length) Wwma_Func(src,length)=> wwalpha = 1/ length WWMA = 0.0 WWMA := wwalpha*src + (1-wwalpha)*nz(WWMA[1]) WWMA=Wwma_Func(src,length) Zlema_Func(src,length)=> zxLag = length/2==math.round(length/2) ? length/2 : (length - 1) / 2 zxEMAData = (src + (src - src[zxLag])) ZLEMA = ta.ema(zxEMAData, length) ZLEMA=Zlema_Func(src,length) Tsf_Func(src,length)=> lrc = ta.linreg(src, length, 0) lrc1 = ta.linreg(src,length,1) lrs = (lrc-lrc1) TSF = ta.linreg(src, length, 0)+lrs TSF=Tsf_Func(src,length) getMA(src, length) => ma = 0.0 if mav == "SMA" ma := ta.sma(src, length) ma if mav == "EMA" ma := ta.ema(src, length) ma if mav == "WMA" ma := ta.wma(src, length) ma if mav == "TMA" ma := ta.sma(ta.sma(src, math.ceil(length / 2)), math.floor(length / 2) + 1) ma if mav == "VAR" ma := VAR ma if mav == "WWMA" ma := WWMA ma if mav == "ZLEMA" ma := ZLEMA ma if mav == "TSF" ma := TSF ma ma MAvg=getMA(src, length) fark=MAvg*percent*0.01 longStop = MAvg - fark longStopPrev = nz(longStop[1], longStop) longStop := MAvg > longStopPrev ? math.max(longStop, longStopPrev) : longStop shortStop = MAvg + fark shortStopPrev = nz(shortStop[1], shortStop) shortStop := MAvg < shortStopPrev ? math.min(shortStop, shortStopPrev) : shortStop dir = 1 dir := nz(dir[1], dir) dir := dir == -1 and MAvg > shortStopPrev ? 1 : dir == 1 and MAvg < longStopPrev ? -1 : dir MT = dir==1 ? longStop: shortStop OTT=MAvg>MT ? MT*(200+percent)/200 : MT*(200-percent)/200 light_green=#08ff12 light_red=#fe0808 OTTupper = nz(OTT[2])*(1+ottUpperPercent) OTTlower = nz(OTT[2])*(1-ottLowerPercent) p1 = plot(OTTupper, color=light_green, linewidth=1, title="OTT UPPER") p2 = plot(nz(OTT[2]), color=color.new(color.yellow,0), linewidth=1, title="OTT MIDDLE") p3 = plot(OTTlower, color=light_red, linewidth=1, title="OTT LOWER") fill(plot1=p1, plot2=p3, title="OTT Background", color=color.new(color.aqua,90), fillgaps=false, editable=true) buyEntry = ta.crossover(src, OTTlower) sellEntry = ta.crossunder(src, OTTupper) //---------- input TP/SL --------------- tp = input.float(title="Take Profit:", defval=0.0, minval=0.0, maxval=100.0, step=0.1) * 0.01 sl = input.float(title="Stop Loss: ", defval=0.0, minval=0.0, maxval=100.0, step=0.1) * 0.01 isEntryLong = input.bool(defval=true, title= 'Long Entry', inline="11") isEntryShort = input.bool(defval=true, title='Short Entry', inline="11") //---------- backtest range setup ------------ fromDay = input.int(defval = 1, title = "From Day", minval = 1, maxval = 31) fromMonth = input.int(defval = 1, title = "From Month", minval = 1, maxval = 12) fromYear = input.int(defval = 2021, title = "From Year", minval = 2010) toDay = input.int(defval = 30, title = "To Day", minval = 1, maxval = 31) toMonth = input.int(defval = 12, title = "To Month", minval = 1, maxval = 12) toYear = input.int(defval = 2022, title = "To Year", minval = 2010) //------------ time interval setup ----------- start = timestamp(fromYear, fromMonth, fromDay, 00, 00) // backtest start window finish = timestamp(toYear, toMonth, toDay, 23, 59) // backtest finish window window() => true // create function "within window of time" //------- define the global variables ------ var bool long = true var bool stoppedOutLong = false var bool stoppedOutShort = false //--------- Colors --------------- //TrendColor = RSIoverBought and (price[1] > BBupper and price < BBupper) and BBbasis < BBbasis[1] ? color.red : RSIoverSold and (price[1] < BBlower and price > BBlower) and BBbasis > BBbasis[1] ? color.green : na //bgcolor(switch2?(color.new(TrendColor,50)):na) //--------- calculate the input/output points ----------- longProfitPrice = strategy.position_avg_price * (1 + tp) // tp -> take profit percentage longStopPrice = strategy.position_avg_price * (1 - sl) // sl -> stop loss percentage shortProfitPrice = strategy.position_avg_price * (1 - tp) shortStopPrice = strategy.position_avg_price * (1 + sl) //---------- RSI + Bollinger Bands Strategy ------------- vrsi = ta.rsi(price, RSIlength) rsiCrossOver = ta.crossover(vrsi, RSIoverSold) rsiCrossUnder = ta.crossunder(vrsi, RSIoverBought) OTTCrossOver = ta.crossover(src, OTTlower) OTTCrossUnder = ta.crossunder(src, OTTupper) if (not na(vrsi)) if rsiCrossOver and OTTCrossOver long := true if rsiCrossUnder and OTTCrossUnder long := false //------- define the global variables ------ buySignall = false sellSignall = false //------------------- determine buy and sell points --------------------- buySignall := window() and long and (not stoppedOutLong) sellSignall := window() and (not long) and (not stoppedOutShort) //---------- execute the strategy ----------------- if(isEntryLong and isEntryShort) if long strategy.entry("LONG", strategy.long, when = buySignall, comment = "ENTER LONG") stoppedOutLong := true stoppedOutShort := false else strategy.entry("SHORT", strategy.short, when = sellSignall, comment = "ENTER SHORT") stoppedOutLong := false stoppedOutShort := true else if(isEntryLong) strategy.entry("LONG", strategy.long, when = buySignall) strategy.close("LONG", when = sellSignall) if long stoppedOutLong := true else stoppedOutLong := false else if(isEntryShort) strategy.entry("SHORT", strategy.short, when = sellSignall) strategy.close("SHORT", when = buySignall) if not long stoppedOutShort := true else stoppedOutShort := false //----------------- take profit and stop loss ----------------- if(tp>0.0 and sl>0.0) if ( strategy.position_size > 0 ) strategy.exit(id="LONG", limit=longProfitPrice, stop=longStopPrice, comment="Long TP/SL Trigger") else if ( strategy.position_size < 0 ) strategy.exit(id="SHORT", limit=shortProfitPrice, stop=shortStopPrice, comment="Short TP/SL Trigger") else if(tp>0.0) if ( strategy.position_size > 0 ) strategy.exit(id="LONG", limit=longProfitPrice, comment="Long TP Trigger") else if ( strategy.position_size < 0 ) strategy.exit(id="SHORT", limit=shortProfitPrice, comment="Short TP Trigger") else if(sl>0.0) if ( strategy.position_size > 0 ) strategy.exit(id="LONG", stop=longStopPrice, comment="Long SL Trigger") else if ( strategy.position_size < 0 ) strategy.exit(id="SHORT", stop=shortStopPrice, comment="Short SL Trigger")