pandas-market-calendars 4.4.0__py3-none-any.whl → 4.6.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -31,6 +31,7 @@ from pandas_market_calendars.holidays.us import (
31
31
  ChristmasEveBefore1993,
32
32
  ChristmasEveInOrAfter1993,
33
33
  USBlackFridayInOrAfter1993,
34
+ USJuneteenthAfter2022,
34
35
  USIndependenceDay,
35
36
  USMartinLutherKingJrAfter1998,
36
37
  USMemorialDay,
@@ -98,6 +99,7 @@ class CMEEquityExchangeCalendar(MarketCalendar):
98
99
  USPresidentsDay,
99
100
  USMemorialDay,
100
101
  USLaborDay,
102
+ USJuneteenthAfter2022,
101
103
  USIndependenceDay,
102
104
  USThanksgivingDay,
103
105
  USBlackFridayInOrAfter1993,
@@ -158,6 +160,7 @@ class CMEAgricultureExchangeCalendar(MarketCalendar):
158
160
  USPresidentsDay,
159
161
  GoodFriday,
160
162
  USMemorialDay,
163
+ USJuneteenthAfter2022,
161
164
  USIndependenceDay,
162
165
  USLaborDay,
163
166
  USThanksgivingDay,
@@ -124,3 +124,49 @@ class CMEGlobexLivestockExchangeCalendar(CMEGlobexAgricultureExchangeCalendar):
124
124
  ),
125
125
  )
126
126
  ]
127
+
128
+
129
+ class CMEGlobexGrainsAndOilseedsExchangeCalendar(CMEGlobexAgricultureExchangeCalendar):
130
+ """
131
+ Exchange calendar for CME for Grains & Oilseeds
132
+
133
+ https://www.cmegroup.com/trading/agricultural/grain-and-oilseed.html
134
+
135
+ GLOBEX Trading Times
136
+ https://www.cmegroup.com/markets/agriculture/oilseeds/soybean.contractSpecs.html
137
+ https://www.cmegroup.com/markets/agriculture/grains/corn.contractSpecs.html
138
+ https://www.cmegroup.com/markets/agriculture/grains/wheat.contractSpecs.html
139
+ Sunday - Friday: 7:00 p.m. - 7:45 a.m. CT and Monday - Friday: 8:30 a.m. - 1:20 p.m. CT
140
+ """
141
+
142
+ aliases = [
143
+ "CMEGlobex_Grains",
144
+ "CMEGlobex_Oilseeds",
145
+ ]
146
+
147
+ regular_market_times = {
148
+ "market_open": ((None, time(19), -1),), # offset by -1 day
149
+ "market_close": ((None, time(13, 20)),),
150
+ "break_start": ((None, time(7, 45)),),
151
+ "break_end": ((None, time(8, 30)),),
152
+ }
153
+
154
+ @property
155
+ def name(self):
156
+ return "CMEGlobex_GrainsAndOilseeds"
157
+
158
+ @property
159
+ def regular_holidays(self):
160
+ return AbstractHolidayCalendar(
161
+ rules=[
162
+ USNewYearsDay,
163
+ USMartinLutherKingJrAfter1998,
164
+ USPresidentsDay,
165
+ GoodFriday,
166
+ USMemorialDay,
167
+ USIndependenceDay,
168
+ USLaborDay,
169
+ USThanksgivingDay,
170
+ Christmas,
171
+ ]
172
+ )
@@ -43,13 +43,6 @@ MayBank = Holiday(
43
43
  day=1,
44
44
  days_of_week=(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY),
45
45
  )
46
- # German National Holiday (Tag der Deutschen Einheit)
47
- GermanNationalDay = Holiday(
48
- "Tag der Deutschen Einheit",
49
- month=10,
50
- day=3,
51
- days_of_week=(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY),
52
- )
53
46
  # Christmas Eve
