Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 18 additions & 10 deletions Common/Data/UniverseSelection/ScheduledUniverse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,35 +107,43 @@ public override IEnumerable<Symbol> SelectSymbols(DateTime utcTime, BaseDataColl
/// </summary>
/// <param name="startTimeUtc">The start time of the range in UTC</param>
/// <param name="endTimeUtc">The end time of the range in UTC</param>
/// <returns>An enumerator of UTC DateTimes that defines when this universe will be invoked</returns>
/// <returns>
/// An enumerator of UTC DateTimes that defines when this universe will be invoked,
/// including trigger times at both bounds when they match the configured date/time rules.
/// </returns>
public IEnumerable<DateTime> GetTriggerTimes(DateTime startTimeUtc, DateTime endTimeUtc, MarketHoursDatabase marketHoursDatabase)
{
var startTimeLocal = startTimeUtc.ConvertFromUtc(Configuration.ExchangeTimeZone);
var endTimeLocal = endTimeUtc.ConvertFromUtc(Configuration.ExchangeTimeZone);

// define date/time rule enumerable
var dates = _dateRule.GetDates(startTimeLocal, endTimeLocal);
var times = _timeRule.CreateUtcEventTimes(dates).GetEnumerator();
using var times = _timeRule.CreateUtcEventTimes(dates).GetEnumerator();

// Make sure and filter out any times before our start time
// GH #5440
var hasNext = false;
do
{
if (!times.MoveNext())
{
times.Dispose();
yield break;
}
hasNext = times.MoveNext();
}
while (times.Current < startTimeUtc);
while (hasNext && times.Current < startTimeUtc);

// Start yielding times
if (!hasNext)
{
yield break;
}

// Start yielding times within the requested time range
do
{
if (times.Current > endTimeUtc)
{
yield break;
}
yield return times.Current;
}
while (times.MoveNext());
times.Dispose();
}

private static SubscriptionDataConfig CreateConfiguration(DateTimeZone timeZone, IDateRule dateRule, ITimeRule timeRule)
Expand Down
21 changes: 21 additions & 0 deletions Tests/Common/Data/UniverseSelection/ScheduledUniverseTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,26 @@ public void TriggerTimesNone()
// Assert that its empty
Assert.IsTrue(!triggerTimesUtc.Any());
}

[Test]
public void TimeTriggeredRespectsEndTimeUtcTimePart()
{
var start = new DateTime(2025, 1, 1, 10, 0, 0);
var end = new DateTime(2025, 1, 8, 15, 32, 0);

using var universe = new ScheduledUniverse(
_dateRules.EveryDay(),
_timeRules.Every(TimeSpan.FromMinutes(1)),
_ => new List<Symbol>());

var startUtc = start.ConvertToUtc(_timezone);
var endUtc = end.ConvertToUtc(_timezone);
var triggerTimesUtc = universe.GetTriggerTimes(startUtc, endUtc, MarketHoursDatabase.AlwaysOpen).ToList();

Assert.IsNotEmpty(triggerTimesUtc);
Assert.That(triggerTimesUtc.All(x => x >= startUtc && x <= endUtc), Is.True);
Assert.AreEqual(endUtc, triggerTimesUtc.Last());
Assert.That(triggerTimesUtc.Any(x => x > endUtc), Is.False);
}
}
}