diff --git a/Common/Securities/Option/OptionSymbol.cs b/Common/Securities/Option/OptionSymbol.cs index f5c98abb5c74..76483d0d19c1 100644 --- a/Common/Securities/Option/OptionSymbol.cs +++ b/Common/Securities/Option/OptionSymbol.cs @@ -28,6 +28,8 @@ public static class OptionSymbol { private static readonly Dictionary _optionExpirationErrorLog = new(); + private static readonly Dictionary _expirationDateTimes = new(); + /// /// Returns true if the option is a standard contract that expires 3rd Friday of the month /// @@ -130,7 +132,7 @@ public static DateTime GetSettlementDateTime(Symbol symbol) { if (!TryGetExpirationDateTime(symbol, out var expiryTime, out var exchangeHours)) { - throw new ArgumentException("The symbol must be an option type"); + throw new ArgumentException($"The symbol {symbol} is not an option type"); } // Standard index options are AM-settled, which means they settle on market open of the expiration date @@ -171,6 +173,11 @@ private static bool TryGetExpirationDateTime(Symbol symbol, out DateTime expiryT exchangeHours = MarketHoursDatabase.FromDataFolder().GetExchangeHours(symbol.ID.Market, symbol, symbol.SecurityType); + if (_expirationDateTimes.TryGetValue(symbol, out expiryTime)) + { + return true; + } + // Ideally we can calculate expiry on the date of the symbol ID, but if that exchange is not open on that day we // will consider expired on the last trading day close before this; Example in AddOptionContractExpiresRegressionAlgorithm var lastTradingDay = exchangeHours.IsDateOpen(symbol.ID.Date) @@ -196,6 +203,8 @@ private static bool TryGetExpirationDateTime(Symbol symbol, out DateTime expiryT expiryTime = symbol.ID.Date.AddDays(1).Date; } + _expirationDateTimes[symbol] = expiryTime; + return true; } }