|
3 | 3 |
|
4 | 4 | from typing import cast |
5 | 5 |
|
| 6 | +import cachetools |
6 | 7 | import pandas as pd |
7 | 8 |
|
8 | 9 | from qlib.backtest import Exchange, Order |
9 | | -from .pickle_styled import IntradayBacktestData |
| 10 | +from qlib.backtest.decision import TradeRange, TradeRangeByTime |
| 11 | +from qlib.constant import ONE_DAY, EPS_T |
| 12 | +from qlib.rl.order_execution.utils import get_ticks_slice |
| 13 | +from qlib.utils.index_data import IndexData |
| 14 | +from .pickle_styled import BaseIntradayBacktestData |
10 | 15 |
|
11 | 16 |
|
12 | | -class QlibIntradayBacktestData(IntradayBacktestData): |
| 17 | +class IntradayBacktestData(BaseIntradayBacktestData): |
13 | 18 | """Backtest data for Qlib simulator""" |
14 | 19 |
|
15 | | - def __init__(self, order: Order, exchange: Exchange, start_time: pd.Timestamp, end_time: pd.Timestamp) -> None: |
16 | | - super(QlibIntradayBacktestData, self).__init__() |
| 20 | + def __init__( |
| 21 | + self, |
| 22 | + order: Order, |
| 23 | + exchange: Exchange, |
| 24 | + ticks_index: pd.DatetimeIndex, |
| 25 | + ticks_for_order: pd.DatetimeIndex, |
| 26 | + ) -> None: |
17 | 27 | self._order = order |
18 | 28 | self._exchange = exchange |
19 | | - self._start_time = start_time |
20 | | - self._end_time = end_time |
| 29 | + self._start_time = ticks_for_order[0] |
| 30 | + self._end_time = ticks_for_order[-1] |
| 31 | + self.ticks_index = ticks_index |
| 32 | + self.ticks_for_order = ticks_for_order |
21 | 33 |
|
22 | 34 | self._deal_price = cast( |
23 | 35 | pd.Series, |
@@ -56,3 +68,43 @@ def get_volume(self) -> pd.Series: |
56 | 68 |
|
57 | 69 | def get_time_index(self) -> pd.DatetimeIndex: |
58 | 70 | return pd.DatetimeIndex([e[1] for e in list(self._exchange.quote_df.index)]) |
| 71 | + |
| 72 | + |
| 73 | +@cachetools.cached( # type: ignore |
| 74 | + cache=cachetools.LRUCache(100), |
| 75 | + key=lambda order, _, __: order.key_by_day, |
| 76 | +) |
| 77 | +def load_qlib_backtest_data( |
| 78 | + order: Order, |
| 79 | + trade_exchange: Exchange, |
| 80 | + trade_range: TradeRange, |
| 81 | +) -> IntradayBacktestData: |
| 82 | + data = cast( |
| 83 | + IndexData, |
| 84 | + trade_exchange.get_deal_price( |
| 85 | + stock_id=order.stock_id, |
| 86 | + start_time=order.date, |
| 87 | + end_time=order.date + ONE_DAY - EPS_T, |
| 88 | + direction=order.direction, |
| 89 | + method=None, |
| 90 | + ), |
| 91 | + ) |
| 92 | + |
| 93 | + ticks_index = pd.DatetimeIndex(data.index) |
| 94 | + if isinstance(trade_range, TradeRangeByTime): |
| 95 | + ticks_for_order = get_ticks_slice( |
| 96 | + ticks_index, |
| 97 | + trade_range.start_time, |
| 98 | + trade_range.end_time, |
| 99 | + include_end=True, |
| 100 | + ) |
| 101 | + else: |
| 102 | + ticks_for_order = None # FIXME: implement this logic |
| 103 | + |
| 104 | + backtest_data = IntradayBacktestData( |
| 105 | + order=order, |
| 106 | + exchange=trade_exchange, |
| 107 | + ticks_index=ticks_index, |
| 108 | + ticks_for_order=ticks_for_order, |
| 109 | + ) |
| 110 | + return backtest_data |
0 commit comments