一、插入数据到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这个文件,没想到这个错误自己消失了。
