Skip to content

Keep symbol early closes and late opens over market-wide holidays - #9869

Merged
Martin-Molinero merged 1 commit into
masterfrom
bug-9866-wildcard-holidays-early-closes
Oct 5, 2026
Merged

Martin-Molinero merged 1 commit into
masterfrom
bug-9866-wildcard-holidays-early-closes

Conversation

@Martin-Molinero

Copy link
Copy Markdown
Member

Description

  • MarketHoursDatabaseJsonConverter: when a market-wide ([*]) entry's holidays are merged into a symbol entry, a date the symbol entry gives its own early close or late open is no longer added as a holiday. It goes to the entry's bank holidays instead, so futures expiry rules keep skipping it. A holiday the symbol entry lists itself still wins.
  • SecurityExchangeHours.GetMarketHours: when an early close fell in the break between two segments, the segment that ended before it was dropped (index = i - 1, from SecurityExchangeHours::GetMarketHours(DateTime) check early closes and late opens  #6278). It is now kept. The newly opened dates reach this path (e.g. the 17:15 ET early close on 2009-01-19 and 2009-02-16 for NYMEX/COMEX/CBOT futures, which otherwise lost their regular session), and it also affected 335 already open dates in 29 entries (e.g. ZW/ZC/KE/ZO on Thanksgiving eves, OANDA NZD pairs on Dec 24/31).
  • market-hours-database.json: removes the 7/3/2020 late open from 95 futures entries. It was a Friday (Independence Day observed) and CME reopened on Sunday; once the date is no longer a holiday the late open produced overlapping segments, which VerifyMarketHoursDataIntegrityForAllSymbols rejects. The 13:00 ET early close stays.

Related Issue

Closes #9866. Alternative to #9867: the change stays in the wildcard merge instead of the SecurityExchangeHours constructor, and keeps the dates as bank holidays so expiries don't move.

Motivation and Context

Future-comex-[*], Future-nymex-[*], Future-cbot-[*] (and 1/20/2025 in Future-cme-[*]) list the CME Globex half-days as full holidays, which overrode the symbol entries' own early closes and late opens. Those dates resolved to closed all day and their data was never read (e.g. MGC on 2020-01-20).

The resulting hours were checked against CME's archived Globex holiday schedules for 2009-2025: NYMEX/COMEX energy and metals, CBOT treasuries (from late 2011), YM/MYM, grains and every 2022-2025 group match. Some symbol entries carry their own data errors that this now exposes, left for a follow-up:

  • EH 2009 to early 2013 traded grain hours and was closed on these holidays (confirmed with EH minute data for 2010-02-15), but its entry gives a 12:15 CT early close and 17:00 CT late open. ICE CT/OJ on 2017-11-23 has the same problem.
  • HG, HRC, CSW, M5F (2009-2019), ICE DX, and Brent/Gasoil on Thanksgiving miss the evening reopen, and a few early close times are off (M5F 2020-2022, treasuries 2011-05-30).

Requires Documentation Change

No.

How Has This Been Tested?

  • New MarketHoursDatabaseJsonConverterTests.WildcardHolidayDoesNotOverrideEntryEarlyCloseAndLateOpen (MGC 2020-01-20, CL 2020-07-03, CL 2009-01-19, EH 2012-07-04): exact market hours, not a holiday, still a bank holiday.
  • New MarketHoursDatabaseJsonConverterTests.KeepsHolidaysTheEntryDoesNotTradeOn (GC 2020-01-20, OANDA HK33HKD 2018-12-31).
  • New SecurityExchangeHoursTests.EarlyCloseBetweenSegmentsKeepsSegmentsBeforeIt. It and the CL 2009-01-19 case fail with the previous index = i - 1.
  • SecurityExchangeHoursTests, MarketHoursDatabaseJsonConverterTests, MarketHoursDatabaseTests (including VerifyMarketHoursDataIntegrityForAllSymbols) and the futures expiry tests pass locally. Regression algorithms were not run locally; the segment fix could move the statistics of any that cover the affected dates.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • Refactor (non-breaking change which improves implementation)
  • Performance (non-breaking change which improves performance. Please add associated performance test and results)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Non-functional change (xml comments/documentation/etc)

Checklist:

  • My code follows the code style of this project.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • My branch follows the naming convention bug-<issue#>-<description> or feature-<issue#>-<description>

🤖 Generated with Claude Code

)

A market-wide ([*]) holiday no longer overrides a date the symbol entry gives its own
early close or late open; the date becomes a bank holiday so expiry rules still skip it.
GetMarketHours kept one segment too few when an early close fell between two segments.
Removes the 7/3/2020 late open from 95 futures entries, a Friday with no evening session.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Martin-Molinero
Martin-Molinero merged commit 82810ea into master Oct 5, 2026
16 checks passed
@Martin-Molinero
Martin-Molinero deleted the bug-9866-wildcard-holidays-early-closes branch October 5, 2026 21:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant