동적 거래 이론의 지수 이동 평균 및 누적 거래량 사이클 크로스오버 전략

EMA CVP AVWP TOD
생성 날짜: 2025-01-06 11:45:38 마지막으로 수정됨: 2025-01-06 11:45:38
복사: 1 클릭수: 346
avatar of ChaoZhang ChaoZhang
1
집중하다
1617
수행원

동적 거래 이론의 지수 이동 평균 및 누적 거래량 사이클 크로스오버 전략

개요

이 전략은 지수 이동 평균(EMA)과 누적 거래량 기간(CVP)을 결합한 거래 시스템입니다. 가격의 지수 이동 평균과 누적 거래량 가중 가격의 교차점을 분석하여 시장 추세의 전환점을 포착합니다. 이 전략에는 거래 시간을 제한하고 거래 기간 종료 시 자동으로 포지션을 마감할 수 있는 시간 필터가 내장되어 있습니다. 이 전략은 역방향 교차 종료와 맞춤형 CVP 종료라는 두 가지 종료 방법을 제공하여 더욱 유연하고 적응력이 뛰어납니다.

전략 원칙

전략의 핵심 논리는 다음과 같은 핵심 계산에 기초합니다.

  1. 평균 가격(AVWP)을 계산합니다. 최고가, 최저가, 종가의 산술 평균에 거래량을 곱합니다.
  2. 누적 거래량 기간 값을 계산합니다. 설정 기간의 거래량 가중 가격을 더한 후 누적 거래량으로 나눕니다.
  3. 종가의 EMA와 CVP의 EMA를 별도로 계산합니다.
  4. 롱 신호는 가격 EMA가 CVP EMA를 위쪽으로 교차할 때 생성됩니다. 숏 신호는 가격 EMA가 CVP EMA를 아래쪽으로 교차할 때 생성됩니다.
  5. 종료 신호는 역 크로스오버 신호이거나 사용자 정의 CVP 사이클을 기반으로 하는 크로스오버 신호가 될 수 있습니다.

전략적 이점

  1. 신호 시스템은 견고합니다. 가격 추세와 거래량 정보를 결합하여 시장 추세를 보다 정확하게 파악합니다.
  2. 강력한 적응성: EMA 기간과 CVP 기간은 다양한 시장 환경에 적응하도록 조정될 수 있습니다.
  3. 완벽한 위험 관리: 내장된 시간 필터를 통해 거래에 적합하지 않은 기간 동안의 거래를 피할 수 있습니다.
  4. 유연한 종료 메커니즘: 두 가지 종료 방법이 제공되며, 시장 특성에 따라 적절한 종료 방법을 선택할 수 있습니다.
  5. 우수한 시각화: 이 전략은 신호 마커와 추세 영역 채우기를 포함한 명확한 그래픽 인터페이스를 제공합니다.

전략적 위험

  1. 히스테리시스 위험: EMA 자체에 특정 히스테리시스가 있어 진입 및 퇴장 시점에 약간의 지연이 발생할 수 있습니다.
  2. 변동성이 큰 시장의 위험: 횡보장이고 변동성이 큰 시장에서는 잘못된 신호가 생성될 수 있습니다.
  3. 매개변수 민감도: 매개변수 조합이 다르면 전략 성과에 큰 차이가 생길 수 있습니다.
  4. 유동성 위험: 유동성이 낮은 시장에서는 CVP 계산이 충분히 정확하지 않을 수 있습니다.
  5. 시간대 종속성: 이 전략은 뉴욕 시간을 시간 필터로 사용하며, 다양한 시장의 거래 시간 차이에 주의를 기울여야 합니다.

