Keep symbol early closes and late opens over market-wide holidays - #9869
Merged
Merged
Conversation
) 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>
6 of 11 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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, whichVerifyMarketHoursDataIntegrityForAllSymbolsrejects. The 13:00 ET early close stays.Related Issue
Closes #9866. Alternative to #9867: the change stays in the wildcard merge instead of the
SecurityExchangeHoursconstructor, 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 inFuture-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:
Requires Documentation Change
No.
How Has This Been Tested?
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.MarketHoursDatabaseJsonConverterTests.KeepsHolidaysTheEntryDoesNotTradeOn(GC 2020-01-20, OANDA HK33HKD 2018-12-31).SecurityExchangeHoursTests.EarlyCloseBetweenSegmentsKeepsSegmentsBeforeIt. It and the CL 2009-01-19 case fail with the previousindex = i - 1.SecurityExchangeHoursTests,MarketHoursDatabaseJsonConverterTests,MarketHoursDatabaseTests(includingVerifyMarketHoursDataIntegrityForAllSymbols) 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
Checklist:
bug-<issue#>-<description>orfeature-<issue#>-<description>🤖 Generated with Claude Code