Diese Strategie ist ein Handelssystem, das den exponentiellen gleitenden Durchschnitt (EMA) und den kumulativen Volumenzeitraum (CVP) kombiniert. Es erfasst Markttrendumkehrpunkte, indem es den Crossover zwischen Preis-EMA und kumulativem volumengewichtetem Preis analysiert. Die Strategie enthält einen eingebauten Zeitfilter zur Begrenzung von Handelssitzungen und unterstützt das automatische Schließen von Positionen am Ende von Handelszeiten. Sie bietet zwei verschiedene Ausstiegsmethoden: Reverse Crossover Exit und Custom CVP Exit, was eine starke Flexibilität und Anpassungsfähigkeit bietet.
Die Kernlogik der Strategie beruht auf folgenden Schlüsselberechnungen:
Dies ist eine quantitative Handelsstrategie mit kompletter Struktur und klarer Logik. Durch die Kombination der Vorteile von EMA und CVP entsteht ein Handelssystem, das Trends erfassen und sich auf die Risikokontrolle konzentrieren kann.
/*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)