• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ricequant / rqalpha / 21424259610

28 Jan 2026 03:51AM UTC coverage: 67.679% (+0.004%) from 67.675%
21424259610

Pull #970

github

DonLin123
fix use symbol to get instrument error
Pull Request #970: fix use symbol to get instrument error

15 of 20 new or added lines in 1 file covered. (75.0%)

56 existing lines in 1 file now uncovered.

7440 of 10993 relevant lines covered (67.68%)

5.36 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.43
/rqalpha/data/base_data_source/data_source.py
1
# -*- coding: utf-8 -*-
2
# 版权所有 2020 深圳米筐科技有限公司(下称“米筐科技”)
3
#
4
# 除非遵守当前许可,否则不得使用本软件。
5
#
6
#     * 非商业用途(非商业用途指个人出于非商业目的使用本软件,或者高校、研究所等非营利机构出于教育、科研等目的使用本软件):
7
#         遵守 Apache License 2.0(下称“Apache 2.0 许可”),
8
#         您可以在以下位置获得 Apache 2.0 许可的副本:http://www.apache.org/licenses/LICENSE-2.0。
9
#         除非法律有要求或以书面形式达成协议,否则本软件分发时需保持当前许可“原样”不变,且不得附加任何条件。
10
#
11
#     * 商业用途(商业用途指个人出于任何商业目的使用本软件,或者法人或其他组织出于任何目的使用本软件):
12
#         未经米筐科技授权,任何个人不得出于任何商业目的使用本软件(包括但不限于向第三方提供、销售、出租、出借、转让本软件、
13
#         本软件的衍生产品、引用或借鉴了本软件功能或源代码的产品或服务),任何法人或其他组织不得出于任何目的使用本软件,
14
#         否则米筐科技有权追究相应的知识产权侵权责任。
15
#         在此前提下,对本软件的使用同样需要遵守 Apache 2.0 许可,Apache 2.0 许可与本许可冲突之处,以本许可为准。
16
#         详细的授权流程,请联系 public@ricequant.com 获取。
17
from collections import defaultdict
8✔
18
import os
8✔
19
from datetime import date, datetime, timedelta
8✔
20
from itertools import chain, repeat
8✔
21
from typing import DefaultDict, Dict, Iterable, List, Mapping, Optional, Sequence, Union, cast, Tuple
8✔
22

23
try:
8✔
24
    from typing import Protocol, runtime_checkable
8✔
25
except ImportError:
1✔
26
    from typing_extensions import Protocol, runtime_checkable
1✔
27

28
import numpy as np
8✔
29
import pandas as pd
8✔
30
import six
8✔
31
from rqalpha.utils.i18n import gettext as _
8✔
32
from rqalpha.const import INSTRUMENT_TYPE, MARKET, TRADING_CALENDAR_TYPE
8✔
33
from rqalpha.interface import AbstractDataSource, ExchangeRate
8✔
34
from rqalpha.model.instrument import Instrument
8✔
35
from rqalpha.utils.datetime_func import (convert_date_to_int, convert_int_to_date, convert_int_to_datetime, convert_dt_to_int)
8✔
36
from rqalpha.utils.exception import RQInvalidArgument
8✔
37
from rqalpha.utils.functools import lru_cache
8✔
38
from rqalpha.utils.typing import DateLike
8✔
39
from rqalpha.utils.logger import system_log
8✔
40
from rqalpha.environment import Environment
8✔
41
from rqalpha.data.base_data_source.adjust import FIELDS_REQUIRE_ADJUSTMENT, adjust_bars
8✔
42
from rqalpha.data.base_data_source.storage_interface import (AbstractCalendarStore, AbstractDateSet,
8✔
43
                                AbstractDayBarStore, AbstractDividendStore,
44
                                AbstractInstrumentStore, AbstractSimpleFactorStore)
45
from rqalpha.data.base_data_source.storages import (DateSet, DayBarStore, DividendStore,
8✔
46
                       ExchangeTradingCalendarStore, FutureDayBarStore,
47
                       FutureInfoStore, ShareTransformationStore, SimpleFactorStore,
48
                       YieldCurveStore, FuturesTradingParameters, load_instruments_from_pkl)
