
이 전략은 지수 이동 평균(EMA)과 시간 간격을 결합한 양방향 거래 시스템입니다. 시스템은 사용자가 정의한 고정된 시간 간격 내에서 서로 다른 기간의 EMA의 위치 관계에 따라 주요 거래 방향을 결정합니다. 동시에 다른 EMA 지표 세트의 교차 신호를 모니터링하거나 시간이 다가올 때 다음 거래 주기에서 시스템은 역방향 헤지 거래를 수행할 적절한 시간을 선택하여 양방향 거래 기회를 포착합니다.
전략 운영은 고정된 시간 간격으로 이루어지는 기본 거래와 유연한 역전 거래라는 두 가지 핵심 메커니즘을 기반으로 합니다. 주요 거래는 추세 방향을 확인하기 위해 5/40분 EMA의 상대적 위치를 기반으로 하며, 거래는 각 거래 간격(기본값은 30분)마다 실행됩니다. 역거래는 5/10분 EMA의 교차 신호를 모니터링하거나 다음 주요 거래 1분 전에 이루어지는데, 이 중 먼저 발생하는 경우에 적용됩니다. 거래의 적시성을 보장하기 위해 전체 거래는 사용자가 정의한 시간 범위 내에서 수행됩니다.
이것은 추세 추적과 역방향 트레이딩을 결합한 포괄적인 전략입니다. 시간 간격과 EMA 지표의 조정을 통해 트레이딩 기회에 대한 양방향 파악을 달성합니다. 이 전략은 높은 수준의 사용자 정의가 가능하고 우수한 위험 통제 잠재력을 가지고 있지만, 실제 시장 상황에 기반한 매개변수 최적화와 위험 관리 개선이 필요합니다. 실시간으로 적용할 경우 충분한 백테스팅과 매개변수 최적화를 수행하고, 시장 특성에 따라 타겟 조정을 하는 것이 좋습니다.
/*backtest
start: 2025-01-02 00:00:00
end: 2025-01-09 00:00:00
period: 3m
basePeriod: 3m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=5
strategy("SPX EMA Strategy with Opposite Trades", overlay=true)
// User-defined inputs
tradeIntervalMinutes = input.int(30, title="Main Trade Interval (in minutes)", minval=1)
oppositeTradeDelayMinutes = input.int(1, title="Opposite Trade time from next trade (in minutes)", minval=1) // Delay of opposite trade (1 min before the next trade)
startHour = input.int(10, title="Start Hour", minval=0, maxval=23)
startMinute = input.int(30, title="Start Minute", minval=0, maxval=59)
stopHour = input.int(15, title="Stop Hour", minval=0, maxval=23)
stopMinute = input.int(0, title="Stop Minute", minval=0, maxval=59)
// User-defined EMA periods for main trade and opposite trade
mainEmaShortPeriod = input.int(5, title="Main Trade EMA Short Period", minval=1)
mainEmaLongPeriod = input.int(40, title="Main Trade EMA Long Period", minval=1)
oppositeEmaShortPeriod = input.int(5, title="Opposite Trade EMA Short Period", minval=1)
oppositeEmaLongPeriod = input.int(10, title="Opposite Trade EMA Long Period", minval=1)
// Calculate the EMAs for main trade
emaMainShort = ta.ema(close, mainEmaShortPeriod)
emaMainLong = ta.ema(close, mainEmaLongPeriod)
// Calculate the EMAs for opposite trade (using different periods)
emaOppositeShort = ta.ema(close, oppositeEmaShortPeriod)
emaOppositeLong = ta.ema(close, oppositeEmaLongPeriod)
// Condition to check if it is during the user-defined time window
startTime = timestamp(year, month, dayofmonth, startHour, startMinute)
stopTime = timestamp(year, month, dayofmonth, stopHour, stopMinute)
currentTime = timestamp(year, month, dayofmonth, hour, minute)
// Ensure the script only trades within the user-defined time window
isTradingTime = currentTime >= startTime and currentTime <= stopTime
// Time condition: Execute the trade every tradeIntervalMinutes
var float lastTradeTime = na
timePassed = na(lastTradeTime) or (currentTime - lastTradeTime) >= tradeIntervalMinutes * 60 * 1000
// Entry Conditions for Main Trade
longCondition = emaMainShort > emaMainLong // Enter long if short EMA is greater than long EMA
shortCondition = emaMainShort < emaMainLong // Enter short if short EMA is less than long EMA
// Detect EMA crossovers for opposite trade (bullish or bearish)
bullishCrossoverOpposite = ta.crossover(emaOppositeShort, emaOppositeLong) // Opposite EMA short crosses above long
bearishCrossoverOpposite = ta.crossunder(emaOppositeShort, emaOppositeLong) // Opposite EMA short crosses below long
// Track the direction of the last main trade (true for long, false for short)
var bool isLastTradeLong = na
// Track whether an opposite trade has already been executed after the last main trade
var bool oppositeTradeExecuted = false
// Execute the main trades if within the time window and at the user-defined interval
if isTradingTime and timePassed
if longCondition
strategy.entry("Main Long", strategy.long)
isLastTradeLong := true // Mark the last trade as long
oppositeTradeExecuted := false // Reset opposite trade status
lastTradeTime := currentTime
// label.new(bar_index, low, "Main Long", color=color.green, textcolor=color.white, size=size.small)
else if shortCondition
strategy.entry("Main Short", strategy.short)
isLastTradeLong := false // Mark the last trade as short
oppositeTradeExecuted := false // Reset opposite trade status
lastTradeTime := currentTime
// label.new(bar_index, high, "Main Short", color=color.red, textcolor=color.white, size=size.small)
// Execute the opposite trade only once after the main trade
if isTradingTime and not oppositeTradeExecuted
// 1 minute before the next main trade or EMA crossover
if (currentTime - lastTradeTime) >= (tradeIntervalMinutes - oppositeTradeDelayMinutes) * 60 * 1000 or bullishCrossoverOpposite or bearishCrossoverOpposite
if isLastTradeLong
// If the last main trade was long, enter opposite short trade
strategy.entry("Opposite Short", strategy.short)
//label.new(bar_index, high, "Opposite Short", color=color.red, textcolor=color.white, size=size.small)
else
// If the last main trade was short, enter opposite long trade
strategy.entry("Opposite Long", strategy.long)
//label.new(bar_index, low, "Opposite Long", color=color.green, textcolor=color.white, size=size.small)
// After entering the opposite trade, set the flag to true so no further opposite trades are placed
oppositeTradeExecuted := true
// Plot the EMAs for visual reference
plot(emaMainShort, title="Main Trade Short EMA", color=color.blue)
plot(emaMainLong, title="Main Trade Long EMA", color=color.red)
plot(emaOppositeShort, title="Opposite Trade Short EMA", color=color.purple)
plot(emaOppositeLong, title="Opposite Trade Long EMA", color=color.orange)