
이 전략은 두 개의 유명한 지표에 기반합니다: 상대적으로 약한 지표 ((RSI) 와 중화 이동 평균 ((Weighted Moving Average, WMA), 시장 추세를 식별하고 그 방향을 추적합니다. RSI는 과매매를 판단하기 위해 사용되며, WMA는 가격 추세를 판단하기 위해 사용되며, 두 가지의 조합은 관련없는 신호를 효과적으로 필터링하여 수익을 올릴 수 있습니다.
RSI는 가장 널리 알려진 과매매 과매매 지표 중 하나입니다.
\[RSI = 100 - \frac{100}{1+\frac{AvgGain}{AvgLoss}}\]
여기서 AvgGain은 일정 기간 동안 개시 가격보다 클로즈 가격이 높은 날의 클로즈 가격의 합으로 나누는 날 수, AvgLoss은 개시 가격보다 클로즈 가격이 낮은 날의 클로즈 가격의 절대값의 합으로 나누는 날 수이다.
이 전략은 RSI 주기를 20로 설정하여 트렌드를 판단하는 지표로 사용한다. RSI가 60보다 크면 멀티 헤드 신호가 발생하고, 40보다 작으면 공백 신호가 발생한다.
WMA는 SMA에 비해 근래 가격 조정에 더 강하다. 계산 공식은 다음과 같다:
\[WMA = \frac{\sum_{i=1}^n w_i x_i}{\sum_{i=1}^n w_i}\]
w는 가중치이며, i가 증가함에 따라 w는 지수적으로 증가한다. 이 전략에서 사용하는 가중치 공식은 다음과 같다.
\[w = \begin{cases} 100/(4+(n-4)*1.3), & i <= 3 \ 1.3*w, & i > 3 \end{cases}\]
즉, 최근 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일 전} - 1) \times 100\]
이 전략은 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)