49

50

51
BAR_RESAMPLE_FIELD_METHODS = {
8✔
52
    "open": "first",
53
    "close": "last",
54
    "iopv": "last",
55
    "high": "max",
56
    "low": "min",
57
    "total_turnover": "sum",
58
    "volume": "sum",
59
    "num_trades": "sum",
60
    "acc_net_value": "last",
61
    "unit_net_value": "last",
62
    "discount_rate": "last",
63
    "settlement": "last",
64
    "prev_settlement": "last",
65
    "open_interest": "last",
66
    "basis_spread": "last",
67
    "contract_multiplier": "last",
68
    "strike_price": "last",
69
}
70

71

72
class InstrumentMapView:
8✔
73
    def __init__(self, id_map, sym_map):
8✔
74
        self._id_map = id_map
8✔
75
        self._sym_map = sym_map
8✔
76

77
    def __getitem__(self, key):
8✔
78
        if key in self._id_map:
8✔
79
            return self._id_map[key]
8✔
NEW
UNCOV
80
        if key in self._sym_map:
×
NEW
UNCOV
81
            return self._sym_map[key]
×
NEW
UNCOV
82
        raise KeyError(key)
×
83

84
    def __contains__(self, key):
8✔
85
        return key in self._id_map or key in self._sym_map
8✔
86

87
    def get(self, key, default=None):
8✔
88
        try:
8✔
89
            return self[key]
8✔
NEW
UNCOV
90
        except KeyError:
×
NEW
UNCOV
91
            return default
×
92

93

94
@runtime_checkable
8✔
95
class BaseDataSourceProtocol(Protocol):
8✔
96
    def register_day_bar_store(self, instrument_type: INSTRUMENT_TYPE, store: AbstractDayBarStore, market: MARKET = MARKET.CN) -> None:
2✔
97
        ...
98
    def register_instruments(self, instruments: Iterable[Instrument]) -> None:
2✔
99
        ...
100
    def register_dividend_store(self, instrument_type: INSTRUMENT_TYPE, dividend_store: AbstractDividendStore, market: MARKET = MARKET.CN) -> None:
2✔
101
        ...
102
    def register_split_store(self, instrument_type: INSTRUMENT_TYPE, split_store: AbstractSimpleFactorStore, market: MARKET = MARKET.CN) -> None:
2✔
103
        ...
104
    def register_calendar_store(self, calendar_type: TRADING_CALENDAR_TYPE, calendar_store: AbstractCalendarStore) -> None:
2✔
105
        ...
106
    def register_ex_factor_store(self, instrument_type: INSTRUMENT_TYPE, ex_factor_store: AbstractSimpleFactorStore, market: MARKET = MARKET.CN) -> None:
2✔
107
        ...
108

109

110
class BaseDataSource(AbstractDataSource):
8✔
111
    DEFAULT_INS_TYPES = (
8✔
112
        INSTRUMENT_TYPE.CS, INSTRUMENT_TYPE.FUTURE, INSTRUMENT_TYPE.ETF, INSTRUMENT_TYPE.LOF, INSTRUMENT_TYPE.INDX,
113
        INSTRUMENT_TYPE.PUBLIC_FUND, INSTRUMENT_TYPE.REITs
114
    )
115

116
    def __init__(self, base_config) -> None:
8✔
117
        path = base_config.data_bundle_path
8✔
118
        custom_future_info = getattr(base_config, "future_info", {})
8✔
119
        if not os.path.exists(path):
8✔
120
            raise RuntimeError('bundle path {} not exist'.format(os.path.abspath(path)))
×
121

122
        def _p(name):
8✔
123
            return os.path.join(path, name)
8✔
124
        
125
        # static registered storages
126
        self._future_info_store = FutureInfoStore(_p("future_info.json"), custom_future_info)
8✔
127
        self._yield_curve = YieldCurveStore(_p('yield_curve.h5'))
8✔
128
        self._share_transformation = ShareTransformationStore(_p('share_transformation.json'))
8✔
129
        self._suspend_days = [DateSet(_p('suspended_days.h5'))]  # type: List[AbstractDateSet]
