Skip to content

Complete the CME holiday calendars through 2029 - #9733

Open
AlexCatarino wants to merge 4 commits into
QuantConnect:masterfrom
AlexCatarino:bug-cme-memorial-day-bank-holidays
Open

Complete the CME holiday calendars through 2029#9733
AlexCatarino wants to merge 4 commits into
QuantConnect:masterfrom
AlexCatarino:bug-cme-memorial-day-bank-holidays

Conversation

@AlexCatarino

@AlexCatarino AlexCatarino commented Aug 20, 2026

Copy link
Copy Markdown
Member

Fill in the CME, CBOT, NYMEX and COMEX holiday calendars for 2027, 2028 and 2029, and correct how Good Friday is recorded on Employment Situation release days.

Description

The CME-family calendars were complete only through 2026. Everything past that was 1/1/2027, the observed Juneteenth 6/18/2027, and nothing else, so every session and every expiry computed beyond 2026 counted the rest of the calendar as ordinary business days. Futures reach a lot further than that: Henry Hub Natural Gas is listed monthly for the next twelve years.

All fifteen holidays are now filled in for 2027-2029 across the 183 per-ticker entries, plus Columbus Day and Veterans Day on the four market-wide entries. 12,384 dates in total. Each entry keeps its own schedule rather than being flattened onto the market entry: a shortened session closes at the time that entry already uses, grains reopen at 19:00 where equity index reopens at 18:00, and livestock stays shut for the whole date because it has no evening session to reopen into.

Two details drive the differences between years.

  • A Friday holiday closes the entire date, because there is no evening session after it; Monday through Thursday it is a bank holiday with a late open instead. Christmas 2027 is observed on Friday 24 December and is a full close, while Christmas 2028 falls on a Monday and is not. Corn shows the rule directly: Juneteenth is bankHolidays + a 19:00 late open in 2023, 2024 and 2025, and a plain holiday in 2026 when it lands on a Friday.
  • New Year's Day 2028 falls on a Saturday. CME trades Friday 31 December 2027 to its regular close, so that date is a bank holiday with no early close, matching 31 December 2021. There is no Christmas Eve early close in 2028 either, since 24 December is a Sunday.

Good Friday

Good Friday is not unconditionally a full close. When it carries the Employment Situation release CME runs an abbreviated session for the financial products and closes everything else, which is why Future-cme-[*] deliberately omits 4/2/2010, 4/6/2012, 4/3/2015, 4/2/2021, 4/7/2023 and 4/3/2026.

Future-cbot-[*] still listed the first four as full holidays. Since every per-ticker entry is unioned with its market entry, that overrode the early close those same products record for themselves: ZB, ZN, ZF, ZT, UB, TN, 10Y, 2YY, 30Y and 5YY each carry 10:15 on all six of those dates and YM and MYM carry 09:15, yet all twelve were reported shut for the whole day on four of them. The dates now sit on the eleven CBOT products that really are closed, so nothing changes for the grains, oilseeds and ethanol. Same holiday-versus-early-close mix-up #9205 fixed for the Dairy, Livestock and Lumber calendars.

The same comparison exposed further gaps, all fixed here:

  • CME agricultural, livestock and dairy - CB, CSC, DC, DY, GDK, GNF, GF, HE and LE - had no record at all for 2010 or 2012 and were reported open, though every later Good Friday closes them. LBR was likewise open on 4/7/2023.
  • F1U had no calendar of its own. It is the 5-Year USD MAC Swap, so it takes the 10:15 close its ten CBOT rate siblings use.
  • M6C, M6J and M6S were missing 4/3/2026 that 6C, 6J and 6S record; MJY was missing 4/3/2015; RX was missing 4/3/2026.
  • GD, MIB and MRB recorded 4/2/2021 as 8:15:00, the only three values in the file without the leading zero.

Every Good Friday is now consistent across all six Employment Situation years, and the non-release ones are a full close for all 187 tickers. None of 2027-2029 carries a release, so all three are full closes; the next that do are 7 April 2034 and 3 April 2037, which will need the 2026 treatment.

Notes

  • The 2027 dates match CME's published holiday notes exactly, including the observed dates for Juneteenth (18 June), Independence Day (5 July) and Christmas (24 December). CME publishes only as far as New Year's Day 2028, so 2028 and 2029 are projected: for each entry and holiday the shape comes from the most recent year that fell on the same kind of weekday, and the early-close time from the most recent year outright, since CME keeps moving those - energy went from 14:30 to 13:00 for Independence Day in 2025 and for Juneteenth in 2026. Projecting 2026 from 2025 and earlier reproduces 91.4% of the recorded values exactly, and the model abstains rather than guessing where it has no precedent.
  • The calendars stop at 2029, so the isolated 2030 and 2031 dates from the first two commits are removed; leaving them would give those years one holiday each and nothing else.
  • Nine entries whose newest record predates 2025 are left inheriting their market entry rather than guessed at: LBS and GE are delisted, and CSW, HCL, HRC, M5F, MRB, RX and F1U have stale calendars that should be filled from their product-group template separately.
  • Future-cfe-[*] still stops at 12/25/2026 with an empty bankHolidays, so VX has the same cliff this removes for the CME family. Left for a separate change.

