一、插入数据到MangoDB
代码如下:
# 加载模块 %matplotlib inline import tushare as ts import pymongo from datetime import datetime from vnpy.trader.vtObject import VtBarData from vnpy.trader.app.ctaStrategy.ctaBase import DAILY_DB_NAME # 定义合约代码 symbol = '510050' exchange = 'SSE' vtSymbol = '.'.join([symbol, exchange]) # 下载历史数据 data = ts.get_hist_data(symbol, '2017-01-01') data = data.sort_values("date") print u'数据下载完成' # 创建MongoDB连接 client = pymongo.MongoClient('localhost', 27017) collection = client[DAILY_DB_NAME][vtSymbol] collection.ensure_index('datetime') print u'MongoDB连接成功' # 将数据插入历史数据库 for row in data.iterrows(): date = row[0] data = row[1] bar = VtBarData() bar.vtSymbol = vtSymbol bar.symbol = symbol bar.exchange = exchange bar.date = date bar.datetime = datetime.strptime(date, '%Y-%m-%d') bar.open = data['open'] bar.high = data['high'] bar.low = data['low'] bar.close = data['close'] bar.volume = data['volume'] flt = {'datetime': bar.datetime} collection.update_one(flt, {'$set':bar.__dict__}, upsert=True) print u'数据插入完成'
upset = True,表示有数据,则进行更新。
运行成功后会提示:
数据下载完成
MongoDB连接成功
数据插入完成
不过我又发现如下错误信息:
C:\ProgramData\Anaconda2\lib\site-packages\ipykernel_launcher.py:25: DeprecationWarning: ensure_index is deprecated. Use create_index instead.
二、Mango DB
1.下载Robomongo
官方有两个版本下载,我下载的是Robo 3T。
2.初次使用
初次使用会弹出如下的界面。
3.连接数据库
点击上图中的create按钮,会弹出下面的对话框,点击test看看是否连接成功。
如果连接成功的话,点击“save”就可以看到mangoDB的数据库了。
小提示:
其实这里还可以给MongoDB添加管理员账户,不过要先切换到一个数据库,可以看这里的教程。
三、开发交易策略
# 开发交易策略 import numpy as np from vnpy.trader.app.ctaStrategy.ctaTemplate import CtaTemplate class DoubleMaStrategy(CtaTemplate): """双均线策略Demo""" className = 'DoubleMaStrategy' author = u'用Python的交易员' # 策略参数 initDays = 25 # 初始化数据所用的天数 # 策略变量 barCount = 0 closeArray = np.zeros(20) ma5 = 0 ma20 = 0 lastMa5 = 0 lastMa20 = 0 # 参数列表,保存了参数的名称 paramList = ['name', 'className', 'author', 'vtSymbol'] # 变量列表,保存了变量的名称 varList = ['inited', 'trading', 'pos'] def __init__(self, ctaEngine, setting): """构造函数""" super(DoubleMaStrategy, self).__init__(ctaEngine, setting) # 针对可变对象类型的变量,需要在这里初始化 self.closeArray = np.zeros(20) def onInit(self): """初始化策略(必须由用户继承实现)""" self.writeCtaLog(u'双均线策略初始化') initData = self.loadBar(self.initDays) for bar in initData: self.onBar(bar) self.putEvent() def onStart(self): """启动策略(必须由用户继承实现)""" self.writeCtaLog(u'双均线策略启动') self.putEvent() def onStop(self): """停止策略(必须由用户继承实现)""" self.writeCtaLog(u'双均线策略停止') self.putEvent() def onTick(self, tick): """收到行情TICK推送(必须由用户继承实现)""" # 因为只是展示如何使用框架,这里直接跳过,实盘需要用户基于Tick自行合成K线 pass def onBar(self, bar): """收到Bar推送(必须由用户继承实现)""" # 缓存数据 self.closeArray[0:19] = self.closeArray[1:20] self.closeArray[-1] = bar.close self.barCount += 1 if self.barCount < self.initDays: return # 计算快慢均线 self.ma5 = self.closeArray[15:20].mean() self.ma20 = self.closeArray.mean() # 判断买卖 crossOver = self.ma5>self.ma20 and self.lastMa5<=self.lastMa20 # 金叉上穿 crossBelow = self.ma5<self.ma20 and self.lastMa5>=self.lastMa20 # 死叉下穿 # 金叉和死叉的条件是互斥 # 所有的委托均以K线收盘价委托,为了保证回测成交超价5%发单 if crossOver: # 如果金叉时手头没有持仓,则直接做多 if self.pos == 0: self.buy(bar.close*1.05, 10000) # 如果有空头持仓,则先平空,再做多 elif self.pos < 0: self.cover(bar.close*1.05, 10000) self.buy(bar.close*1.05, 10000) # 死叉和金叉相反 elif crossBelow: if self.pos == 0: self.short(bar.close*0.95, 10000) elif self.pos > 0: self.sell(bar.close*0.95, 10000) self.short(bar.close*0.95, 10000) # 发出状态更新事件 self.putEvent() def onOrder(self, order): """收到委托变化推送(必须由用户继承实现)""" # 对于无需做细粒度委托控制的策略,可以忽略onOrder pass def onTrade(self, trade): """收到成交推送(必须由用户继承实现)""" # 对于无需做细粒度委托控制的策略,可以忽略onOrder pass def onStopOrder(self, so): """停止单推送""" pass
这一步需要在jupyter里运行一下。
四、正式回测
代码
# 加载回测引擎 from vnpy.trader.app.ctaStrategy.ctaBacktesting import BacktestingEngine # 创建回测引擎实例 engine = BacktestingEngine() # 设置引擎的回测模式为K线 engine.setBacktestingMode(engine.BAR_MODE) # 设置回测用的数据起始日期 engine.setStartDate('20170101', initDays=20) # 设置产品相关参数 engine.setSlippage(0) # 滑点设为0 engine.setRate(1.5/10000) # 万1.5 ETF手续费 engine.setSize(1) # ETF每股为1 engine.setPriceTick(0.001) # ETF最小价格变动 engine.setCapital(1) # 为了只统计净盈亏,设置初始资金为1 # 设置使用的历史数据库 engine.setDatabase(DAILY_DB_NAME, vtSymbol) # 在引擎中创建策略对象 engine.initStrategy(DoubleMaStrategy, {}) # 开始跑回测 engine.runBacktesting() # 显示回测结果 engine.showDailyResult()
不过我遇到了以下的报错信息:
C:\ProgramData\Anaconda2\lib\site-packages\vnpy\trader\app\ctaStrategy\ctaBacktesting.py:1017: RuntimeWarning: invalid value encountered in log
df['return'] = (np.log(df['balance']) - np.log(df['balance'].shift(1))).fillna(0)
下面是回测结果:
五、再次回测
因上次回测出现错误,隔几天后,再次回测.
1. 执行jpyter上的“kernel --restart & clear output”。
2. 将第一段代码中的相关代码注释掉:
# 下载历史数据 # data = ts.get_hist_data(symbol, '2017-01-01') # data = data.sort_values("date") print u'数据下载完成' # 创建MongoDB连接 client = pymongo.MongoClient('localhost', 27017) collection = client[DAILY_DB_NAME][vtSymbol] collection.ensure_index('datetime') print u'MongoDB连接成功' # 将数据插入历史数据库 # for row in data.iterrows(): # date = row[0] # data = row[1] # bar = VtBarData() # bar.vtSymbol = vtSymbol # bar.symbol = symbol # bar.exchange = exchange # bar.date = date # bar.datetime = datetime.strptime(date, '%Y-%m-%d') # bar.open = data['open'] # bar.high = data['high'] # bar.low = data['low'] # bar.close = data['close'] # bar.volume = data['volume'] # flt = {'datetime': bar.datetime} # collection.update_one(flt, {'$set':bar.__dict__}, upsert=True) print u'数据插入完成'
3.执行代码
开始也同样出现上面的错误提示,不过后来我想自己编辑ctaBacktesting.py这个文件,没想到这个错误自己消失了。