Conversation
Add holiday-rule primitives for accurate exchange calendars: ForwardMonday weekend substitution, computed Christmas+Boxing, until_year bounds, per-date exceptions for moved holidays, and WeekdayOnOrBefore (Victoria Day). Reimplement and verify against reference calendars: - US (NYSE/NASDAQ/NYSE American/Cboe/CFE): ad-hoc mourning/9-11/Sandy closures; Juneteenth first observed 2022 (not 2021). - Euronext (Paris/Amsterdam/Brussels/Lisbon): no substitute days; harmonized six-holiday set (drop national holidays the exchange trades through). - UK (LSE): full bank-holiday substitution plus one-offs (Jubilee, Queen's funeral, Coronation, VE Day) and moved spring BH in 2022. - Canada (TSX/TSXV): correct Victoria Day, Canada Day and Christmas substitution. Signed-off-by: prettygoodcap <131185838+pgc-dev@users.noreply.github.com>
Add SundayToMonday roll and generalize Christmas+Boxing into a reusable ConsecutivePair (collision-bumped) rule. Reimplement and verify: - Australia (ASX): substituted New Year/Australia Day, no-substitute ANZAC, King's Birthday, Christmas+Boxing, Queen mourning day (2022-09-22). - New Zealand (NZX): mondayised New Year pair, Waitangi, ANZAC; Matariki tabulated from official dates; Queen mourning day (2022-09-26). - South Africa (JSE): Sunday-only substitution; independent Christmas/Goodwill (no cascade); election and 2016 festive one-offs. - Ireland (Euronext Dublin): model the ISE to Euronext migration (June bank holiday and May bank holiday drift, Labour Day from 2019, Storm Emma 2018). Signed-off-by: prettygoodcap <131185838+pgc-dev@users.noreply.github.com>
Add PrecedingFriday roll (SIX New Year's Eve) and fixed_between helper for calendar drift. Reimplement Germany (Xetra), Switzerland (SIX), Austria (Wiener Borse), Sweden, Denmark, Finland, Norway and Iceland as continental no-substitute calendars, including festive-block closures (Dec 24-26/31), Midsummer Eve and First Day of Summer weekday rules, and historical drift (Xetra Whit Monday through 2021 and Unity Day 2016-2019; Wiener Borse trimming Ascension/Epiphany/religious holidays; Danish Great Prayer Day through 2023). Signed-off-by: prettygoodcap <131185838+pgc-dev@users.noreply.github.com>
Reimplement Italy (Euronext Milan) and Spain (BME) as trimmed no-substitute calendars, and Poland (GPW), Hungary (BSE) and Czechia (PSE) with their national holidays and festive-block closures. Tabulate Hungarian bridge days and one-off closures (Madrid 2021 festive days, Warsaw 2018 independence centenary). Signed-off-by: prettygoodcap <131185838+pgc-dev@users.noreply.github.com>
Add WeekdayOnOrAfter rule (Colombian Emiliani-law holidays move to the next Monday) and fixed_prev_fri helper (year-end closure to the preceding Friday). Reimplement Mexico (BMV), Brazil (B3) and Colombia (BVC), including B3's São Paulo state/city holidays (observed through 2021, 2020 COVID exceptions) and Black Awareness Day becoming national in 2024. Signed-off-by: prettygoodcap <131185838+pgc-dev@users.noreply.github.com>
…olidays Add computed Japanese equinox rule, a JapaneseEquinox holiday type, and a Japanese holiday adjustment (substitute holidays for Sunday closures and citizens' holidays between two holidays). Reimplement JPX with Happy-Monday holidays and their historical fixed-date predecessors, the Emperor's Birthday transition (Dec 23 through 2018, Feb 23 from 2020), Mountain Day (since 2016), the 2019 imperial one-offs, the Tokyo 2020 Olympic holiday moves, and the 2020-10-01 system-outage closure. Signed-off-by: prettygoodcap <131185838+pgc-dev@users.noreply.github.com>
Add a lunisolar calendar module computing new moons (Meeus ch. 49), apparent solar longitude (ch. 25), winter-solstice-anchored month numbering with leap months, and the Qingming solar term, all in China Standard Time. Add ChineseLunar and Qingming holiday rules and a Hong Kong Sunday-substitute adjustment. Reimplement HKEX with computed Lunar New Year, Buddha's Birthday, Dragon Boat, day-after Mid-Autumn, Chung Yeung and Qingming, plus tabulated typhoon/one-off closures. Ching Ming substitution surfaced two pmc errors (2021-04-06, 2026-04-07). Signed-off-by: prettygoodcap <131185838+pgc-dev@users.noreply.github.com>
Parameterize the lunisolar calendar by meridian (CST for China/HK/Taiwan, KST for Korea) so Korea's occasionally-different lunar dates resolve correctly. Reimplement KRX with computed Seollal, Chuseok and Buddha's Birthday, add Labour Day and the exchange year-end closure, and tabulate the substitute holidays and temporary/election closures (whose qualifying rules changed in 2014/2021/2023). Signed-off-by: prettygoodcap <131185838+pgc-dev@users.noreply.github.com>
Reimplement TWSE and SSE using the computed lunisolar anchors (Lunar New Year, Qingming, Dragon Boat, Mid-Autumn) plus their fixed national holidays, and tabulate the annually State-Council/DGPA-decreed Golden Week span extensions, bridge days and make-up arrangements (and Taiwan typhoon closures), curated from the official exchange calendars for 2015-2030. Signed-off-by: prettygoodcap <131185838+pgc-dev@users.noreply.github.com>
Switch these markets to no-substitute fixed holidays and curate the movable- holiday observances and annually-decreed bridge days from the official exchange calendars (additions), with exceptions for the days the recurring rules place on the wrong date. Signed-off-by: prettygoodcap <131185838+pgc-dev@users.noreply.github.com>
Curate the festival closures for Singapore, Malaysia, Indonesia, Thailand, India (NSE/BSE), Saudi Arabia (Tadawul), Istanbul and Tel Aviv from the official exchange calendars (2015-2030). These markets' Islamic (moon-sighting), Hindu lunisolar and Hebrew observances plus bridge days are administratively set and not algorithmically derivable, so they are tabulated alongside each venue's fixed-date rules, with exceptions where a rule places a holiday on another day. Signed-off-by: prettygoodcap <131185838+pgc-dev@users.noreply.github.com>
Update the NYSE Juneteenth test to reflect first observance in 2022 (open on 2021-06-18), and move the APAC lunch-break session test off 2026-05-25, which is now correctly Hong Kong's Buddha's Birthday, to a plain trading day. Signed-off-by: prettygoodcap <131185838+pgc-dev@users.noreply.github.com>
Add a deterministic, offline CI test that validates every mapped exchange against two independent reference calendar packages (pandas-market-calendars and exchange-calendars), whose holiday data ships in the package. It uses a reference-consensus strategy: assert our trading days only where the two references agree, so known reference bugs (where they disagree) need no allowlist. Falls back to a single reference with a documented divergence list when only one covers a market. Adds a [reference] extra (pulled into develop) so CI installs the oracles; the test importorskips when they are absent. Signed-off-by: prettygoodcap <131185838+pgc-dev@users.noreply.github.com>
Add a monthly (and manually-dispatchable) workflow that compares finance-dates calendars against pandas-market-calendars over a future window (2031+, past the 2030 curation horizon), corroborated by exchange-calendars where projectable. When drift is found it opens or updates a 'calendar-drift'-labelled tracking issue with a Markdown report, flagging curated tables that need extending or any computable-calendar regression. Non-blocking: separate from PR CI. Signed-off-by: prettygoodcap <131185838+pgc-dev@users.noreply.github.com>
Contributor
Test Results169 tests +61 169 ✅ +61 40s ⏱️ +39s Results for commit 20c7240. ± Comparison against base commit 463fc18. This pull request removes 3 and adds 64 tests. Note that renamed tests count towards both. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #21 +/- ##
==========================================
- Coverage 89.01% 88.44% -0.57%
==========================================
Files 7 8 +1
Lines 437 502 +65
Branches 26 34 +8
==========================================
+ Hits 389 444 +55
- Misses 43 50 +7
- Partials 5 8 +3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
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.
This started from a single missing NYSE closure — January 9, 2025, the national day of mourning for President Carter — and grew into a full reimplementation of every exchange holiday calendar
finance-datesexposes.All 50 mapped exchange codes now reproduce their exact trading-day set over 2015–2030 when cross-checked against two independent reference libraries (
pandas-market-calendarsandexchange-calendars), verified weekmask-aware so Saudi's Fri/Sat and Tel Aviv's Sun–Thu weekends are handled correctly.Everything computable is implemented from first-principles rules and astronomy (our own code); the references are used only as an oracle to validate against, never vendored into our source. Where a calendar is genuinely administrative (Chinese/Taiwan Golden Weeks, Korean substitutes, Islamic moon-sighting, Hindu festivals, Latin-American bridge days) the observed dates are curated from the official exchange calendars and tabulated alongside the computable anchors.
Motivation
The previous calendars were incomplete: missing ad-hoc closures (days of mourning, typhoons), an off-by-one Juneteenth first-observance, over-closing on national holidays that exchanges trade through, wrong weekend-substitution behavior, and lunar tables hard-coded only to ~2026. This PR makes the calendars correct and, crucially, keeps them correct via automated CI checks.
What changed
Holiday-rule engine (
rust/src/holiday.rs,calendar.rs)New reusable primitives so calendars are expressed as rules, not hand-tabulated where avoidable:
ConsecutivePair— collision-bumped two-day holidays (Christmas+Boxing, NZ New Year, SA Christmas+Goodwill).WeekdayOnOrBefore/WeekdayOnOrAfter— Canadian Victoria Day, Colombian Emiliani-law shifts.until_yearbounds and per-dateexceptions— for calendar drift and one-off holiday moves.Astronomical lunisolar calendar (
rust/src/lunar.rs, new)A from-scratch implementation — no external calendar data:
Plus a Japanese equinox computation (vernal/autumnal) for JPX.
Markets reimplemented (by region)
Reference bugs found
Because we reimplemented rather than copied, the audit surfaced 3 dates where the references are wrong and our calendars are right (confirmed against the official exchange calendars, and the second reference agrees with us):
Testing / CI
test_reference_calendars.py): validates every mapped exchange against a two-reference consensus over 2015–2030 — asserts our trading days only where the two references agree with each other, so known reference bugs need no allowlist. Deterministic and fully offline (reference data ships in the pip packages; added as a test-only[reference]extra pulled intodevelop)..github/workflows/calendar-drift.yaml+scripts/check_calendar_drift.py): monthly, non-blocking. Compares against the forward-projecting reference over 2031+ and opens/updates acalendar-drifttracking issue when a curated table needs extending or a computable calendar regresses. Confirms the computable markets (US, Euronext, DACH/Nordics, UK, Canada, Australia, Japan, HKEX) drift-free through 2040.