From 57ce6958dd717e12d1ca11ec492d80e565584891 Mon Sep 17 00:00:00 2001 From: Jhonathan Abreu Date: Fri, 3 Jan 2025 19:47:52 -0400 Subject: [PATCH] Skip subscription to selected securities when no tradable dates (#8495) * Skip "no tradable dates" log for options added on non-tradable dates * Skip subscription to selected securities when no tradable dates Skip selected securities subscriptions when there are no tradable dates available from selection time till end date * Minor comment * Remove "no tradable days" error log --- Engine/DataFeeds/FileSystemDataFeed.cs | 9 ---- Engine/DataFeeds/UniverseSelection.cs | 7 +++ .../DataFeeds/UniverseSelectionTests.cs | 53 +++++++++++++++++++ 3 files changed, 60 insertions(+), 9 deletions(-) diff --git a/Engine/DataFeeds/FileSystemDataFeed.cs b/Engine/DataFeeds/FileSystemDataFeed.cs index 5cbe1ac1781d..a351f7988973 100644 --- a/Engine/DataFeeds/FileSystemDataFeed.cs +++ b/Engine/DataFeeds/FileSystemDataFeed.cs @@ -99,15 +99,6 @@ protected IEnumerator CreateEnumerator(SubscriptionRequest request, Re private IEnumerator CreateDataEnumerator(SubscriptionRequest request, Resolution? fillForwardResolution) { - // ReSharper disable once PossibleMultipleEnumeration - if (!request.TradableDaysInDataTimeZone.Any()) - { - _algorithm.Error( - $"No data loaded for {request.Security.Symbol} because there were no tradeable dates for this security." - ); - return null; - } - // ReSharper disable once PossibleMultipleEnumeration var enumerator = _subscriptionFactory.CreateEnumerator(request, _dataProvider); enumerator = ConfigureEnumerator(request, false, enumerator, fillForwardResolution); diff --git a/Engine/DataFeeds/UniverseSelection.cs b/Engine/DataFeeds/UniverseSelection.cs index 1c926cd06d9b..dcc68a081e2d 100644 --- a/Engine/DataFeeds/UniverseSelection.cs +++ b/Engine/DataFeeds/UniverseSelection.cs @@ -252,6 +252,13 @@ public SecurityChanges ApplyUniverseSelection(Universe universe, DateTime dateTi foreach (var request in universe.GetSubscriptionRequests(security, dateTimeUtc, algorithmEndDateUtc, _algorithm.SubscriptionManager.SubscriptionDataConfigService)) { + if (!request.TradableDaysInDataTimeZone.Any()) + { + // Remove the config from the data manager. universe.GetSubscriptionRequests() might have added the configs + _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)) { diff --git a/Tests/Engine/DataFeeds/UniverseSelectionTests.cs b/Tests/Engine/DataFeeds/UniverseSelectionTests.cs index 2a8519a3eea5..0c5448f9ea43 100644 --- a/Tests/Engine/DataFeeds/UniverseSelectionTests.cs +++ b/Tests/Engine/DataFeeds/UniverseSelectionTests.cs @@ -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 CoarseSelectionFunction(IEnumerable coarse) { return new List {Symbols.AAPL, Symbols.SPY};