RSI 트렌드 트래일링 스톱 로스 전략

저자:차오장, 날짜: 2023-12-08 11:41:31
태그:

img

전반적인 설명

이 전략은 RSI 지표를 사용하여 트렌드를 식별하고 이동 평균, 스톱 로스 및 영업 설정으로 트렌드를 확인하는 자동화된 거래 전략이다. RSI가 68을 넘어서 현재 이동 평균이 이전 이동 평균을 넘어서면 긴 거리로 이동하고, RSI가 28 이하로 떨어지고 현재 이동 평균이 이전 이동 평균을 넘어서면 짧은 거리로 이동한다. 스톱 로스 및 영업 포인트도 구성된다.

전략 논리

이 전략은 주로 RSI 지표를 사용하여 트렌드를 결정하기 위해 과소매와 과소매 조건을 식별합니다. RSI의 70 이상의 값은 과소매 상태를 나타내고 30 이하의 값은 과소매 상태를 나타냅니다. 트렌드는 이동 평균에서 황금 십자가 및 죽음의 십자가 신호를 사용하여 확인됩니다. 구체적인 거래 신호는 다음과 같습니다.

긴 신호: RSI가 68을 넘어서 현재 이동 평균이 이전 이동 평균을 넘어서면 긴 신호가 됩니다.
짧은 신호: RSI가 28 이하로 떨어지고 현재 이동 평균이 이전 이동 평균보다 낮을 때, 짧습니다.

스톱 로스 및 취득 설정은 더 느슨한 것에서 더 엄격한 것:

이윤을 가져가기: 이윤을 가져가기 1.4%의 높은 지점에서 50%의 이윤을 가져가기 0.8%의 높은 지점에서 100%의 이윤을 가져가기
긴 스톱 로스: 엔트리 가격보다 2% 아래로 스톱 로스를 설정합니다.

짧은 영업이익: 지점의 50%를 0.4%의 낮은 지점에서 영업이익을 취득하고, 0.8%의 낮은 지점에서 100%의 영업이익을 취득합니다. 쇼트 스톱 로스: 엔트리 가격보다 2%의 스톱 로스를 설정합니다.

또한, 트렌드가 반전되면, 예를 들어, RSI가 30 이하로 떨어지면, 시장에서 전체 긴 포지션을 닫습니다.

장점

  1. RSI를 사용해서 과잉 구매/ 과잉 판매를 결정해서 높은 가격에 구매하고 낮은 가격에 판매하는 것을 피합니다.
  2. 주요 트렌드에 반하는 거래를 줄이기 위해 이동 평균을 가진 필터.
  3. 이윤을 극대화하기 위해 수익 목표를 취합니다.
  4. 더 넓은 스톱 손실은 약간의 후퇴를 허용합니다.
  5. 트렌드 역전 기반 포지션 폐쇄는 갑작스러운 사건에 빠르게 반응합니다.

위험성

  1. RSI 매개 변수 조정이 안 되어서 신호가 정확하지 않습니다.
  2. 이동평균 매개 변수 조정이 안 좋아서 필터링이 안 좋아
  3. 너무 큰 손실로 이어지는 스톱 손실.
  4. 이윤을 너무 밀고, 이윤을 테이블에 두고
  5. 부적절한 반전 신호가 부적절하게 위치를 닫습니다.

위 위험 요소를 해결하기 위해 광범위한 매개 변수 조정이 이루어져야 합니다. 시장 변동성에 따라 스톱 로스 및 영업이익도 적절하게 설정되어야 합니다. 불필요한 손실을 피하기 위해 반전 신호를 신중하게 사용해야 합니다.

더 나은 기회

이 전략은 다음과 같이 더 개선될 수 있습니다.

  1. 신호의 정확성을 높이기 위해 볼륨과 같은 필터를 추가합니다.
  2. 수익을 확보하기 위해 후속 스톱 손실을 구현합니다.
  3. 이윤을 극대화하기 위해 일부 출구에서 수익을 취하는 후속을 사용하십시오.
  4. 최적의 매개 변수를 사용하기 위해 기기 전환을 추가합니다.
  5. 파동적으로 정지를 조정하기 위해 선물에 대한 운반 비용을 포함합니다.

결론

전체적으로 이것은 성숙하고 신뢰할 수있는 트렌드 다음 전략입니다. 그것은 RSI를 사용하여 트렌드를 잘 식별하고 이동 평균과 함께 더 많은 필터를 사용합니다. 또한 합리적인 스톱 손실 및 단계적 인 수익 설정을 구현합니다. 적절하게 조정되면 트렌딩 시장에서 매우 잘 수행 할 수 있습니다. 추가 최적화는 더 나은 성과를 가져올 수 있습니다.


// © 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)      


더 많은