8✔
130
        self._st_stock_days = DateSet(_p('st_stock_days.h5'))
8✔
131

132
        # dynamic registered storages
133
        self._ins_id_or_sym_type_map: Dict[str, INSTRUMENT_TYPE] = {}
8✔
134
        self._day_bar_stores: Dict[Tuple[INSTRUMENT_TYPE, MARKET], AbstractDayBarStore] = {}
8✔
135
        self._dividend_stores: Dict[Tuple[INSTRUMENT_TYPE, MARKET], AbstractDividendStore] = {}
8✔
136
        self._split_stores: Dict[Tuple[INSTRUMENT_TYPE, MARKET], AbstractSimpleFactorStore] = {}
8✔
137
        self._calendar_stores: Dict[TRADING_CALENDAR_TYPE, AbstractCalendarStore] = {}
8✔
138
        self._ex_factor_stores: Dict[Tuple[INSTRUMENT_TYPE, MARKET], AbstractSimpleFactorStore] = {}
8✔
139

140
        # instruments
141
        self._id_instrument_map: DefaultDict[str, dict[datetime, Instrument]] = defaultdict(dict)
8✔
142
        self._sym_instrument_map: DefaultDict[str, dict[datetime, Instrument]] = defaultdict(dict)
8✔
143
        self._id_or_sym_instrument_map: Mapping[str, dict[datetime, Instrument]] = InstrumentMapView(self._id_instrument_map, self._sym_instrument_map)
8✔
144
        self._grouped_instruments: DefaultDict[INSTRUMENT_TYPE, dict[datetime, Instrument]] = defaultdict(dict)
8✔
145

146
        # register instruments
147
        self.register_instruments(load_instruments_from_pkl(_p('instruments.pk'), self._future_info_store))
8✔
148

149
        # register day bar stores
150
        funds_day_bar_store = DayBarStore(_p('funds.h5'))
8✔
151
        for ins_type, store in chain([
8✔
152
            (INSTRUMENT_TYPE.CS, DayBarStore(_p('stocks.h5'))),
153
            (INSTRUMENT_TYPE.INDX, DayBarStore(_p('indexes.h5'))),
154
            (INSTRUMENT_TYPE.FUTURE, FutureDayBarStore(_p('futures.h5'))),
155
        ], zip([INSTRUMENT_TYPE.ETF, INSTRUMENT_TYPE.LOF, INSTRUMENT_TYPE.REITs], repeat(funds_day_bar_store))):
156
            self.register_day_bar_store(ins_type, store)
8✔
157

158
        # register dividends and split factors stores
159
        dividend_store = DividendStore(_p('dividends.h5'))
8✔
160
        split_store = SimpleFactorStore(_p('split_factor.h5'))
8✔
161
        ex_factor_store = SimpleFactorStore(_p('ex_cum_factor.h5'))
8✔
162
        for ins_type in [INSTRUMENT_TYPE.CS, INSTRUMENT_TYPE.ETF, INSTRUMENT_TYPE.LOF, INSTRUMENT_TYPE.REITs]:
8✔
163
            self.register_dividend_store(ins_type, dividend_store)
8✔
164
            self.register_split_store(ins_type, split_store)
8✔
165
            self.register_ex_factor_store(ins_type, ex_factor_store)
8✔
166

167
        # register calendar stores
168
        self.register_calendar_store(TRADING_CALENDAR_TYPE.CN_STOCK, ExchangeTradingCalendarStore(_p("trading_dates.npy")))
8✔
169

170
    def register_day_bar_store(self, instrument_type: INSTRUMENT_TYPE, store: AbstractDayBarStore, market: MARKET = MARKET.CN):
8✔
171
        self._day_bar_stores[instrument_type, market] = store
8✔
172

173
    def register_instruments(self, instruments: Iterable[Instrument]):
8✔
174
        for ins in instruments:
8✔
175
            self._id_instrument_map[ins.order_book_id][ins.listed_date] = ins
8✔
176
            self._sym_instrument_map[ins.symbol][ins.listed_date] = ins
8✔
177
            self._grouped_instruments[ins.type][ins.listed_date] = ins
8✔
178
    
