이중 EMA 크로스오버 전략

저자:차오장, 날짜: 2024-02-22
태그:

img

전반적인 설명

듀얼 EMA 크로스오버 전략 (Dual EMA Crossover Strategy) 은 양적 거래에서 간단하고 효과적이며 이해하기 쉽고 일반적으로 사용되는 다른 기간의 두 개의 EMA 라인의 크로스오버를 기반으로 포지션을 열고 닫는 양적 거래 전략이다.

전략 논리

이 전략은 두 개의 EMA 라인을 사용합니다. 하나는 25기 EMA 라인이 빠른 라인이며 다른 하나는 50기 EMA 라인이 느린 라인입니다. 빠른 라인이 느린 라인의 위로 넘어가면 길게 이동합니다. 빠른 라인이 느린 라인의 아래에 넘어가면 짧게 이동합니다.

장차가 끝나면, 영업이익을 입시 가격의 2%로 설정하고, 스톱 로스를 입시 가격의 2%로 설정합니다. 가격이 영업이익이나 스톱 로스에 도달하면 포지션을 닫습니다. 쇼트는 동일합니다.

이 전략의 핵심은 시장 추세와 반전을 판단하기 위해 EMA 빠른 및 느린 라인의 교차를 사용하는 것입니다. 빠른 라인이 위에서 넘으면 황소 시장으로 판단되고 길게 갈 것입니다. 빠른 라인이 아래를 넘으면 곰 시장으로 판단되고 짧게 갈 것입니다. 이윤을 취하고 손실을 멈추는 것은 이익을 잠금하고 위험을 제어하도록 설정됩니다.

이점 분석

이중 EMA 크로스오버 전략은 다음과 같은 장점을 가지고 있습니다.

  1. 아이디어는 명확하고 논리는 간단하고 이해하기 쉽고 실행하기 쉽습니다.
  2. 빠른 선과 느린 선은 중장기 및 단기 동향을 포착하기 위해 함께 작동합니다.
  3. 시장의 흐름을 적절히 따라가며 시장의 전환점을 파악할 수 있습니다.
  4. 적당한 취익 및 스톱 로스 설정으로 위험 통제가 이루어집니다.

일반적으로 이 전략은 시장을 명확하게 판단하고, EMA 자체의 장점을 활용하고, 중장기 및 단기적으로 좋은 수익을 얻으며 위험을 통제합니다.

위험 분석

이중 EMA 크로스오버 전략은 또한 몇 가지 위험을 가지고 있습니다:

  1. 강력한 시장 변동의 경우, EMA 크로스오버 신호는 정확하지 않을 수 있으며, 잘못된 판단의 가능성이 있습니다.
  2. 비합리적인 수익을 취하고 손실을 멈추는 지점은 더 큰 움직임을 놓칠 수도 있고 더 큰 손실을 입을 수도 있습니다.
  3. 거래 수수료와 미끄러짐의 영향도 무시할 수 없습니다.

이러한 위험은 다음과 같은 방법으로 최적화되고 해결 될 수 있습니다.

  1. 다른 지표를 결합하여 시장을 판단하고 EMA 크로스오버 신호를 잘못 판단하는 것을 피하십시오.
  2. 수익과 위험 사이의 균형을 맞추기 위해 수익을 취하고 손실을 멈추는 지점을 테스트하고 최적화하십시오.
  3. 낮은 수수료를 지불하는 거래 플랫폼을 선택하고 적당하게 포지션 크기를 늘립니다.

최적화 방향

이 전략의 주요 최적화 방향은 다음과 같습니다.

  1. 가장 좋은 매개 변수 조합을 찾기 위해 EMA 기간 매개 변수를 최적화합니다.
  2. 거래 조합을 형성하고 정확도를 향상시키기 위해 판단을위한 다른 지표를 증가시킵니다.
  3. 동적으로 수익을 취하고 손실을 멈추는 지점을 조정합니다. 예를 들어, 손실이 특정 수준에 도달하면 손실을 멈추는 지점을 확장하고, 이익이 특정 수준에 도달하면 수익을 취하는 지점을 이동합니다.
  4. 지향적인 거래에서 황소 시장과 곰 시장을 구별하십시오.

