Skip to content

Commit

Permalink
Fix backtesting event bug
Browse files Browse the repository at this point in the history
- After skipping scheduled events it will re order them
- Fix bug where when only a single scheduled event was present it
wouldn't fire
  • Loading branch information
Martin-Molinero committed Mar 3, 2020
1 parent 0a7a4c3 commit 7ea241b
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 3 deletions.
6 changes: 4 additions & 2 deletions Engine/RealTime/BacktestingRealTimeHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ public void Setup(IAlgorithm algorithm, AlgorithmNodePacket job, IResultHandler
// set logging accordingly
scheduledEvent.IsLoggingEnabled = Log.DebuggingEnabled;
}
// after skipping events we should re order
_sortingScheduledEventsRequired = true;

_timeMonitor = new TimeMonitor();
}
Expand Down Expand Up @@ -117,7 +119,7 @@ public void SetTime(DateTime time)
var scheduledEvents = GetScheduledEventsSortedByTime();

// the first element is always the next
while (scheduledEvents.Count > 1 && scheduledEvents[0].NextEventUtcTime <= time)
while (scheduledEvents.Count > 0 && scheduledEvents[0].NextEventUtcTime <= time)
{
_isolatorLimitProvider.Consume(scheduledEvents[0], time, _timeMonitor);

Expand All @@ -134,7 +136,7 @@ public void ScanPastEvents(DateTime time)
var scheduledEvents = GetScheduledEventsSortedByTime();

// the first element is always the next
while (scheduledEvents.Count > 1 && scheduledEvents[0].NextEventUtcTime < time)
while (scheduledEvents.Count > 0 && scheduledEvents[0].NextEventUtcTime < time)
{
var scheduledEvent = scheduledEvents[0];
var nextEventUtcTime = scheduledEvent.NextEventUtcTime;
Expand Down
87 changes: 86 additions & 1 deletion Tests/Engine/RealTime/BacktestingRealTimeHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,85 @@ namespace QuantConnect.Tests.Engine.RealTime
[TestFixture]
public class BacktestingRealTimeHandlerTests
{
[Test]
public void SortsEventsAfterSetup()
{
var realTimeHandler = new BacktestingRealTimeHandler();
var algo = new TestAlgorithm();
algo.SubscriptionManager.SetDataManager(new DataManagerStub(algo));
algo.AddEquity("SPY");
var startDate = new DateTime(2019, 1, 1);
algo.SetStartDate(startDate);
algo.SetDateTime(startDate);
algo.SetEndDate(2020, 1, 1);

var firstCalled = false;
var secondCalled = false;
var events = new List<ScheduledEvent>
{
new ScheduledEvent("1", new List<DateTime> { startDate.AddMinutes(-10), startDate.AddMinutes(5)},
(s, time) => { firstCalled = true; }),
new ScheduledEvent("2", new List<DateTime> { startDate.AddMinutes(1)},
(s, time) => { secondCalled = true; }),
new ScheduledEvent("3", new List<DateTime> { startDate.AddMinutes(10)}, (s, time) => { })
};
foreach (var scheduledEvent in events)
{
realTimeHandler.Add(scheduledEvent);
}

realTimeHandler.Setup(algo,
new AlgorithmNodePacket(PacketType.AlgorithmNode),
new BacktestingResultHandler(),
null,
null);

realTimeHandler.SetTime(startDate.AddMinutes(1));
Assert.IsTrue(secondCalled);
// 'first' should of been called and should be moved behind 'second' after setup
Assert.IsFalse(firstCalled);
}

[Test]
public void SingleScheduledEventFires_SetTime()
{
var realTimeHandler = new BacktestingRealTimeHandler();
var algo = new TestAlgorithm();
algo.SubscriptionManager.SetDataManager(new DataManagerStub(algo));
algo.AddEquity("SPY");
algo.SetStartDate(2019, 1, 1);
algo.SetDateTime(new DateTime(2019, 1, 1));
algo.SetEndDate(2020, 1, 1);
realTimeHandler.Setup(algo,
new AlgorithmNodePacket(PacketType.AlgorithmNode),
new BacktestingResultHandler(),
null,
null);

realTimeHandler.SetTime(DateTime.UtcNow);
Assert.IsTrue(algo.OnEndOfDayFired);
}

[Test]
public void SingleScheduledEventFires_ScanPastEvents()
{
var realTimeHandler = new BacktestingRealTimeHandler();
var algo = new TestAlgorithm();
algo.SubscriptionManager.SetDataManager(new DataManagerStub(algo));
algo.AddEquity("SPY");
algo.SetStartDate(2019, 1, 1);
algo.SetDateTime(new DateTime(2019, 1, 1));
algo.SetEndDate(2020, 1, 1);
realTimeHandler.Setup(algo,
new AlgorithmNodePacket(PacketType.AlgorithmNode),
new BacktestingResultHandler(),
null,
null);

realTimeHandler.ScanPastEvents(DateTime.UtcNow);
Assert.IsTrue(algo.OnEndOfDayFired);
}

[Test]
public void TriggersScheduledEventsSameTimeInOrder()
{
Expand Down Expand Up @@ -368,9 +447,15 @@ private class TestBacktestingRealTimeHandler : BacktestingRealTimeHandler

private class TestAlgorithm : AlgorithmStub
{
public override void OnEndOfDay(Symbol symbol)
public bool OnEndOfDayFired { get; set; }

public override void OnEndOfDay()
{
OnEndOfDayFired = true;
}

public override void OnEndOfDay(Symbol symbol)
{
}
}
}
Expand Down

0 comments on commit 7ea241b

Please sign in to comment.