Phân tích chiến lược RSI và OTT Bands

Tác giả:ChaoZhang, Ngày: 2023-10-09 16:21:20
Tags:

Tổng quan

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 logic

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. Chiến lược cũng cho phép giao dịch chỉ dài, chỉ ngắn hoặc cả hai hướng.

Ưu điểm

  1. 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.

  2. 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.

  3. 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.

  4. Cấu trúc mã là rõ ràng với đủ các bình luận, dễ hiểu và sửa đổi.

  5. 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.

Rủi ro

  1. 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.

  2. Các băng tần OTT cũng có thể tạo ra tín hiệu sai.

  3. 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.

  4. 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.

  5. 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.

Hướng dẫn tối ưu hóa

  1. 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.

  2. 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.

  3. 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ố.

  4. 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.

  5. 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.

  6. 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

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")




Thêm nữa