179
    def register_dividend_store(self, instrument_type: INSTRUMENT_TYPE, dividend_store: AbstractDividendStore, market: MARKET = MARKET.CN):
8✔
180
        self._dividend_stores[instrument_type, market] = dividend_store
8✔
181

182
    def register_split_store(self, instrument_type: INSTRUMENT_TYPE, split_store: AbstractSimpleFactorStore, market: MARKET = MARKET.CN):
8✔
183
        self._split_stores[instrument_type, market] = split_store
8✔
184

185
    def register_calendar_store(self, calendar_type: TRADING_CALENDAR_TYPE, calendar_store: AbstractCalendarStore):
8✔
186
        self._calendar_stores[calendar_type] = calendar_store
8✔
187

188
    def register_ex_factor_store(self, instrument_type: INSTRUMENT_TYPE, ex_factor_store: AbstractSimpleFactorStore, market: MARKET = MARKET.CN):
8✔
189
        self._ex_factor_stores[instrument_type, market] = ex_factor_store
8✔
190

191
    def append_suspend_date_set(self, date_set):
8✔
192
        # type: (AbstractDateSet) -> None
193
        self._suspend_days.append(date_set)
×
194

195
    @lru_cache(2048)
8✔
196
    def get_dividend(self, instrument):
7✔
197
        try:
8✔
198
            dividend_store = self._dividend_stores[instrument.type, instrument.market]
8✔
199
        except KeyError:
8✔
200
            return None
8✔
201

202
        return dividend_store.get_dividend(instrument.order_book_id)
8✔
203

204
    def get_trading_minutes_for(self, instrument, trading_dt):
8✔
UNCOV
205
        raise NotImplementedError
×
206

207
    def get_trading_calendars(self) -> Dict[TRADING_CALENDAR_TYPE, pd.DatetimeIndex]:
8✔
208
        return {t: store.get_trading_calendar() for t, store in self._calendar_stores.items()}
8✔
209

210
    def get_instruments(self, id_or_syms: Optional[Iterable[str]] = None, types: Optional[Iterable[INSTRUMENT_TYPE]] = None) -> Iterable[Instrument]:
8✔
211
        if id_or_syms is not None:
8✔
212
            seen = set()
8✔
213
            for i in id_or_syms:
8✔
214
                if i in self._id_or_sym_instrument_map:
8✔
215
                    for ins in self._id_or_sym_instrument_map.get(i, {}).values():
8✔
216
                        if ins not in seen:
8✔
217
                            seen.add(ins)
8✔
218
                            yield ins
8✔
219
        else:
220
            for t in types or self._grouped_instruments.keys():
8✔
221
                yield from self._grouped_instruments[t].values()
8✔
222

223
    def get_share_transformation(self, order_book_id):
8✔
224
        return self._share_transformation.get_share_transformation(order_book_id)
8✔
225

226
    def is_suspended(self, order_book_id: str, dates: Sequence[DateLike]) -> List[bool]:
8✔
227
        for date_set in self._suspend_days:
8✔
228
            result = date_set.contains(order_book_id, dates)
8✔
229
            if result is not None:
8✔
230
                return result
8✔
231
        else:
232
            return [False] * len(dates)
8✔
233

234
    def is_st_stock(self, order_book_id: str, dates: Sequence[DateLike]) -> List[bool]:
8✔
235
        result = self._st_stock_days.contains(order_book_id, dates)
8✔
236
        return result if result is not None else [False] * len(dates)
8✔
237

238
    @lru_cache(None)
8✔
239
    def _all_day_bars_of(self, instrument):
7✔
240
        return self._day_bar_stores[instrument.type, instrument.market].get_bars(instrument.order_book_id)
8✔
241

242
    @lru_cache(None)
8✔
243
    def _filtered_day_bars(self, instrument):
7✔
244
        bars = self._all_day_bars_of(instrument)
8✔
245
        return bars[bars['volume'] > 0]
8✔
246

247
    def get_bar(self, instrument, dt, frequency):
8✔
248
        # type: (Instrument, Union[datetime, date], str) -> Optional[np.ndarray]
249
        if frequency != '1d':
8✔
UNCOV
250
            raise NotImplementedError
