如下图所示,no ui 模式运行, 策略“貌似”停止,用鼠标触发一下前台界面,才会输出,才会执行下单等操作,导致了一系列错误
下图是使用 datarecorder 记录的 tick 行情数据
下图是使用 datarecorder 模块记录的 1min K 线,可以看到,郑商所的 RM205 没有正常合成 1min K线。
在策略运行时,同样会出现这样的问题,如果是盘后启动,可以正常生成 1min K,不知道是什么原因。
只有郑商所才有这样的问题。
还有个问题,合成 K 线是最好对 tick.volume 进行过滤,否则会生产如下 K 线, 会有 volume = 0 的 K 线,那么预测值等等就会计算出错,可能会发生随机交易等问题。
在该模板中,执行交易时:
假设
self.pos = -2
self.target_pos = 2
按照逻辑,应该是 cover(2) buy(2)
根据模板代码
pos_change = self.target_pos - self.pos = 2 - (-2) = 4
执行交易
if pos_change > 0:
if self.pos < 0:
if pos_chagne < abs(self.pos):
不满足条件
else:
cover(2)
执行后的 self.pos = 0, 与 self.target_pos = 2 不相等
简单说明:
非常感谢楼主,最近也的确遇到了这个问题,反复思考不得其解,在这里看到楼主的帖子柳暗花明。但是,有一个问题,
“还有就是需要有个for_init_system变量,在全部初始化后该变量改为False”, 这一步如何实现呢?如何检测策略全部初始化结束呢?使用计数器还是其他什么方法呢。
或者是,参考楼主的代码,加上这样的循环检测
while for_init_system:
sleep(5)
for strategy in cta_engine.strategies.values():
if strategy.inited == False:
for_init_system = True
break
for_init_system = False
VNPY升级到最新版之后,需要修改部分代码,代码思路同楼主:
from datetime import datetime
from vnpy.trader.rqdata import RqdataClient
from vnpy.trader.object import HistoryRequest
from vnpy.trader.database import database_manager
rqdataClient=RqdataClient()
rqdataClient.init()
updateInfo=[]
barOverViews=database_manager.get_bar_overview()
for barOverView in barOverViews:
#print(f"{barOverView.symbol} start:{barOverView.start} end:{barOverView.end} count:{barOverView.count}")
updateInfo.append((barOverView.symbol,barOverView.exchange,barOverView.end,barOverView.interval))
endDt=datetime.now()
for info in updateInfo:
print(f'更新:{info[0]},Interval:{info[3]}')
req=HistoryRequest(
symbol=info[0],
exchange=info[1],
start=info[2],
end=endDt,
interval=info[3],
)
rData=rqdataClient.query_history(req)
database_manager.save_bar_data(rData)
在量化中,研究策略和实盘交易,都离不开数据。如果要提升回测速度,那么就需要搭建本地数据库。
vn.py对米匡的rqdatac库进行了再次封装调用实现。
实现类: RqdataClient
相关代码: vnpy\trader\rqdata.py
操作步骤:
1) 初始化rqdataClient
2) 构造请求对象
3) 从rqdata获取数据
4) 将数据保存到本地数据库
from vnpy.trader.rqdata import RqdataClient
from vnpy.trader.object import HistoryRequest
#初始化rqdataClient
rqdataClient=RqdataClient()
rqdataClient.init()
#构造请求对象
historyReq=HistoryRequest(
#symbol='C2105.DCE',
symbol='C2105',
exchange=Exchange('DCE'),
start=datetime(2021,1,1),
end=datetime(2021,2,1),
interval=Interval.DAILY
)
#从rqdata获取数据
retData=rqdataClient.query_history(historyReq)
#将数据保存到本地数据库
database_manager.save_bar_data(retData)
对应接口交易接口Gateway类的query_history函数,实现历史数据的下载。这里亿盈透证券(IB)接口为例。
实现类: IbGateway(BaseGateway)
相关代码: vnpy\gateway\ib\ib_gateway.py
通过对象database_manager实现,该对象通过抽象工厂模式,根据实际情况调用具体的数据库实现类:
相关类: BaseDatabase
相关代码
driver: str = SETTINGS["database.driver"]
module_name: str = f"vnpy.database.{driver}"
try:
database_manager: BaseDatabase = import_module(module_name).database_manager
except ModuleNotFoundError:
print(f"找不到数据库驱动{module_name},使用默认的SQLite数据库")
database_manager: BaseDatabase = import_module("vnpy.database.sqlite").database_manager
代码位置: vnpy\trader\database.py
类的具体实现: vnpy\database
为了提高性能,使用MongoDB,因此,只需要关注MongoDB的实现。
相关类: MongodbDatabase(BaseDatabase)
代码位置: vnpy\database\mongodb\mongodb_database.py
在使用monggoDB时,使用了mongoengine的ORM功能,实现了以下三个对象:
demo:获取本地数据库的数据
from datetime import datetime
from vnpy.trader.database import database_manager
from vnpy.trader.object import Interval
from vnpy.trader.constant import Exchange
barDatas=database_manager.load_bar_data(
'C2105',
Exchange('DCE'),
Interval.MINUTE,
start=datetime(2021,1,1),
end=datetime(2021,1,10)
)
for bar in barDatas:
print(f"{bar.datetime} {bar.symbol}:open_price:{bar.open_price}")
barOverViews=database_manager.get_bar_overview()
for barOverView in barOverViews:
print(f"{barOverView.symbol} start:{barOverView.start} end:{barOverView.end} count:{barOverView.count}")
一句话概括:用好database_manager这个对象,提供了如下方法: