还没有Tushare账号?注册由此去:官网注册Tushare
本篇为vnpy-tushare-ctp系列文章之一,其他文章请前往:
ubuntu 18.04 安装 vnpy2.0.9 吐血总结
一、缘起
为vnpy制作tushare数据接口,实际上是为了日线级别的均线策略。目前的思路是在每天的9:30分时候策略开始生效,读取之前一天的数据,而这些数据可以通过tushare获取存入数据库。读取到数据之后立马就可以进行计算并产生策略信号。
因为rqdata是付费产品,虽然vnpy官方对于rqdata支持比较好,但对于本屌,最好的还是免费产品。
所以新开坑,在vnpy中使用tushare代替rqdata一部分功能,最终达到日线级别的基于tushare的cta策略运行。
在vnpy的源代码中寻找rqdata,找到/vnpy/app/cta_strategy/engine.py中的
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 ) data = rqdata_client.query_history(req)
这就是cta_strategy调用rqdata的直接入口了。
设想,在这个类中,可以通过另外增加一个参数的方式,从上层指导:到底数据取得是通过米筐还是通过tushare。
二、实现
2.1 tushare获取数据
要想用起tushare,必先获取token。在官网社区注册后到“个人主页”->“接口token”获取。另外,要想获取期货日线数据,现在需要至少200积分。小白有一百,填上个人信息再拉两个人头,积分到达220,就可以用了。
在Ubuntu系统下,安装好的miniconda可以让你舒舒服服地用上python,安装配置过程见前文《ubuntu 18.04 安装 vnpy2.0.9 吐血总结》,此处略过。用pip安装好tushare之后,还要再装一个lxml库,还有bs4,接下来开始写文件读取数据。
import tushare as ts ts.set_token('你的token') pro = ts.pro_api() df = pro.fut_daily(ts_code='CU1811.SHF', start_date='20180101', end_date='20181113') print(df)
这个demo运行正常,之后,我们试图将它以正确的姿势写进数据库。
为什么要写进数据库呢,直接在策略里使用tushare读取的数据不是也挺好吗?使用数据库能够将数据获取与使用分离,可以日后单独将数据获取做得更健壮。
2.2 vnpy的sqlite
vnpy在2020年1月20日正在写这篇文章的时候的最新版本是vnpy-2.0.9,默认的数据库是sqlite3。连接到sqlite,需要找到vnpy的设置文件,用find命令找到了在/hom/han目录下的.vntrader文件夹,在这个文件夹下有vnpy的设置文件(各种.json)和sqlite文件database.db。
sqlite是一个无需配置的轻量数据库,默认情况下连密码都不需要的。我们直接在.vntrader下打开一个终端,运行
sqlite3 database.db
即可打开数据库,之后用.tables命令查看数据库的表,查到有两个,分别是dbbardata和dbtickdata,继续查询表的内容:
select * from dbbardata
终端输出了数据,类似
3878|rb1910|SHFE|2019-10-15 00:00:00|d|7260.0|0.0|3610.0|3650.0|3550.0|3650.0
这样的形式。我们可以把数据的形式弄得好看一点,继续使用命令.header on和.mode column,再次查询表,得到下面的输出:
继续在稍高的层次上操作数据库,下面是从vnpy社区中找到的数据调用分析图:
2.3 在回测引擎中找到数据库插入位置
在更上层的vnpy的app层面,对数据库的调用可以在/app/cta_backtester/engine.py中找到。在run_downloading中,先找到合约,再寻找它在原有数据库中存不存在,如果存在,则直接main_engine.query_history(req, contract.gateway_name),否则就要去米筐那里取数据data = rqdata_client.query_history(req)。取到数据之后进行存储
database_manager.save_bar_data(data)
进行操作就应该在这里把rqdata的语句用tushare加以补充。
仔细地分析vnpy的回测引擎,CtaBacktesterApp可以得到调取数据库操作的途径。我们进行如下操作
from vnpy.event import EventEngine from vnpy.trader.engine import MainEngine from vnpy.app.cta_backtester import CtaBacktesterApp from datetime import datetime def main(): event_engine = EventEngine() main_engine = MainEngine(event_engine) app = CtaBacktesterApp main_engine.add_app(app) back_engine = main_engine.get_engine("CtaBacktester") back_engine.init_engine() vt_symbol = "rb1908.SHFE" interval = "d" start = datetime(2019,6,1) end = datetime(2019,8,31) back_engine.start_downloading(vt_symbol,interval,start,end)
之后,可以看到sqlite数据库增加了rb1908.SHFE的相关记录,证明调用成功。并且,当我们再次运行同样的程序,发现sqlite并没有把重复的数据再插入,重复数据的担心也可以省了。
三、tushare-vnpy综合
3.1 将tushare获取的数据集成到vnpy中,并且放到数据库里面。经过了很多次调试,暂定如下代码。在/vnpy/trader目录下建立tuquery.py文件,输入以下内容:
import tushare as ts from vnpy.trader.object import HistoryRequest,BarData from vnpy.trader.constant import Exchange from datetime import datetime class TushareData: def __init__(self): ts.set_token('你的token') return def exchange_bond(self,exchange:Exchange): if exchange.value == "SHFE": return "SHF" elif exchange.value == "CZCE": return "ZCE" else : return exchange.value def tuquery(self,req:HistoryRequest): symbol = req.symbol exchange = req.exchange interval = req.interval start = req.start.strftime('%Y%m%d') end = req.end.strftime('%Y%m%d') tcode = f'{symbol}'+'.'+ self.exchange_bond(exchange) pro = ts.pro_api(); df = pro.fut_daily(ts_code= tcode, start_date= start, end_date= end) data: List[BarData] = [] if df is not None: for ix, row in df.iterrows(): date = datetime.strptime(row.trade_date,'%Y%m%d') bar = BarData( symbol=symbol, exchange=exchange, interval=interval, datetime=date, open_price=row["open"], high_price=row["high"], low_price=row["low"], close_price=row["close"], volume=row["amount"], gateway_name="TU" ) print(bar) data.append(bar) return data tusharedata = TushareData()
同时在/vnpy/app/cta_backtester目录下找到engine.py,导入包
from vnpy.trader.tuquery import tusharedata
在run_downloading函数下找到“try:”,if……else:这里将原来的
data = rqdata_client.query_history(req)
替换为
tq = tusharedata
data = tq.tuquery(req)
最后在最顶层的主文件中添加调用代码即可:
vt_symbol = "fg1909.CZCE" interval = "d" start = datetime(2019,6,1) end = datetime(2019,8,1) back_engine.start_downloading(vt_symbol,interval,start,end)
我们可以看到,最终在sqlite数据库中,得到了使用tushare获取的数据:
至此,我们已经完成了在vnpy中使用tushare作为数据源进行期货日线级别支持。后面的工作即可提取数据并编制策略,留待后面再续……
四、后记
4.1 rqdata后续
新问题出现了,之前我运行程序一直是在学校,而回到家后,学生试用的账号受到了限制,运行出现了如下错误:
rqdatac.share.errors.PermissionDenied: this license is only allowed to access through the education network
这意味着,我们还没有完全绕过rqdata,我们必须再次进行修改,修改的办法就是将/vnpy/app/cta_backtester/engine.py中的init_engine函数的
self.init_rqdata()
注释掉。
4.2 为数据替换顺序
我们最后插入的数据的顺序与之前vnpy默认的日期顺序是反的,可以在tuquery.py中加入一行,将数据顺序调整过来:
df= df.sort_values( by = 'trade_date', ascending= True)