
이 전략은 듀얼 EMA와 RSI 지표를 조합하여 가격 트렌드를 식별하고 트렌드 방향이 변할 때 적시에 입문한다. 구체적으로, 전략은 더 긴 기간의 EMA를 사용하여 큰 트렌드 방향을 판단하고, RSI 지표를 사용하여 단기간의 과매 과매매 현상을 판단한다. 가격이 주 트렌드 방향에서 돌아갔을 때, RSI 지표를 통해 거래 신호를 발산하고, 트렌드 방향에 따라 더 많이 또는 더 많이 한다.
200주기의 EMA를 사용하여 큰 트렌드 방향을 판단한다. 가격이 상단 EMA선을 통과하면 호불호 신호이며, 하단 EMA선을 통과하면 하락 신호이다.
RSI 지표의 파라미터는 10주기로 설정한다. 이 중 RSI 상위 40번을 넘으면 과매매 신호이며, 하위 60번을 넘으면 과매매 신호이다.
큰 트렌드가 상승할 때 (가격이 EMA 라인보다 높다) RSI 지표 아래 40의 오버셀 신호가 발생하면 더 많은 입장을 니다.
큰 트렌드가 하향 (가격이 EMA 라인보다 낮다) 할 때 RSI 지표에 60의 오버 바이 신호가 발생하면, 코스피에 진입한다.
스톱로스는 ATR 지표의 4배. 스톱은 스톱로스의 2배로 설정되어, 2:1의 리스크 수익률을 달성한다.
이 전략의 가장 큰 장점은 동시적으로 트렌드와 역전 지표를 결합하여 트렌드가 발생했을 때 적시에 진입하여 더 나은 성과를 얻을 수 있다는 것입니다. 구체적인 장점은 다음과 같습니다:
이중 EMA 시스템을 사용하여 주요 트렌드 방향을 판단하여 가격 트렌드를 효과적으로 추적할 수 있다.
RSI 지표는 단기간에 과매매되는 상황을 식별하여 시장에 진입할 때를 결정하는 데 도움을 줍니다.
ATR 지표로 설정된 스톱로스는 시장의 변동성에 따라 스톱로스의 폭을 조정할 수 있으며, 위험 통제에 도움이 된다.
트렌드 트레이딩 원칙을 철저히 준수하면 불필요한 트레이딩을 줄이고 시스템적 위험을 줄일 수 있습니다.
이 전략에는 다음과 같은 위험들이 있습니다.
추세 흔들림이 약화되는 과정에서 잘못된 거래 신호가 발생할 수 있다. 이 때 시기를 재고하고 신중하게 진입해야 한다.
극단적인 상황에서는, ATR 지표에 의해 설정된 스톱로드는 너무 크거나 너무 작아 동적으로 조정할 필요가 있다. 다른 스톱로드로 대체하는 것도 고려할 수 있다.
거래 신호는 높은 주파수를 생성할 수 있으며, 자신의 거래 주파수 선호도에 맞는지에 주의를 기울여야 한다.
RSI 파라미터가 적절하게 설정되어 있는지에 주의를 기울여야 하며, 적절한 때에 파라미터를 최적화해야 한다.
이 전략의 주요 최적화 방향은 다음과 같습니다.
다른 트렌드 지표, 예를 들어 MACD를 추가하여 트렌드 방향을 판단하는 데 도움을 줄 수 있습니다.
다른 반전 지표인 KDJ, 브린 띠와 같은 RSI와 결합하여 더 나은 거래 신호를 찾기 위해 테스트 할 수 있습니다.
기계학습 알고리즘을 도입하여 동적 중지 및 정지 작업을 수행할 수 있습니다.
감정 지표, 뉴스 면 등과 같은 더 많은 요소를 결합하여 판단할 수 있고, 시스템의 전반적인 안정성을 향상시킬 수 있다.
이 전략은 전체적으로 매우 전형적인 트렌드 추적과 반전 지표의 조합 짧은 라인 전략이다. 쌍 EMA를 사용하여 큰 트렌드를 판단, 동시에 RSI 지표의 반전 특성을 활용하여 트렌드 속의 Pullback 기회를 입력한다. 원칙적으로, 이 전략은 서로 다른 지표의 장점을 결합하여 FORM은 좋은 상호 보완 효과를 낸다.
/*backtest
start: 2024-01-10 00:00:00
end: 2024-01-14 13:00:00
period: 5m
basePeriod: 1m
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/
// © kevinmck100
// @description
// This strategy is intended to be used as a base template for building new strategies.
//
// It incorporates the following features:
//
// - Risk management: Configurable X% loss per stop loss
// Configurable R:R ratio
//
// - Trade entry: Calculated position size based on risk tolerance
//
// - Trade exit: Stop Loss currently configurable ATR multiplier but can be replaced based on strategy
// Take Profit calculated from Stop Loss using R:R ratio
//
// - Backtesting: Configurable backtesting range by date
//
// - Trade drawings: TP/SL boxes drawn for all trades. Can be turned on and off
// Trade exit information labels. Can be turned on and off
// NOTE: Trade drawings will only be applicable when using overlay strategies
//
// - Debugging: Includes section with useful debugging techniques
//
// Strategy conditions:
//
// - Trade entry: LONG: C1: Price is above EMA line
// C2: RSI is crossing out of oversold area
// SHORT: C1: Price is below EMA line
// C2: RSI is crossing out of overbought area
//
// - Trade exit: Stop Loss: Stop Loss ATR multiplier is hit
// Take Profit: R:R multiplier * Stop Loss is hit
//
// The idea is to use RSI to catch pullbacks within the main trend. Note that
// this strategy is intended to be a simple base strategy for building upon.
// It was not designed to be traded in its current form.
//@version=5
INITIAL_CAPITAL = 1000
DEFAULT_COMMISSION = 0.02
MAX_DRAWINGS = 500
IS_OVERLAY = true
strategy("Risk Management Strategy Template", "Strategy Template", overlay = IS_OVERLAY, initial_capital = INITIAL_CAPITAL, currency = currency.NONE, max_labels_count = MAX_DRAWINGS, max_boxes_count = MAX_DRAWINGS, max_lines_count = MAX_DRAWINGS, default_qty_type = strategy.cash, commission_type = strategy.commission.percent, commission_value = DEFAULT_COMMISSION)
// =============================================================================
// INPUTS
// =============================================================================
// ------------------------ Replacable section - Start -------------------------
// ------------------
// Indicator Settings
// ------------------
emaLength = input.int (200, "EMA Length ", group = "Indicators: Settings", inline = "IS1", minval = 1, tooltip = "EMA line to identify trend direction. Above EMA trend line is bullish. Below EMA trend line is bearish")
rsiLength = input.int (10, "RSI Length ", group = "Indicators: Settings", inline = "IS2", minval = 1)
// ----------------------
// Trade Entry Conditions
// ----------------------
rsiOverbought = input.int (60, "RSI Overbought ", group = "Strategy: Conditions", inline = "SC1", minval = 50, maxval = 100, tooltip = "RSI overbought level used to identify pullbacks within the main trend. RSI crossing BELOW this level triggers a SHORT when in a DOWN trend")
rsiOversold = input.int (40, "RSI Oversold ", group = "Strategy: Conditions", inline = "SC2", minval = 0, maxval = 50, tooltip = "RSI overbought level used to identify pullbacks within the main trend. RSI crossing ABOVE this level triggers a LONG when in an UP trend")
// ---------------------
// Trade Exit Conditions
// ---------------------
atrLength = input.int (14, "Stop Loss ATR Length ", group = "Strategy: Exit Conditions", inline = "EC1", minval = 0, tooltip = "Length of ATR used to calculate Stop Loss.")
slAtrMultiplier = input.float(4, "Stop Loss ATR Multiplier ", group = "Strategy: Exit Conditions", inline = "EC2", minval = 0, step = 0.1, tooltip = "Size of StopLoss is determined by multiplication of ATR value. Take Profit is derived from this also by multiplying the StopLoss value by the Risk:Reward multiplier.")
// ------------------------- Replacable section - End --------------------------
// ---------------
// Risk Management
// ---------------
riskReward = input.float(2, "Risk : Reward 1 :", group = "Strategy: Risk Management", inline = "RM1", minval = 0, step = 0.1, tooltip = "Previous high or low (long/short dependant) is used to determine TP level. 'Risk : Reward' ratio is then used to calculate SL based of previous high/low level.\n\nIn short, the higher the R:R ratio, the smaller the SL since TP target is fixed by previous high/low price data.")
accountRiskPercent = input.float(1, "Portfolio Risk % ", group = "Strategy: Risk Management", inline = "RM1", minval = 0, step = 0.1, tooltip = "Percentage of portfolio you lose if trade hits SL.\n\nYou then stand to gain\n Portfolio Risk % * Risk : Reward\nif trade hits TP.")
// ----------
// Date Range
// ----------
startYear = input.int (2022, "Start Date ", group = 'Strategy: Date Range', inline = 'DR1', minval = 1900, maxval = 2100)
startMonth = input.int (1, "", group = 'Strategy: Date Range', inline = 'DR1', options = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
startDate = input.int (1, "", group = 'Strategy: Date Range', inline = 'DR1', options = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31])
endYear = input.int (2100, "End Date ", group = 'Strategy: Date Range', inline = 'DR2', minval = 1900, maxval = 2100)
endMonth = input.int (1, "", group = 'Strategy: Date Range', inline = 'DR2', options = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
endDate = input.int (1, "", group = 'Strategy: Date Range', inline = 'DR2', options = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31])
// ----------------
// Drawing Settings
// ----------------
showTpSlBoxes = input.bool(false, "Show TP / SL Boxes", group = "Strategy: Drawings", inline = "D1", tooltip = "Show or hide TP and SL position boxes.\n\nNote: TradingView limits the maximum number of boxes that can be displayed to 500 so they may not appear for all price data under test.")
showLabels = input.bool(false, "Show Trade Exit Labels", group = "Strategy: Drawings", inline = "D2", tooltip = "Useful labels to identify Profit/Loss and cumulative portfolio capital after each trade closes.\n\nAlso note that TradingView limits the max number of 'boxes' that can be displayed on a chart (max 500). This means when you lookback far enough on the chart you will not see the TP/SL boxes. However you can check this option to identify where trades exited.")
// =============================================================================
// INDICATORS
// =============================================================================
// ------------------------ Replacable section - Start -------------------------
// ---
// EMA
// ---
ema = ta.ema(close, emaLength)
plot(ema, "EMA Trend Line", color.white)
// ---
// RSI
// ---
rsi = ta.rsi(close, rsiLength)
// ------------------------- Replacable section - End --------------------------
// =============================================================================
// STRATEGY LOGIC
// =============================================================================
// ---------
// FUNCTIONS
// ---------
percentAsPoints(pcnt) =>
math.round(pcnt / 100 * close / syminfo.mintick)
calcStopLossPrice(pointsOffset, isLong) =>
priceOffset = pointsOffset * syminfo.mintick
if isLong
close - priceOffset
else
close + priceOffset
calcProfitTrgtPrice(pointsOffset, isLong) =>
calcStopLossPrice(-pointsOffset, isLong)
printLabel(barIndex, msg) => label.new(barIndex, close, msg)
printTpSlHitBox(left, right, slHit, tpHit, entryPrice, slPrice, tpPrice) =>
if showTpSlBoxes
box.new (left = left, top = entryPrice, right = right, bottom = slPrice, bgcolor = slHit ? color.new(color.red, 60) : color.new(color.gray, 90), border_width = 0)
box.new (left = left, top = entryPrice, right = right, bottom = tpPrice, bgcolor = tpHit ? color.new(color.green, 60) : color.new(color.gray, 90), border_width = 0)
line.new(x1 = left, y1 = entryPrice, x2 = right, y2 = entryPrice, color = color.new(color.yellow, 20))
line.new(x1 = left, y1 = slPrice, x2 = right, y2 = slPrice, color = color.new(color.red, 20))
line.new(x1 = left, y1 = tpPrice, x2 = right, y2 = tpPrice, color = color.new(color.green, 20))
printTpSlNotHitBox(left, right, entryPrice, slPrice, tpPrice) =>
if showTpSlBoxes
box.new (left = left, top = entryPrice, right = right, bottom = slPrice, bgcolor = color.new(color.gray, 90), border_width = 0)
box.new (left = left, top = entryPrice, right = right, bottom = tpPrice, bgcolor = color.new(color.gray, 90), border_width = 0)
line.new(x1 = left, y1 = entryPrice, x2 = right, y2 = entryPrice, color = color.new(color.yellow, 20))
line.new(x1 = left, y1 = slPrice, x2 = right, y2 = slPrice, color = color.new(color.red, 20))
line.new(x1 = left, y1 = tpPrice, x2 = right, y2 = tpPrice, color = color.new(color.green, 20))
printTradeExitLabel(x, y, posSize, entryPrice, pnl) =>
if showLabels
labelStr = "Position Size: " + str.tostring(math.abs(posSize), "#.##") + "\nPNL: " + str.tostring(pnl, "#.##") + "\nCapital: " + str.tostring(strategy.equity, "#.##") + "\nEntry Price: " + str.tostring(entryPrice, "#.##")
label.new(x = x, y = y, text = labelStr, color = pnl > 0 ? color.new(color.green, 60) : color.new(color.red, 60), textcolor = color.white, style = label.style_label_down)
// ----------
// CONDITIONS
// ----------
inDateRange = time >= timestamp(syminfo.timezone, startYear, startMonth, startDate, 0, 0) and time < timestamp(syminfo.timezone, endYear, endMonth, endDate, 0, 0)
// ------------------------ Replacable section - Start -------------------------
// Condition 1: Price above EMA indicates bullish trend, price below EMA indicates bearish trend
bullEma = close > ema
bearEma = close < ema
// Condition 2: RSI crossing back from overbought/oversold indicates pullback within trend
bullRsi = ta.crossover (rsi, rsiOversold)
bearRsi = ta.crossunder (rsi, rsiOverbought)
// Combine all entry conditions
goLong = inDateRange and bullEma and bullRsi
goShort = inDateRange and bearEma and bearRsi
// ------------------------- Replacable section - End --------------------------
// Trade entry and exit variables
var tradeEntryBar = bar_index
var profitPoints = 0.
var lossPoints = 0.
var slPrice = 0.
var tpPrice = 0.
var inLong = false
var inShort = false
// Entry decisions
openLong = (goLong and not inLong)
openShort = (goShort and not inShort)
flippingSides = (goLong and inShort) or (goShort and inLong)
enteringTrade = openLong or openShort
inTrade = inLong or inShort
// ------------------------ Replacable section - Start -------------------------
// Exit calculations
atr = ta.atr(atrLength)
slAmount = atr * slAtrMultiplier
slPercent = math.abs((1 - (close - slAmount) / close) * 100)
tpPercent = slPercent * riskReward
// ------------------------- Replacable section - End --------------------------
// Risk calculations
riskAmt = strategy.equity * accountRiskPercent / 100
entryQty = math.abs(riskAmt / slPercent * 100) / close
if openLong
if strategy.position_size < 0
printTpSlNotHitBox(tradeEntryBar + 1, bar_index + 1, strategy.position_avg_price, slPrice, tpPrice)
printTradeExitLabel(bar_index + 1, math.max(tpPrice, slPrice), strategy.position_size, strategy.position_avg_price, strategy.openprofit)
strategy.entry("Long", strategy.long, qty = entryQty, alert_message = "Long Entry")
enteringTrade := true
inLong := true
inShort := false
if openShort
if strategy.position_size > 0
printTpSlNotHitBox(tradeEntryBar + 1, bar_index + 1, strategy.position_avg_price, slPrice, tpPrice)
printTradeExitLabel(bar_index + 1, math.max(tpPrice, slPrice), strategy.position_size, strategy.position_avg_price, strategy.openprofit)
strategy.entry("Short", strategy.short, qty = entryQty, alert_message = "Short Entry")
enteringTrade := true
inShort := true
inLong := false
if enteringTrade
profitPoints := percentAsPoints(tpPercent)
lossPoints := percentAsPoints(slPercent)
slPrice := calcStopLossPrice(lossPoints, openLong)
tpPrice := calcProfitTrgtPrice(profitPoints, openLong)
tradeEntryBar := bar_index
strategy.exit("TP/SL", profit = profitPoints, loss = lossPoints, comment_profit = "TP Hit", comment_loss = "SL Hit", alert_profit = "TP Hit Alert", alert_loss = "SL Hit Alert")
// =============================================================================
// DRAWINGS
// =============================================================================
// -----------
// TP/SL Boxes
// -----------
slHit = (inShort and high >= slPrice) or (inLong and low <= slPrice)
tpHit = (inLong and high >= tpPrice) or (inShort and low <= tpPrice)
exitTriggered = slHit or tpHit
entryPrice = strategy.closedtrades.entry_price (strategy.closedtrades - 1)
pnl = strategy.closedtrades.profit (strategy.closedtrades - 1)
posSize = strategy.closedtrades.size (strategy.closedtrades - 1)
// Print boxes for trades closed at profit or loss
if (inTrade and exitTriggered)
inShort := false
inLong := false
printTpSlHitBox(tradeEntryBar + 1, bar_index, slHit, tpHit, entryPrice, slPrice, tpPrice)
printTradeExitLabel(bar_index, math.max(tpPrice, slPrice), posSize, entryPrice, pnl)
// Print TP/SL box for current open trade
if barstate.islastconfirmedhistory and strategy.position_size != 0
printTpSlNotHitBox(tradeEntryBar + 1, bar_index + 1, strategy.position_avg_price, slPrice, tpPrice)
// =============================================================================
// DEBUGGING
// =============================================================================
// Data window plots
plotchar(slPrice, "Stop Loss Price", "")
plotchar(tpPrice, "Take Profit Price", "")
// Label plots
plotDebugLabels = false
if plotDebugLabels
if bar_index == tradeEntryBar
printLabel(bar_index, "Position size: " + str.tostring(entryQty * close, "#.##"))