diff --git a/Algorithm.CSharp/MarketHourAwareIntradayConsolidationRegressionAlgorithm.cs b/Algorithm.CSharp/MarketHourAwareIntradayConsolidationRegressionAlgorithm.cs
deleted file mode 100644
index b76bdbe5be6e..000000000000
--- a/Algorithm.CSharp/MarketHourAwareIntradayConsolidationRegressionAlgorithm.cs
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
- * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-*/
-
-using System;
-using System.Collections.Generic;
-using QuantConnect.Data;
-using QuantConnect.Data.Common;
-using QuantConnect.Data.Market;
-using QuantConnect.Interfaces;
-using QuantConnect.Securities;
-using QuantConnect.Securities.Future;
-
-namespace QuantConnect.Algorithm.CSharp
-{
- ///
- /// Regression algorithm asserting that a with an intraday period
- /// anchors each bar to the market open and never lets a bar extend past the market close.
- ///
- public class MarketHourAwareIntradayConsolidationRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
- {
- private readonly TimeSpan _period = TimeSpan.FromMinutes(7);
- private Future _future;
- private SecurityExchangeHours _hours;
- private int _consolidatedBarCount;
-
- public override void Initialize()
- {
- SetStartDate(2013, 10, 06);
- SetEndDate(2013, 10, 11);
-
- _future = AddFuture(Futures.Indices.SP500EMini, Resolution.Minute, extendedMarketHours: true);
- _hours = _future.Exchange.Hours;
-
- var consolidator = new MarketHourAwareConsolidator(false, _period, typeof(TradeBar), TickType.Trade, extendedMarketHours: true);
- consolidator.DataConsolidated += OnSevenMinuteBar;
- SubscriptionManager.AddConsolidator(_future.Symbol, consolidator);
- }
-
- private void OnSevenMinuteBar(object sender, IBaseData consolidated)
- {
- var bar = (TradeBar)consolidated;
- var marketOpen = _hours.GetPreviousMarketOpen(bar.Time.AddTicks(1), extendedMarketHours: true);
- var marketClose = _hours.GetNextMarketClose(marketOpen, extendedMarketHours: true);
-
- // the bar must be anchored to the market open
- if ((bar.Time - marketOpen).Ticks % _period.Ticks != 0)
- {
- throw new RegressionTestException($"Bar starting at {bar.Time} is not anchored to the market open {marketOpen}");
- }
-
- // the bar must not extend past the market close
- if (bar.EndTime > marketClose)
- {
- throw new RegressionTestException($"Bar ending at {bar.EndTime} extends past the market close {marketClose}");
- }
-
- // bars span the full period unless the last one is clipped at the market close
- var barPeriod = bar.EndTime - bar.Time;
- if (barPeriod != _period && bar.EndTime != marketClose)
- {
- throw new RegressionTestException($"Bar from {bar.Time} to {bar.EndTime} has period {barPeriod} instead of {_period}");
- }
-
- _consolidatedBarCount++;
- }
-
- public override void OnEndOfAlgorithm()
- {
- if (_consolidatedBarCount == 0)
- {
- throw new RegressionTestException("The consolidator did not produce any bar");
- }
- }
-
- ///
- /// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
- ///
- public bool CanRunLocally { get; } = true;
-
- ///
- /// This is used by the regression test system to indicate which languages this algorithm is written in.
- ///
- public List Languages { get; } = new() { Language.CSharp, Language.Python };
-
- ///
- /// Data Points count of all timeslices of algorithm
- ///
- public long DataPoints => 41486;
-
- ///
- /// Data Points count of the algorithm history
- ///
- public int AlgorithmHistoryDataPoints => 0;
-
- ///
- /// Final status of the algorithm
- ///
- public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
-
- ///
- /// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
- ///
- public Dictionary ExpectedStatistics => new Dictionary
- {
- {"Total Orders", "0"},
- {"Average Win", "0%"},
- {"Average Loss", "0%"},
- {"Compounding Annual Return", "0%"},
- {"Drawdown", "0%"},
- {"Expectancy", "0"},
- {"Start Equity", "100000"},
- {"End Equity", "100000"},
- {"Net Profit", "0%"},
- {"Sharpe Ratio", "0"},
- {"Sortino Ratio", "0"},
- {"Probabilistic Sharpe Ratio", "0%"},
- {"Loss Rate", "0%"},
- {"Win Rate", "0%"},
- {"Profit-Loss Ratio", "0"},
- {"Alpha", "0"},
- {"Beta", "0"},
- {"Annual Standard Deviation", "0"},
- {"Annual Variance", "0"},
- {"Information Ratio", "-2.564"},
- {"Tracking Error", "0.214"},
- {"Treynor Ratio", "0"},
- {"Total Fees", "$0.00"},
- {"Estimated Strategy Capacity", "$0"},
- {"Lowest Capacity Asset", ""},
- {"Portfolio Turnover", "0%"},
- {"Drawdown Recovery", "0"},
- {"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
- };
- }
-}
diff --git a/Algorithm.Python/MarketHourAwareIntradayConsolidationRegressionAlgorithm.py b/Algorithm.Python/MarketHourAwareIntradayConsolidationRegressionAlgorithm.py
deleted file mode 100644
index fdf8ff4ed855..000000000000
--- a/Algorithm.Python/MarketHourAwareIntradayConsolidationRegressionAlgorithm.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
-# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from AlgorithmImports import *
-
-###
-### Regression algorithm asserting that a MarketHourAwareConsolidator with an intraday period
-### anchors each bar to the market open and never lets a bar extend past the market close.
-###
-class MarketHourAwareIntradayConsolidationRegressionAlgorithm(QCAlgorithm):
-
- def initialize(self):
- self.set_start_date(2013, 10, 6)
- self.set_end_date(2013, 10, 11)
-
- self._period = timedelta(minutes=7)
- self._consolidated_bar_count = 0
-
- self._future = self.add_future(Futures.Indices.SP_500_E_MINI, Resolution.MINUTE, extended_market_hours=True)
- self._hours = self._future.exchange.hours
-
- consolidator = MarketHourAwareConsolidator(False, self._period, TradeBar, TickType.TRADE, True)
- consolidator.data_consolidated += self._on_seven_minute_bar
- self.subscription_manager.add_consolidator(self._future.symbol, consolidator)
-
- def _on_seven_minute_bar(self, sender, consolidated):
- bar = consolidated
- market_open = self._hours.get_previous_market_open(bar.time + timedelta(microseconds=1), True)
- market_close = self._hours.get_next_market_close(market_open, True)
-
- # the bar must be anchored to the market open
- if (bar.time - market_open) % self._period != timedelta(0):
- raise RegressionTestException(f"Bar starting at {bar.time} is not anchored to the market open {market_open}")
-
- # the bar must not extend past the market close
- if bar.end_time > market_close:
- raise RegressionTestException(f"Bar ending at {bar.end_time} extends past the market close {market_close}")
-
- # bars span the full period unless the last one is clipped at the market close
- bar_period = bar.end_time - bar.time
- if bar_period != self._period and bar.end_time != market_close:
- raise RegressionTestException(f"Bar from {bar.time} to {bar.end_time} has period {bar_period} instead of {self._period}")
-
- self._consolidated_bar_count += 1
-
- def on_end_of_algorithm(self):
- if self._consolidated_bar_count == 0:
- raise RegressionTestException("The consolidator did not produce any bar")
diff --git a/Common/AlgorithmImports.py b/Common/AlgorithmImports.py
index eb4a39208869..35cda517a1ca 100644
--- a/Common/AlgorithmImports.py
+++ b/Common/AlgorithmImports.py
@@ -68,7 +68,6 @@
from QuantConnect.Securities.Equity import *
from QuantConnect.Securities.Future import *
from QuantConnect.Data.Consolidators import *
-from QuantConnect.Data.Common import *
from QuantConnect.Orders.TimeInForces import *
from QuantConnect.Algorithm.Framework import *
from QuantConnect.Algorithm.Selection import *
diff --git a/Common/Data/Consolidators/MarketHourAwareConsolidator.cs b/Common/Data/Consolidators/MarketHourAwareConsolidator.cs
index 6f406f57aa26..b674cfd9d1f8 100644
--- a/Common/Data/Consolidators/MarketHourAwareConsolidator.cs
+++ b/Common/Data/Consolidators/MarketHourAwareConsolidator.cs
@@ -89,36 +89,6 @@ public MarketHourAwareConsolidator(bool dailyStrictEndTimeEnabled, Resolution re
Consolidator.DataConsolidated += ForwardConsolidatedBar;
}
- ///
- /// Initializes a new instance of the class for an arbitrary period.
- /// Intraday periods are anchored to the market open without extending past the close.
- ///
- /// True if daily strict end times should be enabled
- /// The consolidation period
- /// The target data type
- /// The target tick type
- /// True if extended market hours should be consolidated
- public MarketHourAwareConsolidator(bool dailyStrictEndTimeEnabled, TimeSpan period, Type dataType, TickType tickType, bool extendedMarketHours)
- {
- _dailyStrictEndTimeEnabled = dailyStrictEndTimeEnabled;
- Period = period;
- _extendedMarketHours = extendedMarketHours;
-
- // when the period exactly matches a standard resolution, reuse the resolution based consolidation so its
- // well-tested behavior is preserved; only arbitrary periods need the market-open anchored intraday calendar
- var resolution = period.ToHigherResolutionEquivalent(false);
- if (resolution.ToTimeSpan() == period)
- {
- Consolidator = CreateConsolidator(resolution, dataType, tickType);
- }
- else
- {
- Func calendar = period < Time.OneDay ? IntradayCalendar : DailyStrictEndTime;
- Consolidator = CreateConsolidator(calendar, dataType, tickType);
- }
- Consolidator.DataConsolidated += ForwardConsolidatedBar;
- }
-
///
/// Creates the inner consolidator that produces the requested output.
///
@@ -151,28 +121,6 @@ protected virtual IDataConsolidator CreateConsolidator(Resolution resolution, Ty
throw new ArgumentNullException(nameof(dataType), $"{dataType.Name} not supported");
}
- ///
- /// Creates the underlying calendar based consolidator for the given data type, used for arbitrary periods
- ///
- protected virtual IDataConsolidator CreateConsolidator(Func calendar, Type dataType, TickType tickType)
- {
- if (dataType == typeof(Tick))
- {
- return tickType == TickType.Trade
- ? new TickConsolidator(calendar)
- : new TickQuoteBarConsolidator(calendar);
- }
- if (dataType == typeof(TradeBar))
- {
- return new TradeBarConsolidator(calendar);
- }
- if (dataType == typeof(QuoteBar))
- {
- return new QuoteBarConsolidator(calendar);
- }
- throw new ArgumentNullException(nameof(dataType), $"{dataType.Name} not supported");
- }
-
///
/// Event handler that fires when a new piece of data is produced
///
@@ -247,27 +195,13 @@ protected void Initialize(IBaseData data)
///
protected virtual CalendarInfo DailyStrictEndTime(DateTime dateTime)
{
- // strict end times describe a single daily bar, so periods larger than a day fall back to standard period consolidation
- if (!_useStrictEndTime || Period > Time.OneDay)
+ if (!_useStrictEndTime)
{
return new(Period > Time.OneDay ? dateTime : dateTime.RoundDown(Period), Period);
}
return LeanData.GetDailyCalendar(dateTime, ExchangeHours, _extendedMarketHours);
}
- ///
- /// Determines a bar start time and period for intraday consolidation, anchored to the market open
- /// without extending past the market close so a bar never spans across closed market hours
- ///
- protected virtual CalendarInfo IntradayCalendar(DateTime dateTime)
- {
- if (ExchangeHours == null || ExchangeHours.IsMarketAlwaysOpen)
- {
- return new(dateTime.RoundDown(Period), Period);
- }
- return LeanData.GetIntradayCalendar(dateTime, Period, ExchangeHours, _extendedMarketHours);
- }
-
///
/// Useful for testing
///
diff --git a/Common/Util/LeanData.cs b/Common/Util/LeanData.cs
index f473c9f115e0..4bbcf1e62e97 100644
--- a/Common/Util/LeanData.cs
+++ b/Common/Util/LeanData.cs
@@ -1476,33 +1476,6 @@ public static CalendarInfo GetDailyCalendar(DateTime exchangeTimeZoneDate, Secur
return new CalendarInfo(startTime, period);
}
- ///
- /// Helper method to return the intraday bar start time and period, anchored to the market open, without extending past the close
- ///
- /// The point in time we want to get the bar information about
- /// The intraday consolidation period
- /// The associated exchange hours
- /// True if extended market hours should be taken into consideration
- /// The calendar information that holds a start time and a period
- public static CalendarInfo GetIntradayCalendar(DateTime exchangeTimeZoneDate, TimeSpan period, SecurityExchangeHours exchangeHours, bool extendedMarketHours)
- {
- var marketOpen = exchangeHours.IsOpen(exchangeTimeZoneDate, extendedMarketHours)
- ? exchangeHours.GetPreviousMarketOpen(exchangeTimeZoneDate.AddTicks(1), extendedMarketHours)
- : exchangeHours.GetPreviousMarketOpen(exchangeTimeZoneDate, extendedMarketHours);
-
- var intervalsPassed = (long)Math.Floor((exchangeTimeZoneDate - marketOpen).Ticks / (double)period.Ticks);
- var startTime = marketOpen.AddTicks(intervalsPassed * period.Ticks);
-
- // keep the last bar from extending past the market close
- var endTime = startTime + period;
- var marketClose = exchangeHours.GetNextMarketClose(marketOpen, extendedMarketHours);
- if (endTime > marketClose)
- {
- endTime = marketClose;
- }
- return new CalendarInfo(startTime, endTime - startTime);
- }
-
///
/// Helper method to get the next daily end time, taking into account strict end times if appropriate
///
diff --git a/Tests/Common/Data/MarketHourAwareConsolidatorTests.cs b/Tests/Common/Data/MarketHourAwareConsolidatorTests.cs
index d6153996dee2..3ad59c56396b 100644
--- a/Tests/Common/Data/MarketHourAwareConsolidatorTests.cs
+++ b/Tests/Common/Data/MarketHourAwareConsolidatorTests.cs
@@ -21,7 +21,6 @@
using QuantConnect.Data.Consolidators;
using System.Collections.Generic;
using QuantConnect.Data;
-using QuantConnect.Securities;
namespace QuantConnect.Tests.Common.Data
{
@@ -295,91 +294,6 @@ public void WorksWithDailyResolutionAndPreciseEndTimeFalse()
Assert.AreEqual(100, consolidatedData.High);
}
- [Test]
- public void IntradayConsolidatorIsAnchoredToMarketOpen()
- {
- var symbol = Symbols.Future_ESZ18_Dec2018;
- var exchangeHours = MarketHoursDatabase.FromDataFolder().GetExchangeHours(symbol.ID.Market, symbol, symbol.SecurityType);
- var marketOpen = exchangeHours.GetNextMarketOpen(new DateTime(2024, 11, 30, 12, 0, 0), extendedMarketHours: true);
-
- using var consolidator = new MarketHourAwareConsolidator(false, TimeSpan.FromMinutes(7), typeof(TradeBar), TickType.Trade, extendedMarketHours: true);
- var bars = new List();
- consolidator.DataConsolidated += (_, b) => bars.Add((TradeBar)b);
-
- // feed the first 30 minutes after the open, one bar per minute
- Feed(consolidator, symbol, marketOpen, 30);
-
- Assert.GreaterOrEqual(bars.Count, 3);
- Assert.AreEqual(marketOpen, bars[0].Time);
- Assert.AreEqual(marketOpen.AddMinutes(7), bars[0].EndTime);
- Assert.AreEqual(marketOpen.AddMinutes(14), bars[1].EndTime);
- Assert.AreEqual(marketOpen.AddMinutes(21), bars[2].EndTime);
- }
-
- [Test]
- public void IntradayConsolidatorLastBarEndsAtMarketClose()
- {
- var symbol = Symbols.SPY;
- using var consolidator = new MarketHourAwareConsolidator(false, TimeSpan.FromMinutes(7), typeof(TradeBar), TickType.Trade, extendedMarketHours: false);
- var bars = new List();
- consolidator.DataConsolidated += (_, b) => bars.Add((TradeBar)b);
-
- // feed the last 10 minutes of day 1 (up to the 16:00 close) and the first 10 of day 2
- Feed(consolidator, symbol, new DateTime(2015, 04, 13, 15, 50, 0), 10);
- Feed(consolidator, symbol, new DateTime(2015, 04, 14, 9, 30, 0), 10);
-
- // day 1 produces two 7 minute bars anchored to the market open at 9:30
- var day1Bars = bars.FindAll(b => b.Time.Date == new DateTime(2015, 04, 13));
- Assert.AreEqual(2, day1Bars.Count);
- Assert.AreEqual(new DateTime(2015, 04, 13, 15, 48, 0), day1Bars[0].Time);
- Assert.AreEqual(new DateTime(2015, 04, 13, 15, 55, 0), day1Bars[0].EndTime);
- Assert.AreEqual(new DateTime(2015, 04, 13, 15, 55, 0), day1Bars[1].Time);
- Assert.AreEqual(new DateTime(2015, 04, 13, 16, 0, 0), day1Bars[1].EndTime);
-
- // next day starts over at the market open at 9:30
- var day2Open = new DateTime(2015, 04, 14, 9, 30, 0);
- var firstDay2 = bars.Find(b => b.Time == day2Open);
- Assert.IsNotNull(firstDay2);
- Assert.AreEqual(day2Open.AddMinutes(7), firstDay2.EndTime);
- }
-
- [TestCase(true)]
- [TestCase(false)]
- public void ConsolidatesPeriodGreaterThanOneDay(bool dailyStrictEndTimeEnabled)
- {
- var symbol = Symbols.SPX;
- using var consolidator = new MarketHourAwareConsolidator(dailyStrictEndTimeEnabled, TimeSpan.FromDays(2), typeof(TradeBar), TickType.Trade, extendedMarketHours: true);
- var bars = new List();
- consolidator.DataConsolidated += (_, b) => bars.Add((TradeBar)b);
-
- // feed 4 daily bars
- var start = new DateTime(2015, 04, 13, 10, 0, 0);
- for (var i = 0; i < 4; i++)
- {
- consolidator.Update(new TradeBar { Time = start.AddDays(i), Period = Time.OneDay, Symbol = symbol, Open = 1, High = 1, Low = 1, Close = 1, Volume = 1 });
- }
- consolidator.Scan(start.AddDays(4));
-
- Assert.AreEqual(2, bars.Count);
- // first bar
- Assert.AreEqual(TimeSpan.FromDays(2), bars[0].Period);
- Assert.AreEqual(start, bars[0].Time);
- Assert.AreEqual(start.AddDays(2), bars[0].EndTime);
- // second bar
- Assert.AreEqual(TimeSpan.FromDays(2), bars[1].Period);
- Assert.AreEqual(start.AddDays(2), bars[1].Time);
- Assert.AreEqual(start.AddDays(4), bars[1].EndTime);
- }
-
- private static void Feed(IDataConsolidator consolidator, Symbol symbol, DateTime from, int minutes)
- {
- for (var i = 0; i < minutes; i++)
- {
- var t = from.AddMinutes(i);
- consolidator.Update(new TradeBar { Time = t, Period = Time.OneMinute, Symbol = symbol, Open = 1, High = 1, Low = 1, Close = 1, Volume = 1 });
- }
- }
-
protected override IDataConsolidator CreateConsolidator()
{
return new MarketHourAwareConsolidator(true, Resolution.Hour, typeof(TradeBar), TickType.Trade, false);