듀얼 EMA 크로스오버 전략 (Dual EMA Crossover Strategy) 은 양적 거래에서 간단하고 효과적이며 이해하기 쉽고 일반적으로 사용되는 다른 기간의 두 개의 EMA 라인의 크로스오버를 기반으로 포지션을 열고 닫는 양적 거래 전략이다.
이 전략은 두 개의 EMA 라인을 사용합니다. 하나는 25기 EMA 라인이 빠른 라인이며 다른 하나는 50기 EMA 라인이 느린 라인입니다. 빠른 라인이 느린 라인의 위로 넘어가면 길게 이동합니다. 빠른 라인이 느린 라인의 아래에 넘어가면 짧게 이동합니다.
장차가 끝나면, 영업이익을 입시 가격의 2%로 설정하고, 스톱 로스를 입시 가격의 2%로 설정합니다. 가격이 영업이익이나 스톱 로스에 도달하면 포지션을 닫습니다. 쇼트는 동일합니다.
이 전략의 핵심은 시장 추세와 반전을 판단하기 위해 EMA 빠른 및 느린 라인의 교차를 사용하는 것입니다. 빠른 라인이 위에서 넘으면 황소 시장으로 판단되고 길게 갈 것입니다. 빠른 라인이 아래를 넘으면 곰 시장으로 판단되고 짧게 갈 것입니다. 이윤을 취하고 손실을 멈추는 것은 이익을 잠금하고 위험을 제어하도록 설정됩니다.
이중 EMA 크로스오버 전략은 다음과 같은 장점을 가지고 있습니다.
일반적으로 이 전략은 시장을 명확하게 판단하고, EMA 자체의 장점을 활용하고, 중장기 및 단기적으로 좋은 수익을 얻으며 위험을 통제합니다.
이중 EMA 크로스오버 전략은 또한 몇 가지 위험을 가지고 있습니다:
이러한 위험은 다음과 같은 방법으로 최적화되고 해결 될 수 있습니다.
이 전략의 주요 최적화 방향은 다음과 같습니다.
이러한 최적화는 수익률을 향상시키고 전략을 단순하고 명확하게 유지 할 수 있습니다.
요약하자면, 이중 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")