54
47
  ChristmasEve = Holiday(
55
48
  "Christmas Eve",
@@ -116,7 +109,6 @@ class EUREXExchangeCalendar(MarketCalendar):
116
109
  GoodFriday,
117
110
  EasterMonday,
118
111
  MayBank,
119
- GermanNationalDay,
120
112
  Christmas,
121
113
  WeekendChristmas,
122
114
  BoxingDay,
@@ -354,6 +354,9 @@ HKClosedDay = [
354
354
  Timestamp("2016-10-21", tz="UTC"), # 台风海马1622
355
355
  # Timestamp(2017-06-12', tz='UTC'), # 台风苗柏1702,期货夜盘17:35休市
356
356
  Timestamp("2017-08-23", tz="UTC"), # 台风天鸽1713
357
+ Timestamp("2023-07-17", tz="UTC"), # Typhoon closure
358
+ Timestamp("2023-09-01", tz="UTC"), # Typhoon closure
359
+ Timestamp("2023-09-08", tz="UTC"), # Typhoon closure
357
360
  ]
358
361
 
359
362
 
@@ -1,9 +1,13 @@
1
1
  from datetime import time
2
2
  from itertools import chain
3
3
 
4
+ from pandas import Timestamp, DatetimeIndex, Timedelta
4
5
  from pandas.tseries.holiday import AbstractHolidayCalendar
5
6
  from pytz import timezone
6
7
 
8
+ from typing import Literal, Union
9
+ from pandas_market_calendars import calendar_utils as u
10
+
7
11
  from pandas_market_calendars.holidays.nyse import (
8
12
  USPresidentsDay,
9
13
  GoodFriday,
@@ -106,7 +110,42 @@ class IEXExchangeCalendar(NYSEExchangeCalendar):
106
110
  return []
107
111
 
108
112
  def valid_days(self, start_date, end_date, tz="UTC"):
109
- trading_days = super().valid_days(
110
- start_date, end_date, tz=tz
111
- ) # all NYSE valid days
112
- return trading_days[~(trading_days <= "2013-08-25")]
113
+ start_date = Timestamp(start_date)
114
+ if start_date.tz is not None:
115
+ # Ensure valid Comparison to "2013-08-25" is possible
116
+ start_date.tz_convert(self.tz).tz_localize(None)
117
+
118
+ # Limit Start_date to the Exchange's Open
119
+ start_date = max(start_date, Timestamp("2013-08-25"))
120
+ return super().valid_days(start_date, end_date, tz=tz)
121
+
122
+ def date_range_htf(
123
+ self,
124
+ frequency: Union[str, Timedelta, int, float],
125
+ start: Union[str, Timestamp, int, float, None] = None,
126
+ end: Union[str, Timestamp, int, float, None] = None,
127
+ periods: Union[int, None] = None,
128
+ closed: Union[Literal["left", "right"], None] = "right",
129
+ *,
130
+ day_anchor: u.Day_Anchor = "SUN",
131
+ month_anchor: u.Month_Anchor = "JAN",
132
+ ) -> DatetimeIndex:
133
+
134
+ start, end, periods = u._error_check_htf_range(start, end, periods)
135
+
136
+ # Cap Beginning and end dates to the opening date of IEX
137
+ if start is not None:
138
+ start = max(start, Timestamp("2013-08-25"))
139
+ if end is not None:
140
+ end = max(end, Timestamp("2013-08-25"))
141
+
142
+ return u.date_range_htf(
143
+ self.holidays(),
144
+ frequency,
145
+ start,
146
+ end,
147
+ periods,
148
+ closed,
149
+ day_anchor=day_anchor,
150
+ month_anchor=month_anchor,
151
+ )
@@ -21,13 +21,17 @@ class JPXExchangeCalendar(MarketCalendar):
21
21
 
22
22
  Open Time: 9:31 AM, Asia/Tokyo
23
23
  LUNCH BREAK :facepalm: : 11:30 AM - 12:30 PM Asia/Tokyo
24
- Close Time: 4:00 PM, Asia/Tokyo
24
+ Close Time: 3:30 PM, Asia/Tokyo
25
+
26
+ Market close of Japan changed from 3:00 PM to 3:30 PM on November 5, 2024
27
+ Reference:
28
+ https://www.jpx.co.jp/english/equities/trading/domestic/tvdivq0000006blj-att/tradinghours_eg.pdf
25
29
  """
26
30
 
27
31
  aliases = ["JPX", "XJPX"]
28
32
  regular_market_times = {
29
33
  "market_open": ((None, time(9)),),
30
- "market_close": ((None, time(15)),),
34
+ "market_close": ((None, time(15)), ("2024-11-05", time(15, 30))),
31
35
  "break_start": ((None, time(11, 30)),),
32
36
  "break_end": ((None, time(12, 30)),),
33
37
  }
@@ -8,6 +8,8 @@ import exchange_calendars
8
8
 
9
9
  from pandas_market_calendars.market_calendar import MarketCalendar
10
10
 
11
+ DAYMASKS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
12
+
11
13
 
12
14
  class TradingCalendar(MarketCalendar):
13
15
  """
@@ -97,6 +99,23 @@ class TradingCalendar(MarketCalendar):
97
99
  def special_closes_adhoc(self):
98
100
  return self._ec.special_closes_adhoc
99
101
 
102
+ @property
103
+ def weekmask(self):
104
+ if hasattr(self._ec, "weekmask"):
105
+ if "1" in self._ec.weekmask or "0" in self._ec.weekmask:
106
+ # Convert 1s & 0s to Day Abbreviations
107
+ return " ".join(
108
+ [
109
+ DAYMASKS[i]
110
+ for i, val in enumerate(self._ec.weekmask)
111
+ if val == "1"
112
+ ]
113
+ )
114
+ else:
115
+ return self._ec.weekmask
116
+ else:
117
+ return "Mon Tue Wed Thu Fri"
118
+
100
119
 
101
120
  calendars = exchange_calendars.calendar_utils._default_calendar_factories # noqa
102
121
 
@@ -18,8 +18,12 @@ from itertools import chain
18
18
 
19
19
  import pandas as pd
20
20
  from pandas.tseries.holiday import AbstractHolidayCalendar
21
+ from pandas.tseries.offsets import CustomBusinessDay
21
22
  from pytz import timezone
22
23
 
24
+ from typing import Literal, Union
25
+ from pandas_market_calendars import calendar_utils as u
26
+
23
27
  from pandas_market_calendars.holidays.nyse import (
24
28
  # Always Celebrated Holidays
25
29
  USNewYearsDayNYSEpost1952,
@@ -297,6 +301,8 @@ from pandas_market_calendars.holidays.nyse import (
297
301
  HurricaneSandyClosings2012,
298
302
  # 2018
299
303
  GeorgeHWBushDeath2018,
304
+ # 2025
305
+ JimmyCarterDeath2025,
300
306
  )
301
307
  from pandas_market_calendars.market_calendar import MarketCalendar
302
308
 
@@ -828,7 +834,28 @@ class NYSEExchangeCalendar(MarketCalendar):
828
834
 
829
835
  @property
830
836
  def weekmask(self):
831
- return "Mon Tue Wed Thu Fri Sat" # Market open on Saturdays thru 5/24/1952
837
+ return "Mon Tue Wed Thu Fri"
838
+
839
+ @property
840
+ def weekmask_pre_1952(self):
841
+ return "Mon Tue Wed Thu Fri Sat"
842
+
843
+ def holidays_pre_1952(self):
844
+ """
845
+ NYSE Market open on Saturdays pre 5/24/1952.
846
+ CustomBusinessDay object that can be used inplace of holidays() for dates prior to crossover
847
+
848
+ :return: CustomBusinessDay object of holidays
849
+ """
850
+ if hasattr(self, "_holidays_hist"):
851
+ return self._holidays_hist
852
+
853
+ self._holidays_hist = CustomBusinessDay(
854
+ holidays=self.adhoc_holidays,
855
+ calendar=self.regular_holidays,
856
+ weekmask=self.weekmask_pre_1952,
857
+ )
858
+ return self._holidays_hist
832
859
 
833
860
  @property
834
861
  def regular_holidays(self):
@@ -961,10 +988,10 @@ class NYSEExchangeCalendar(MarketCalendar):
961
988
  September11Closings2001,
962
989
  HurricaneSandyClosings2012,
963
990
  GeorgeHWBushDeath2018,
991
+ JimmyCarterDeath2025,
964
992
  )
965
993
  )
966
994
 
967
- #
968
995
  @property
969
996
  def special_closes(self):
970
997
  return [
@@ -1085,7 +1112,6 @@ class NYSEExchangeCalendar(MarketCalendar):
1085
1112
  ),
1086
1113
  ]
