首先个人推荐使用第三方数据源,如果数据源质量有保证的话。
如果启动第三方数据源,在cta策略启动时候,会从数据源下载load_bar所需要的预期的数据,看策略需求,下载日期或长或短。
如果策略较少没关系,如果策略较多,尤其是同一合约有多个策略时候,每次启动就花费非常多时间,而且很多是重复下载,比如如果有多个螺纹钢策略,就要下载多次螺纹钢数据,还是不太方法。
这里思路很简单,策略启动时候,对比启动需要数据是否在数据库内,如果有使用数据库数据,如果没有,下载再使用。
对比是按照需要数据的开始结束和数据库内bar overview表的开始和结束。查询结束时候可能大于bar结束时候,比如下午8点半启动,但是bar结束数据是下午3点;这样可能有差异取读取,想想为了安全,冗余一些没有关系。
代码如下,只要用这个替代cta_engine里面同名方法即可。这个是基于vntrade 2.3 的,2.6 的版本,改query_bar_from_datafeed即可
from vnpy.trader.database import database_manager
from tzlocal import get_localzone
LOCAL_TZ = get_localzone()
def query_bar_from_rq(
self, symbol: str, exchange: Exchange, interval: Interval, start: datetime, end: datetime
):
"""
Query bar data from RQData.
"""
req = HistoryRequest(
symbol=symbol,
exchange=exchange,
interval=interval,
start=start,
end=end
)
bar_start = None
bar_end = None
bar_overview_list = database_manager.get_bar_overview()
for bar_overview in bar_overview_list:
if bar_overview.symbol == symbol and bar_overview.exchange == exchange and bar_overview.interval == interval:
bar_start = bar_overview.start.astimezone(LOCAL_TZ)
bar_end = bar_overview.end.astimezone(LOCAL_TZ)
if bar_start <= start:
req = HistoryRequest(
symbol=symbol,
exchange=exchange,
interval=interval,
start= bar_end,
end=end + timedelta(minutes=1)
)
data = rqdata_client.query_history(req)
if data:
database_manager.save_bar_data(data)
if bar_end:
self.write_log(f"{symbol}.{exchange}-{interval.value},数据库已有 {bar_start} 到 {bar_end}数据,从 {bar_end} 到{end}历史数据下载完成")
else:
self.write_log(
f"{symbol}.{exchange}-{interval.value},从 {start} 到{end}历史数据下载完成")
else:
if bar_end:
self.write_log(f"{symbol}.{exchange}-{interval.value},数据库已有 {bar_start} 到 {bar_end}数据,从 {bar_end} 到{end}或无历史数据")
else:
self.write_log(
f"{symbol}.{exchange}-{interval.value},从 {start} 到{end}历史数据下载失败")
bars = database_manager.load_bar_data(
symbol=symbol,
exchange=exchange,
interval=interval,
start=start,
end=end,
)
return bars