diff --git a/Common/Data/Consolidators/SessionConsolidator.cs b/Common/Data/Consolidators/SessionConsolidator.cs
index 564f444dadd9..efd416db6529 100644
--- a/Common/Data/Consolidators/SessionConsolidator.cs
+++ b/Common/Data/Consolidators/SessionConsolidator.cs
@@ -65,6 +65,15 @@ public SessionConsolidator(SecurityExchangeHours exchangeHours, TickType sourceT
/// The new data
protected override void AggregateBar(ref SessionBar workingBar, BaseData data)
{
+ if (!_initialized)
+ {
+ if (workingBar.Time == DateTime.MaxValue || data.Time.Date > workingBar.Time.Date)
+ {
+ workingBar.Time = data.Time.Date;
+ }
+ _initialized = true;
+ }
+
// Handle open interest
if (data.DataType == MarketDataType.Tick && data is Tick oiTick && oiTick.TickType == TickType.OpenInterest)
{
@@ -82,20 +91,6 @@ protected override void AggregateBar(ref SessionBar workingBar, BaseData data)
workingBar.Update(data, Consolidated);
}
- ///
- /// Updates the session with new market data and initializes the consolidator if needed
- ///
- /// The new data to update the session with
- public override void Update(BaseData data)
- {
- if (!_initialized)
- {
- _workingBar.Time = data.Time.Date;
- _initialized = true;
- }
- base.Update(data);
- }
-
///
/// Validates the current local time and triggers Scan() if a new day is detected.
///
diff --git a/Tests/Indicators/SessionTests.cs b/Tests/Indicators/SessionTests.cs
index 3a12e3674286..825b8fab8de5 100644
--- a/Tests/Indicators/SessionTests.cs
+++ b/Tests/Indicators/SessionTests.cs
@@ -171,6 +171,49 @@ private static IEnumerable NextSessionTradingDayCases()
yield return new TestCaseData(new DateTime(2025, 8, 29, 10, 0, 0), new DateTime(2025, 9, 2));
}
+ [Test]
+ public void ManualDailyBarUpdateProducesOneConsolidationPerBar()
+ {
+ var symbol = Symbols.SPY;
+ var barCount = 20;
+ var exchangeHours = MarketHoursDatabase.FromDataFolder().GetExchangeHours(symbol.ID.Market, symbol, symbol.SecurityType);
+ var session = new Session(TickType.Trade, exchangeHours, symbol, barCount + 1);
+
+ var barDate = new DateTime(2025, 9, 2, 9, 30, 0);
+ for (var i = 0; i < barCount; i++)
+ {
+ session.Update(new TradeBar(barDate, symbol, 100 + i, 101 + i, 99 + i, 100 + i, 1000, Time.OneDay));
+ barDate = barDate.AddDays(1);
+ while (!exchangeHours.IsDateOpen(barDate.Date, false))
+ {
+ barDate = barDate.AddDays(1);
+ }
+ }
+
+ Assert.AreEqual(barCount, session.Samples);
+ }
+
+ [Test]
+ public void GapDayDataPreservesCorrectTimestampAndContent()
+ {
+ var symbol = Symbols.SPY;
+ var exchangeHours = MarketHoursDatabase.FromDataFolder().GetExchangeHours(symbol.ID.Market, symbol, symbol.SecurityType);
+ var session = new Session(TickType.Trade, exchangeHours, symbol, 5);
+
+ var sep2 = new DateTime(2025, 9, 2, 9, 30, 0);
+ var sep4 = new DateTime(2025, 9, 4, 9, 30, 0);
+ var sep5 = new DateTime(2025, 9, 5, 9, 30, 0);
+
+ session.Update(new TradeBar(sep2, symbol, 100, 110, 90, 105, 1000, Time.OneDay));
+ session.Update(new TradeBar(sep4, symbol, 200, 210, 190, 205, 2000, Time.OneDay));
+ session.Update(new TradeBar(sep5, symbol, 300, 310, 290, 305, 3000, Time.OneDay));
+
+ Assert.AreEqual(sep4.Date, session[1].Time);
+ Assert.AreEqual(200, session[1].Open);
+ Assert.AreEqual(sep2.Date, session[2].Time);
+ Assert.AreEqual(100, session[2].Open);
+ }
+
private static Session GetSession(TickType tickType, int initialSize)
{
var symbol = Symbols.SPY;