1087
1114
 
1088
- #
1089
1115
  @property
1090
1116
  def special_closes_adhoc(self):
1091
1117
  def _union_many(indexes):
@@ -1140,7 +1166,6 @@ class NYSEExchangeCalendar(MarketCalendar):
1140
1166
  ),
1141
1167
  ]
1142
1168
 
1143
- #
1144
1169
  @property
1145
1170
  def special_opens(self):
1146
1171
  return [
@@ -1254,7 +1279,6 @@ class NYSEExchangeCalendar(MarketCalendar):
1254
1279
  ),
1255
1280
  ]
1256
1281
 
1257
- #
1258
1282
  @property
1259
1283
  def special_opens_adhoc(self):
1260
1284
  return [
@@ -1272,7 +1296,7 @@ class NYSEExchangeCalendar(MarketCalendar):
1272
1296
  ),
1273
1297
  ]
1274
1298
 
1275
- # Override market_calendar.py
1299
+ # Override market_calendar.py to split calc between pre & post 1952 Saturday Close
1276
1300
  def valid_days(self, start_date, end_date, tz="UTC"):
1277
1301
  """
1278
1302
  Get a DatetimeIndex of valid open business days.
@@ -1282,7 +1306,8 @@ class NYSEExchangeCalendar(MarketCalendar):
1282
1306
  :param tz: time zone in either string or pytz.timezone
1283
1307
  :return: DatetimeIndex of valid business days
1284
1308
  """