×
251

252
        bars = self._all_day_bars_of(instrument)
8✔
253
        if len(bars) <= 0:
8✔
UNCOV
254
            return
×
255
        dt_int = np.uint64(convert_date_to_int(dt))
8✔
256
        pos = bars['datetime'].searchsorted(dt_int)
8✔
257
        if pos >= len(bars) or bars['datetime'][pos] != dt_int:
8✔
UNCOV
258
            return None
×
259

260
        return bars[pos]
8✔
261

262
    OPEN_AUCTION_BAR_FIELDS = ["datetime", "open", "limit_up", "limit_down", "volume", "total_turnover"]
8✔
263

264
    def get_open_auction_bar(self, instrument, dt):
8✔
265
        # type: (Instrument, Union[datetime, date]) -> Dict
266
        day_bar = self.get_bar(instrument, dt, "1d")
8✔
267
        if day_bar is None:
8✔
UNCOV
268
            bar = dict.fromkeys(self.OPEN_AUCTION_BAR_FIELDS, np.nan)
×
269
        else:
270
            bar = {k: day_bar[k] if k in day_bar.dtype.names else np.nan for k in self.OPEN_AUCTION_BAR_FIELDS}
8✔
271
        bar["last"] = bar["open"]  # type: ignore
8✔
272
        return bar
8✔
273

274
    def get_settle_price(self, instrument, date):
8✔
275
        bar = self.get_bar(instrument, date, '1d')
8✔
276
        if bar is None:
8✔
277
            return np.nan
×
278
        return bar['settlement']
8✔
279

280
    @staticmethod
8✔
281
    def _are_fields_valid(fields, valid_fields):
7✔
282
        if fields is None:
8✔
UNCOV
283
            return True
×
284
        if isinstance(fields, six.string_types):
8✔
285
            return fields in valid_fields
8✔
286
        for field in fields:
8✔
287
            if field not in valid_fields:
8✔
UNCOV
288
                return False
×
289
        return True
8✔
290

291
    @lru_cache(1024)
8✔
292
    def get_ex_cum_factor(self, instrument: Instrument):
8✔
293
        try:
8✔
294
            ex_factor_store = self._ex_factor_stores[instrument.type, instrument.market]
8✔
UNCOV
295
        except KeyError:
×
UNCOV
296
            return None
×
297
        factors = ex_factor_store.get_factors(instrument.order_book_id)
8✔
298
        if factors is None:
8✔
299
            return None
×
300
        # 考虑代码复用的情况,需要过滤掉不在上市日期范围内到数据
301
        factors = factors[
8✔
302
            (factors["start_date"] >= convert_dt_to_int(instrument.listed_date)) & 
303
            (factors["start_date"] <= convert_dt_to_int(instrument.de_listed_date))
304
        ]
305
        if len(factors) == 0:
8✔
306
            return None
×
307
        if factors["start_date"][0] != 0:
8✔
308
            # kind of dirty,强行设置初始值为 1
309
            factors = np.concatenate([np.array([(0, 1.0)], dtype=factors.dtype), factors])
8✔
310
        return factors
8✔
311

312
    def _update_weekly_trading_date_index(self, idx):
8✔
313
        env = Environment.get_instance()
×
314
        if env.data_proxy.is_trading_date(idx):
×
UNCOV
315
            return idx
×
UNCOV
316
        return env.data_proxy.get_previous_trading_date(idx)
×
317

318
    def resample_week_bars(self, bars, bar_count: Optional[int], fields: Union[str, List[str]]):
8✔
UNCOV
319
        df_bars: pd.DataFrame = pd.DataFrame(bars)
×
UNCOV
320
        df_bars['datetime'] = df_bars.apply(lambda x: convert_int_to_datetime(x['datetime']), axis=1)
×
UNCOV
321
        df_bars = df_bars.set_index('datetime')
×
UNCOV
322
        nead_fields = fields
×
UNCOV
323
        if isinstance(nead_fields, str):
×
UNCOV
324
            nead_fields = [nead_fields]
×
UNCOV
325
        hows = {field: BAR_RESAMPLE_FIELD_METHODS[field] for field in nead_fields if field in BAR_RESAMPLE_FIELD_METHODS}
