다중 EMA 트렌드 캐처 전략

EMA SMA ATR CROSSOVER RISK
생성 날짜: 2025-09-19 15:02:19 마지막으로 수정됨: 2025-09-19 15:02:19
복사: 17 클릭수: 272
avatar of ianzeng123 ianzeng123
2
집중하다
319
수행원

다중 EMA 트렌드 캐처 전략 다중 EMA 트렌드 캐처 전략

전략의 핵심점

아세요? 이 전략은 마치 초현실적인 “트렌드 탐지”와 같습니다! 4개의 EMA 라인 (기계 1, 5, 10, 20) 을 사용하여 완벽한 “계단 모양”으로 트렌드 방향을 식별합니다. EMA1> EMA5> EMA10> EMA20이 초록색으로 완전히 밝아지면, 마치 빨간색과 초록색이 모두 밝아지면, “부격!“라고 알려줍니다. 반대로 “정지! 정지!“입니다.

다중 필터 방침

이 전략은 “신호를 보며 공격”하는 겁쟁이 방식이 아니라, 세 개의 “안전검사문”을 설정합니다: SMA20, SMA50, SMA200 필터. 비행기를 타고 세 개의 보안검사를 통과하는 것과 마찬가지로, 가격이 올바른 이동 평균의 한쪽에 있을 때만 전략은 거래를 할 수 있습니다. 또한, 신중한 SMA200 기울기 필터는 당신이 “반류”하지 않도록합니다.

동적 위험 관리 도구

이 전략의 가장 좋은 점은 4과 1의 손해 방지 시스템입니다.

  • EMA20 동적 상쇄: 경비원처럼 가격을 따라가다
  • ATR 배수 상쇄 손실: 시장 변동성에 따라 지능 조정
  • 100% 절감: 단순하고 거칠고 초보자에게 적합하다
  • 스윙포인트 손실: 중요한 지지 저항 지점을 찾아라

포지션 관리는 리스크 비율 모드를 사용해서, 매번 계좌의 1%만 리스크를 감수하고, 연이어 손실을 입어도 신경쓰지 않는다!

지능형 거래 제어 시스템

이 전략에는 게임 기술 냉각과 마찬가지로, 감정적 인 거래를 피하기 위해 몇 가지 K 라인을 기다려야 한다. 또한 시간 퇴출 메커니즘을 지원합니다. 지점에서 나가십시오. 절대 전쟁하지 마십시오! 거래 시간 및 거래 날을 자유롭게 설정할 수 있으며, 언제 휴식을 취할지, 언제 휴식을 취할지 생각할 수 있습니다.

전략 소스 코드
/*backtest
start: 2024-09-19 00:00:00
end: 2025-09-18 00:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT","balance":500000}]
*/

//@version=6
strategy("Hilega Milega v6 - Pure EMA/SMA (Nitesh Kumar) + Full Backtest",
     overlay=true, initial_capital=100000,
     commission_type=strategy.commission.percent, commission_value=0.05,
     pyramiding=0, calc_on_order_fills=true, calc_on_every_tick=false,
     max_labels_count=200, max_boxes_count=0)

// ============================
// Backtest Controls
// ============================
string G_BT = "Backtest"
bool   useDateRange = input.bool(false, "Use Date Range (OFF = all history)", group=G_BT)
int    bt_from      = input(timestamp("2022-01-01T00:00:00"), "From", group=G_BT)
int    bt_to        = input(timestamp("2099-12-31T23:59:59"),  "To",   group=G_BT)
string sess         = input("0000-2359:1234567", "Session (Exchange Time)", group=G_BT)
bool   mon          = input.bool(true,  "Mon", group=G_BT)
bool   tue          = input.bool(true,  "Tue", group=G_BT)
bool   wed          = input.bool(true,  "Wed", group=G_BT)
bool   thu          = input.bool(true,  "Thu", group=G_BT)
bool   fri          = input.bool(true,  "Fri", group=G_BT)
bool   sat          = input.bool(true,  "Sat", group=G_BT)
bool   sun          = input.bool(true,  "Sun", group=G_BT)
int    cooldownBars = input.int(3, "Cooldown bars after flat", 0, 500, group=G_BT)
int    timeExitBars = input.int(0, "Time-based exit (0 = off)", 0, 5000, group=G_BT)
bool   allowLongs   = input.bool(true,  "Allow Longs", group=G_BT)
bool   allowShorts  = input.bool(true,  "Allow Shorts", group=G_BT)