1285
- trading_days = super().valid_days(start_date, end_date, tz=tz)
1309
+ start_date = pd.Timestamp(start_date, tz=tz)
1310
+ end_date = pd.Timestamp(end_date, tz=tz)
1286
1311
 
1287
1312
  # Starting Monday Sept. 29, 1952, no more saturday trading days
1288
1313
  if tz is None:
@@ -1290,12 +1315,32 @@ class NYSEExchangeCalendar(MarketCalendar):
1290
1315
  else:
1291
1316
  saturday_end = self._saturday_end
1292
1317
 
1293
- above_cut_off = trading_days >= saturday_end
1294
- if above_cut_off.any():
1295
- above_and_saturday = (trading_days.weekday == 5) & above_cut_off
1296
- trading_days = trading_days[~above_and_saturday]
1318
+ # Don't care about Saturdays. Call super.
1319
+ if start_date > saturday_end:
1320
+ return super().valid_days(start_date, end_date, tz=tz)
1297
1321
 
1298
- return trading_days
1322
+ # Full Date Range is pre 1952. Augment the Super call
1323
+ if end_date <= saturday_end:
1324
+ return pd.date_range(
1325
+ start_date,
1326
+ end_date,
1327
+ freq=self.holidays_pre_1952(),
1328
+ normalize=True,
1329
+ tz=tz,
1330
+ )
1331
+
1332
+ # Range is split across 1952. Concatenate Two different Date_Range calls
1333
+ days_pre = pd.date_range(
1334
+ start_date,
1335
+ saturday_end,
1336
+ freq=self.holidays_pre_1952(),
1337
+ normalize=True,
1338
+ tz=tz,
1339
+ )
1340
+ days_post = pd.date_range(
1341
+ saturday_end, end_date, freq=self.holidays(), normalize=True, tz=tz
1342
+ )
1343
+ return days_pre.union(days_post)
1299
1344
 
1300
1345
  def days_at_time(self, days, market_time, day_offset=0):
1301
1346
  days = super().days_at_time(days, market_time, day_offset=day_offset)
@@ -1309,6 +1354,103 @@ class NYSEExchangeCalendar(MarketCalendar):
1309
1354
  days = days.dt.tz_convert("UTC")
1310
1355
  return days
1311
1356
 
