@Channelchan
2018-11-29T16:09:46.000000Z
字数 6226
阅读 61353
安装vnpy_fxdayu:
https://github.com/xingetouzi/vnpy_fxdayu
from vnpy.trader.app.ctaStrategy import BacktestingEngine# 创建回测引擎对象engine = BacktestingEngine()# 设置回测使用的数据engine.setBacktestingMode(engine.BAR_MODE) # 设置引擎的回测模式为K线engine.setDatabase('VnTrader_1Min_Db') # 设置使用的历史数据库engine.setStartDate('20180901 12:00',initHours=200) # 设置回测用的数据起始日期engine.setEndDate('20181123 12:00') # 设置回测用的数据终止日期# 配置回测引擎参数engine.setSlippage(0.002) # 设置滑点engine.setRate(5/10000) # 设置手续费千1engine.setCapital(1000000) # 设置回测本金
参数与变量的区别: 参数用来传递并且可以优化,变量是随着过程的赋值改变的
"""这里的Demo是一个最简单的双均线策略实现"""from __future__ import divisionfrom vnpy.trader.vtConstant import *from vnpy.trader.app.ctaStrategy import CtaTemplateimport talib as ta######################################################################### 策略继承CtaTemplateclass DoubleMaStrategy(CtaTemplate):"""双指数均线策略Demo"""className = 'DoubleMaStrategy'author = 'ChannelCMT'# 策略参数fastPeriod = 20 # 快速均线参数slowPeriod = 55 # 慢速均线参数lot = 1 # 设置手数# 策略变量transactionPrice = {} # 记录成交价格# 参数列表paramList = ['fastPeriod','slowPeriod']# 变量列表varList = ['transactionPrice']# 同步列表,保存了需要保存到数据库的变量名称syncList = ['posDict', 'eveningDict']#----------------------------------------------------------------------def __init__(self, ctaEngine, setting):# 首先找到策略的父类(就是类CtaTemplate),然后把DoubleMaStrategy的对象转换为类CtaTemplate的对象super().__init__(ctaEngine, setting)#----------------------------------------------------------------------def onInit(self):"""初始化策略"""self.writeCtaLog(u'策略初始化')self.transactionPrice = {s:0 for s in self.symbolList} # 生成成交价格的字典self.putEvent()#----------------------------------------------------------------------def onStart(self):"""启动策略(必须由用户继承实现)"""self.writeCtaLog(u'策略启动')self.putEvent()#----------------------------------------------------------------------def onStop(self):"""停止策略"""self.writeCtaLog(u'策略停止')self.putEvent()#----------------------------------------------------------------------def onTick(self, tick):"""收到行情TICK推送"""pass#----------------------------------------------------------------------def on60MinBar(self, bar):"""收到60分钟Bar推送"""symbol = bar.vtSymbolam60 = self.getArrayManager(symbol, "60m") # 获取历史数组if not am60.inited:return# 计算策略需要的信号-------------------------------------------------fastMa = ta.EMA(am60.close, self.fastPeriod)slowMa = ta.EMA(am60.close, self.slowPeriod)crossOver = (fastMa[-1]>slowMa[-1]) and (fastMa[-2]<=slowMa[-2]) # 金叉上穿crossBelow = (fastMa[-1]<slowMa[-1]) and (fastMa[-2]>=slowMa[-2]) # 死叉下穿# 构建进出场逻辑-------------------------------------------------# 如果金叉时手头没有多头持仓if (crossOver) and (self.posDict[symbol+'_LONG']==0):# 如果没有空头持仓,则直接做多if self.posDict[symbol+'_SHORT']==0:self.buy(symbol, bar.close*1.01, self.lot) # 成交价*1.01发送高价位的限价单,以最优市价买入进场# 如果有空头持仓,则先平空,再做多elif self.posDict[symbol+'_SHORT'] > 0:self.cancelAll() # 撤销挂单self.cover(symbol, bar.close*1.01, self.posDict[symbol+'_SHORT'])self.buy(symbol, bar.close*1.01, self.lot)# 如果金叉时手头没有空头持仓elif (crossBelow) and (self.posDict[symbol+'_SHORT']==0):if self.posDict[symbol+'_LONG']==0:self.short(symbol, bar.close*0.99, self.lot) # 成交价*0.99发送低价位的限价单,以最优市价卖出进场elif self.posDict[symbol+'_LONG'] > 0:self.cancelAll() # 撤销挂单self.sell(symbol, bar.close*0.99, self.posDict[symbol+'_LONG'])self.short(symbol, bar.close*0.99, self.lot)# 发出状态更新事件self.putEvent()#----------------------------------------------------------------------def onOrder(self, order):"""收到委托变化推送"""# 对于无需做细粒度委托控制的策略,可以忽略onOrderpass#----------------------------------------------------------------------def onTrade(self, trade):"""收到成交推送"""symbol = trade.vtSymbolif trade.offset == OFFSET_OPEN: # 判断成交订单类型self.transactionPrice[symbol] = trade.price # 记录成交价格#----------------------------------------------------------------------def onStopOrder(self, so):"""停止单推送"""pass
# 在引擎中创建策略对象parameterDict = {'symbolList':['EOSUSDT:binance']} # 策略参数配置engine.initStrategy(DoubleMaStrategy, parameterDict) # 创建策略对象engine.runBacktesting()
import pandas as pdtradeReport = pd.DataFrame([obj.__dict__ for obj in engine.tradeDict.values()])tradeDf = tradeReport.set_index('dt')tradeDf.tail()
# 显示逐日回测结果engine.showDailyResult()
2018-11-27 16:38:28.461857 计算按日统计结果
2018-11-27 16:38:28.481836 ------------------------------
2018-11-27 16:38:28.481836 首个交易日: 2018-09-01 00:00:00
2018-11-27 16:38:28.481836 最后交易日: 2018-11-23 00:00:00
2018-11-27 16:38:28.481836 总交易日: 84
2018-11-27 16:38:28.481836 盈利交易日 39
2018-11-27 16:38:28.481836 亏损交易日: 42
2018-11-27 16:38:28.481836 起始资金: 1000000
2018-11-27 16:38:28.481836 结束资金: 1,000,002.22
2018-11-27 16:38:28.481836 总收益率: 0.0%
2018-11-27 16:38:28.481836 年化收益: 0.0%
2018-11-27 16:38:28.481836 总盈亏: 2.22
2018-11-27 16:38:28.481836 最大回撤: -1.26
2018-11-27 16:38:28.481836 百分比最大回撤: -0.0%
2018-11-27 16:38:28.481836 总手续费: 0.14
2018-11-27 16:38:28.481836 总滑点: 0.1
2018-11-27 16:38:28.482835 总成交金额: 271.25
2018-11-27 16:38:28.482835 总成交笔数: 49
2018-11-27 16:38:28.482835 日均盈亏: 0.03
2018-11-27 16:38:28.482835 日均手续费: 0.0
2018-11-27 16:38:28.482835 日均滑点: 0.0
2018-11-27 16:38:28.482835 日均成交金额: 3.23
2018-11-27 16:38:28.482835 日均成交笔数: 0.58
2018-11-27 16:38:28.482835 日均收益率: 0.0%
2018-11-27 16:38:28.482835 收益标准差: 0.0%
2018-11-27 16:38:28.482835 Sharpe Ratio: 2.21