// ============================
// Hilega Milega Inputs
// ============================
string G_HM = "Hilega Milega Filters (Side Rules)"
bool needSMA20  = input.bool(true,  "Long above SMA20 / Short below SMA20", group=G_HM)
bool needSMA50  = input.bool(true,  "Long above SMA50 / Short below SMA50", group=G_HM)
bool needSMA200 = input.bool(false, "Long above SMA200 / Short below SMA200", group=G_HM)
bool useSlope200= input.bool(false, "200 SMA slope filter (up for long / down for short)", group=G_HM)
int  slopeLook  = input.int(5, "Slope lookback (bars)", 1, 200, group=G_HM)

// ============================
// Risk / Targets
// ============================
string G_RM = "Risk / Targets"
string stopMode = input.string("EMA20", "Stop Type", options=["EMA20","ATR","Percent","Swing"], group=G_RM)
int    atrLen   = input.int(14, "ATR Length (for ATR/Swing calc)", 1, 200, group=G_RM)
float  atrMult  = input.float(2.0, "ATR Stop Mult (if Stop=ATR)", 0.1, 10, group=G_RM)
float  pctSL    = input.float(1.5, "Percent Stop % (if Stop=Percent)", 0.1, 50, group=G_RM)
int    swingLen = input.int(10, "Swing lookback (if Stop=Swing)", 1, 200, group=G_RM)
float  rrTarget = input.float(1.5, "Take Profit at R (x Risk)", 0.5, 20, group=G_RM)
bool   riskPctMode = input.bool(true, "Position size by Risk % of equity", group=G_RM)
float  riskPct     = input.float(1.0, "Risk %", 0.05, 20, group=G_RM)
float  fixedQty    = input.float(1, "Fixed Qty (if Risk% OFF)", 0.0001, 1e9, group=G_RM)

// ============================
// Guards
// ============================
bool inDate = not useDateRange or (time >= bt_from and time <= bt_to)
bool inSess = not na(time(timeframe.period, sess))
bool inDOW  = (dayofweek == dayofweek.monday   and mon) or
              (dayofweek == dayofweek.tuesday  and tue) or
              (dayofweek == dayofweek.wednesday and wed) or
              (dayofweek == dayofweek.thursday and thu) or
              (dayofweek == dayofweek.friday   and fri) or
              (dayofweek == dayofweek.saturday and sat) or
              (dayofweek == dayofweek.sunday   and sun)
bool canCalc = inDate and inSess and inDOW

// ============================
// Indicators (Pure HM stack)
// ============================
float ema1   = ta.ema(close, 1)
float ema5   = ta.ema(close, 5)
float ema10  = ta.ema(close, 10)
float ema20  = ta.ema(close, 20)
float sma20  = ta.sma(close, 20)
float sma50  = ta.sma(close, 50)
float sma200 = ta.sma(close, 200)
float atrVal = ta.atr(atrLen)

// Visuals
plot(ema1,  "EMA 1",  linewidth=1)
plot(ema5,  "EMA 5",  linewidth=1)
plot(ema10, "EMA 10", linewidth=1)
plot(ema20, "EMA 20", linewidth=2)
plot(sma20, "SMA 20", linewidth=2)
plot(sma50, "SMA 50", linewidth=2)
plot(sma200,"SMA 200",linewidth=3)

// ============================
// Hilega Milega Conditions
// ============================
bool emaBull = ema1 > ema5 and ema5 > ema10 and ema10 > ema20
bool emaBear = ema1 < ema5 and ema5 < ema10 and ema10 < ema20

bool sideLong  = (not needSMA20  or close > sma20)  and (not needSMA50 or close > sma50) and (not needSMA200 or close > sma200)
bool sideShort = (not needSMA20  or close < sma20)  and (not needSMA50 or close < sma50) and (not needSMA200 or close < sma200)

bool slopeUp   = not useSlope200 or sma200 > sma200[slopeLook]
bool slopeDown = not useSlope200 or sma200 < sma200[slopeLook]

// Entry triggers (classic HM: EMA5/EMA10 cross)
bool trigLong  = ta.crossover(ema5, ema10)
bool trigShort = ta.crossunder(ema5, ema10)

bool setupLong  = emaBull and sideLong and slopeUp
bool setupShort = emaBear and sideShort and slopeDown