1357
+ def date_range_htf(
1358
+ self,
1359
+ frequency: Union[str, pd.Timedelta, int, float],
1360
+ start: Union[str, pd.Timestamp, int, float, None] = None,
1361
+ end: Union[str, pd.Timestamp, int, float, None] = None,
1362
+ periods: Union[int, None] = None,
1363
+ closed: Union[Literal["left", "right"], None] = "right",
1364
+ *,
1365
+ day_anchor: u.Day_Anchor = "SUN",
1366
+ month_anchor: u.Month_Anchor = "JAN",
1367
+ ) -> pd.DatetimeIndex:
1368
+ # __doc__ = MarketCalendar.date_range_htf.__doc__
1369
+
1370
+ start, end, periods = u._error_check_htf_range(start, end, periods)
1371
+
1372
+ args = {
1373
+ "frequency": frequency,
1374
+ "start": start,
1375
+ "end": end,
1376
+ "periods": periods,
1377
+ "closed": closed,
1378
+ "day_anchor": day_anchor,
1379
+ "month_anchor": month_anchor,
1380
+ }
1381
+
1382
+ saturday_end = self._saturday_end.tz_localize(None)
1383
+
1384
+ # All Dates post 1952 This is the most common use case so return it first
1385
+ if start is not None and start > saturday_end:
1386
+ return u.date_range_htf(self.holidays(), **args)
1387
+
1388
+ # ---- Start-Date to End-Date w/ pre-1952 ----
1389
+ if start is not None and end is not None:
1390
+ if end <= saturday_end:
1391
+ # All pre 1952 Dates
1392
+ return u.date_range_htf(self.holidays_pre_1952(), **args)
1393
+ else:
1394
+ # Split Range Across 1952
1395
+ pre = u.date_range_htf( # Only Generate to the last saturday
1396
+ self.holidays_pre_1952(), **(args | {"end": saturday_end})
1397
+ )
1398
+ post = u.date_range_htf( # start generating from the last date of 'pre'
1399
+ self.holidays(), **(args | {"start": pre[-1]})
1400
+ )
1401
+ return pd.DatetimeIndex(pre.union(post), dtype="datetime64[ns]")
1402
+
1403
+ # ---- Periods from Start-Date w/ pre-1952 ----
1404
+ elif start is not None and periods is not None:
1405
+ # Start prior to 1952 & Number of periods given
1406
+ rtn_dt = u.date_range_htf(self.holidays_pre_1952(), **args)
1407
+ if rtn_dt[-1] <= saturday_end:
1408
+ return rtn_dt # never passed 1952, good to return
1409
+
1410
+ # Date Range Split.
1411
+ pre = rtn_dt[rtn_dt <= saturday_end]
1412
+ post = u.date_range_htf(
1413
+ self.holidays(),
1414
+ **(args | {"start": pre[-1], "periods": periods - len(pre) + 1}),
1415
+ )
1416
+ return pd.DatetimeIndex(pre.union(post)[:periods], dtype="datetime64[ns]")
1417
+
1418
+ # ---- Periods from End-Date ----
1419
+ elif end is not None and periods is not None:
1420
+ if end <= saturday_end:
1421
+ # All Dates pre-1952, Good to return the normal call
1422
+ return u.date_range_htf(self.holidays_pre_1952(), **args)
1423
+ else:
1424
+ rtn_dt = u.date_range_htf(self.holidays(), **args)
1425
+
1426
+ if rtn_dt[0] > saturday_end:
1427
+ return rtn_dt # never passed 1952, good to return
1428
+
1429
+ # Date Range Split
1430
+ post = rtn_dt[rtn_dt > saturday_end]
1431
+ _, period_code = u._standardize_htf_freq(frequency)
1432
+ altered_args = {
1433
+ # This nonsense is to realign the schedules as best as possible. This
1434
+ # essentially creates the 'pre-1952' equivalent date to the last generated 'post-1952'
1435
+ # date. Start the Range from there, then pre[0:-1] trims off that extra date where we
1436
+ # started from
1437
+ "end": post[0].to_period(period_code).end_time.normalize(),
1438
+ "periods": periods - len(post) + 2,
1439
+ }
1440
+ pre = u.date_range_htf(
1441
+ self.holidays_pre_1952(),
1442
+ **(args | altered_args),
1443
+ )
1444
+
1445
+ return pd.DatetimeIndex(
1446
+ pre[:-1].union(post)[-periods:], dtype="datetime64[ns]"
1447
+ )
1448
+ else:
1449
+ _, _ = u._standardize_htf_freq(frequency)
1450
+ raise ValueError(
1451
+ "This should never be raised, the above call should error first"
1452
+ )
1453
+
1312
1454
  def early_closes(self, schedule):