×
UNCOV
326
        df_bars = df_bars.resample('W-Fri').agg(hows)  # type: ignore
×
UNCOV
327
        df_bars.index = df_bars.index.map(self._update_weekly_trading_date_index)
×
UNCOV
328
        df_bars = cast(pd.DataFrame, df_bars[~df_bars.index.duplicated(keep='first')])
×
UNCOV
329
        df_bars.sort_index(inplace=True)
×
330
        if bar_count is not None:
×
UNCOV
331
            df_bars = cast(pd.DataFrame, df_bars[-bar_count:])
×
UNCOV
332
        df_bars = df_bars.reset_index()
×
UNCOV
333
        df_bars['datetime'] = df_bars.apply(lambda x: np.uint64(convert_date_to_int(x['datetime'].date())), axis=1)  # type: ignore
×
UNCOV
334
        df_bars = df_bars.set_index('datetime')
×
UNCOV
335
        bars = df_bars.to_records()
×
UNCOV
336
        return bars
×
337

338
    def history_bars(
8✔
339
        self, 
340
        instrument: Instrument, 
341
        bar_count: Optional[int], 
342
        frequency: str, 
343
        fields: Union[str, List[str], None], 
344
        dt: datetime, 
345
        skip_suspended: bool = True,
346
        include_now: bool = False, 
347
        adjust_type: str = 'pre', 
348
        adjust_orig: Optional[datetime] = None
349
    ) -> Optional[np.ndarray]:
350

351
        if frequency != '1d' and frequency != '1w':
8✔
352
            raise NotImplementedError
×
353

354
        if skip_suspended and instrument.type == 'CS':
8✔
355
            bars = self._filtered_day_bars(instrument)
8✔
356
        else:
357
            bars = self._all_day_bars_of(instrument)
8✔
358

359
        if not self._are_fields_valid(fields, bars.dtype.names):
8✔
360
            raise RQInvalidArgument("invalid fields: {}".format(fields))
×
361

362
        if len(bars) <= 0:
8✔
363
            return bars
8✔
364

365
        if frequency == '1w':
8✔
UNCOV
366
            if include_now:
×
367
                i = bars['datetime'].searchsorted(np.uint64(convert_date_to_int(dt)), side='right')
×
368
            else:
369
                monday = dt - timedelta(days=dt.weekday())
×
370
                monday = np.uint64(convert_date_to_int(monday))
×
UNCOV
371
                i = bars['datetime'].searchsorted(monday, side='left')
×
372
            
UNCOV
373
            if bar_count is None:
×
UNCOV
374
                left = 0
×
375
            else:
UNCOV
376
                left = i - bar_count * 5 if i >= bar_count * 5 else 0
×
UNCOV
377
            bars = bars[left:i]
×
378

UNCOV
379
            resample_fields: Union[str, List[str]] = list(bars.dtype.names) if fields is None else fields
×
UNCOV
380
            if adjust_type == 'none' or instrument.type in {'Future', 'INDX'}:
×
381
                # 期货及指数无需复权
382
                week_bars = self.resample_week_bars(bars, bar_count, resample_fields)
×
UNCOV
383
                return week_bars if fields is None else week_bars[fields]
×
384

UNCOV
385
            if isinstance(fields, str) and fields not in FIELDS_REQUIRE_ADJUSTMENT:
×
UNCOV
386
                week_bars = self.resample_week_bars(bars, bar_count, resample_fields)
×
UNCOV
387
                return week_bars if fields is None else week_bars[fields]
×
388

UNCOV
389
            adjust_bars_date = adjust_bars(bars, self.get_ex_cum_factor(instrument),
×
390
                                           fields, adjust_type, adjust_orig)
UNCOV
391
            adjust_week_bars = self.resample_week_bars(adjust_bars_date, bar_count, resample_fields)
×
UNCOV
392
            return adjust_week_bars if fields is None else adjust_week_bars[fields]
×
393
        i = bars['datetime'].searchsorted(np.uint64(convert_date_to_int(dt)), side='right')
8✔
394
        if bar_count is None:
8✔
395
            left = 0
