diff --git a/Algorithm/QCAlgorithm.cs b/Algorithm/QCAlgorithm.cs index f4e2c5241ac4..e8b8c9b4d871 100644 --- a/Algorithm/QCAlgorithm.cs +++ b/Algorithm/QCAlgorithm.cs @@ -2341,6 +2341,11 @@ public Option AddOptionContract(Symbol symbol, Resolution? resolution = null, bo underlyingConfigs = SubscriptionManager.SubscriptionDataConfigService .GetSubscriptionDataConfigs(underlying); } + else if (underlyingSecurity != null && underlyingSecurity.IsDelisted) + { + throw new ArgumentException($"The underlying {underlying.SecurityType} asset ({underlying.Value}) is delisted " + + $"(current time is {Time})"); + } else { underlyingConfigs = SubscriptionManager.SubscriptionDataConfigService diff --git a/Tests/Algorithm/AlgorithmAddDataTests.cs b/Tests/Algorithm/AlgorithmAddDataTests.cs index 6c93b74db262..67c0c6214583 100644 --- a/Tests/Algorithm/AlgorithmAddDataTests.cs +++ b/Tests/Algorithm/AlgorithmAddDataTests.cs @@ -16,7 +16,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Python.Runtime; using Newtonsoft.Json; using NodaTime; using NUnit.Framework; @@ -645,6 +644,33 @@ public void DoesNotCauseCollision_WhenRegisteringMultipleDifferentCustomDataType Assert.AreNotSame(unlinkedData, bitcoin); } + [TestCase(SecurityType.Equity)] + [TestCase(SecurityType.Index)] + [TestCase(SecurityType.Future)] + public void AddOptionContractWithDelistedUnderlyingThrows(SecurityType underlyingSecurityType) + { + var algorithm = Algorithm(); + algorithm.SetStartDate(2007, 05, 25); + + Security underlying = underlyingSecurityType switch + { + SecurityType.Equity => algorithm.AddEquity("SPY"), + SecurityType.Index => algorithm.AddIndex("SPX"), + SecurityType.Future => algorithm.AddFuture("ES"), + _ => throw new ArgumentException($"Invalid test underlying security type {underlyingSecurityType}") + }; + + underlying.IsDelisted = true; + // let's remove the underlying since it's delisted + algorithm.RemoveSecurity(underlying.Symbol); + + var optionContractSymbol = Symbol.CreateOption(underlying.Symbol, Market.USA, OptionStyle.American, OptionRight.Call, 100, + new DateTime(2007, 06, 15)); + + var exception = Assert.Throws(() => algorithm.AddOptionContract(optionContractSymbol)); + Assert.IsTrue(exception.Message.Contains("is delisted"), $"Unexpected exception message: {exception.Message}"); + } + private static SubscriptionDataConfig GetMatchingSubscription(QCAlgorithm algorithm, Symbol symbol, Type type) { // find a subscription matchin the requested type with a higher resolution than requested