diff --git a/Common/Securities/Future/FuturesExpiryFunctions.cs b/Common/Securities/Future/FuturesExpiryFunctions.cs index 8075f7e4a261..2aec92aa32f3 100644 --- a/Common/Securities/Future/FuturesExpiryFunctions.cs +++ b/Common/Securities/Future/FuturesExpiryFunctions.cs @@ -916,13 +916,12 @@ public static Func FuturesExpiryFunction(Symbol symbol) // The Business Day immediately preceding the last Business Day of the Contract Month var lastDay = new DateTime(time.Year, time.Month, DateTime.DaysInMonth(time.Year, time.Month)); - var priorBusinessDay = lastDay.AddDays(-1); var holidays = FuturesExpiryUtilityFunctions.GetHolidays(Market.HKFE, Futures.Indices.HangSeng); - while (holidays.Contains(priorBusinessDay) || !priorBusinessDay.IsCommonBusinessDay()) - { - priorBusinessDay = priorBusinessDay.AddDays(-1); - } + var lastBusinessDay = FuturesExpiryUtilityFunctions.AddBusinessDaysIfHoliday(lastDay, -1, holidays); + var priorBusinessDay = lastBusinessDay.AddDays(-1); + + priorBusinessDay = FuturesExpiryUtilityFunctions.AddBusinessDaysIfHoliday(priorBusinessDay, -1, holidays); return priorBusinessDay.Add(new TimeSpan(16, 0, 0)); }) }, diff --git a/Tests/Common/Securities/Futures/FuturesExpiryFunctionsTests.cs b/Tests/Common/Securities/Futures/FuturesExpiryFunctionsTests.cs index e4e55c6ac351..3ec128cea75c 100644 --- a/Tests/Common/Securities/Futures/FuturesExpiryFunctionsTests.cs +++ b/Tests/Common/Securities/Futures/FuturesExpiryFunctionsTests.cs @@ -69,6 +69,18 @@ public void Init() } } + [Test] + public void HSIFutures() + { + var canonical = Symbol.Create("HSI", SecurityType.Future, Market.HKFE); + var expiration = FuturesExpiryFunctions.FuturesExpiryDictionary[canonical]; + + // last day and previous are holidays + Assert.AreEqual(new DateTime(2025, 1, 27, 16, 0, 0), expiration(new DateTime(2025, 1, 1))); + // normal case + Assert.AreEqual(new DateTime(2025, 2, 27, 16, 0, 0), expiration(new DateTime(2025, 2, 1))); + } + [Test] public void FuturesExpiryFunction_MissingSymbol_ShouldThrowArgumentException() {