8✔
396
        else:
397
            left = i - bar_count if i >= bar_count else 0
8✔
398
        bars = bars[left:i]
8✔
399
        if adjust_type == 'none' or instrument.type in {'Future', 'INDX'}:
8✔
400
            # 期货及指数无需复权
401
            return bars if fields is None else bars[fields]
8✔
402

403
        if isinstance(fields, str) and fields not in FIELDS_REQUIRE_ADJUSTMENT:
8✔
UNCOV
404
            return bars if fields is None else bars[fields]
×
405

406
        bars = adjust_bars(bars, self.get_ex_cum_factor(instrument),
8✔
407
                           fields, adjust_type, adjust_orig)
408

409
        return bars if fields is None else bars[fields]
8✔
410

411
    def current_snapshot(self, instrument, frequency, dt):
8✔
UNCOV
412
        raise NotImplementedError
×
413

414
    @lru_cache(2048)
8✔
415
    def get_split(self, instrument):
7✔
416
        try:
8✔
417
            splilt_store = self._split_stores[instrument.type, instrument.market]
8✔
418
        except KeyError:
8✔
419
            return None
8✔
420

421
        return splilt_store.get_factors(instrument.order_book_id)
8✔
422

423
    def available_data_range(self, frequency):
8✔
424
        # FIXME
425
        from rqalpha.const import DEFAULT_ACCOUNT_TYPE
8✔
426
        accounts = Environment.get_instance().config.base.accounts
8✔
427
        if not (DEFAULT_ACCOUNT_TYPE.STOCK in accounts or DEFAULT_ACCOUNT_TYPE.FUTURE in accounts):
8✔
428
            return date.min, date.max
8✔
429
        if frequency in ['tick', '1d']:
8✔
430
            s, e = self._day_bar_stores[INSTRUMENT_TYPE.INDX, MARKET.CN].get_date_range('000001.XSHG')
8✔
431
            return convert_int_to_date(s).date(), convert_int_to_date(e).date()
8✔
432

433
    def get_yield_curve(self, start_date, end_date, tenor=None):
8✔
434
        return self._yield_curve.get_yield_curve(start_date, end_date, tenor=tenor)
8✔
435

436
    @lru_cache(1024)
8✔
437
    def get_futures_trading_parameters(self, instrument: Instrument, dt: datetime) -> FuturesTradingParameters:
8✔
438
        return self._future_info_store.get_future_info(instrument.order_book_id, instrument.underlying_symbol)
8✔
439

440
    def get_merge_ticks(self, order_book_id_list, trading_date, last_dt=None):
8✔
UNCOV
441
        raise NotImplementedError
×
442

443
    def history_ticks(self, instrument, count, dt):
8✔
UNCOV
444
        raise NotImplementedError
×
445

446
    def get_algo_bar(self, id_or_ins: Union[str, Instrument], start_min: int, end_min: int, dt: datetime) -> Optional[np.ndarray]:
8✔
UNCOV
447
        raise NotImplementedError("open source rqalpha not support algo order")
×
448

449
    def get_open_auction_volume(self, instrument: Instrument, dt: datetime):
8✔
450
        volume = self.get_open_auction_bar(instrument, dt)['volume']
8✔
451
        return volume
8✔
452

453
    # deprecated
454
    def register_instruments_store(self, instruments_store, market: MARKET = MARKET.CN):
8✔
UNCOV
455
        system_log.warn("register_instruments_store is deprecated, please use register_instruments instead")
×
UNCOV
456
        self.register_instruments(instruments_store.get_instruments(None))
×
457

458
    exchange_rate_1 = ExchangeRate(
8✔
459
        bid_reference=1,
460
        ask_reference=1,
461
        bid_settlement_sh=1,
462
        ask_settlement_sh=1,
463
        bid_settlement_sz=1,
464
        ask_settlement_sz=1
465
    )
466

467
    def get_exchange_rate(self, trading_date: date, local: MARKET, settlement: MARKET = MARKET.CN) -> ExchangeRate:
8✔
468
        if local == settlement:
8✔
469
            return self.exchange_rate_1
8✔
470
        else:
UNCOV
471
            raise NotImplementedError
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc