Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions qlib/utils/resam.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ def resam_calendar(
Frequency of the raw calendar
freq_sam : str
Sample frequency
Weekly and monthly sampling counts periods present in the input, so entirely
missing weeks or months do not advance the sampling count.
region: str
Region, for example, "cn", "us"
Returns
Expand Down Expand Up @@ -57,13 +59,13 @@ def resam_calendar(
return _calendar_day[:: freq_sam.count]

elif freq_sam.base == Freq.NORM_FREQ_WEEK:
_day_in_week = np.array(list(map(lambda x: x.dayofweek, _calendar_day)))
_calendar_week = _calendar_day[np.ediff1d(_day_in_week, to_begin=-1) < 0]
_week = pd.DatetimeIndex(_calendar_day).to_period("W")
_calendar_week = _calendar_day[~_week.duplicated()]
return _calendar_week[:: freq_sam.count]

elif freq_sam.base == Freq.NORM_FREQ_MONTH:
_day_in_month = np.array(list(map(lambda x: x.day, _calendar_day)))
_calendar_month = _calendar_day[np.ediff1d(_day_in_month, to_begin=-1) < 0]
_month = pd.DatetimeIndex(_calendar_day).to_period("M")
_calendar_month = _calendar_day[~_month.duplicated()]
return _calendar_month[:: freq_sam.count]
else:
raise ValueError("sampling freq must be xmin, xd, xw, xm")
Expand Down
84 changes: 84 additions & 0 deletions tests/misc/test_resam.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

import numpy as np
import pandas as pd
import pytest

from qlib.constant import REG_CN
from qlib.utils.resam import resam_calendar


@pytest.mark.parametrize(
"dates, raw_freq, sampled_freq, expected",
[
(
["2024-01-01", "2024-01-02", "2024-01-09", "2024-01-10", "2024-01-17"],
"day",
"week",
["2024-01-01", "2024-01-09", "2024-01-17"],
),
(
["2023-12-25", "2024-01-01", "2024-01-08", "2024-01-15"],
"week",
"2week",
["2023-12-25", "2024-01-08"],
),
(
["2023-12-04", "2023-12-05", "2024-01-08", "2024-01-09", "2024-02-12"],
"day",
"month",
["2023-12-04", "2024-01-08", "2024-02-12"],
),
(
["2023-12-01", "2024-01-01", "2024-02-01", "2024-03-01"],
"month",
"2month",
["2023-12-01", "2024-02-01"],
),
(
["2023-12-29 09:30", "2023-12-29 13:00", "2024-01-02 09:30", "2024-01-02 13:00"],
"1min",
"week",
["2023-12-29", "2024-01-02"],
),
],
)
def test_resam_calendar_period_boundaries(dates, raw_freq, sampled_freq, expected):
calendar = np.array([pd.Timestamp(value) for value in dates])
result = resam_calendar(calendar, raw_freq, sampled_freq, region=REG_CN)
np.testing.assert_array_equal(result, np.array([pd.Timestamp(value) for value in expected]))


@pytest.mark.parametrize(
"start, end, gap_start, gap_end, sampled_freq, expected",
[
(
"2024-01-29",
"2024-03-08",
"2024-02-12",
"2024-02-16",
"2week",
["2024-01-29", "2024-02-19", "2024-03-04"],
),
(
"2024-01-01",
"2024-06-28",
"2024-03-01",
"2024-03-31",
"2month",
["2024-01-01", "2024-04-01", "2024-06-03"],
),
],
)
def test_resam_calendar_counts_nonempty_periods(start, end, gap_start, gap_end, sampled_freq, expected):
calendar = pd.bdate_range(start, end)
calendar = calendar[(calendar < gap_start) | (calendar > gap_end)]
result = resam_calendar(calendar.to_pydatetime(), "day", sampled_freq, region=REG_CN)
np.testing.assert_array_equal(result, np.array([pd.Timestamp(value) for value in expected]))


@pytest.mark.parametrize("sampled_freq", ["week", "month", "2week", "2month"])
def test_resam_calendar_empty(sampled_freq):
calendar = np.array([], dtype=object)
np.testing.assert_array_equal(resam_calendar(calendar, "day", sampled_freq, region=REG_CN), calendar)