Related Issue

n/a

Motivation and Context

Keeps LEAN's trading calendars and futures expiry dates correct past 2026 for the CME family, and stops twelve CBOT products being reported closed on days they actually traded.

Requires Documentation Change

N/A. The QuantConnect/Documentation repo regenerates MHDB-related docs on a weekly schedule.

How Has This Been Tested?

FuturesExpiryFunctionsTests, MarketHoursDatabaseTests, SecurityExchangeHoursTests, SymbolPropertiesDatabaseTests, SymbolRepresentationTests - 522/522 pass.

Three recorded rows in FuturesExpiryFunctionsTestData.xml move, all in December 2027 and all because 31 December is now a bank holiday. BK and CSX cease trading on the last business day of the contract month, so December 2027 goes from the 31st to the 30th, and HH's January 2028 contract goes from the 29th to the 28th. December 2021 was the same situation and is already recorded that way: BK and CSX on 2021-12-30, HH's January 2022 contract on 2021-12-28. No other recorded row moves, and the Good Friday correction moves none at all.

The earlier Memorial Day work was also verified live against Interactive Brokers (paper) by subscribing to every enumerable contract of a set of roots and seeing which IB resolves, with SIL as a positive control. GC and SI May-2027 and May-2028 were rejected before the change and resolve after; HH26M27 and NG26M27 stream on 2027-05-26, HO28M27 and RB28M27 on 2027-05-28.

Types of changes

  • Bug fix / data update (non-breaking)

Checklist:

  • My code follows the code style of this project.
  • I have read the CONTRIBUTING document.
  • All new and existing tests passed.

@AlexCatarino
AlexCatarino force-pushed the bug-cme-memorial-day-bank-holidays branch from def3de6 to 62baa26 Compare August 20, 2026 19:24
@AlexCatarino AlexCatarino changed the title Add Memorial Day 2027-2031 to the CME bank holiday calendars Extend the CME holiday calendars past 2026 (Memorial Day and Good Friday) Aug 20, 2026
The bankHolidays lists of the CME/CBOT/COMEX/NYMEX market-hours entries
carry Memorial Day every year up to 5/25/2026 and then stop, so every
expiry computed past that point silently counts it as a business day.
GetExpirationHolidays() is the only consumer of BankHolidays, so the gap
shows up purely as wrong future expiry dates.

The dates go on the four Future-<market>-[*] entries, because
MarketHoursDatabaseJsonConverter unions every per-ticker entry with its
market entry - so this reaches all 175 CME-family entries, including the
ones whose own bankHolidays list never tracked Memorial Day.

It only bites when Memorial Day lands inside the window a contract's rule
looks at, which is why it went unnoticed: 2027 and 2028 are affected,
2029-2031 are not.

Verified live against Interactive Brokers. Before the change IB rejected
GC/SI May-2027 and May-2028 with error 200 "No security definition has
been found", because LEAN asked for 2027-05-27 and 2028-05-29 - the
latter is Memorial Day itself. After it, all 24 GC and all 24 SI
contracts resolve and stream. CME's published calendar confirms the new
dates: the 1-Ounce Gold JUN 2027 and JUN 2028 contracts, which use the
same third-last-business-day-of-the-prior-month rule, last trade on
26 May 2027 and 26 May 2028.

Four recorded rows in FuturesExpiryFunctionsTestData.xml encoded the old
behaviour and are corrected here. Two of them, BK and CSX for the
May-2027 contract, expected trading to cease on 2027-05-31, which is
Memorial Day - a date those contracts cannot settle on. The other two
are HH for the June-2027 and June-2028 contracts.
Same gap as the previous commit, in the other field. The holidays lists
of the Future-<market>-[*] entries carry Good Friday up to 4/3/2026 and
then stop, so contracts whose rule looks at late March or April compute
dates that count Good Friday as a business day - or land on it outright.

Verified live against Interactive Brokers: IB rejects NG28J29 and HH28J29
at 2029-03-28 with error 200 "No security definition has been found",
reproducibly across three runs, while every neighbouring NG month out to
July 2029 resolves and streams. An isolated rejection inside an otherwise
continuous chain is the signature of a wrong date rather than a listing
window. With Good Friday 2029-03-30 in the calendar the April-2029
contracts move to 2029-03-27.

Unlike Memorial Day this goes in holidays rather than bankHolidays, so it
also feeds SecurityExchangeHours.IsDateOpen and therefore trading
calendars. Every date added is in the future, so no historical backtest
or regression test can observe the change.

