Chiến lược dừng lỗ theo xu hướng RSI


Ngày tạo: 2023-12-08 11:41:31 sửa đổi lần cuối: 2023-12-08 11:41:31
sao chép: 3 Số nhấp chuột: 722
1
tập trung vào
1621
Người theo dõi

Chiến lược dừng lỗ theo xu hướng RSI

Tổng quan

Chiến lược này là một chiến lược giao dịch tự động sử dụng chỉ số RSI để xác định xu hướng và kết hợp với đường trung bình di chuyển để xác nhận xu hướng, thiết lập điểm dừng lỗ. Khi RSI lớn hơn 68 và trên đường trung bình di chuyển hiện tại, hãy làm nhiều; khi RSI nhỏ hơn 28 và trên đường trung bình di chuyển hiện tại, hãy làm trống.

Nguyên tắc chiến lược

Chiến lược này chủ yếu sử dụng chỉ số RSI để xác định xu hướng quá mua và quá bán. RSI lớn hơn 70 là khu vực quá mua và nhỏ hơn 30 là khu vực quá bán.

Tín hiệu đa đầu: RSI lớn hơn 68 và trên đường trung bình di chuyển hiện tại trước đường trung bình di chuyển, làm nhiều hơn. Tín hiệu đầu trống: RSI nhỏ hơn 28 và đi dưới đường trung bình di chuyển hiện tại trước khi đi ngang.

Cài đặt dừng lỗ cho mỗi điểm đặt tỷ lệ dừng lỗ khác nhau, từ thoải mái hơn đến nghiêm ngặt hơn, cụ thể là:

Multihead Stop: 1,4% stop bán một nửa vị trí tại điểm cao, 0,8% stop bán toàn bộ vị trí tại điểm cao. Hạn chế nhiều đầu: 2% giá vé.

Ngăn chặn đầu không: 0.4% ở mức thấp dừng một nửa vị trí, 0.8% ở mức thấp dừng toàn bộ vị trí.
Hạn chế đầu rỗng: 2% giá vé.

Trong khi đó, khi xu hướng đảo ngược, ví dụ như làm nhiều khi RSI phá vỡ 30 thì giá thị trường sẽ hoàn toàn bằng phẳng; khi RSI phá vỡ 60 thì giá thị trường sẽ hoàn toàn bằng phẳng.

Lợi thế chiến lược

  1. Sử dụng chỉ số RSI để đánh giá quá mua quá bán, tránh theo đuổi quá cao.
  2. Trung bình di chuyển lọc xu hướng, giảm hoạt động theo hướng phi chính thống.
  3. Cài đặt giới hạn tiến độ để tối đa hóa lợi nhuận.
  4. Cài đặt điểm dừng cao hơn, cho xu hướng một khoảng trống thích hợp.
  5. Chiến lược thanh lý ngược kết hợp với chỉ số chuyển hướng xu hướng, phản ứng nhanh chóng với sự cố bất ngờ.

Rủi ro chiến lược

  1. Các vấn đề về thiết lập tham số RSI dẫn đến hiệu quả nhận dạng kém.
  2. Vấn đề trong thiết lập tham số trung bình di chuyển, gây ra hiệu quả lọc không tốt.
  3. Các điểm dừng lỗ quá nhẹ, rủi ro tăng lỗ.
  4. Các điểm dừng quá chật hẹp, không thể tối đa hóa lợi nhuận.
  5. Chiến lược thanh lý ngược đã gây ra những tổn thất không cần thiết.

Đối với các rủi ro trên, các tham số phải được thử nghiệm nhiều lần. Cài đặt trạm dừng lỗ phải phù hợp, nới lỏng một khoảng nhất định và điều chỉnh tham số tùy theo biến động của thị trường. Chiến lược thanh toán phải thận trọng để tránh thiệt hại do đánh giá sai về chỉ số.

Hướng tối ưu hóa

Có thể tối ưu hóa hơn nữa bằng cách:

  1. Thêm thêm các chỉ số vi sóng để cải thiện độ chính xác tín hiệu. Ví dụ như thêm bộ lọc khối lượng giao dịch.
  2. Điều chỉnh chiến lược dừng lỗ, theo dõi giá cao nhất và giá thấp nhất, thực hiện dừng lỗ di động.
  3. Điều chỉnh một số điểm dừng để theo dõi các điểm dừng để tối đa hóa lợi nhuận.
  4. Thêm các tham số khác nhau như chuyển đổi nguồn dữ liệu, các giống khác nhau sử dụng các chu kỳ khác nhau.
  5. Tăng cân nhắc chi phí nắm giữ kho trống tương lai, động thái điều chỉnh dừng lỗ.

Tóm tắt

Chiến lược tổng thể là một chiến lược theo dõi xu hướng đáng tin cậy hơn. Sử dụng RSI để đánh giá quá mua quá bán để xác định hướng giao dịch. Sử dụng trung bình di chuyển để xác nhận sóng. Đồng thời thiết lập các điểm dừng và dừng đà thích hợp. Có thể nhận được lợi nhuận tốt hơn trong xu hướng.

Mã nguồn chiến lược
// © 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)