# 显示逐笔回测结果engine.showBacktestingResult()
2018-11-27 16:38:29.848438 计算回测结果
2018-11-27 16:38:29.854432 ------------------------------
2018-11-27 16:38:29.854432 第一笔交易: 2018-09-05 00:00:00
2018-11-27 16:38:29.854432 最后一笔交易: 2018-11-23 11:58:00
2018-11-27 16:38:29.854432 总交易次数: 25
2018-11-27 16:38:29.854432 总盈亏: 2.21
2018-11-27 16:38:29.854432 最大回撤: -1.02
2018-11-27 16:38:29.854432 平均每笔盈利: 0.09
2018-11-27 16:38:29.854432 平均每笔滑点: 0.0
2018-11-27 16:38:29.854432 平均每笔佣金: 0.01
2018-11-27 16:38:29.854432 胜率 40.0%
2018-11-27 16:38:29.854432 盈利交易平均值 0.44
2018-11-27 16:38:29.854432 亏损交易平均值 -0.15
2018-11-27 16:38:29.854432 盈亏比: 2.99

df = engine.calculateDailyResult()df1, result = engine.calculateDailyStatistics(df)
2018-11-27 16:38:30.473799 计算按日统计结果
print(pd.Series(result)) # 显示绩效指标
annualizedReturn 0.000633478
dailyCommission 0.00161459
dailyNetPnl 0.0263949
dailyReturn 2.63949e-06
dailySlippage 0.00116667
dailyTradeCount 0.583333
dailyTurnover 3.22919
endBalance 1e+06
endDate 2018-11-23 00:00:00
lossDays 42
maxDdPercent -0.000125684
maxDrawdown -1.25684
profitDays 39
returnStd 1.85059e-05
sharpeRatio 2.20961
startDate 2018-09-01 00:00:00
totalCommission 0.135626
totalDays 84
totalNetPnl 2.21717
totalReturn 0.000221717
totalSlippage 0.098
totalTradeCount 49
totalTurnover 271.252
dtype: object