pandas-market-calendars 4.6.1__py3-none-any.whl → 5.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pandas_market_calendars/calendar_utils.py +27 -80
- pandas_market_calendars/calendars/asx.py +6 -2
- pandas_market_calendars/calendars/bmf.py +4 -8
- pandas_market_calendars/calendars/bse.py +6 -2
- pandas_market_calendars/calendars/cboe.py +6 -2
- pandas_market_calendars/calendars/cme.py +4 -4
- pandas_market_calendars/calendars/cme_globex_base.py +2 -2
- pandas_market_calendars/calendars/cme_globex_crypto.py +12 -14
- pandas_market_calendars/calendars/cme_globex_energy_and_metals.py +4 -4
- pandas_market_calendars/calendars/cme_globex_equities.py +2 -2
- pandas_market_calendars/calendars/eurex.py +2 -2
- pandas_market_calendars/calendars/eurex_fixed_income.py +2 -2
- pandas_market_calendars/calendars/hkex.py +7 -5
- pandas_market_calendars/calendars/ice.py +2 -2
- pandas_market_calendars/calendars/iex.py +7 -3
- pandas_market_calendars/calendars/jpx.py +6 -2
- pandas_market_calendars/calendars/lse.py +6 -2
- pandas_market_calendars/calendars/mirror.py +6 -11
- pandas_market_calendars/calendars/nyse.py +41 -42
- pandas_market_calendars/calendars/ose.py +7 -5
- pandas_market_calendars/calendars/sifma.py +12 -10
- pandas_market_calendars/calendars/six.py +6 -2
- pandas_market_calendars/calendars/sse.py +6 -2
- pandas_market_calendars/calendars/tase.py +6 -2
- pandas_market_calendars/calendars/tsx.py +6 -2
- pandas_market_calendars/class_registry.py +1 -3
- pandas_market_calendars/market_calendar.py +33 -82
- {pandas_market_calendars-4.6.1.dist-info → pandas_market_calendars-5.0.0.dist-info}/METADATA +7 -4
- pandas_market_calendars-5.0.0.dist-info/RECORD +50 -0
- {pandas_market_calendars-4.6.1.dist-info → pandas_market_calendars-5.0.0.dist-info}/WHEEL +1 -1
- pandas_market_calendars-4.6.1.dist-info/RECORD +0 -50
- {pandas_market_calendars-4.6.1.dist-info → pandas_market_calendars-5.0.0.dist-info/licenses}/LICENSE +0 -0
- {pandas_market_calendars-4.6.1.dist-info → pandas_market_calendars-5.0.0.dist-info/licenses}/NOTICE +0 -0
- {pandas_market_calendars-4.6.1.dist-info → pandas_market_calendars-5.0.0.dist-info}/top_level.txt +0 -0
@@ -151,27 +151,17 @@ def merge_schedules(schedules, how="outer"):
|
|
151
151
|
all_cols = [x.columns for x in schedules]
|
152
152
|
all_cols = list(itertools.chain(*all_cols))
|
153
153
|
if ("break_start" in all_cols) or ("break_end" in all_cols):
|
154
|
-
warnings.warn(
|
155
|
-
"Merge schedules will drop the break_start and break_end from result."
|
156
|
-
)
|
154
|
+
warnings.warn("Merge schedules will drop the break_start and break_end from result.")
|
157
155
|
|
158
156
|
result = schedules[0]
|
159
157
|
for schedule in schedules[1:]:
|
160
158
|
result = result.merge(schedule, how=how, right_index=True, left_index=True)
|
161
159
|
if how == "outer":
|
162
|
-
result["market_open"] = result.apply(
|
163
|
-
|
164
|
-
)
|
165
|
-
result["market_close"] = result.apply(
|
166
|
-
lambda x: max(x.market_close_x, x.market_close_y), axis=1
|
167
|
-
)
|
160
|
+
result["market_open"] = result.apply(lambda x: min(x.market_open_x, x.market_open_y), axis=1)
|
161
|
+
result["market_close"] = result.apply(lambda x: max(x.market_close_x, x.market_close_y), axis=1)
|
168
162
|
elif how == "inner":
|
169
|
-
result["market_open"] = result.apply(
|
170
|
-
|
171
|
-
)
|
172
|
-
result["market_close"] = result.apply(
|
173
|
-
lambda x: min(x.market_close_x, x.market_close_y), axis=1
|
174
|
-
)
|
163
|
+
result["market_open"] = result.apply(lambda x: max(x.market_open_x, x.market_open_y), axis=1)
|
164
|
+
result["market_close"] = result.apply(lambda x: min(x.market_close_x, x.market_close_y), axis=1)
|
175
165
|
else:
|
176
166
|
raise ValueError('how argument must be "inner" or "outer"')
|
177
167
|
result = result[["market_open", "market_close"]]
|
@@ -211,9 +201,7 @@ SESSIONS = Literal[
|
|
211
201
|
"closed",
|
212
202
|
"closed_masked",
|
213
203
|
]
|
214
|
-
MKT_TIMES = Literal[
|
215
|
-
"pre", "post", "market_open", "market_close", "break_start", "break_end"
|
216
|
-
]
|
204
|
+
MKT_TIMES = Literal["pre", "post", "market_open", "market_close", "break_start", "break_end"]
|
217
205
|
|
218
206
|
|
219
207
|
# region ---- ---- ---- Date Range Warning Types ---- ---- ----
|
@@ -279,9 +267,7 @@ class InsufficientScheduleWarning(DateRangeWarning):
|
|
279
267
|
|
280
268
|
def filter_date_range_warnings(
|
281
269
|
action: Literal["error", "ignore", "always", "default", "once"],
|
282
|
-
source: Union[
|
283
|
-
Iterable[type[DateRangeWarning]], type[DateRangeWarning]
|
284
|
-
] = DateRangeWarning,
|
270
|
+
source: Union[Iterable[type[DateRangeWarning]], type[DateRangeWarning]] = DateRangeWarning,
|
285
271
|
):
|
286
272
|
"""
|
287
273
|
Adjust the behavior of the date_range() warnings to the desired action.
|
@@ -471,13 +457,9 @@ def date_range(
|
|
471
457
|
if frequency <= pd.Timedelta("0s"):
|
472
458
|
raise ValueError("Market Calendar Date_Range Frequency must be Positive.")
|
473
459
|
if frequency > pd.Timedelta("1D"):
|
474
|
-
raise ValueError(
|
475
|
-
"Market Calendar Date_Range Frequency Cannot Be longer than '1D'."
|
476
|
-
)
|
460
|
+
raise ValueError("Market Calendar Date_Range Frequency Cannot Be longer than '1D'.")
|
477
461
|
|
478
|
-
session_list, mask = _make_session_list(
|
479
|
-
set(schedule.columns), session, merge_adjacent
|
480
|
-
)
|
462
|
+
session_list, mask = _make_session_list(set(schedule.columns), session, merge_adjacent)
|
481
463
|
if len(session_list) == 0:
|
482
464
|
return pd.DatetimeIndex([], dtype="datetime64[ns, UTC]")
|
483
465
|
|
@@ -490,9 +472,7 @@ def date_range(
|
|
490
472
|
dtype = schedule[session_list[0][0]].dtype # copy dtype info from schedule
|
491
473
|
start, end, periods = _standardize_times(schedule, start, end, periods, tz)
|
492
474
|
|
493
|
-
time_series = _calc_time_series(
|
494
|
-
session_times, frequency, closed, force_close, start, end, periods
|
495
|
-
)
|
475
|
+
time_series = _calc_time_series(session_times, frequency, closed, force_close, start, end, periods)
|
496
476
|
time_series.name = None
|
497
477
|
|
498
478
|
return pd.DatetimeIndex(time_series, tz=tz, dtype=dtype)
|
@@ -501,9 +481,7 @@ def date_range(
|
|
501
481
|
# region ------------------ Date Range LTF Subroutines ------------------
|
502
482
|
|
503
483
|
|
504
|
-
def _make_session_list(
|
505
|
-
columns: set, sessions: Union[str, Iterable], merge_adjacent: bool
|
506
|
-
) -> Tuple[list, bool]:
|
484
|
+
def _make_session_list(columns: set, sessions: Union[str, Iterable], merge_adjacent: bool) -> Tuple[list, bool]:
|
507
485
|
"Create a list of (Session Start, Session End) Tuples"
|
508
486
|
session_times = []
|
509
487
|
missing_cols = set()
|
@@ -571,9 +549,7 @@ def _make_session_list(
|
|
571
549
|
return session_pairs, "closed_masked" in sessions
|
572
550
|
|
573
551
|
|
574
|
-
def _standardize_times(
|
575
|
-
schedule, start, end, periods, tz
|
576
|
-
) -> Tuple[pd.Timestamp, pd.Timestamp, Union[int, None]]:
|
552
|
+
def _standardize_times(schedule, start, end, periods, tz) -> Tuple[pd.Timestamp, pd.Timestamp, Union[int, None]]:
|
577
553
|
"Standardize start and end into a timestamp of the relevant timezone"
|
578
554
|
if all((start, end, periods)):
|
579
555
|
periods = None # Ignore Periods if all 3 params are given.
|
@@ -617,8 +593,7 @@ def _standardize_times(
|
|
617
593
|
|
618
594
|
if start is not None and end is not None and start > end:
|
619
595
|
raise ValueError(
|
620
|
-
"Date_range() given a start-date that occurs after the given end-date. "
|
621
|
-
f"{start = }, {end = }"
|
596
|
+
"Date_range() given a start-date that occurs after the given end-date. " f"{start = }, {end = }"
|
622
597
|
)
|
623
598
|
|
624
599
|
return start, end, periods
|
@@ -633,9 +608,7 @@ def _reconfigure_schedule(schedule, session_list, mask_close) -> pd.DataFrame:
|
|
633
608
|
if not end.endswith("_wrap"):
|
634
609
|
# Simple Session where 'start' occurs before 'end'
|
635
610
|
sessions.append(
|
636
|
-
schedule[[start, end]]
|
637
|
-
.rename(columns={start: "start", end: "end"})
|
638
|
-
.set_index("start", drop=False)
|
611
|
+
schedule[[start, end]].rename(columns={start: "start", end: "end"}).set_index("start", drop=False)
|
639
612
|
)
|
640
613
|
continue
|
641
614
|
|
@@ -779,9 +752,7 @@ def _course_trim_to_period_count(num_bars, periods, reverse) -> pd.Series:
|
|
779
752
|
return sessions_to_keep
|
780
753
|
|
781
754
|
|
782
|
-
def _calc_time_series(
|
783
|
-
session_times, timestep, closed, force_close, start, end, periods
|
784
|
-
) -> pd.Series:
|
755
|
+
def _calc_time_series(session_times, timestep, closed, force_close, start, end, periods) -> pd.Series:
|
785
756
|
"Interpolate each session into a datetime series at the desired frequency."
|
786
757
|
# region ---- ---- ---- Trim the Sessions ---- ---- ----
|
787
758
|
# Compare 'start' to the session end times so that if 'start' is in the middle of a session
|
@@ -798,23 +769,17 @@ def _calc_time_series(
|
|
798
769
|
# Align the start to a multiple of the timestep after the session's beginning.
|
799
770
|
# This is to make the returned DTIndex consistent across all start/end/period settings.
|
800
771
|
session_start = session_times.loc[session_times.index[0], "start"]
|
801
|
-
start_aligned = session_start + (
|
802
|
-
ceil((start - session_start) / timestep) * timestep
|
803
|
-
)
|
772
|
+
start_aligned = session_start + (ceil((start - session_start) / timestep) * timestep)
|
804
773
|
session_times.loc[session_times.index[0], "start"] = start_aligned
|
805
774
|
if end is not None and end < session_times.loc[session_times.index[-1], "end"]:
|
806
775
|
session_start = session_times.loc[session_times.index[0], "start"]
|
807
|
-
end_aligned = session_start + (
|
808
|
-
floor((end - session_start) / timestep) * timestep
|
809
|
-
)
|
776
|
+
end_aligned = session_start + (floor((end - session_start) / timestep) * timestep)
|
810
777
|
session_times.loc[session_times.index[-1], "end"] = end_aligned
|
811
778
|
|
812
779
|
num_bars = _num_bars_ltf(session_times, timestep, closed)
|
813
780
|
|
814
781
|
if periods is not None:
|
815
|
-
sessions_to_keep = _course_trim_to_period_count(
|
816
|
-
num_bars, periods, end is not None
|
817
|
-
)
|
782
|
+
sessions_to_keep = _course_trim_to_period_count(num_bars, periods, end is not None)
|
818
783
|
num_bars = num_bars[sessions_to_keep]
|
819
784
|
session_times = session_times[sessions_to_keep]
|
820
785
|
|
@@ -853,9 +818,7 @@ def _calc_time_series(
|
|
853
818
|
|
854
819
|
PeriodCode = Literal["D", "W", "M", "Q", "Y"]
|
855
820
|
Day_Anchor = Literal["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"]
|
856
|
-
Month_Anchor = Literal[
|
857
|
-
"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
|
858
|
-
]
|
821
|
+
Month_Anchor = Literal["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"]
|
859
822
|
|
860
823
|
# These needed because the pandas Period Object is stupid and not consistant w/ date_range.
|
861
824
|
# pd.date_range(s,e, freq = 'W-SUN') == [DatetimeIndex of all sundays] (as Expected)
|
@@ -970,9 +933,7 @@ def _error_check_htf_range(
|
|
970
933
|
"Standardize and Error Check Start, End, and period params"
|
971
934
|
if periods is not None:
|
972
935
|
if not isinstance(periods, int):
|
973
|
-
raise ValueError(
|
974
|
-
f"Date_Range_HTF Must be either an int or None. Given {type(periods)}"
|
975
|
-
)
|
936
|
+
raise ValueError(f"Date_Range_HTF Must be either an int or None. Given {type(periods)}")
|
976
937
|
if periods < 0:
|
977
938
|
raise ValueError("Date_range_HTF Periods must be Positive.")
|
978
939
|
|
@@ -989,9 +950,7 @@ def _error_check_htf_range(
|
|
989
950
|
if all((start, end, periods)):
|
990
951
|
periods = None # Ignore Periods if passed too many params
|
991
952
|
if len([param for param in (start, end, periods) if param is not None]) < 2:
|
992
|
-
raise ValueError(
|
993
|
-
"Date_Range_HTF must be given two of the three following params: (start, end, periods)"
|
994
|
-
)
|
953
|
+
raise ValueError("Date_Range_HTF must be given two of the three following params: (start, end, periods)")
|
995
954
|
|
996
955
|
if start is not None and end is not None and end < start:
|
997
956
|
raise ValueError("Date_Range_HTF() Start-Date must be before the End-Date")
|
@@ -999,9 +958,7 @@ def _error_check_htf_range(
|
|
999
958
|
return start, end, periods
|
1000
959
|
|
1001
960
|
|
1002
|
-
def _standardize_htf_freq(
|
1003
|
-
frequency: Union[str, pd.Timedelta, int, float]
|
1004
|
-
) -> Tuple[int, PeriodCode]:
|
961
|
+
def _standardize_htf_freq(frequency: Union[str, pd.Timedelta, int, float]) -> Tuple[int, PeriodCode]:
|
1005
962
|
"Standardize the frequency multiplier and Code, throwing errors as needed."
|
1006
963
|
if isinstance(frequency, str):
|
1007
964
|
if len(frequency) == 0:
|
@@ -1027,9 +984,7 @@ def _standardize_htf_freq(
|
|
1027
984
|
if frequency < pd.Timedelta("1D"):
|
1028
985
|
raise ValueError("Date_Range_HTF() Frequency must be '1D' or Higher.")
|
1029
986
|
if frequency % pd.Timedelta("1D") != pd.Timedelta(0):
|
1030
|
-
raise ValueError(
|
1031
|
-
"Date_Range_HTF() Week and Day frequency must be an integer multiple of Days"
|
1032
|
-
)
|
987
|
+
raise ValueError("Date_Range_HTF() Week and Day frequency must be an integer multiple of Days")
|
1033
988
|
|
1034
989
|
return frequency.days, "D"
|
1035
990
|
|
@@ -1052,9 +1007,7 @@ def _days_per_week(weekmask: Union[Iterable, str]) -> int:
|
|
1052
1007
|
return len([day for day in weekmask if bool(day)])
|
1053
1008
|
|
1054
1009
|
|
1055
|
-
def _cal_day_range(
|
1056
|
-
cb_day: "CustomBusinessDay", start, end, periods, mult
|
1057
|
-
) -> pd.DatetimeIndex:
|
1010
|
+
def _cal_day_range(cb_day: "CustomBusinessDay", start, end, periods, mult) -> pd.DatetimeIndex:
|
1058
1011
|
"""
|
1059
1012
|
Returns a Normalized DateTimeIndex of Open Buisness Days.
|
1060
1013
|
Exactly two of the (start, end, periods) arguments must be given.
|
@@ -1080,9 +1033,7 @@ def _cal_day_range(
|
|
1080
1033
|
if isinstance(start, pd.Timestamp) and isinstance(end, pd.Timestamp):
|
1081
1034
|
num_days = (end - start) / mult
|
1082
1035
|
# Get a better estimate of the number of open days since date_range calc is slow
|
1083
|
-
est_open_days = (
|
1084
|
-
(num_days // 7) * _days_per_week(cb_day.weekmask)
|
1085
|
-
) + num_days % pd.Timedelta("1W")
|
1036
|
+
est_open_days = ((num_days // 7) * _days_per_week(cb_day.weekmask)) + num_days % pd.Timedelta("1W")
|
1086
1037
|
|
1087
1038
|
# Should always produce a small overestimate since Holidays aren't accounted for.
|
1088
1039
|
est_open_days = ceil(est_open_days / pd.Timedelta("1D"))
|
@@ -1149,9 +1100,7 @@ def _cal_WMQY_range(
|
|
1149
1100
|
roll_func = cb_day.rollforward
|
1150
1101
|
if start is not None:
|
1151
1102
|
normalized_start = start.to_period(grouping_period).start_time
|
1152
|
-
_dr_start = (
|
1153
|
-
normalized_start if start <= roll_func(normalized_start) else start
|
1154
|
-
)
|
1103
|
+
_dr_start = normalized_start if start <= roll_func(normalized_start) else start
|
1155
1104
|
|
1156
1105
|
if end is not None:
|
1157
1106
|
if periods is not None:
|
@@ -1181,9 +1130,7 @@ def _cal_WMQY_range(
|
|
1181
1130
|
normalized_end = end.to_period(grouping_period).end_time.normalize()
|
1182
1131
|
_dr_end = normalized_end if end >= roll_func(normalized_end) else end
|
1183
1132
|
|
1184
|
-
_range = (
|
1185
|
-
pd.date_range(_dr_start, _dr_end, periods, freq).to_series().apply(roll_func)
|
1186
|
-
)
|
1133
|
+
_range = pd.date_range(_dr_start, _dr_end, periods, freq).to_series().apply(roll_func)
|
1187
1134
|
|
1188
1135
|
# Ensure that Rolled Timestamps are in the desired range When given both Start and End
|
1189
1136
|
if start is not None and end is not None:
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from datetime import time
|
2
2
|
|
3
3
|
from pandas.tseries.holiday import AbstractHolidayCalendar, GoodFriday, EasterMonday
|
4
|
-
from
|
4
|
+
from zoneinfo import ZoneInfo
|
5
5
|
|
6
6
|
from pandas_market_calendars.holidays.oz import *
|
7
7
|
from pandas_market_calendars.market_calendar import MarketCalendar
|
@@ -42,9 +42,13 @@ class ASXExchangeCalendar(MarketCalendar):
|
|
42
42
|
def name(self):
|
43
43
|
return "ASX"
|
44
44
|
|
45
|
+
@property
|
46
|
+
def full_name(self):
|
47
|
+
return "Australian Securities Exchange"
|
48
|
+
|
45
49
|
@property
|
46
50
|
def tz(self):
|
47
|
-
return
|
51
|
+
return ZoneInfo("Australia/Sydney")
|
48
52
|
|
49
53
|
@property
|
50
54
|
def regular_holidays(self):
|
@@ -23,7 +23,7 @@ from pandas.tseries.holiday import (
|
|
23
23
|
GoodFriday,
|
24
24
|
Holiday,
|
25
25
|
)
|
26
|
-
from
|
26
|
+
from zoneinfo import ZoneInfo
|
27
27
|
|
28
28
|
from pandas_market_calendars.market_calendar import FRIDAY, MarketCalendar
|
29
29
|
|
@@ -38,9 +38,7 @@ AniversarioSaoPaulo = Holiday(
|
|
38
38
|
"Aniversario de Sao Paulo", month=1, day=25, end_date="2021-12-31"
|
39
39
|
)
|
40
40
|
# Carnival Monday
|
41
|
-
CarnavalSegunda = Holiday(
|
42
|
-
"Carnaval Segunda", month=1, day=1, offset=[Easter(), Day(-48)]
|
43
|
-
)
|
41
|
+
CarnavalSegunda = Holiday("Carnaval Segunda", month=1, day=1, offset=[Easter(), Day(-48)])
|
44
42
|
# Carnival Tuesday
|
45
43
|
CarnavalTerca = Holiday("Carnaval Terca", month=1, day=1, offset=[Easter(), Day(-47)])
|
46
44
|
# Ash Wednesday (short day)
|
@@ -62,9 +60,7 @@ DiaTrabalho = Holiday(
|
|
62
60
|
day=1,
|
63
61
|
)
|
64
62
|
# Constitutionalist Revolution
|
65
|
-
Constitucionalista = Holiday(
|
66
|
-
"Constitucionalista", month=7, day=9, start_date="1997-01-01", end_date="2019-12-31"
|
67
|
-
)
|
63
|
+
Constitucionalista = Holiday("Constitucionalista", month=7, day=9, start_date="1997-01-01", end_date="2019-12-31")
|
68
64
|
# Independence Day
|
69
65
|
Independencia = Holiday(
|
70
66
|
"Independencia",
|
@@ -185,7 +181,7 @@ class BMFExchangeCalendar(MarketCalendar):
|
|
185
181
|
|
186
182
|
@property
|
187
183
|
def tz(self):
|
188
|
-
return
|
184
|
+
return ZoneInfo("America/Sao_Paulo")
|
189
185
|
|
190
186
|
@property
|
191
187
|
def regular_holidays(self):
|
@@ -5,7 +5,7 @@ Bombay Stock Exchnage
|
|
5
5
|
from datetime import time
|
6
6
|
|
7
7
|
from pandas import Timestamp
|
8
|
-
from
|
8
|
+
from zoneinfo import ZoneInfo
|
9
9
|
|
10
10
|
from pandas_market_calendars.market_calendar import MarketCalendar
|
11
11
|
|
@@ -412,9 +412,13 @@ class BSEExchangeCalendar(MarketCalendar):
|
|
412
412
|
def name(self):
|
413
413
|
return "BSE"
|
414
414
|
|
415
|
+
@property
|
416
|
+
def full_name(self):
|
417
|
+
return "Bombay Stock Exchange"
|
418
|
+
|
415
419
|
@property
|
416
420
|
def tz(self):
|
417
|
-
return
|
421
|
+
return ZoneInfo("Asia/Calcutta")
|
418
422
|
|
419
423
|
@property
|
420
424
|
def adhoc_holidays(self):
|
@@ -10,7 +10,7 @@ from pandas.tseries.holiday import (
|
|
10
10
|
USThanksgivingDay,
|
11
11
|
Holiday,
|
12
12
|
)
|
13
|
-
from
|
13
|
+
from zoneinfo import ZoneInfo
|
14
14
|
|
15
15
|
from pandas_market_calendars.holidays.us import (
|
16
16
|
Christmas,
|
@@ -83,9 +83,13 @@ class CFEExchangeCalendar(MarketCalendar):
|
|
83
83
|
def name(self):
|
84
84
|
return "CFE"
|
85
85
|
|
86
|
+
@property
|
87
|
+
def full_name(self):
|
88
|
+
return "CBOE Futures Exchange"
|
89
|
+
|
86
90
|
@property
|
87
91
|
def tz(self):
|
88
|
-
return
|
92
|
+
return ZoneInfo("America/Chicago")
|
89
93
|
|
90
94
|
@property
|
91
95
|
def regular_holidays(self):
|
@@ -24,7 +24,7 @@ from pandas.tseries.holiday import (
|
|
24
24
|
USPresidentsDay,
|
25
25
|
USThanksgivingDay,
|
26
26
|
)
|
27
|
-
from
|
27
|
+
from zoneinfo import ZoneInfo
|
28
28
|
|
29
29
|
from pandas_market_calendars.holidays.us import (
|
30
30
|
Christmas,
|
@@ -71,7 +71,7 @@ class CMEEquityExchangeCalendar(MarketCalendar):
|
|
71
71
|
|
72
72
|
@property
|
73
73
|
def tz(self):
|
74
|
-
return
|
74
|
+
return ZoneInfo("America/Chicago")
|
75
75
|
|
76
76
|
@property
|
77
77
|
def regular_holidays(self):
|
@@ -141,7 +141,7 @@ class CMEAgricultureExchangeCalendar(MarketCalendar):
|
|
141
141
|
|
142
142
|
@property
|
143
143
|
def tz(self):
|
144
|
-
return
|
144
|
+
return ZoneInfo("America/Chicago")
|
145
145
|
|
146
146
|
@property
|
147
147
|
def regular_holidays(self):
|
@@ -357,7 +357,7 @@ class CMEBondExchangeCalendar(MarketCalendar):
|
|
357
357
|
|
358
358
|
@property
|
359
359
|
def tz(self):
|
360
|
-
return
|
360
|
+
return ZoneInfo("America/Chicago")
|
361
361
|
|
362
362
|
@property
|
363
363
|
def regular_holidays(self):
|
@@ -22,7 +22,7 @@ from pandas.tseries.holiday import (
|
|
22
22
|
USPresidentsDay,
|
23
23
|
USThanksgivingDay,
|
24
24
|
)
|
25
|
-
from
|
25
|
+
from zoneinfo import ZoneInfo
|
26
26
|
|
27
27
|
from pandas_market_calendars.holidays.us import (
|
28
28
|
Christmas,
|
@@ -79,7 +79,7 @@ class CMEGlobexBaseExchangeCalendar(MarketCalendar, ABC):
|
|
79
79
|
|
80
80
|
@property
|
81
81
|
def tz(self):
|
82
|
-
return
|
82
|
+
return ZoneInfo("America/Chicago")
|
83
83
|
|
84
84
|
@property
|
85
85
|
def regular_holidays(self):
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import datetime as dt
|
2
2
|
|
3
|
-
import
|
3
|
+
from zoneinfo import ZoneInfo
|
4
4
|
from pandas.tseries.holiday import AbstractHolidayCalendar
|
5
5
|
|
6
6
|
from pandas_market_calendars.holidays.cme import (
|
@@ -45,25 +45,23 @@ class CMEGlobexCryptoExchangeCalendar(CMEGlobexBaseExchangeCalendar):
|
|
45
45
|
# Tuple[Tuple[first date used, time, offset], ...]
|
46
46
|
# -1 offset indicates that the open is on the previous day
|
47
47
|
# None for first date used marks the start, subsequent market times must have an actual timestamp
|
48
|
-
"market_open": (
|
49
|
-
(None, dt.time(17, tzinfo=pytz.timezone("America/Chicago")), -1),
|
50
|
-
),
|
48
|
+
"market_open": ((None, dt.time(17, tzinfo=ZoneInfo("America/Chicago")), -1),),
|
51
49
|
"market_close": (
|
52
50
|
(
|
53
51
|
None,
|
54
|
-
dt.time(16, tzinfo=
|
52
|
+
dt.time(16, tzinfo=ZoneInfo("America/Chicago")),
|
55
53
|
),
|
56
54
|
),
|
57
55
|
"break_start": (
|
58
56
|
(
|
59
57
|
None,
|
60
|
-
dt.time(16, tzinfo=
|
58
|
+
dt.time(16, tzinfo=ZoneInfo("America/Chicago")),
|
61
59
|
),
|
62
60
|
),
|
63
61
|
"break_end": (
|
64
62
|
(
|
65
63
|
None,
|
66
|
-
dt.time(17, tzinfo=
|
64
|
+
dt.time(17, tzinfo=ZoneInfo("America/Chicago")),
|
67
65
|
),
|
68
66
|
),
|
69
67
|
}
|
@@ -71,7 +69,7 @@ class CMEGlobexCryptoExchangeCalendar(CMEGlobexBaseExchangeCalendar):
|
|
71
69
|
@property
|
72
70
|
def tz(self):
|
73
71
|
# Central Time
|
74
|
-
return
|
72
|
+
return ZoneInfo("America/Chicago")
|
75
73
|
|
76
74
|
@property
|
77
75
|
def name(self):
|
@@ -100,7 +98,7 @@ class CMEGlobexCryptoExchangeCalendar(CMEGlobexBaseExchangeCalendar):
|
|
100
98
|
# list[Tuple[time, AbstractHolidayCalendar]]
|
101
99
|
return [
|
102
100
|
(
|
103
|
-
dt.time(8, 15, tzinfo=
|
101
|
+
dt.time(8, 15, tzinfo=ZoneInfo("America/Chicago")),
|
104
102
|
AbstractHolidayCalendar(
|
105
103
|
rules=[
|
106
104
|
GoodFriday2021,
|
@@ -108,7 +106,7 @@ class CMEGlobexCryptoExchangeCalendar(CMEGlobexBaseExchangeCalendar):
|
|
108
106
|
),
|
109
107
|
),
|
110
108
|
(
|
111
|
-
dt.time(10, 15, tzinfo=
|
109
|
+
dt.time(10, 15, tzinfo=ZoneInfo("America/Chicago")),
|
112
110
|
AbstractHolidayCalendar(
|
113
111
|
rules=[
|
114
112
|
GoodFridayAfter2022,
|
@@ -116,7 +114,7 @@ class CMEGlobexCryptoExchangeCalendar(CMEGlobexBaseExchangeCalendar):
|
|
116
114
|
),
|
117
115
|
),
|
118
116
|
(
|
119
|
-
dt.time(12, tzinfo=
|
117
|
+
dt.time(12, tzinfo=ZoneInfo("America/Chicago")),
|
120
118
|
AbstractHolidayCalendar(
|
121
119
|
rules=[
|
122
120
|
USMartinLutherKingJrPre2022,
|
@@ -129,7 +127,7 @@ class CMEGlobexCryptoExchangeCalendar(CMEGlobexBaseExchangeCalendar):
|
|
129
127
|
),
|
130
128
|
),
|
131
129
|
(
|
132
|
-
dt.time(12, 15, tzinfo=
|
130
|
+
dt.time(12, 15, tzinfo=ZoneInfo("America/Chicago")),
|
133
131
|
AbstractHolidayCalendar(
|
134
132
|
rules=[
|
135
133
|
ChristmasEveInOrAfter1993,
|
@@ -139,12 +137,12 @@ class CMEGlobexCryptoExchangeCalendar(CMEGlobexBaseExchangeCalendar):
|
|
139
137
|
),
|
140
138
|
),
|
141
139
|
(
|
142
|
-
dt.time(12, 45, tzinfo=
|
140
|
+
dt.time(12, 45, tzinfo=ZoneInfo("America/Chicago")),
|
143
141
|
AbstractHolidayCalendar(rules=[USThanksgivingFridayFrom2021]),
|
144
142
|
),
|
145
143
|
# TODO: this market already closes at 1600 normally, do we need these holidays?
|
146
144
|
(
|
147
|
-
dt.time(16, tzinfo=
|
145
|
+
dt.time(16, tzinfo=ZoneInfo("America/Chicago")),
|
148
146
|
AbstractHolidayCalendar(
|
149
147
|
rules=[
|
150
148
|
USMartinLutherKingJrFrom2022,
|
@@ -18,7 +18,7 @@ from datetime import time
|
|
18
18
|
from pandas.tseries.holiday import (
|
19
19
|
AbstractHolidayCalendar,
|
20
20
|
) # , GoodFriday, USLaborDay, USPresidentsDay, USThanksgivingDay
|
21
|
-
from
|
21
|
+
from zoneinfo import ZoneInfo
|
22
22
|
|
23
23
|
from pandas_market_calendars.holidays.cme_globex import (
|
24
24
|
USMartinLutherKingJrFrom2022,
|
@@ -180,7 +180,7 @@ class CMEGlobexEnergyAndMetalsExchangeCalendar(CMEGlobexBaseExchangeCalendar):
|
|
180
180
|
def special_closes(self):
|
181
181
|
return [
|
182
182
|
(
|
183
|
-
time(12, tzinfo=
|
183
|
+
time(12, tzinfo=ZoneInfo("America/Chicago")),
|
184
184
|
AbstractHolidayCalendar(
|
185
185
|
rules=[
|
186
186
|
USMartinLutherKingJrPre2022,
|
@@ -193,7 +193,7 @@ class CMEGlobexEnergyAndMetalsExchangeCalendar(CMEGlobexBaseExchangeCalendar):
|
|
193
193
|
),
|
194
194
|
),
|
195
195
|
(
|
196
|
-
time(12, 45, tzinfo=
|
196
|
+
time(12, 45, tzinfo=ZoneInfo("America/Chicago")),
|
197
197
|
AbstractHolidayCalendar(
|
198
198
|
rules=[
|
199
199
|
FridayAfterThanksgiving,
|
@@ -201,7 +201,7 @@ class CMEGlobexEnergyAndMetalsExchangeCalendar(CMEGlobexBaseExchangeCalendar):
|
|
201
201
|
),
|
202
202
|
),
|
203
203
|
(
|
204
|
-
time(13, 30, tzinfo=
|
204
|
+
time(13, 30, tzinfo=ZoneInfo("America/Chicago")),
|
205
205
|
AbstractHolidayCalendar(
|
206
206
|
rules=[
|
207
207
|
USMartinLutherKingJrFrom2022,
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from datetime import time
|
2
2
|
|
3
3
|
from pandas.tseries.holiday import AbstractHolidayCalendar
|
4
|
-
from
|
4
|
+
from zoneinfo import ZoneInfo
|
5
5
|
|
6
6
|
from pandas_market_calendars.holidays.cme import (
|
7
7
|
USMartinLutherKingJrAfter1998Before2015,
|
@@ -45,7 +45,7 @@ class CMEGlobexEquitiesExchangeCalendar(CMEGlobexBaseExchangeCalendar):
|
|
45
45
|
|
46
46
|
@property
|
47
47
|
def tz(self):
|
48
|
-
return
|
48
|
+
return ZoneInfo("America/Chicago")
|
49
49
|
|
50
50
|
@property
|
51
51
|
def name(self):
|
@@ -11,7 +11,7 @@ from pandas.tseries.holiday import (
|
|
11
11
|
Holiday,
|
12
12
|
previous_friday,
|
13
13
|
)
|
14
|
-
from
|
14
|
+
from zoneinfo import ZoneInfo
|
15
15
|
|
16
16
|
from pandas_market_calendars.market_calendar import (
|
17
17
|
FRIDAY,
|
@@ -99,7 +99,7 @@ class EUREXExchangeCalendar(MarketCalendar):
|
|
99
99
|
|
100
100
|
@property
|
101
101
|
def tz(self):
|
102
|
-
return
|
102
|
+
return ZoneInfo("Europe/Berlin")
|
103
103
|
|
104
104
|
@property
|
105
105
|
def regular_holidays(self):
|
@@ -6,7 +6,7 @@ from pandas.tseries.holiday import (
|
|
6
6
|
GoodFriday,
|
7
7
|
Holiday,
|
8
8
|
)
|
9
|
-
from
|
9
|
+
from zoneinfo import ZoneInfo
|
10
10
|
|
11
11
|
from pandas_market_calendars.market_calendar import (
|
12
12
|
FRIDAY,
|
@@ -80,7 +80,7 @@ class EUREXFixedIncomeCalendar(MarketCalendar):
|
|
80
80
|
|
81
81
|
@property
|
82
82
|
def tz(self):
|
83
|
-
return
|
83
|
+
return ZoneInfo("Europe/Berlin")
|
84
84
|
|
85
85
|
@property
|
86
86
|
def regular_holidays(self):
|
@@ -10,7 +10,7 @@ from pandas.tseries.holiday import (
|
|
10
10
|
sunday_to_monday,
|
11
11
|
)
|
12
12
|
from pandas.tseries.offsets import LastWeekOfMonth, WeekOfMonth
|
13
|
-
from
|
13
|
+
from zoneinfo import ZoneInfo
|
14
14
|
|
15
15
|
from pandas_market_calendars.holidays.cn import (
|
16
16
|
bsd_mapping,
|
@@ -198,9 +198,7 @@ MidAutumnFestivalDay = Holiday(
|
|
198
198
|
name="Mid-autumn Festival", # 中秋节翌日
|
199
199
|
month=9,
|
200
200
|
day=7,
|
201
|
-
observance=partial(
|
202
|
-
process_date, mapping=maf_mapping, delta=1, func=sunday_to_monday
|
203
|
-
),
|
201
|
+
observance=partial(process_date, mapping=maf_mapping, delta=1, func=sunday_to_monday),
|
204
202
|
start_date=Timestamp("2011-01-01"),
|
205
203
|
)
|
206
204
|
|
@@ -381,9 +379,13 @@ class HKEXExchangeCalendar(MarketCalendar):
|
|
381
379
|
def name(self):
|
382
380
|
return "HKEX"
|
383
381
|
|
382
|
+
@property
|
383
|
+
def full_name(self):
|
384
|
+
return "Hong Kong Stock Exchange"
|
385
|
+
|
384
386
|
@property
|
385
387
|
def tz(self):
|
386
|
-
return
|
388
|
+
return ZoneInfo("Asia/Shanghai")
|
387
389
|
|
388
390
|
@property
|
389
391
|
def regular_holidays(self):
|
@@ -9,7 +9,7 @@ from pandas.tseries.holiday import (
|
|
9
9
|
USPresidentsDay,
|
10
10
|
USThanksgivingDay,
|
11
11
|
)
|
12
|
-
from
|
12
|
+
from zoneinfo import ZoneInfo
|
13
13
|
|
14
14
|
from pandas_market_calendars.holidays.us import (
|
15
15
|
Christmas,
|
@@ -44,7 +44,7 @@ class ICEExchangeCalendar(MarketCalendar):
|
|
44
44
|
|
45
45
|
@property
|
46
46
|
def tz(self):
|
47
|
-
return
|
47
|
+
return ZoneInfo("US/Eastern")
|
48
48
|
|
49
49
|
@property
|
50
50
|
def special_closes(self):
|