// ============================
// Cooldown & Signals
// ============================
var int barsSinceFlat = 1000000000
barsSinceFlat += 1
bool posChanged = strategy.position_size != nz(strategy.position_size[1], 0)
bool flatNow    = posChanged and strategy.position_size == 0
if flatNow
    barsSinceFlat := 0
bool coolOK = barsSinceFlat >= cooldownBars

bool longSignal  = canCalc and allowLongs  and setupLong  and trigLong  and coolOK
bool shortSignal = canCalc and allowShorts and setupShort and trigShort and coolOK

plotshape(longSignal,  title="BUY",  style=shape.triangleup,   size=size.tiny, location=location.belowbar, text="Buy")
plotshape(shortSignal, title="SELL", style=shape.triangledown, size=size.tiny, location=location.abovebar, text="Sell")

// ============================
// Position Sizing & Orders
// ============================
var float entrySLlong  = na
var float entrySLshort = na

// Compute dynamic stops with simple if/else
float slLongByMode = na
if stopMode == "EMA20"
    slLongByMode := ema20
else if stopMode == "ATR"
    slLongByMode := close - atrMult * atrVal
else if stopMode == "Percent"
    slLongByMode := close * (1 - pctSL/100.0)
else
    slLongByMode := ta.lowest(low, swingLen)

float slShortByMode = na
if stopMode == "EMA20"
    slShortByMode := ema20
else if stopMode == "ATR"
    slShortByMode := close + atrMult * atrVal
else if stopMode == "Percent"
    slShortByMode := close * (1 + pctSL/100.0)
else
    slShortByMode := ta.highest(high, swingLen)

// Entries
if longSignal and strategy.position_size <= 0
    float riskPerUnit = math.max(close - slLongByMode, syminfo.mintick)
    float qty = riskPctMode ? (strategy.equity * (riskPct/100.0) / riskPerUnit) : fixedQty
    entrySLlong := slLongByMode
    strategy.entry("Long", strategy.long, qty=qty)

if shortSignal and strategy.position_size >= 0
    float riskPerUnitS = math.max(slShortByMode - close, syminfo.mintick)
    float qtyS = riskPctMode ? (strategy.equity * (riskPct/100.0) / riskPerUnitS) : fixedQty
    entrySLshort := slShortByMode
    strategy.entry("Short", strategy.short, qty=qtyS)

// Track entry bar index for time-based exits (no valuewhen)
var int entryBarL = na
var int entryBarS = na
if posChanged
    if strategy.position_size > 0 and strategy.position_size[1] == 0
        entryBarL := bar_index
        entryBarS := na
    if strategy.position_size < 0 and strategy.position_size[1] == 0
        entryBarS := bar_index
        entryBarL := na

// Exits (stop + RR limit) and optional time exit
if strategy.position_size > 0
    float ep    = strategy.position_avg_price
    float rBase = math.max(ep - nz(entrySLlong, ep - atrVal), syminfo.mintick)
    float tp    = ep + rrTarget * rBase
    float st    = nz(entrySLlong, ep - atrVal)
    strategy.exit("LX", from_entry="Long", stop=st, limit=tp)
    if timeExitBars > 0 and not na(entryBarL) and (bar_index - entryBarL >= timeExitBars)
        strategy.close("Long", comment="TimeExitL")

if strategy.position_size < 0
    float epS   = strategy.position_avg_price
    float rBaseS= math.max(nz(entrySLshort, epS + atrVal) - epS, syminfo.mintick)
    float tpS   = epS - rrTarget * rBaseS
    float stS   = nz(entrySLshort, epS + atrVal)
    strategy.exit("SX", from_entry="Short", stop=stS, limit=tpS)
    if timeExitBars > 0 and not na(entryBarS) and (bar_index - entryBarS >= timeExitBars)
        strategy.close("Short", comment="TimeExitS")

// Reset snapshots when flat
if strategy.position_size == 0
    entrySLlong  := na
    entrySLshort := na

// ============================
// Alerts
// ============================
alertcondition(longSignal,  title="HM Long",  message="Hilega Milega LONG: EMA1>5>10>20; 5 crossed above 10; side filters OK")
alertcondition(shortSignal, title="HM Short", message="Hilega Milega SHORT: EMA1<5<10<20; 5 crossed below 10; side filters OK")