이러한 최적화는 수익률을 향상시키고 전략을 단순하고 명확하게 유지 할 수 있습니다.

요약

요약하자면, 이중 EMA 크로스오버 전략은 매우 실용적인 양적 거래 전략이다. 이해와 구현이 쉽고, 시장 트렌드를 효과적으로 포착한다. 동시에 최적화할 여지가 있다. 매개 변수 조정 및 조합을 통해 수익률을 더욱 향상시킬 수 있다. 이 전략의 단순성과 직설성은 투자자들에게 학습하고 적용할 가치가 있다.


/*backtest
start: 2024-01-22 00:00:00
end: 2024-02-21 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// SEMA-X(SEMA CROSS) [AB] : Simple EMA cross strategy Alert & Backtest
// 1. 2 EMA cross
// 2. Next candle entry
// 3. TP & SL

//@version=5
strategy("SEMA-X", "SEMA-X", overlay=false, margin_long=1,
 initial_capital=1000000, default_qty_type=strategy.percent_of_equity, default_qty_value=100,
 commission_type=strategy.commission.percent, commission_value=0.075, slippage=3)

//****************************************************************************//
// Input
//****************************************************************************//
// EMA length
emaLen25 = input.int(25, "Short", minval=1, confirm=true, group="[EMA]----------", inline="1")
emaLen50 = input.int(50, "Long",  minval=1, confirm=true, group="[EMA]----------", inline="1")

// TP & SL
isLong   = input.bool(true, "Long - ",    confirm=true, group="[TP & SL(%)]----------", inline="1")
tpLong   = input.float(2, "TP", minval=0, confirm=true, group="[TP & SL(%)]----------", inline="1")*0.01
slLong   = input.float(2, "SL", minval=0, confirm=true, group="[TP & SL(%)]----------", inline="1")*0.01
isShort  = input.bool(false, "Short - ",  confirm=true, group="[TP & SL(%)]----------", inline="2")
tpShort  = input.float(2, "TP", minval=0, confirm=true, group="[TP & SL(%)]----------", inline="2")*0.01
slShort  = input.float(2, "SL", minval=0, confirm=true, group="[TP & SL(%)]----------", inline="2")*0.01

// Backtest period
sTime = input(timestamp("0001-01-01"), "Start", group="[Backtest]----------")
eTime = input(timestamp("9999-01-01"), "End",   group="[Backtest]----------")
inDateRange   = true
periodBg      = input.bool(false, "Backtest BGcolor", confirm=true, group="[Backtest]----------", inline="1")
bgLong        = input.bool(false, "Position BGcolor", confirm=true, group="[Backtest]----------", inline="1")
periodBgColor = periodBg and inDateRange ? color.new(color.green, 95) : na
bgcolor(periodBgColor, title="Backtest BGcolor")
bgColorLong   = bgLong and strategy.position_size>0 ? color.new(color.green, 95) : na
bgcolor(bgColorLong, title="Position BGcolor")

// IRISBOT
exchange = input.string("binance",  "Exchange", confirm=true, group="[IRISBOT]----------", inline="2", options=["binance", "bybit", "upbit"])
account  = input.string("account1", "Account",  confirm=true, group="[IRISBOT]----------", inline="2")
symbol   = input.string("BTC/USDT", "Symbol",   confirm=true, group="[IRISBOT]----------", inline="3")
strategy = input.string("sema-x",   "Strategy", confirm=true, group="[IRISBOT]----------", inline="3")
token    = input.string("token",    "Token",    confirm=true, group="[IRISBOT]----------", inline="4")
stRatio  = input.float(100.0,       "Ratio(%)", confirm=true, group="[IRISBOT]----------", inline="5", tooltip="하나의 거래소에서 이 전략을 몇 % 비중으로 투자할 것인가?") * 0.01
leverage = input.float(1,           "Leverage", confirm=true, group="[IRISBOT]----------", inline="5")
isPlotMsg = input.bool(false, "View alert msg", confirm=true, group="[IRISBOT]----------", inline="6")

