Skip to content

Commit

Permalink
Skip subscription to selected securities when no tradable dates
Browse files Browse the repository at this point in the history
Skip selected securities subscriptions when there are no tradable dates available from selection time till end date
  • Loading branch information
jhonabreul committed Jan 3, 2025
1 parent ac393a3 commit 94602da
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 8 deletions.
9 changes: 1 addition & 8 deletions Engine/DataFeeds/FileSystemDataFeed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,7 @@ protected IEnumerator<BaseData> CreateEnumerator(SubscriptionRequest request, Re
private IEnumerator<BaseData> CreateDataEnumerator(SubscriptionRequest request, Resolution? fillForwardResolution)
{
// ReSharper disable once PossibleMultipleEnumeration
if (!request.TradableDaysInDataTimeZone.Any() &&
// We won't log this warning for options: options could be selected or manually added on Saturdays
// or non-tradable dates at midnight (selection for Monday or next tradable date happens on Saturday)
// and there might not be a tradable date between that and the algorithm's end date, causing the
// tradable dates enumerable to be empty. e.g an algorithm that starts on a Saturday and ends the
// following Sunday adds an option: selection happens on that Saturday at midnight, but the next
// tradable date is Monday.
!request.Configuration.Symbol.SecurityType.IsOption())
if (!request.TradableDaysInDataTimeZone.Any())
{
_algorithm.Error(
$"No data loaded for {request.Security.Symbol} because there were no tradeable dates for this security."
Expand Down
6 changes: 6 additions & 0 deletions Engine/DataFeeds/UniverseSelection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,12 @@ public SecurityChanges ApplyUniverseSelection(Universe universe, DateTime dateTi
foreach (var request in universe.GetSubscriptionRequests(security, dateTimeUtc, algorithmEndDateUtc,
_algorithm.SubscriptionManager.SubscriptionDataConfigService))
{
if (!request.TradableDaysInDataTimeZone.Any())
{
_dataManager.RemoveSubscription(request.Configuration, universe);
continue;
}

if (security.Symbol == request.Configuration.Symbol // Just in case check its the same symbol, else AddData will throw.
&& !security.Subscriptions.Contains(request.Configuration))
{
Expand Down
53 changes: 53 additions & 0 deletions Tests/Engine/DataFeeds/UniverseSelectionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,59 @@ public void CoarseFundamentalHasFundamentalDataFalseExcludedInFineUniverseSelect
Assert.AreEqual(Symbols.AAPL, securityChanges.AddedSecurities.First().Symbol);
}

[Test]
public void DoesNotAddSelectedSecuritiesIfNoTradableDates()
{
var algorithm = new AlgorithmStub(new MockDataFeed());
algorithm.SetStartDate(2023, 12, 01);
algorithm.SetEndDate(2023, 12, 30); // Sunday

algorithm.AddUniverse(
coarse => coarse.Select(c => c.Symbol),
fine => fine.Select(f => f.Symbol));
algorithm.OnEndOfTimeStep();

var universe = algorithm.UniverseManager.Values.First();

var getUniverseData = (DateTime dt) => new BaseDataCollection(
dt,
Symbols.AAPL,
[
new CoarseFundamental
{
Symbol = Symbols.AAPL,
Time = dt
},
new CoarseFundamental
{
Symbol = Symbols.SPY,
Time = dt
}
]
);

// Friday, one tradeale day left before end date
var dateTime = new DateTime(2023, 12, 29).ConvertToUtc(algorithm.TimeZone);
var universeData = getUniverseData(dateTime);

var securityChanges = algorithm.DataManager.UniverseSelection.ApplyUniverseSelection(
universe,
dateTime,
universeData);
Assert.AreEqual(2, securityChanges.AddedSecurities.Count);
CollectionAssert.AreEquivalent(universeData.Select(x => x.Symbol), securityChanges.AddedSecurities.Select(x => x.Symbol));

// Saturday, no tradable days left before end date
dateTime += TimeSpan.FromDays(1);
universeData = getUniverseData(dateTime);

securityChanges = algorithm.DataManager.UniverseSelection.ApplyUniverseSelection(
universe,
dateTime,
universeData);
Assert.AreEqual(0, securityChanges.AddedSecurities.Count);
}

private IEnumerable<Symbol> CoarseSelectionFunction(IEnumerable<CoarseFundamental> coarse)
{
return new List<Symbol> {Symbols.AAPL, Symbols.SPY};
Expand Down

0 comments on commit 94602da

Please sign in to comment.