Xu hướng RSI theo chiến lược với Trailing Stop Loss

Tác giả:ChaoZhang, Ngày: 2023-12-08 11:41:31
Tags:

img

Tổng quan

Chiến lược này là một chiến lược giao dịch tự động xác định xu hướng bằng cách sử dụng chỉ số RSI và xác nhận xu hướng bằng đường trung bình động, với thiết lập dừng lỗ và lấy lợi nhuận. Nó sẽ dài khi RSI vượt quá 68 và đường trung bình động hiện tại vượt qua đường trung bình động trước đó, và ngắn khi RSI giảm xuống dưới 28 và đường trung bình động hiện tại vượt qua đường trung bình động trước đó.

Chiến lược logic

Chiến lược này chủ yếu sử dụng chỉ số RSI để xác định các điều kiện mua quá mức và bán quá mức để xác định xu hướng. Giá trị trên 70 cho RSI cho thấy một điều kiện mua quá mức và các giá trị dưới 30 cho thấy một điều kiện bán quá mức. Xu hướng được xác nhận bằng cách sử dụng các tín hiệu chéo vàng và chéo chết từ các đường trung bình động. Các tín hiệu giao dịch cụ thể là:

Tín hiệu dài: RSI đi trên 68 và trung bình động hiện tại vượt qua trung bình động trước đó, đi dài.
Tín hiệu ngắn: RSI đi dưới 28 và trung bình di chuyển hiện tại vượt qua dưới trung bình di chuyển trước đó, đi ngắn.

Các thiết lập dừng lỗ và lấy lợi nhuận được phân chia, từ lỏng lẻo hơn đến nghiêm ngặt hơn:

Lợi nhuận dài: Lợi nhuận 50% của vị trí ở mức 1,4% trên mức cao, lợi nhuận 100% ở mức 0,8% trên mức cao.
Stop loss dài: Đặt stop loss ở mức 2% dưới giá nhập cảnh.

Lợi nhuận ngắn: Lợi nhuận 50% của vị trí ở mức 0,4% dưới mức thấp, lấy lợi nhuận 100% ở mức 0,8% dưới mức thấp. Đặt stop loss ngắn ở mức 2% trên giá nhập cảnh.

Ngoài ra, khi xu hướng đảo ngược, như RSI phá vỡ dưới 30 khi dài, đóng toàn bộ vị trí dài trên thị trường; khi RSI phá vỡ trên 60 khi ngắn, đóng toàn bộ vị trí ngắn trên thị trường.

Ưu điểm

  1. Sử dụng chỉ số RSI để xác định quá mua / quá bán để tránh mua cao và bán thấp.
  2. Các bộ lọc với đường trung bình động để giảm giao dịch chống lại xu hướng chính.
  3. Những người bị đình trệ lấy mục tiêu lợi nhuận để tối đa hóa lợi nhuận.
  4. Stop loss rộng hơn cho phép rút lại một số.
  5. Khóa vị trí dựa trên sự đảo ngược xu hướng phản ứng nhanh với các sự kiện đột ngột.

Rủi ro

  1. Điều chỉnh tham số RSI kém dẫn đến tín hiệu không chính xác.
  2. Chế độ điều chỉnh thông số trung bình di chuyển kém dẫn đến lọc yếu.
  3. Giữ lỗ quá rộng dẫn đến tổn thất lớn.
  4. Lấy lợi nhuận quá chặt để lại lợi nhuận trên bàn.
  5. Tín hiệu đảo ngược không chính xác đóng các vị trí không cần thiết.

Để giải quyết các rủi ro trên, điều chỉnh tham số rộng rãi nên được thực hiện. Dừng lỗ và lấy lợi nhuận cũng nên được thiết lập phù hợp dựa trên sự biến động của thị trường. Các tín hiệu đảo ngược nên được sử dụng cẩn thận để tránh tổn thất không cần thiết.

Cơ hội gia tăng

Chiến lược có thể được cải thiện thêm:

  1. Thêm nhiều bộ lọc như âm lượng để cải thiện độ chính xác tín hiệu.
  2. Thực hiện lệnh dừng lỗ để giữ lợi nhuận.
  3. Sử dụng trailing lấy lợi nhuận cho một số lối ra để tối đa hóa lợi nhuận.
  4. Thêm chuyển đổi thiết bị để sử dụng các thông số tối ưu.
  5. Bao gồm chi phí mang lại cho tương lai để điều chỉnh động dừng.

