이 전략은 기하급수적인 이동 평균 (EMA) 과 누적 볼륨 기간 (CVP) 을 결합한 거래 시스템이다. 가격 EMA와 누적 볼륨 가중된 가격 사이의 교차점을 분석하여 시장 트렌드 반전 지점을 포착합니다. 전략에는 거래 세션을 제한하기위한 내장 시간 필터가 포함되어 있으며 거래 기간의 끝에서 자동 포지션 폐쇄를 지원합니다. 두 가지 다른 출구 방법을 제공합니다. 역 교차 출구 및 사용자 지정 CVP 출구, 강력한 유연성과 적응성을 제공합니다.
전략의 핵심 논리는 다음의 핵심 계산에 기초합니다.
이것은 완전한 구조와 명확한 논리를 가진 양적 거래 전략이다. 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)