전략 최적화 방향

  1. 변동성 필터 소개: 전략 매개변수는 시장 변동성에 따라 조정되어 전략의 적응성을 개선할 수 있습니다.
  2. 최적화된 시간 필터: 여러 시간 창을 추가하여 거래 세션을 더욱 세밀하게 제어할 수 있습니다.
  3. 볼륨 품질 평가 강화: 볼륨 분석 지표를 도입하여 품질이 낮은 볼륨 신호를 걸러냅니다.
  4. 동적 매개변수 조정: 시장 상황에 따라 EMA 및 CVP 기간을 자동으로 조정하는 적응형 매개변수 시스템을 개발합니다.
  5. 시장 심리 지표 추가: 다른 기술 지표와 결합하여 거래 신호를 확인합니다.

요약하다

이는 완전한 구조와 명확한 논리를 갖춘 양적 거래 전략입니다. EMA와 CVP의 장점을 결합하여 위험 관리에 집중하면서 추세를 포착할 수 있는 거래 시스템이 만들어졌습니다. 이 전략은 매우 사용자 정의가 가능하며 다양한 시장 환경에서 사용하기에 적합합니다. 최적화 제안을 구현함으로써 전략 성과를 더욱 개선할 수 있는 여지가 있습니다.

전략 소스 코드
/*backtest
start: 2019-12-23 08:00:00
end: 2025-01-04 08:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5
// © sapphire_edge 

// # ========================================================================= #
// #                  
// #        _____                   __    _              ______    __         
// #      / ___/____ _____  ____  / /_  (_)_______     / ____/___/ /___ ____ 
// #      \__ \/ __ `/ __ \/ __ \/ __ \/ / ___/ _ \   / __/ / __  / __ `/ _ \
// #     ___/ / /_/ / /_/ / /_/ / / / / / /  /  __/  / /___/ /_/ / /_/ /  __/
// #    /____/\__,_/ .___/ .___/_/ /_/_/_/   \___/  /_____/\__,_/\__, /\___/ 
// #              /_/   /_/                                     /____/       
// #                                      
// # ========================================================================= #

strategy(shorttitle="⟡Sapphire⟡ EMA/CVP", title="[Sapphire] EMA/CVP Strategy", initial_capital= 50000, currency= currency.USD,default_qty_value = 1,commission_type= strategy.commission.cash_per_contract,overlay= true )

// # ========================================================================= #
// #                       // Settings Menu //
// # ========================================================================= #

// --------------------    Main Settings    -------------------- //
groupEMACVP = "EMA / Cumulative Volume Period"
tradeDirection = input.string(title='Trade Direction', defval='LONG', options=['LONG', 'SHORT'], group=groupEMACVP)
emaLength = input.int(25, title='EMA Length', minval=1, maxval=200, group=groupEMACVP)
cumulativePeriod = input.int(100, title='Cumulative Volume Period', minval=1, maxval=200, step=5, group=groupEMACVP)
exitType = input.string(title="Exit Type", defval="Crossover", options=["Crossover", "Custom CVP" ], group=groupEMACVP)
cumulativePeriodForClose = input.int(50, title='Cumulative Period for Close Signal', minval=1, maxval=200, step=5, group=groupEMACVP)
showSignals = input.bool(true, title="Show Signals", group=groupEMACVP)
signalOffset = input.int(5, title="Signal Vertical Offset", group=groupEMACVP)

// --------------------    Time Filter Inputs    -------------------- //
groupTimeOfDayFilter = "Time of Day Filter"
useTimeFilter1  = input.bool(false, title="Enable Time Filter 1", group=groupTimeOfDayFilter)
startHour1      = input.int(0, title="Start Hour (24-hour format)", minval=0, maxval=23, group=groupTimeOfDayFilter)
startMinute1    = input.int(0, title="Start Minute", minval=0, maxval=59, group=groupTimeOfDayFilter)
endHour1        = input.int(23, title="End Hour (24-hour format)", minval=0, maxval=23, group=groupTimeOfDayFilter)
endMinute1      = input.int(45, title="End Minute", minval=0, maxval=59, group=groupTimeOfDayFilter)
closeAtEndTimeWindow = input.bool(false, title="Close Trades at End of Time Window", group=groupTimeOfDayFilter)

// --------------------    Trading Window    -------------------- //
isWithinTradingWindow(startHour, startMinute, endHour, endMinute) =>
    nyTime            = timestamp("America/New_York", year, month, dayofmonth, hour, minute)
    nyHour            = hour(nyTime)
    nyMinute          = minute(nyTime)
    timeInMinutes     = nyHour * 60 + nyMinute
    startInMinutes    = startHour * 60 + startMinute
    endInMinutes      = endHour * 60 + endMinute
    timeInMinutes    >= startInMinutes and timeInMinutes <= endInMinutes

timeCondition =  (useTimeFilter1 ? isWithinTradingWindow(startHour1, startMinute1, endHour1, endMinute1) : true)

// Check if the current bar is the last one within the specified time window
isEndOfTimeWindow() =>
    nyTime            = timestamp("America/New_York", year, month, dayofmonth, hour, minute)
    nyHour            = hour(nyTime)
    nyMinute          = minute(nyTime)
    timeInMinutes     = nyHour * 60 + nyMinute
    endInMinutes      = endHour1 * 60 + endMinute1
    timeInMinutes == endInMinutes

// Logic to close trades if the time window ends
if timeCondition and closeAtEndTimeWindow and isEndOfTimeWindow()
    strategy.close_all(comment="Closing trades at end of time window")

// # ========================================================================= #
// #                       // Calculations //
// # ========================================================================= #

avgPrice = (high + low + close) / 3
avgPriceVolume = avgPrice * volume

cumulPriceVolume = math.sum(avgPriceVolume, cumulativePeriod)
cumulVolume = math.sum(volume, cumulativePeriod)
cumValue = cumulPriceVolume / cumulVolume

cumulPriceVolumeClose = math.sum(avgPriceVolume, cumulativePeriodForClose)
cumulVolumeClose = math.sum(volume, cumulativePeriodForClose)
cumValueClose = cumulPriceVolumeClose / cumulVolumeClose

emaVal = ta.ema(close, emaLength)
emaCumValue = ta.ema(cumValue, emaLength)

// # ========================================================================= #
// #                       // Signal Logic //
// # ========================================================================= #

// Strategy Entry Conditions
longEntryCondition = ta.crossover(emaVal, emaCumValue) and tradeDirection == 'LONG'
shortEntryCondition = ta.crossunder(emaVal, emaCumValue) and tradeDirection == 'SHORT'

// User-Defined Exit Conditions
longExitCondition = false
shortExitCondition = false

if exitType == "Crossover"
    longExitCondition := ta.crossunder(emaVal, emaCumValue)
    shortExitCondition := ta.crossover(emaVal, emaCumValue)

if exitType == "Custom CVP"
    emaCumValueClose = ta.ema(cumValueClose, emaLength)
    longExitCondition := ta.crossunder(emaVal, emaCumValueClose)
    shortExitCondition := ta.crossover(emaVal, emaCumValueClose)

// # ========================================================================= #
// #                       // Strategy Management //
// # ========================================================================= #

// Strategy Execution
if longEntryCondition and timeCondition
    strategy.entry('Long', strategy.long)
    label.new(bar_index, high - signalOffset, "◭", style=label.style_label_up, color = color.rgb(119, 0, 255, 20), textcolor=color.white)

if shortEntryCondition and timeCondition
    strategy.entry('Short', strategy.short)
    label.new(bar_index, low + signalOffset, "⧩", style=label.style_label_down, color = color.rgb(255, 85, 0, 20), textcolor=color.white)

if strategy.position_size > 0 and longExitCondition
    strategy.close('Long')

if strategy.position_size < 0 and shortExitCondition
    strategy.close('Short')

// # ========================================================================= #
// #                         // Plots and Charts //
// # ========================================================================= #

plot(emaVal, title='EMA', color=color.new(color.green, 25))
plot(emaCumValue, title='Cumulative EMA', color=color.new(color.purple, 35))
fill(plot(emaVal), plot(emaCumValue), color=emaVal > emaCumValue ? #008ee6 : #d436a285, title='EMA and Cumulative Area', transp=70)