1313
1455
  """
1314
1456
  Get a DataFrame of the dates that are an early close.
@@ -42,7 +42,7 @@ class SSEExchangeCalendar(MarketCalendar):
42
42
  # Since all past holidays are adhoc, start_year should always be a year in the future.
43
43
  # For example: Holiday arrangements for 2022 are now included,
44
44
  # then our guesswork starts from the next year so start_year = 2023
45
- start_year = 2024
45
+ start_year = 2026
46
46
 
47
47
  return AbstractHolidayCalendar(
48
48
  rules=[
@@ -1,9 +1,11 @@
1
1
  from datetime import time
2
2
 
3
- from pandas import Timestamp
3
+ from typing import Literal, Union
4
+ from pandas import Timestamp, Timedelta, DatetimeIndex
4
5
  from pytz import timezone
5
6
 
6
7
  from pandas_market_calendars.market_calendar import MarketCalendar
8
+ from pandas_market_calendars.calendar_utils import Day_Anchor, Month_Anchor
7
9
 
8
10
  TASEClosedDay = [
9
11
  # 2019
@@ -195,3 +197,24 @@ class TASEExchangeCalendar(MarketCalendar):
195
197
  @property
196
198
  def weekmask(self):
197
199
  return "Sun Mon Tue Wed Thu"
200
+
201
+ def date_range_htf(
202
+ self,
203
+ frequency: Union[str, Timedelta, int, float],
204
+ start: Union[str, Timestamp, int, float, None] = None,
205
+ end: Union[str, Timestamp, int, float, None] = None,
206
+ periods: Union[int, None] = None,
207
+ closed: Union[Literal["left", "right"], None] = "right",
208
+ *,
209
+ day_anchor: Day_Anchor = "SAT", # Change the default day anchor
210
+ month_anchor: Month_Anchor = "JAN",
211
+ ) -> DatetimeIndex:
212
+ return super().date_range_htf(
213
+ frequency,
214
+ start,
215
+ end,
216
+ periods,
217
+ closed,
218
+ day_anchor=day_anchor,
219
+ month_anchor=month_anchor,
220
+ )
@@ -565,6 +565,7 @@ all_holidays = [
565
565
  Timestamp("2023-10-05"),
566
566
  Timestamp("2023-10-06"),
567
567
  Timestamp("2024-01-01"),
568
+ Timestamp("2024-02-09"),
568
569
  Timestamp("2024-02-12"),
569
570
  Timestamp("2024-02-13"),
570
571
  Timestamp("2024-02-14"),
@@ -583,6 +584,26 @@ all_holidays = [
583
584
  Timestamp("2024-10-03"),
584
585
  Timestamp("2024-10-04"),
585
586
  Timestamp("2024-10-07"),
587
+ # 2025 holidays
588
+ Timestamp("2025-01-01"), # New Year
589
+ Timestamp("2025-01-28"), # Spring Festival
590
+ Timestamp("2025-01-29"),
591
+ Timestamp("2025-01-30"),
592
+ Timestamp("2025-01-31"),
593
+ Timestamp("2025-02-03"),
594
+ Timestamp("2025-02-04"),
595
+ Timestamp("2025-04-04"), # Tomb-sweeping Day
596
+ Timestamp("2025-04-05"),
597
+ Timestamp("2025-05-01"), # Labor Day
598
+ Timestamp("2025-05-02"),
599
+ Timestamp("2025-05-05"),
600
+ Timestamp("2025-06-02"), # Dragon Boat Festival
601
+ Timestamp("2025-10-01"), # National Day & Mid-autumn Festival
602
+ Timestamp("2025-10-02"),
603
+ Timestamp("2025-10-03"),
604
+ Timestamp("2025-10-06"),
605
+ Timestamp("2025-10-07"),
606
+ Timestamp("2025-10-08"),
586
607
  ]
587
608
 
588
609
  # The following holidays are based on Solar terms or Chinese lunisolar calendar,
@@ -11,6 +11,7 @@ from the Tokyo exchange inauguration through 2099,
11
11
  using pyephem (http://rhodesmill.org/pyephem/quick.html#equinoxes-solstices).
12
12
  For a double check, see: https://aa.usno.navy.mil/data/docs/EarthSeasons.php
13
13
  """
14
+
14
15
  import pandas as pd
15
16
  from pandas.tseries.holiday import sunday_to_monday
16
17
 
@@ -1529,3 +1529,8 @@ HurricaneSandyClosings2012 = [
1529
1529
  GeorgeHWBushDeath2018 = [
1530
1530
  Timestamp("2018-12-05", tz="UTC"),
1531
1531
  ]
1532
+
1533
+ # 2025
1534
+ JimmyCarterDeath2025 = [
1535
+ Timestamp("2025-01-09", tz="UTC"),
1536
+ ]