From 597c9fb4d3fb39fa93e707991354354963953b86 Mon Sep 17 00:00:00 2001 From: Marcus Read Date: Wed, 31 Jan 2024 14:49:24 +0000 Subject: [PATCH] Fix pandas deprecation warnings Fixes pandas 2.2 deprecation warnings concerning deprecation of frequency units "T", "H" and "S" in favor of "min", "h" and "s". --- README.md | 2 +- exchange_calendars/calendar_helpers.py | 8 +- exchange_calendars/exchange_calendar.py | 18 ++-- exchange_calendars/utils/pandas_utils.py | 4 +- tests/test_calendar_helpers.py | 130 +++++++++++------------ tests/test_cmes_calendar.py | 2 +- tests/test_exchange_calendar.py | 66 ++++++------ tests/test_iepa_calendar.py | 2 +- tests/test_xasx_calendar.py | 2 +- tests/test_xbue_calendar.py | 2 +- tests/test_xetr_calendar.py | 6 +- tests/test_xhkg_calendar.py | 6 +- tests/test_xmad_calendar.py | 8 +- tests/test_xnys_calendar.py | 6 +- tests/test_xosl_calendar.py | 2 +- tests/test_xsto_calendar.py | 2 +- tests/test_xtse_calendar.py | 4 +- 17 files changed, 133 insertions(+), 137 deletions(-) diff --git a/README.md b/README.md index 490b98d3..cc9ae6a6 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ Timestamp('2022-01-03 00:00:00', freq='C') Timestamp('2022-01-10 00:00:00', freq='C') >>> xhkg.trading_index( -... "2021-12-30", "2021-12-31", period="90T", force=True +... "2021-12-30", "2021-12-31", period="90min", force=True ... ) IntervalIndex([[2021-12-30 01:30:00, 2021-12-30 03:00:00), [2021-12-30 03:00:00, 2021-12-30 04:00:00), [2021-12-30 05:00:00, 2021-12-30 06:30:00), [2021-12-30 06:30:00, 2021-12-30 08:00:00), [2021-12-31 01:30:00, 2021-12-31 03:00:00), [2021-12-31 03:00:00, 2021-12-31 04:00:00)], dtype='interval[datetime64[ns, UTC], left]') ``` diff --git a/exchange_calendars/calendar_helpers.py b/exchange_calendars/calendar_helpers.py index 64c8aefe..55809059 100644 --- a/exchange_calendars/calendar_helpers.py +++ b/exchange_calendars/calendar_helpers.py @@ -236,9 +236,9 @@ def parse_timestamp( ) side = side if side is not None else calendar.side if side == "left": - ts = ts.floor("T") + ts = ts.floor("min") elif side == "right": - ts = ts.ceil("T") + ts = ts.ceil("min") else: raise ValueError( "`timestamp` cannot have a non-zero second (or more accurate)" @@ -493,7 +493,7 @@ def align_opens(opens: pd.Series, align: pd.Timedelta) -> np.ndarray: opens = opens.dt.ceil(align) return opens.values.astype(np.int64) - if align != pd.Timedelta(1, "T"): + if align != pd.Timedelta(1, "min"): self.opens = align_opens(calendar.opens[slce], align) else: self.opens = calendar.opens_nanos[slce] @@ -503,7 +503,7 @@ def align_opens(opens: pd.Series, align: pd.Timedelta) -> np.ndarray: else: self.break_starts = calendar.break_starts_nanos[slce] - if align_pm != pd.Timedelta(1, "T"): + if align_pm != pd.Timedelta(1, "min"): self.break_ends = align_opens(calendar.break_ends[slce], align_pm) else: self.break_ends = calendar.break_ends_nanos[slce] diff --git a/exchange_calendars/exchange_calendar.py b/exchange_calendars/exchange_calendar.py index de36366a..e57127ac 100644 --- a/exchange_calendars/exchange_calendar.py +++ b/exchange_calendars/exchange_calendar.py @@ -2344,7 +2344,7 @@ def trading_index( force: bool | None = None, curtail_overlaps: bool = False, ignore_breaks: bool = False, - align: pd.Timedelta | str = pd.Timedelta(1, "T"), + align: pd.Timedelta | str = pd.Timedelta(1, "min"), align_pm: pd.Timedelta | bool = True, parse: bool = True, ) -> pd.DatetimeIndex | pd.IntervalIndex: @@ -2538,7 +2538,7 @@ def trading_index( component then can pass `parse` as False to save around 500µs on the execution. - align : default: pd.Timedelta(1, "T") + align : default: pd.Timedelta(1, "min") Anchor the first indice of each session such that it aligns with the nearest occurrence of a specific fraction of an hour. @@ -2547,14 +2547,14 @@ def trading_index( forwards, -ve values to shift indices backwards. Valid values are (or equivalent): - "2T", "3T", "4T", "5T", "6T", "10T", "12T", "15T", "20T", - "30T", "-2T", "-4T", "-5T", "-6T", "-10T", "-12T", "-15T", - "-20T", "-30T" + "2min", "3min", "4min", "5min", "6min", "10min", "12min", "15min", "20min", + "30min", "-2min", "-4min", "-5min", "-6min", "-10min", "-12min", "-15min", + "-20min", "-30min" For example, if `intervals` is True and `period` is '5T' then the first interval of a session with open time as 07:59 would be: - 07:59 - 08:04 if `align` is pd.Timedelta(1, "T") (default) + 07:59 - 08:04 if `align` is pd.Timedelta(1, "min") (default) 08:00 - 08:05 if `align` is '5T' 07:55 - 08:00 if `align` is '-5T' @@ -2662,13 +2662,13 @@ def get_align(name: Literal["align", "align_pm"], value: Any) -> pd.Timedelta: ) raise ValueError(msg) from None - ONE_HOUR = pd.Timedelta("1H") + ONE_HOUR = pd.Timedelta("1h") if value > ONE_HOUR or value < -ONE_HOUR or not value or (ONE_HOUR % value): raise ValueError( f"`{name}` must be factor of 1H although received '{value}'." ) - if value % pd.Timedelta(1, "T"): + if value % pd.Timedelta(1, "min"): raise ValueError( f"`{name}` cannot include a fraction of a minute although received" f" '{value}'." @@ -2678,7 +2678,7 @@ def get_align(name: Literal["align", "align_pm"], value: Any) -> pd.Timedelta: align = get_align("align", align) if align_pm is False: - align_pm = pd.Timedelta(1, "T") + align_pm = pd.Timedelta(1, "min") else: align_pm = align if align_pm is True else get_align("align_pm", align_pm) diff --git a/exchange_calendars/utils/pandas_utils.py b/exchange_calendars/utils/pandas_utils.py index 2f7e6a88..2942f9f9 100644 --- a/exchange_calendars/utils/pandas_utils.py +++ b/exchange_calendars/utils/pandas_utils.py @@ -140,8 +140,8 @@ def indexes_union(indexes: list[pd.Index]) -> pd.Index: Examples -------- - >>> index1 = pd.date_range('2021-05-01 12:20', periods=2, freq='1H') - >>> index2 = pd.date_range('2021-05-02 17:10', periods=2, freq='22T') + >>> index1 = pd.date_range('2021-05-01 12:20', periods=2, freq='1h') + >>> index2 = pd.date_range('2021-05-02 17:10', periods=2, freq='22min') >>> index3 = pd.date_range('2021-05-03', periods=2, freq='1D') >>> indexes_union([index1, index2, index3]) DatetimeIndex(['2021-05-01 12:20:00', '2021-05-01 13:20:00', diff --git a/tests/test_calendar_helpers.py b/tests/test_calendar_helpers.py index d0193d37..6d44479f 100644 --- a/tests/test_calendar_helpers.py +++ b/tests/test_calendar_helpers.py @@ -37,7 +37,7 @@ def test_constants(): @pytest.fixture(scope="class") def one_min() -> abc.Iterator[pd.Timedelta]: - yield pd.Timedelta(1, "T") + yield pd.Timedelta(1, "min") def test_is_date(one_min): @@ -182,7 +182,7 @@ def test_parse_timestamp_with_date(date_mult, param_name, calendar, utc): assert dt == pd.Timestamp("2021-06-05") else: assert dt == pd.Timestamp("2021-06-05", tz=UTC) - assert dt == dt.floor("T") + assert dt == dt.floor("min") def test_parse_timestamp_with_minute(minute_mult, param_name, calendar, utc): @@ -193,7 +193,7 @@ def test_parse_timestamp_with_minute(minute_mult, param_name, calendar, utc): assert dt == pd.Timestamp("2021-06-02 23:00") else: assert dt == pd.Timestamp("2021-06-02 23:00", tz=UTC) - assert dt == dt.floor("T") + assert dt == dt.floor("min") def test_parse_timestamp_with_second(second, sides, param_name): @@ -395,7 +395,7 @@ def test_parse_trading_minute( def st_align() -> st.SearchStrategy[pd.Timedelta]: """SearchStrategy for a valid alignment.""" - sample_pos = [pd.Timedelta(i, "T") for i in range(1, 31) if not 60 % i] + sample_pos = [pd.Timedelta(i, "min") for i in range(1, 31) if not 60 % i] sample_neg = [-td for td in sample_pos] return st.sampled_from(sample_pos + sample_neg) @@ -502,12 +502,12 @@ def st_start_end( @st.composite def st_periods( draw, - minimum: pd.Timedelta = pd.Timedelta(1, "T"), - maximum: pd.Timedelta = pd.Timedelta(1, "D") - pd.Timedelta(1, "T"), + minimum: pd.Timedelta = pd.Timedelta(1, "min"), + maximum: pd.Timedelta = pd.Timedelta(1, "D") - pd.Timedelta(1, "min"), ) -> st.SearchStrategy[pd.Timedelta]: """SearchStrategy for a period between a `minimum` and `maximum`.""" period = draw(st.integers(minimum.seconds // 60, maximum.seconds // 60)) - return pd.Timedelta(period, "T") + return pd.Timedelta(period, "min") # Helper methods @@ -1043,7 +1043,7 @@ def cal_start_end( pd.Timestamp("2018-12-31"), ) - @pytest.fixture(params=itertools.product(("105T", "106T"), ("right", "both"))) + @pytest.fixture(params=itertools.product(("105min", "106min"), ("right", "both"))) def ti_for_overlap( self, request, cal_start_end, curtail_all, one_min ) -> abc.Iterator[m._TradingIndex]: @@ -1074,7 +1074,7 @@ def test_overlaps(self, ti_for_overlap, answers): """Test 'curtail_overlaps' and for overlaps against concrete parameters.""" ti = ti_for_overlap period = pd.Timedelta(ti.interval_nanos) - period_106 = period == pd.Timedelta("106T") + period_106 = period == pd.Timedelta("106min") if period_106 or ti.closed == "both": with pytest.raises(errors.IndicesOverlapError): @@ -1084,7 +1084,7 @@ def test_overlaps(self, ti_for_overlap, answers): return if not ti.curtail_overlaps and period_106: - # won't raise on "105T" as right side of last interval of am + # won't raise on "105min" as right side of last interval of am # session won't clash on coinciding with left side of first # interval of pm session as one of these sides will always be # open (in this case the left side). NB can't close on both @@ -1105,7 +1105,7 @@ def ti_for_overlap_error_negative_case( 104T is the edge case, one minute short of coinciding with pm subsession open. """ cal, start, end = cal_start_end - period, closed = pd.Timedelta("104T"), request.param + period, closed = pd.Timedelta("104min"), request.param yield m._TradingIndex( cal, start, @@ -1135,7 +1135,7 @@ def test_overlaps_2(self, ti_for_overlap_error_negative_case): def test_force(self, cal_start_end): """Verify `force` option overrides `force_close` and `force_break_close`.""" cal, start, end = cal_start_end - kwargs = dict(start=start, end=end, period="1H", intervals=True) + kwargs = dict(start=start, end=end, period="1h", intervals=True) expected_true = cal.trading_index( **kwargs, force_close=True, force_break_close=True @@ -1168,7 +1168,7 @@ def test_ignore_breaks(self, cal_start_end): """Verify effect of ignore_breaks option.""" cal, start, end = cal_start_end assert cal.sessions_has_break(start, end) - kwargs = dict(start=start, end=end, period="1H", intervals=True) + kwargs = dict(start=start, end=end, period="1h", intervals=True) # verify a difference index_false = cal.trading_index(**kwargs, ignore_breaks=False) @@ -1256,27 +1256,27 @@ def test_align( cal, ans = cal_with_ans_align from_, to = dates_align aligned_start_times = { - "-1T": (time(7, 59), time(15, 28)), - "-2T": (time(7, 58), time(15, 28)), - "-3T": (time(7, 57), time(15, 27)), - "-5T": (time(7, 55), time(15, 25)), - "-15T": (time(7, 45), time(15, 15)), - "-20T": (time(7, 40), time(15, 20)), - "-30T": (time(7, 30), time(15)), - "-60T": (time(7), time(15)), - "1T": (time(7, 59), time(15, 28)), - "2T": (time(8), time(15, 28)), - "3T": (time(8), time(15, 30)), - "5T": (time(8), time(15, 30)), - "15T": (time(8), time(15, 30)), - "20T": (time(8), time(15, 40)), - "30T": (time(8), time(15, 30)), - "60T": (time(8), time(16)), + "-1min": (time(7, 59), time(15, 28)), + "-2min": (time(7, 58), time(15, 28)), + "-3min": (time(7, 57), time(15, 27)), + "-5min": (time(7, 55), time(15, 25)), + "-15min": (time(7, 45), time(15, 15)), + "-20min": (time(7, 40), time(15, 20)), + "-30min": (time(7, 30), time(15)), + "-60min": (time(7), time(15)), + "1min": (time(7, 59), time(15, 28)), + "2min": (time(8), time(15, 28)), + "3min": (time(8), time(15, 30)), + "5min": (time(8), time(15, 30)), + "15min": (time(8), time(15, 30)), + "20min": (time(8), time(15, 40)), + "30min": (time(8), time(15, 30)), + "60min": (time(8), time(16)), } alignments = list(aligned_start_times.keys()) align = data.draw(st.sampled_from(alignments)) align_pm = data.draw(st.one_of([st.sampled_from(alignments), st.booleans()])) - period = data.draw(self.st_periods(maximum=pd.Timedelta(1, "H"))) + period = data.draw(self.st_periods(maximum=pd.Timedelta(1, "h"))) open_pm = ans.break_ends[from_] closes = (ans.break_starts[from_], ans.closes[from_], ans.closes[to]) @@ -1383,12 +1383,12 @@ def test_align_overlap(self, cal_with_ans_align, dates_align, one_min): """ cal, _ = cal_with_ans_align - kwargs = dict(closed="right", align="-5T") - align_pm = "-1H" + kwargs = dict(closed="right", align="-5min") + align_pm = "-1h" intervals = True # assert returns at edge - period = pd.Timedelta(85, "T") + period = pd.Timedelta(85, "min") rtrn = cal.trading_index( *dates_align, period, intervals=intervals, align_pm=align_pm, **kwargs ) @@ -1423,7 +1423,7 @@ def test_align_overlap(self, cal_with_ans_align, dates_align, one_min): intervals = False # assert returns at edge - period = pd.Timedelta(85, "T") + period = pd.Timedelta(85, "min") rtrn = cal.trading_index( *dates_align, period, intervals=intervals, align_pm=align_pm, **kwargs ) @@ -1589,7 +1589,7 @@ def assertions( assertions(starts, ends, period, force, ignore_breaks) - period = pd.Timedelta(5, "T") + period = pd.Timedelta(5, "min") delta = period * 2 starts = [ @@ -1609,17 +1609,17 @@ def assertions( assertions(starts, ends, period, force, ignore_breaks) - period = pd.Timedelta(1, "H") + period = pd.Timedelta(1, "h") end_s_open = cal.session_open(end_s) # ignoring breaks... # assert assumption that end unaligned by 30mins - assert (end_s_close - end_s_open) % period == pd.Timedelta(30, "T") + assert (end_s_close - end_s_open) % period == pd.Timedelta(30, "min") - end_s_aligned_post_close = end_s_close + pd.Timedelta(30, "T") + end_s_aligned_post_close = end_s_close + pd.Timedelta(30, "min") end_s_break_end = cal.session_break_end(end_s) # assert assumption that pm session 3H duration - assert end_s_close - end_s_break_end == pd.Timedelta(3, "H") + assert end_s_close - end_s_break_end == pd.Timedelta(3, "h") starts = [ (start_s, None, None, None, None, None), @@ -1638,10 +1638,10 @@ def assertions( (end_s_aligned_post_close - period, -1, None, -1, -1, None), (end_s_aligned_post_close - period - one_min, -2, -1, -2, -2, -1), (end_s_break_end, -4, -3, -4, -4, -3), - (end_s_break_end + pd.Timedelta(30, "T"), -3, -2, -3, -3, -2), - (end_s_break_end + pd.Timedelta(29, "T"), -4, -3, -4, -4, -3), - (end_s_break_end - pd.Timedelta(30, "T"), -4, -3, -4, -4, -3), - (end_s_break_end - pd.Timedelta(31, "T"), -5, -4, -5, -5, -4), + (end_s_break_end + pd.Timedelta(30, "min"), -3, -2, -3, -3, -2), + (end_s_break_end + pd.Timedelta(29, "min"), -4, -3, -4, -4, -3), + (end_s_break_end - pd.Timedelta(30, "min"), -4, -3, -4, -4, -3), + (end_s_break_end - pd.Timedelta(31, "min"), -5, -4, -5, -5, -4), ] assertions(starts, ends, period, force, ignore_breaks) @@ -1659,14 +1659,14 @@ def assertions( (end_s_aligned_post_close, None, None, None, None, None), (end_s_close, None, None, None, None, None), (end_s_close - one_min, -1, None, -1, -1, None), - (end_s_close - pd.Timedelta(30, "T"), -1, None, -1, -1, None), - (end_s_close - pd.Timedelta(31, "T"), -2, -1, -2, -2, -1), + (end_s_close - pd.Timedelta(30, "min"), -1, None, -1, -1, None), + (end_s_close - pd.Timedelta(31, "min"), -2, -1, -2, -2, -1), # break end as before... (end_s_break_end, -4, -3, -4, -4, -3), - (end_s_break_end + pd.Timedelta(30, "T"), -3, -2, -3, -3, -2), - (end_s_break_end + pd.Timedelta(29, "T"), -4, -3, -4, -4, -3), - (end_s_break_end - pd.Timedelta(30, "T"), -4, -3, -4, -4, -3), - (end_s_break_end - pd.Timedelta(31, "T"), -5, -4, -5, -5, -4), + (end_s_break_end + pd.Timedelta(30, "min"), -3, -2, -3, -3, -2), + (end_s_break_end + pd.Timedelta(29, "min"), -4, -3, -4, -4, -3), + (end_s_break_end - pd.Timedelta(30, "min"), -4, -3, -4, -4, -3), + (end_s_break_end - pd.Timedelta(31, "min"), -5, -4, -5, -5, -4), ] force = True @@ -1676,7 +1676,7 @@ def assertions( end_s_break_start = cal.session_break_start(end_s) # assert assumption that break start unaligned by 30mins - assert (end_s_break_start - end_s_open) % period == pd.Timedelta(30, "T") + assert (end_s_break_start - end_s_open) % period == pd.Timedelta(30, "min") starts = [ (start_s, None, None, None, None, None), @@ -1696,10 +1696,10 @@ def assertions( (end_s_break_end + one_min, -3, -2, -3, -3, -2), (end_s_break_end - one_min, -3, -3, -3, -4, -2), (end_s_break_start, -4, -3, -4, -5, -2), - (end_s_break_start + pd.Timedelta(30, "T"), -3, -3, -3, -4, -2), - (end_s_break_start + pd.Timedelta(29, "T"), -4, -3, -4, -5, -2), - (end_s_break_start - pd.Timedelta(30, "T"), -4, -3, -4, -5, -2), - (end_s_break_start - pd.Timedelta(31, "T"), -5, -4, -5, -6, -3), + (end_s_break_start + pd.Timedelta(30, "min"), -3, -3, -3, -4, -2), + (end_s_break_start + pd.Timedelta(29, "min"), -4, -3, -4, -5, -2), + (end_s_break_start - pd.Timedelta(30, "min"), -4, -3, -4, -5, -2), + (end_s_break_start - pd.Timedelta(31, "min"), -5, -4, -5, -6, -3), ] force, ignore_breaks = False, False @@ -1729,8 +1729,8 @@ def assertions( # end_s_break_start affected by force (end_s_break_start, -3, -3, -3, -4, -2), (end_s_break_start - one_min, -4, -3, -4, -5, -2), - (end_s_break_start - pd.Timedelta(30, "T"), -4, -3, -4, -5, -2), - (end_s_break_start - pd.Timedelta(31, "T"), -5, -4, -5, -6, -3), + (end_s_break_start - pd.Timedelta(30, "min"), -4, -3, -4, -5, -2), + (end_s_break_start - pd.Timedelta(31, "min"), -5, -4, -5, -6, -3), ] force, ignore_breaks = True, False @@ -1750,13 +1750,13 @@ def test_parsing_errors(self, cal_start_end): error_msg = "If `intervals` is True then `closed` cannot be 'neither'." with pytest.raises(ValueError, match=re.escape(error_msg)): cal.trading_index( - start, end, "20T", intervals=True, closed="neither", parse=False + start, end, "20min", intervals=True, closed="neither", parse=False ) error_msg = "If `intervals` is True then `closed` cannot be 'both'." with pytest.raises(ValueError, match=re.escape(error_msg)): cal.trading_index( - start, end, "20T", intervals=True, closed="both", parse=False + start, end, "20min", intervals=True, closed="both", parse=False ) # Verify raises error if period "1D" and start or end not passed as a date. @@ -1782,7 +1782,7 @@ def test_parsing_errors(self, cal_start_end): with pytest.raises(ValueError, match=re.escape(error_msg)): cal.trading_index(start, end, invalid_str) - invalid_value = pd.Timedelta(1441, "T") + invalid_value = pd.Timedelta(1441, "min") error_msg = re.escape( "`period` cannot be greater than one day although received as" f" '{invalid_value}'." @@ -1807,20 +1807,20 @@ def test_parsing_errors(self, cal_start_end): " '5min', '5T', pd.Timedelta('-5T'), '-5min', '-5T'." ) with pytest.raises(ValueError, match=re.escape(error_msg)): - cal.trading_index(start, end, "1H", align="5T", align_pm=invalid_str) + cal.trading_index(start, end, "1h", align="5min", align_pm=invalid_str) - invalid_values = [pd.Timedelta(7, "T"), pd.Timedelta(0), "0T"] + invalid_values = [pd.Timedelta(7, "min"), pd.Timedelta(0), "0min"] for value in invalid_values: error_msg_end = ( f" must be factor of 1H although received '{pd.Timedelta(value)}'." ) with pytest.raises(ValueError, match=re.escape("`align`" + error_msg_end)): - cal.trading_index(start, end, "1H", align=value) + cal.trading_index(start, end, "1h", align=value) with pytest.raises( ValueError, match=re.escape("`align_pm`" + error_msg_end) ): - cal.trading_index(start, end, "1H", align="5T", align_pm=value) + cal.trading_index(start, end, "1h", align="5min", align_pm=value) invalid_minute_fractions = [3, pd.Timedelta(3600, "ms"), 3.6, "3s"] for value in invalid_minute_fractions: @@ -1829,9 +1829,9 @@ def test_parsing_errors(self, cal_start_end): f"'{pd.Timedelta(value)}'." ) with pytest.raises(ValueError, match=re.escape("`align`" + error_msg_end)): - cal.trading_index(start, end, "1H", align=value) + cal.trading_index(start, end, "1h", align=value) with pytest.raises( ValueError, match=re.escape("`align_pm`" + error_msg_end) ): - cal.trading_index(start, end, "1H", align="5T", align_pm=value) + cal.trading_index(start, end, "1h", align="5min", align_pm=value) diff --git a/tests/test_cmes_calendar.py b/tests/test_cmes_calendar.py index 39bcd61b..e4e9f32c 100644 --- a/tests/test_cmes_calendar.py +++ b/tests/test_cmes_calendar.py @@ -36,4 +36,4 @@ def early_closes_sample(self): @pytest.fixture def early_closes_sample_time(self): - yield pd.Timedelta(12, "H") + yield pd.Timedelta(12, "h") diff --git a/tests/test_exchange_calendar.py b/tests/test_exchange_calendar.py index d753f7b2..44848e34 100644 --- a/tests/test_exchange_calendar.py +++ b/tests/test_exchange_calendar.py @@ -211,8 +211,8 @@ class Answers: Side of sessions to treat as trading minutes. """ - ONE_MIN = pd.Timedelta(1, "T") - TWO_MIN = pd.Timedelta(2, "T") + ONE_MIN = pd.Timedelta(1, "min") + TWO_MIN = pd.Timedelta(2, "min") ONE_DAY = pd.Timedelta(1, "D") LEFT_SIDES = ["left", "both"] @@ -355,10 +355,10 @@ def get_sessions_minutes( self.first_pm_minutes[indexer], ): if pd.isna(last_am): - dtis.append(pd.date_range(first, last, freq="T")) + dtis.append(pd.date_range(first, last, freq="min")) else: - dtis.append(pd.date_range(first, last_am, freq="T")) - dtis.append(pd.date_range(first_pm, last, freq="T")) + dtis.append(pd.date_range(first, last_am, freq="min")) + dtis.append(pd.date_range(first_pm, last, freq="min")) return pandas_utils.indexes_union(dtis) @@ -382,11 +382,11 @@ def get_session_minutes( first_pm = self.first_pm_minutes[session] if pd.isna(last_am): - return (pd.date_range(first, last, freq="T"),) + return (pd.date_range(first, last, freq="min"),) else: return ( - pd.date_range(first, last_am, freq="T"), - pd.date_range(first_pm, last, freq="T"), + pd.date_range(first, last_am, freq="min"), + pd.date_range(first_pm, last, freq="min"), ) def get_session_break_minutes(self, session: pd.Timestamp) -> pd.DatetimeIndex: @@ -397,7 +397,7 @@ def get_session_break_minutes(self, session: pd.Timestamp) -> pd.DatetimeIndex: am_minutes, pm_minutes = self.get_session_minutes(session) first = am_minutes[-1] + self.ONE_MIN last = pm_minutes[0] - self.ONE_MIN - return pd.date_range(first, last, freq="T") + return pd.date_range(first, last, freq="min") def get_session_edge_minutes( self, session: pd.Timestamp, delta: int = 0 @@ -411,7 +411,7 @@ def get_session_edge_minutes( the session/subsession duration - this condition is NOT VERIFIED by this method. """ - delta = pd.Timedelta(delta, "T") + delta = pd.Timedelta(delta, "min") first_minute = self.first_minutes[session] last_minute = self.last_minutes[session] has_break = self.session_has_break(session) @@ -641,7 +641,7 @@ def _mask_sessions_without_gap_after(self) -> pd.Series: # a trading minute cannot be a minute of more than one session. assert not (self.closes == self.opens.shift(-1)).any() # there will be no gap if next open is one minute after previous close - closes_plus_min = self.closes + pd.Timedelta(1, "T") + closes_plus_min = self.closes + pd.Timedelta(1, "min") return self.opens.shift(-1) == closes_plus_min else: @@ -658,7 +658,7 @@ def _mask_sessions_without_gap_before(self) -> pd.Series: # a trading minute cannot be a minute of more than one session. assert not (self.closes == self.opens.shift(-1)).any() # there will be no gap if previous close is one minute before next open - opens_minus_one = self.opens - pd.Timedelta(1, "T") + opens_minus_one = self.opens - pd.Timedelta(1, "min") return self.closes.shift(1) == opens_minus_one else: @@ -1354,7 +1354,7 @@ def non_trading_minutes_only(self) -> abc.Iterator[pd.Timestamp]: def _trading_minute_to_break_minute( self, sessions, break_sessions ) -> list[pd.DatetimeIndex, pd.DatetimeIndex, pd.DatetimeIndex]: - times = (self.last_am_minutes[break_sessions] + pd.Timedelta(1, "T")).dt.time + times = (self.last_am_minutes[break_sessions] + pd.Timedelta(1, "min")).dt.time mask = (self.first_minutes[sessions].dt.time.values < times.values) & ( times.values < self.last_minutes[sessions].dt.time.values @@ -1863,7 +1863,7 @@ def early_closes_sample_time(self) -> abc.Iterator[pd.Timedelta | None]: subclass). Example returns: - pd.Timedelta(14, "H") # 14:00 local time + pd.Timedelta(14, "h") # 14:00 local time pd.Timedelta(hours=13, minutes=15) # 13:15 local time """ yield None @@ -1912,7 +1912,7 @@ def early_closes_weekdays_sample_time(self) -> abc.Iterator[pd.Timedelta | None] overriden by subclass. Example returns: - pd.Timedelta(14, "H") # 14:00 local time + pd.Timedelta(14, "h") # 14:00 local time pd.Timedelta(hours=13, minutes=15) # 13:15 local time """ yield None @@ -1958,7 +1958,7 @@ def non_early_closes_sample_time(self) -> abc.Iterator[pd.Timedelta | None]: subclass). Example returns: - pd.Timedelta(17, "H") # 17:00 local time + pd.Timedelta(17, "h") # 17:00 local time pd.Timedelta(hours=16, minutes=30) # 16:30 local time """ yield None @@ -2063,7 +2063,7 @@ def default_calendar_with_answers( @pytest.fixture(scope="class") def one_minute(self) -> abc.Iterator[pd.Timedelta]: - yield pd.Timedelta(1, "T") + yield pd.Timedelta(1, "min") @pytest.fixture(scope="class") def today(self) -> abc.Iterator[pd.Timedelta]: @@ -2924,7 +2924,7 @@ def test_is_open_at_time(self, all_calendars_with_answers, one_minute): cal, ans = all_calendars_with_answers one_min = one_minute - one_sec = pd.Timedelta(1, "S") + one_sec = pd.Timedelta(1, "s") sides = ("left", "both", "right", "neither") @@ -3343,12 +3343,12 @@ def test_minute_offset(self, all_calendars_with_answers, one_minute): for i, session in enumerate(sessions): # intra session first_minute = ans.first_minutes[session] - rtrn = f(first_minute + pd.Timedelta(20, "T"), 10) - assert rtrn == first_minute + pd.Timedelta(30, "T") + rtrn = f(first_minute + pd.Timedelta(20, "min"), 10) + assert rtrn == first_minute + pd.Timedelta(30, "min") last_minute = ans.last_minutes[session] - rtrn = f(last_minute - pd.Timedelta(20, "T"), -10) - assert rtrn == last_minute - pd.Timedelta(30, "T") + rtrn = f(last_minute - pd.Timedelta(20, "min"), -10) + assert rtrn == last_minute - pd.Timedelta(30, "min") # crossing break if ans.session_has_break(session): @@ -3388,7 +3388,7 @@ def test_minute_offset_by_sessions(self, all_calendars_with_answers): cal, ans = all_calendars_with_answers f = no_parsing(cal.minute_offset_by_sessions) delta_int = 20 - delta = pd.Timedelta(delta_int, "T") + delta = pd.Timedelta(delta_int, "min") # tests for rtrn with same time. @@ -3550,9 +3550,9 @@ def test_minutes_in_range(self, all_calendars_with_answers, one_minute): tm.assert_index_equal(ans_dti, cal_dti[start_idx:end_idx]) # intra-session - from_ = ans.first_minutes[ans.first_session] + pd.Timedelta(15, "T") - to = ans.first_minutes[ans.first_session] + pd.Timedelta(45, "T") - expected = pd.date_range(from_, to, freq="T") + from_ = ans.first_minutes[ans.first_session] + pd.Timedelta(15, "min") + to = ans.first_minutes[ans.first_session] + pd.Timedelta(45, "min") + expected = pd.date_range(from_, to, freq="min") rtrn = f(from_, to) tm.assert_index_equal(expected, rtrn) @@ -3581,9 +3581,9 @@ def test_minutes_window(self, all_calendars_with_answers): tm.assert_index_equal(ans_dti, cal_dti) # intra-session - from_ = ans.first_minutes[ans.first_session] + pd.Timedelta(15, "T") + from_ = ans.first_minutes[ans.first_session] + pd.Timedelta(15, "min") count = 30 - expected = pd.date_range(from_, periods=count, freq="T") + expected = pd.date_range(from_, periods=count, freq="min") rtrn = f(from_, count) tm.assert_index_equal(expected, rtrn) @@ -3591,18 +3591,18 @@ def test_minutes_window(self, all_calendars_with_answers): if not ans.sessions_with_gap_after.empty: session = ans.sessions_with_gap_after[0] next_session = ans.get_next_session(session) - from_ = ans.last_minutes[session] - pd.Timedelta(4, "T") + from_ = ans.last_minutes[session] - pd.Timedelta(4, "min") count = 10 - expected_1 = pd.date_range(from_, periods=5, freq="T") + expected_1 = pd.date_range(from_, periods=5, freq="min") from_2 = ans.first_minutes[next_session] - expected_2 = pd.date_range(from_2, periods=5, freq="T") + expected_2 = pd.date_range(from_2, periods=5, freq="min") expected = expected_1.union(expected_2) rtrn = f(from_, count) tm.assert_index_equal(expected, rtrn) # verify raises ValueError when window extends beyond calendar's minute bounds # at limit, window starts on first calendar minute - delta = pd.Timedelta(2, "T") + delta = pd.Timedelta(2, "min") minute = ans.first_minute + delta assert f(minute, count=-3)[0] == ans.first_minute # window would start before first calendar minute @@ -3848,7 +3848,7 @@ def unite(dtis: list[pd.DatetimeIndex]) -> pd.DatetimeIndex: for _, sessions in ans.session_block_generator(): for mins in [5, 17, 60, 123, 333, 1033]: - period = pd.Timedelta(mins, "T") + period = pd.Timedelta(mins, "min") dtis = [] for session in sessions: indexes = ans.get_session_minutes(session) diff --git a/tests/test_iepa_calendar.py b/tests/test_iepa_calendar.py index 424caf41..c448dc46 100644 --- a/tests/test_iepa_calendar.py +++ b/tests/test_iepa_calendar.py @@ -40,4 +40,4 @@ def early_closes_sample(self): @pytest.fixture def early_closes_sample_time(self): - yield pd.Timedelta(13, "H") + yield pd.Timedelta(13, "h") diff --git a/tests/test_xasx_calendar.py b/tests/test_xasx_calendar.py index b265a06e..97201462 100644 --- a/tests/test_xasx_calendar.py +++ b/tests/test_xasx_calendar.py @@ -84,4 +84,4 @@ def non_early_closes_sample(self): @pytest.fixture def non_early_closes_sample_time(self): - yield pd.Timedelta(16, "H") + yield pd.Timedelta(16, "h") diff --git a/tests/test_xbue_calendar.py b/tests/test_xbue_calendar.py index 33d95421..7c74121a 100644 --- a/tests/test_xbue_calendar.py +++ b/tests/test_xbue_calendar.py @@ -99,4 +99,4 @@ def early_closes_sample(self): @pytest.fixture def early_closes_sample_time(self): - yield pd.Timedelta(13, "H") + yield pd.Timedelta(13, "h") diff --git a/tests/test_xetr_calendar.py b/tests/test_xetr_calendar.py index fd5f6ec6..412f55f9 100644 --- a/tests/test_xetr_calendar.py +++ b/tests/test_xetr_calendar.py @@ -33,7 +33,7 @@ def regular_holidays_sample(self): # Whit Monday "2015-05-25", # regularly observed from 2015 "2016-05-16", - "2021-05-24" + "2021-05-24", ] @pytest.fixture @@ -58,7 +58,7 @@ def non_holidays_sample(self): "2016-10-31", "2018-10-31", # German Unity Day was not observed in 2022 - "2022-10-03" + "2022-10-03", ] @pytest.fixture @@ -70,4 +70,4 @@ def early_closes_sample(self): @pytest.fixture def early_closes_sample_time(self): - yield pd.Timedelta(14, "H") + yield pd.Timedelta(14, "h") diff --git a/tests/test_xhkg_calendar.py b/tests/test_xhkg_calendar.py index c85a4735..d29fc50c 100644 --- a/tests/test_xhkg_calendar.py +++ b/tests/test_xhkg_calendar.py @@ -177,9 +177,7 @@ def adhoc_holidays_sample(self): "2017-12-26", # The day after Christmas ] - typhoon_days = [ - "2021-10-13" - ] + typhoon_days = ["2021-10-13"] mid_autumn_festival_holidays = [ "2022-09-12" # In 2019, the mid-autumn festival holiday was observed on the following business day. @@ -193,4 +191,4 @@ def early_closes_sample(self): @pytest.fixture def early_closes_sample_time(self): - yield pd.Timedelta(12, "H") + yield pd.Timedelta(12, "h") diff --git a/tests/test_xmad_calendar.py b/tests/test_xmad_calendar.py index 7479cb8f..2997aae3 100644 --- a/tests/test_xmad_calendar.py +++ b/tests/test_xmad_calendar.py @@ -46,7 +46,7 @@ def regular_holidays_sample(self): # New Year's Eve was a holiday through to 2010, then became an early # close, and then went back to being a full day's holiday from 2021. "2010-12-31", - "2021-12-31" + "2021-12-31", ] @pytest.fixture @@ -76,11 +76,10 @@ def non_holidays_sample(self): "2005-11-01", # All Saints Day "2005-12-06", # Constitution Day "2005-12-08", # Immaculate Conception - # New Year's Eve was holiday through to 2010, but then became an early # close after that, before becoming a full market holiday again in 2021. "2012-12-31", - "2020-12-31" + "2020-12-31", ] @pytest.fixture @@ -89,10 +88,9 @@ def early_closes_sample(self): # Christmas Eve was an early close from 2012-12-24, to 2020-12-24 "2012-12-24", "2020-12-24", - "2012-12-31", # New Year's Eve ] @pytest.fixture def early_closes_sample_time(self): - yield pd.Timedelta(14, "H") + yield pd.Timedelta(14, "h") diff --git a/tests/test_xnys_calendar.py b/tests/test_xnys_calendar.py index 1402f2a7..ffbafce8 100644 --- a/tests/test_xnys_calendar.py +++ b/tests/test_xnys_calendar.py @@ -36,7 +36,7 @@ def regular_holidays_sample(self): # Juneteenth 2022-2024 "2022-06-20", "2023-06-19", - "2024-06-19" + "2024-06-19", ] @pytest.fixture @@ -89,7 +89,7 @@ def early_closes_sample(self): @pytest.fixture def early_closes_sample_time(self): - yield pd.Timedelta(13, "H") + yield pd.Timedelta(13, "h") @pytest.fixture def non_early_closes_sample(self): @@ -102,4 +102,4 @@ def non_early_closes_sample(self): @pytest.fixture def non_early_closes_sample_time(self): - yield pd.Timedelta(16, "H") + yield pd.Timedelta(16, "h") diff --git a/tests/test_xosl_calendar.py b/tests/test_xosl_calendar.py index a82b1c9d..74d77b6c 100644 --- a/tests/test_xosl_calendar.py +++ b/tests/test_xosl_calendar.py @@ -62,7 +62,7 @@ def early_closes_sample(self): @pytest.fixture def early_closes_sample_time(self): - yield pd.Timedelta(13, "H") + yield pd.Timedelta(13, "h") @pytest.fixture def non_early_closes_sample(self): diff --git a/tests/test_xsto_calendar.py b/tests/test_xsto_calendar.py index 01634222..aff5b743 100644 --- a/tests/test_xsto_calendar.py +++ b/tests/test_xsto_calendar.py @@ -85,4 +85,4 @@ def early_closes_sample(self): @pytest.fixture def early_closes_sample_time(self): - yield pd.Timedelta(13, "H") + yield pd.Timedelta(13, "h") diff --git a/tests/test_xtse_calendar.py b/tests/test_xtse_calendar.py index 18a315f6..4f2213c7 100644 --- a/tests/test_xtse_calendar.py +++ b/tests/test_xtse_calendar.py @@ -67,7 +67,7 @@ def early_closes_sample(self): @pytest.fixture def early_closes_sample_time(self): - yield pd.Timedelta(13, "H") + yield pd.Timedelta(13, "h") @pytest.fixture def non_early_closes_sample(self): @@ -77,4 +77,4 @@ def non_early_closes_sample(self): @pytest.fixture def non_early_closes_sample_time(self): - yield pd.Timedelta(16, "H") + yield pd.Timedelta(16, "h")