还没有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)