//****************************************************************************//
// Process
//****************************************************************************//
ema25=ta.ema(close, emaLen25)
ema50=ta.ema(close, emaLen50)

// Entry condition
longCondition  = isLong and ta.crossover(ema25, ema50)
shortCondition = isShort and ta.crossunder(ema25, ema50)

// Entry price
var price=0.0
var pricePlot=0.0
if (longCondition or shortCondition) and strategy.position_size == 0
    price:=close
pricePlot:=price
if (strategy.position_size==0)
    pricePlot:=na

// Amount
amount = str.tostring(stRatio*100)

// IRISBOT alert msg (for auto trading, you can change this for autoview, tvextbot, thanksbot, etc webhookbot)
msgLong  = '{"exchange":"'+exchange+'","account":"'+account+'","strategy":"'+strategy+'","symbol":"'+symbol+'","type":"market","side":"buy","amount":"'+amount+'%","leverage":"'+str.tostring(leverage)+'","token":"'+token+'"}'
msgShort = '{"exchange":"'+exchange+'","account":"'+account+'","strategy":"'+strategy+'","symbol":"'+symbol+'","type":"market","side":"sell","amount":"'+amount+'%","leverage":"'+str.tostring(leverage)+'","token":"'+token+'"}'
msgExit  = '{"exchange":"'+exchange+'","account":"'+account+'","strategy":"'+strategy+'","symbol":"'+symbol+'","type":"market","side":"close","token":"'+token+'"}'

// Entry signal
if inDateRange
    strategy.entry("L", strategy.long,  when=longCondition,  comment="L", alert_message=msgLong)
    strategy.entry("S", strategy.short, when=shortCondition, comment="S", alert_message=msgShort)
    strategy.exit("XL", "L", profit=price*tpLong/syminfo.mintick,  loss=price*slLong/syminfo.mintick,  comment="X", alert_message=msgExit)
    strategy.exit("XS", "S", profit=price*tpShort/syminfo.mintick, loss=price*slShort/syminfo.mintick, comment="X", alert_message=msgExit)

//****************************************************************************//
// Plot
//****************************************************************************//
// Alert msg plot
var msgTable = table.new(position = position.bottom_right, columns = 2, rows = 3, bgcolor = color.new(color.blue, 80), border_width = 1)
if isPlotMsg
    if isLong
        table.cell(msgTable, 0, 0, "Long",  text_halign = text.align_left)
        table.cell(msgTable, 1, 0, msgLong,  text_halign = text.align_left)
    
    if isShort
        table.cell(msgTable, 0, 1, "Short", text_halign = text.align_left, bgcolor=color.new(color.red, 80))
        table.cell(msgTable, 1, 1, msgShort, text_halign = text.align_left, bgcolor=color.new(color.red, 80))
    
    if isLong or isShort
        table.cell(msgTable, 0, 2, "Exit",  text_halign = text.align_left, bgcolor=color.new(color.purple, 80))
        table.cell(msgTable, 1, 2, msgExit,  text_halign = text.align_left, bgcolor=color.new(color.purple, 80))

// EMA
e0=plot(ema25, "Short", color.green)
e1=plot(ema50, "Long", color.red)
fill(e0, e1, ema25>ema50 ? color.new(color.green, 50) : color.new(color.red, 50), "EMA BG")

// TP & SL
p0=plot(pricePlot, "Entry", color.black, style=plot.style_linebr)
p1=plot(pricePlot*(strategy.position_size>0 ? 1+tpLong : 1-tpShort), "TP", color.new(color.green, 50), style=plot.style_linebr)
p2=plot(pricePlot*(strategy.position_size>0 ? 1-slLong : 1+slShort), "SL", color.new(color.red, 50), style=plot.style_linebr)
fill(p0, p1, color.new(color.green, 80), "TP BG")
fill(p0, p2, color.new(color.red, 80), "SL BG")

더 많은