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
12 changes: 9 additions & 3 deletions qlib/backtest/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import numpy as np

from qlib.utils.time import epsilon_change
from qlib.utils.time import Freq, epsilon_change

if TYPE_CHECKING:
from qlib.backtest.decision import BaseTradeDecision
Expand Down Expand Up @@ -86,7 +86,7 @@ def finished(self) -> bool:

def step(self) -> None:
if self.finished():
raise RuntimeError(f"The calendar is finished, please reset it if you want to call it!")
raise RuntimeError("The calendar is finished, please reset it if you want to call it!")
self.trade_step += 1

def get_freq(self) -> str:
Expand Down Expand Up @@ -128,7 +128,13 @@ def get_step_time(self, trade_step: int | None = None, shift: int = 0) -> Tuple[
if trade_step is None:
trade_step = self.get_trade_step()
calendar_index = self.start_index + trade_step - shift
return self._calendar[calendar_index], epsilon_change(self._calendar[calendar_index + 1])
step_start = pd.Timestamp(self._calendar[calendar_index])
if calendar_index + 1 < len(self._calendar):
step_end = self._calendar[calendar_index + 1]
else:
freq = Freq(self.freq)
step_end = step_start + Freq.get_timedelta(freq.count, freq.base)
return step_start, epsilon_change(pd.Timestamp(step_end))

def get_data_cal_range(self, rtype: str = "full") -> Tuple[int, int]:
"""
Expand Down
35 changes: 35 additions & 0 deletions tests/backtest/test_trade_calendar_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import numpy as np
import pandas as pd

from qlib.backtest.utils import TradeCalendarManager


def _make_calendar_manager():
trade_calendar = TradeCalendarManager.__new__(TradeCalendarManager)
trade_calendar.freq = "day"
trade_calendar.start_index = 0
trade_calendar.end_index = 1
trade_calendar.trade_len = 2
trade_calendar.trade_step = 1
trade_calendar._calendar = np.array(
[pd.Timestamp("2020-01-01"), pd.Timestamp("2020-01-02")]
)
return trade_calendar


def test_get_step_time_uses_next_calendar_when_available():
trade_calendar = _make_calendar_manager()

start_time, end_time = trade_calendar.get_step_time(trade_step=0)

assert start_time == pd.Timestamp("2020-01-01")
assert end_time == pd.Timestamp("2020-01-01 23:59:59")


def test_get_step_time_infers_right_boundary_for_last_calendar_bar():
trade_calendar = _make_calendar_manager()

start_time, end_time = trade_calendar.get_step_time()

assert start_time == pd.Timestamp("2020-01-02")
assert end_time == pd.Timestamp("2020-01-02 23:59:59")