One recorded row in FuturesExpiryFunctionsTestData.xml, HH for the
April-2029 contract, encoded the old behaviour and is corrected. The
other 18 rows landing in March or April of 2027-2031 are unaffected,
because their Good Friday falls outside the window their rule inspects.
@AlexCatarino
AlexCatarino force-pushed the bug-cme-memorial-day-bank-holidays branch from 62baa26 to eeed880 Compare August 21, 2026 18:10
AlexCatarino and others added 2 commits August 21, 2026 20:02
The CME, CBOT, NYMEX and COMEX calendars were complete only through 2026.
Past that the whole family carried nothing but New Year's Day 2027, the
observed Juneteenth 2027, and the two holidays added earlier on this branch,
so every session and every expiry computed beyond 2026 treated the rest of
the calendar as ordinary business days.

All fifteen holidays are now filled in for 2027, 2028 and 2029 across the 183
per-ticker entries, plus Columbus Day and Veterans Day on the four market-wide
entries. Each entry keeps its own schedule: a shortened session closes at the
time that entry already uses, grains reopen at 19:00 where equity index reopens
at 18:00, and livestock stays shut for the whole date because it has no evening
session to reopen into.

Two details drive the differences between years:

  * A holiday falling on a Friday closes the entire date, because there is no
    evening session after it. Monday through Thursday it is a bank holiday with
    a late open instead. Christmas 2027 is observed on Friday 24 December and
    is a full close; Christmas 2028 falls on a Monday and is not.
  * New Year's Day 2028 falls on a Saturday. CME trades Friday 31 December 2027
    to its regular close, so that date is a bank holiday with no early close,
    matching 31 December 2021. There is no Christmas Eve early close in 2028
    either, since 24 December is a Sunday.

Good Friday stays on the market-wide entries. None of 26 March 2027, 14 April
2028 or 30 March 2029 carries an Employment Situation release, so all three are
full closes for every product. The next Good Fridays that do are 7 April 2034
and 3 April 2037, which need the abbreviated-session treatment 3 April 2026 has.

The dates for 2027 match CME's published holiday notes exactly. 2028 and 2029
are projected: for each entry and holiday the shape is taken from the most
recent year that fell on the same kind of weekday, and the early-close time from
the most recent year outright, since CME keeps moving those - energy went from
14:30 to 13:00 for Independence Day in 2025 and for Juneteenth in 2026.
Projecting 2026 from 2025 and earlier reproduces 91.4% of the recorded values
exactly, and the model abstains rather than guessing where it has no precedent.

The calendars now stop at 2029, so the isolated 2030 and 2031 dates added
earlier on this branch are removed; leaving them would give those two years one
holiday each and nothing else.

Three recorded expiries move, all in December 2027 and all because 31 December
is now a bank holiday. BK and CSX cease trading on the last business day of the
contract month, so December 2027 moves from the 31st to the 30th, and HH's
January 2028 contract moves from the 29th to the 28th. December 2021 was the
same situation and is already recorded that way: BK and CSX on 2021-12-30, HH's
January 2022 contract on 2021-12-28.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ridays

Good Friday is not unconditionally a full CME close. When it carries the
Employment Situation release, CME runs an abbreviated session for the financial
products and closes everything else. The data already says so for 7 April 2023
and 3 April 2026, where the early close is recorded per ticker and the date is
deliberately absent from the market-wide entry.

The four earlier ones - 2 April 2010, 6 April 2012, 3 April 2015 and 2 April
2021 - were still listed as holidays on Future-cbot-[*]. Every per-ticker entry
is unioned with its market entry, so that full close overrode the early close
those same products record for themselves: ZB, ZN, ZF, ZT, UB, TN, 10Y, 2YY, 30Y
and 5YY each carry 10:15 on all six of those dates, and YM and MYM carry 09:15,
yet all twelve were reported shut for the whole day on four of them. They now
trade the abbreviated session, and the date counts as a business day for their
expiries, as it already did for 2023 and 2026.

The dates move onto the eleven CBOT products that really are closed - the
grains, oilseeds and ethanol - so nothing changes for them. This is the same
holiday-versus-early-close mix-up QuantConnect#9205 fixed for the Dairy, Livestock and
Lumber calendars.

Also filled in the gaps the same comparison exposed:

  * CME agricultural, livestock and dairy - CB, CSC, DC, DY, GDK, GNF, GF, HE
    and LE - had no record at all for 2010 or 2012 and so were reported open,
    though every later Good Friday closes them. LBR was likewise open on
    7 April 2023.
  * F1U had no calendar of its own, so removing the market-wide date would have
    left it open. It is the 5-Year USD MAC Swap, so it takes the 10:15 close its
    ten CBOT rate siblings use.
  * M6C, M6J and M6S were missing 3 April 2026 that 6C, 6J and 6S record; MJY was
    missing 3 April 2015; RX was missing 3 April 2026.
  * GD, MIB and MRB recorded 2 April 2021 as "8:15:00", the only three values in
    the file without the leading zero.

Every Good Friday is now consistent across all six Employment Situation years,
and the non-release ones stay a full close for all 187 tickers.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@AlexCatarino AlexCatarino changed the title Extend the CME holiday calendars past 2026 (Memorial Day and Good Friday) Complete the CME holiday calendars through 2029 Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant