17 using System.Collections.Generic;
18 using System.Runtime.CompilerServices;
29 private static readonly Dictionary<string, byte> _optionExpirationErrorLog =
new();
51 var firstDayOfMonth =
new DateTime(date.Year, date.Month, 1).DayOfWeek;
54 var firstFriday = firstDayOfMonth == DayOfWeek.Saturday ? 7 : 6 - (int)firstDayOfMonth;
58 return firstFriday + 7 + 5 < date.Day && date.Day < firstFriday + 2 * 7 + 2 ;
103 var symbolDateTime = symbol.
ID.
Date;
106 symbolDateTime.DayOfWeek == DayOfWeek.Saturday &&
107 symbolDateTime <
new DateTime(2015, 2, 1))
116 while (!exchangeHours.IsDateOpen(symbolDateTime.AddDays(daysBefore)))
121 return symbolDateTime.AddDays(daysBefore).Date;
131 if (!TryGetExpirationDateTime(symbol, out var expiryTime, out var exchangeHours))
133 throw new ArgumentException($
"The symbol {symbol} is not an option type");
139 expiryTime = exchangeHours.GetNextMarketOpen(expiryTime.Date,
false);
153 if (TryGetExpirationDateTime(symbol, out var expiryTime, out var exchangeHours))
155 var currentTime = currentTimeUtc.ConvertFromUtc(exchangeHours.TimeZone);
156 return currentTime >= expiryTime;
162 [MethodImpl(MethodImplOptions.AggressiveInlining)]
167 expiryTime =
default;
168 exchangeHours =
null;
178 : exchangeHours.GetPreviousTradingDay(symbol.
ID.
Date);
180 expiryTime = exchangeHours.GetNextMarketClose(lastTradingDay,
false);
185 if (expiryTime >= symbol.
ID.
Date.AddDays(1).Date)
187 lock (_optionExpirationErrorLog)
191 && _optionExpirationErrorLog.TryAdd($
"{symbol.ID.Underlying}-{symbol.ID.Date}", 1))
193 Logging.Log.Error($
"OptionSymbol.IsOptionContractExpired(): limiting unexpected option expiration time for symbol {symbol.ID}. Symbol.ID.Date {symbol.ID.Date}. ExpiryTime: {expiryTime}");
196 expiryTime = symbol.
ID.
Date.AddDays(1).Date;