RSI와 가중화 이동 평균에 기초한 트렌드 다음 전략

저자:차오장, 날짜: 2023-12-25 13:28:24
태그:

img

전반적인 설명

이 전략은 두 가지 잘 알려진 지표: 상대적 강도 지표 (RSI) 와 가중 이동 평균 (WMA) 를 기반으로 합니다. 시장 추세를 파악하고 그 방향을 따르고 있습니다. RSI는 과잉 구매/ 과잉 판매 수준을 판단하고, WMA는 가격 추세를 결정합니다. 이 둘의 조합은 무관한 신호를 효과적으로 필터링하여 수익성을 향상시킬 수 있습니다. 이것은 중장기 전략이며, 이윤/손실에 따라 포지션 크기를 조정하는 돈 관리 방법과 결합됩니다.

전략 논리

RSI 지표

RSI 는 가장 잘 알려진 과잉 구매/ 과잉 판매 지표 중 하나입니다. 그 공식은:

$$RSI=100 - \frac{100}{1+\frac{AvgGain}{AvgLoss}}$$

여기서 AvgGain는 지난 x일 동안 닫는 날이 열기보다 많았던 날의 평균이고, AvgLoss는 지난 x일 동안 닫는 날이 열기보다 낮았던 날의 절대값의 평균입니다.

이 전략은 트렌드를 판단하기 위해 RSI 기간을 20로 설정합니다. 60 이상의 RSI는 긴 신호를 생성하고 40 이하의 RSI는 짧은 신호를 생성합니다.

가중화 이동 평균 (WMA)

SMA와 비교하면 WMA는 최근 가격을 더 중요하게 여긴다. 그 공식은:

$$WMA= \frac{\sum_{i=1}^n w_i x_i}{\sum_{i=1}^n w_i}$

이 전략은 다음과 같은 무게 공식을 사용합니다.

$$w = \begin{cases} 100/(4+(n-4)1.3), & i <= 3 \ 1.3w, & i > 3 \end{case}$$

즉, 무게는 지난 3 일 동안 같고, 1 일마다 1.3 배 증가합니다. 이것은 최근의 가격의 영향을 강조합니다.

이 전략의 WMA 길이는 20입니다.

전략 신호

긴 신호: RSI > 60 및 WMA의 20일 ROC < -1 짧은 신호: RSI < 40 및 WMA의 20일 ROC > 1

WMA의 20일 ROC는 다음과 같이 계산됩니다.

$$ROC = (WMA_{오늘}/WMA_{20_days_ago} - 1) \times 100$$

장점

  • 트렌드 방향을 결정하기 위해 RSI를 사용하십시오. 윙사 시장에서 돈을 잃지 마십시오.
  • WMA는 소음을 줄이고 주요 추세를 파악하기 위해 최근 가격을 가중합니다.
  • RSI와 WMA ROC의 조합은 무관한 신호를 필터링합니다.
  • 복수 ATR 후속 취득, 유연한 취득
  • 자금 관리 는 수익/손실 에 근거 한 위치 크기를 조정 하고 위험 을 제어 합니다

위험성

  • 잘못된 매개 변수 설정은 거래 빈도를 증가시킬 수 있습니다.
  • 잘못된 스톱 로스 설정은 손실을 증가시킬 수 있습니다.
  • 트렌드를 따르는 전략으로, 범위 제한 시장에 적합하지 않습니다.
  • 거시적 환경 변화에 주의를 기울이고 필요한 경우 수동 개입

개선 방향

  • 테스트 RSI 길이, WMA 길이, ROC 문턱 최적의 매개 변수 세트를 찾기 위해
  • 가장 좋은 위치 조정 계획을 찾기 위해 다른 돈 관리 방법을 테스트
  • 추가 신호 필터링을 위한 다른 표시기를 추가합니다.
  • 거래당 손실 위험을 제한하기 위해 스톱 로스 전략을 포함합니다.
  • 트렌드 기간 동안 수익을 극대화하기 위해 수익 전략을 최적화

결론

이 전략은 트렌드 방향을 결정하기 위해 RSI와 WMA를 결합하여 중장기 주요 트렌드로부터 이익을 얻는 것을 목표로합니다. 금전 관리 및 수익 취득 전략도 위험을 제어하는 데 사용됩니다. 실용적인 가치가 있지만 매개 변수 설정 및 스톱 로스 메커니즘은 더 나은 결과를 위해 지속적인 테스트와 최적화가 필요합니다. 투자자는 상황을 평가하고 필요한 경우 수동으로 개입하고 통제 가능한 위험을 보장해야합니다.