Kết luận

Nhìn chung, đây là một chiến lược theo xu hướng trưởng thành và đáng tin cậy. Nó xác định xu hướng tốt bằng cách sử dụng chỉ số RSI và lọc thêm bằng đường trung bình động. Nó cũng thực hiện các thiết lập dừng lỗ hợp lý và lấy lợi nhuận phân đoạn. Nó có thể hoạt động rất tốt trong thị trường xu hướng nếu điều chỉnh thích hợp. Tăng cường hơn có thể dẫn đến hiệu suất thậm chí tốt hơn.


// © CRabbit
//@version=5

// Starting with $100 and using 10% of the account per trade
strategy("RSI Template", shorttitle="RSI", overlay=false, initial_capital=100, default_qty_value=10, default_qty_type=strategy.percent_of_equity)

// RSI Indicator
ma(source, length, type) =>
    switch type
        "SMA" => ta.sma(source, length)
        "Bollinger Bands" => ta.sma(source, length)
        "EMA" => ta.ema(source, length)
        "SMMA (RMA)" => ta.rma(source, length)
        "WMA" => ta.wma(source, length)
        "VWMA" => ta.vwma(source, length)

rsiLengthInput = input.int(4, minval=1, title="RSI Length", group="RSI Settings")
rsiSourceInput = input.source(close, "Source", group="RSI Settings")
maTypeInput = input.string("SMA", title="MA Type", options=["SMA", "Bollinger Bands", "EMA", "SMMA (RMA)", "WMA", "VWMA"], group="MA Settings")
maLengthInput = input.int(23, title="MA Length", group="MA Settings")
bbMultInput = input.float(2.0, minval=0.001, maxval=50, title="BB StdDev", group="MA Settings")

up = ta.rma(math.max(ta.change(rsiSourceInput), 0), rsiLengthInput)
down = ta.rma(-math.min(ta.change(rsiSourceInput), 0), rsiLengthInput)
rsi = down == 0 ? 100 : up == 0 ? 0 : 100 - (100 / (1 + up / down))
rsiMA = ma(rsi, maLengthInput, maTypeInput)
isBB = maTypeInput == "Bollinger Bands"

plot(rsi, "RSI", color=#7E57C2)
plot(rsiMA, "RSI-based MA", color=color.green)
rsiUpperBand = hline(70, "RSI Upper Band", color=#787B86)
hline(50, "RSI Middle Band", color=color.new(#787B86, 50))
rsiLowerBand = hline(30, "RSI Lower Band", color=#787B86)
fill(rsiUpperBand, rsiLowerBand, color=color.rgb(126, 87, 194, 90), title="RSI Background Fill")


// Configure backtest start date with inputs
startDate = input.int(title="Start Date", defval=1, minval=1, maxval=31)
startMonth = input.int(title="Start Month", defval=6, minval=1, maxval=12)
startYear = input.int(title="Start Year", defval=2022, minval=1800, maxval=2100)

// See if this bar's time happened on/after start date
afterStartDate = (time >= timestamp(syminfo.timezone,
     startYear, startMonth, startDate, 0, 0))


// Long and Short buy strategy
// Submit a market open/ close Long order, but only on/after start date
if (afterStartDate)
    if rsi > 68 and (rsiMA > rsiMA[1])
        strategy.entry("Long Order", strategy.long, comment="ENTER-LONG")
    if rsi < 30
        strategy.close("Long Order", alert_message="L-CL")

strategy.exit("L-TP1", from_entry="Long Order", limit=high * 1.004, qty_percent=50, alert_message="L-TP1" + str.tostring(high * 1.004))
strategy.exit("L-TP2", from_entry="Long Order", limit=high * 1.008, qty_percent=100, alert_message="L-TP2" + str.tostring(high * 1.008))
strategy.exit("Exit Long", from_entry="Long Order", stop=low * 0.98, alert_message="L-SL" + str.tostring(low * 0.98))        


// Submit a market Open/ Close Short order, but only on/after start date
if (afterStartDate)
    if rsi < 28 and (rsiMA < rsiMA[1])
        strategy.entry("Short Order", strategy.short, comment="ENTER-SHORT")
    if rsi > 60
        strategy.close("Short Order", alert_message="S-CL")    

strategy.exit("S-TP1", from_entry="Short Order", limit=low * 0.996, qty_percent=50, alert_message="S-TP1" + str.tostring(low * 0.996))
strategy.exit("S-TP2", from_entry="Short Order", limit=low * 0.992, qty_percent=100, alert_message="S-TP2" + str.tostring(low * 0.992))
strategy.exit("Exit Short", from_entry="Short Order", stop=high * 1.02, alert_message="S-SL" + str.tostring(high * 1.02))

// MONTHLY TABLE //

prec      = input(2, title = "Return Precision")

new_month = month(time) != month(time[1])
new_year  = year(time)  != year(time[1])

eq = strategy.equity

bar_pnl = eq / eq[1] - 1

cur_month_pnl = 0.0
cur_year_pnl  = 0.0

// Current Monthly P&L
cur_month_pnl := new_month ? 0.0 : 
                 (1 + cur_month_pnl[1]) * (1 + bar_pnl) - 1 

// Current Yearly P&L
cur_year_pnl := new_year ? 0.0 : 
                 (1 + cur_year_pnl[1]) * (1 + bar_pnl) - 1  

// Arrays to store Yearly and Monthly P&Ls
var month_pnl  = array.new_float(0)
var month_time = array.new_int(0)

var year_pnl  = array.new_float(0)
var year_time = array.new_int(0)

if (not na(cur_month_pnl[1]) and (new_month or barstate.islast))
    array.push(month_pnl , cur_month_pnl[1])
    array.push(month_time, time[1])

if (not na(cur_year_pnl[1]) and (new_year or barstate.islast))
    array.push(year_pnl , cur_year_pnl[1])
    array.push(year_time, time[1])

// Monthly P&L Table    
var monthly_table = table(na)

if (barstate.islast)
    monthly_table := table.new(position.bottom_right, columns = 14, rows = array.size(year_pnl) + 1, border_width = 1)

    table.cell(monthly_table, 0,  0, "",     bgcolor = #cccccc)
    table.cell(monthly_table, 1,  0, "Jan",  bgcolor = #cccccc)
    table.cell(monthly_table, 2,  0, "Feb",  bgcolor = #cccccc)
    table.cell(monthly_table, 3,  0, "Mar",  bgcolor = #cccccc)
    table.cell(monthly_table, 4,  0, "Apr",  bgcolor = #cccccc)
    table.cell(monthly_table, 5,  0, "May",  bgcolor = #cccccc)
    table.cell(monthly_table, 6,  0, "Jun",  bgcolor = #cccccc)
    table.cell(monthly_table, 7,  0, "Jul",  bgcolor = #cccccc)
    table.cell(monthly_table, 8,  0, "Aug",  bgcolor = #cccccc)
    table.cell(monthly_table, 9,  0, "Sep",  bgcolor = #cccccc)
    table.cell(monthly_table, 10, 0, "Oct",  bgcolor = #cccccc)
    table.cell(monthly_table, 11, 0, "Nov",  bgcolor = #cccccc)
    table.cell(monthly_table, 12, 0, "Dec",  bgcolor = #cccccc)
    table.cell(monthly_table, 13, 0, "Year", bgcolor = #999999)


    for yi = 0 to array.size(year_pnl) - 1
        table.cell(monthly_table, 0,  yi + 1, str.tostring(year(array.get(year_time, yi))), bgcolor = #cccccc)
        
        y_color = array.get(year_pnl, yi) > 0 ? color.new(color.green, transp = 50) : color.new(color.red, transp = 50)
        table.cell(monthly_table, 13, yi + 1, str.tostring(math.round(array.get(year_pnl, yi) * 100, prec)), bgcolor = y_color)
        
    for mi = 0 to array.size(month_time) - 1
        m_row   = year(array.get(month_time, mi))  - year(array.get(year_time, 0)) + 1
        m_col   = month(array.get(month_time, mi)) 
        m_color = array.get(month_pnl, mi) > 0 ? color.new(color.green, transp = 70) : color.new(color.red, transp = 70)
        
        table.cell(monthly_table, m_col, m_row, str.tostring(math.round(array.get(month_pnl, mi) * 100, prec)), bgcolor = m_color)      


Thêm nữa