/*backtest
start: 2022-12-24 00:00:00
end: 2023-12-06 05:20:00
period: 1d
basePeriod: 1h
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/
// © gsanson66


//This code is based on RSI and a backed weighted MA
//@version=5
strategy("RSI + MA BACKTESTING", overlay=true, initial_capital=1000, default_qty_type=strategy.fixed, commission_type=strategy.commission.percent, commission_value=0.18, slippage=3)


//------------------------TOOL TIPS---------------------------//

t1 = "Choice between a Standard MA (SMA) or a backed-weighted MA (RWMA) which permits to minimize the impact of short term reversal. Default is RWMA."
t2 = "Value of RSI to send a LONG or a SHORT signal. RSI above 60 is a LONG signal and RSI below 40 is a SHORT signal."
t3 = "Rate of Change Value of selected MA to send a LONG or a SHORT signal. By default : ROC MA below -1 is a LONG signal and ROC MA above 1 is a SHORT signal"
t4 = "Threshold value to trigger trailing Take Profit. This threshold is calculated as a multiple of the ATR (Average True Range)."
t5 = "Percentage value of trailing Take Profit. This Trailing TP follows the profit if it increases, remaining selected percentage below it, but stops if the profit decreases."
t6 = "Each gain or losse (relative to the previous reference) in an amount equal to this fixed ratio will change quantity of orders."
t7 = "The amount of money to be added to or subtracted from orders once the fixed ratio has been reached."


//------------------------FUNCTIONS---------------------------//

//@function which calculate a retro weighted moving average to minimize the impact of short term reversal
rwma(source, length) =>
    sum = 0.0
    denominator = 0.0
    weight = 0.0
    weight_x = 100/(4+(length-4)*1.30)
    weight_y = 1.30*weight_x
    for i=0 to length - 1
        if i <= 3
            weight := weight_x
        else
            weight := weight_y
        sum := sum + source[i] * weight
        denominator := denominator + weight
    rwma = sum/denominator

//@function which permits the user to choose a moving average type
ma(source, length, type) =>
    switch type
        "SMA" => ta.sma(source, length)
        "RWMA" => rwma(source, length)

//@function Displays text passed to `txt` when called.
debugLabel(txt, color) =>
    label.new(bar_index, high, text = txt, color=color, style = label.style_label_lower_right, textcolor = color.black, size = size.small)

//@function which looks if the close date of the current bar falls inside the date range
inBacktestPeriod(start, end) => (time >= start) and (time <= end)


//--------------------------------USER INPUTS-------------------------------//

//Technical parameters
rsiLengthInput = input.int(20, minval=1, title="RSI Length", group="RSI Settings")
maTypeInput = input.string("RWMA", title="MA Type", options=["SMA", "RWMA"], group="MA Settings", inline="1", tooltip=t1)
maLenghtInput = input.int(20, minval=1, title="MA Length", group="MA Settings", inline="1")
rsiLongSignalValue = input.int(60, minval=1, maxval=99, title="RSI Long Signal", group="Strategy parameters", inline="3")
rsiShortSignalValue = input.int(40, minval=1, maxval=99, title="RSI Short Signal", group="Strategy parameters", inline="3", tooltip=t2)
rocMovAverLongSignalValue = input.float(-1, maxval=0, title="ROC MA Long Signal", group="Strategy parameters", inline="4")
rocMovAverShortSignalValue = input.float(1, minval=0, title="ROC MA Short Signal", group="Strategy parameters", inline="4", tooltip=t3)
//TP Activation and Trailing TP
takeProfitActivationInput = input.float(5, minval=1.0, title="TP activation in multiple of ATR", group="Strategy parameters", tooltip=t4)
trailingStopInput = input.float(3, minval=0, title="Trailing TP in percentage", group="Strategy parameters", tooltip=t5)
//Money Management
fixedRatio = input.int(defval=400, minval=1, title="Fixed Ratio Value ($)", group="Money Management", tooltip=t6)
increasingOrderAmount = input.int(defval=200, minval=1, title="Increasing Order Amount ($)", group="Money Management", tooltip=t7)
//Backtesting period
startDate = input(title="Start Date", defval=timestamp("1 Jan 2018 00:00:00"), group="Backtesting Period")
endDate = input(title="End Date", defval=timestamp("1 July 2024 00:00:00"), group="Backtesting Period")


//------------------------------VARIABLES INITIALISATION-----------------------------//

float rsi = ta.rsi(close, rsiLengthInput)
float ma = ma(close, maLenghtInput, maTypeInput)
float roc_ma = ((ma/ma[maLenghtInput]) - 1)*100
float atr = ta.atr(20)
var float trailingStopOffset = na
var float trailingStopActivation = na
var float trailingStop = na
var float stopLoss = na
var bool long = na
var bool short = na
var bool bufferTrailingStopDrawing = na
float theoreticalStopPrice = na
bool inRange = na
equity = math.abs(strategy.equity - strategy.openprofit)
strategy.initial_capital = 50000
var float capital_ref = strategy.initial_capital
var float cashOrder = strategy.initial_capital * 0.95


//------------------------------CHECKING SOME CONDITIONS ON EACH SCRIPT EXECUTION-------------------------------//

//Checking if the date belong to the range
inRange := true

//Checking performances of the strategy
if equity > capital_ref + fixedRatio
    spread = (equity - capital_ref)/fixedRatio
    nb_level = int(spread)
    increasingOrder = nb_level * increasingOrderAmount
    cashOrder := cashOrder + increasingOrder
    capital_ref := capital_ref + nb_level*fixedRatio
if equity < capital_ref - fixedRatio
    spread = (capital_ref - equity)/fixedRatio
    nb_level = int(spread)
    decreasingOrder = nb_level * increasingOrderAmount
    cashOrder := cashOrder - decreasingOrder
    capital_ref := capital_ref - nb_level*fixedRatio

//Checking if we close all trades in case where we exit the backtesting period
if strategy.position_size!=0 and not inRange
    debugLabel("END OF BACKTESTING PERIOD : we close the trade", color=color.rgb(116, 116, 116))
    strategy.close_all()
    bufferTrailingStopDrawing := false
    stopLoss := na
    trailingStopActivation := na
    trailingStop := na
    short := false
    long := false


//------------------------------STOP LOSS AND TRAILING STOP ACTIVATION----------------------------//

// We handle the stop loss and trailing stop activation 
if (low <= stopLoss or high >= trailingStopActivation) and long
    if high >= trailingStopActivation
        bufferTrailingStopDrawing := true
    else if low <= stopLoss
        long := false
    stopLoss := na
    trailingStopActivation := na
if (low <= trailingStopActivation or high >= stopLoss) and short
    if low <= trailingStopActivation
        bufferTrailingStopDrawing := true
    else if high >= stopLoss
        short := false
    stopLoss := na
    trailingStopActivation := na


//-------------------------------------TRAILING STOP--------------------------------------//

// If the traling stop is activated, we manage its plotting with the bufferTrailingStopDrawing
if bufferTrailingStopDrawing and long
    theoreticalStopPrice := high - trailingStopOffset * syminfo.mintick
    if na(trailingStop)
        trailingStop := theoreticalStopPrice
    else if theoreticalStopPrice > trailingStop
        trailingStop := theoreticalStopPrice
    else if low <= trailingStop
        trailingStop := na
        bufferTrailingStopDrawing := false
        long := false
if bufferTrailingStopDrawing and short
    theoreticalStopPrice := low + trailingStopOffset * syminfo.mintick
    if na(trailingStop)
        trailingStop := theoreticalStopPrice
    else if theoreticalStopPrice < trailingStop
        trailingStop := theoreticalStopPrice
    else if high >= trailingStop
        trailingStop := na
        bufferTrailingStopDrawing := false
        short := false


//---------------------------------LONG CONDITION--------------------------//

if rsi >= 60 and roc_ma <= rocMovAverLongSignalValue and inRange and not long
    if short
        bufferTrailingStopDrawing := false
        stopLoss := na
        trailingStopActivation := na
        trailingStop := na
        short := false
    trailingStopActivation := close + takeProfitActivationInput*atr
    trailingStopOffset := (trailingStopActivation * trailingStopInput/100) / syminfo.mintick
    stopLoss := close - 3*atr
    long := true
    qty = cashOrder/close
    strategy.entry("Long", strategy.long, qty)
    strategy.exit("Exit Long", "Long", stop = stopLoss, trail_price = trailingStopActivation,
                 trail_offset = trailingStopOffset)


//--------------------------------SHORT CONDITION-------------------------------//

if rsi <= 40 and roc_ma >= rocMovAverShortSignalValue and inRange and not short
    if long
        bufferTrailingStopDrawing := false
        stopLoss := na
        trailingStopActivation := na
        trailingStop := na
        long := false
    trailingStopActivation := close - takeProfitActivationInput*atr
    trailingStopOffset := (trailingStopActivation * trailingStopInput/100) / syminfo.mintick
    stopLoss := close + 3*atr
    short := true
    qty = cashOrder/close
    strategy.entry("Short", strategy.short, qty)
    strategy.exit("Exit Short", "Short", stop = stopLoss, trail_price = trailingStopActivation,
                 trail_offset = trailingStopOffset)


//--------------------------------PLOTTING ELEMENT---------------------------------//

// Plotting of element in the graph
plotchar(rsi, "RSI", "", location.top, color.rgb(0, 214, 243))
plot(ma, "MA", color.rgb(219, 219, 18))
plotchar(roc_ma, "ROC MA", "", location.top, color=color.orange)
// Visualizer trailing stop and stop loss movement
plot(stopLoss, "SL", color.red, 3, plot.style_linebr)
plot(trailingStopActivation, "Trigger Trail", color.green, 3, plot.style_linebr)
plot(trailingStop, "Trailing Stop",  color.blue, 3, plot.style_linebr)


더 많은