[关闭]
@Channelchan 2018-11-30T00:09:46.000000Z 字数 6226 阅读 61165

1_doubleMaStrategy


安装方式(release的最新版本):

安装vnpy_fxdayu:

https://github.com/xingetouzi/vnpy_fxdayu

配置引擎参数

  1. from vnpy.trader.app.ctaStrategy import BacktestingEngine
  2. # 创建回测引擎对象
  3. engine = BacktestingEngine()
  4. # 设置回测使用的数据
  5. engine.setBacktestingMode(engine.BAR_MODE) # 设置引擎的回测模式为K线
  6. engine.setDatabase('VnTrader_1Min_Db') # 设置使用的历史数据库
  7. engine.setStartDate('20180901 12:00',initHours=200) # 设置回测用的数据起始日期
  8. engine.setEndDate('20181123 12:00') # 设置回测用的数据终止日期
  9. # 配置回测引擎参数
  10. engine.setSlippage(0.002) # 设置滑点
  11. engine.setRate(5/10000) # 设置手续费千1
  12. engine.setCapital(1000000) # 设置回测本金

策略编写与参数设置

参数与变量的区别: 参数用来传递并且可以优化,变量是随着过程的赋值改变的

CtaTemplate 继承的属性与方法

  1. self.symbolList: 支持多品种以列表格式输入引擎
  2. self.posDict: 可记录多个品种的多空持仓的字典
  3. self.cancelAll(): 取消所有订单
  4. self.getArrayManager(symbol, freq): 数组管理器
  1. """
  2. 这里的Demo是一个最简单的双均线策略实现
  3. """
  4. from __future__ import division
  5. from vnpy.trader.vtConstant import *
  6. from vnpy.trader.app.ctaStrategy import CtaTemplate
  7. import talib as ta
  8. ########################################################################
  9. # 策略继承CtaTemplate
  10. class DoubleMaStrategy(CtaTemplate):
  11. """双指数均线策略Demo"""
  12. className = 'DoubleMaStrategy'
  13. author = 'ChannelCMT'
  14. # 策略参数
  15. fastPeriod = 20 # 快速均线参数
  16. slowPeriod = 55 # 慢速均线参数
  17. lot = 1 # 设置手数
  18. # 策略变量
  19. transactionPrice = {} # 记录成交价格
  20. # 参数列表
  21. paramList = ['fastPeriod',
  22. 'slowPeriod']
  23. # 变量列表
  24. varList = ['transactionPrice']
  25. # 同步列表,保存了需要保存到数据库的变量名称
  26. syncList = ['posDict', 'eveningDict']
  27. #----------------------------------------------------------------------
  28. def __init__(self, ctaEngine, setting):
  29. # 首先找到策略的父类(就是类CtaTemplate),然后把DoubleMaStrategy的对象转换为类CtaTemplate的对象
  30. super().__init__(ctaEngine, setting)
  31. #----------------------------------------------------------------------
  32. def onInit(self):
  33. """初始化策略"""
  34. self.writeCtaLog(u'策略初始化')
  35. self.transactionPrice = {s:0 for s in self.symbolList} # 生成成交价格的字典
  36. self.putEvent()
  37. #----------------------------------------------------------------------
  38. def onStart(self):
  39. """启动策略(必须由用户继承实现)"""
  40. self.writeCtaLog(u'策略启动')
  41. self.putEvent()
  42. #----------------------------------------------------------------------
  43. def onStop(self):
  44. """停止策略"""
  45. self.writeCtaLog(u'策略停止')
  46. self.putEvent()
  47. #----------------------------------------------------------------------
  48. def onTick(self, tick):
  49. """收到行情TICK推送"""
  50. pass
  51. #----------------------------------------------------------------------
  52. def on60MinBar(self, bar):
  53. """收到60分钟Bar推送"""
  54. symbol = bar.vtSymbol
  55. am60 = self.getArrayManager(symbol, "60m") # 获取历史数组
  56. if not am60.inited:
  57. return
  58. # 计算策略需要的信号-------------------------------------------------
  59. fastMa = ta.EMA(am60.close, self.fastPeriod)
  60. slowMa = ta.EMA(am60.close, self.slowPeriod)
  61. crossOver = (fastMa[-1]>slowMa[-1]) and (fastMa[-2]<=slowMa[-2]) # 金叉上穿
  62. crossBelow = (fastMa[-1]<slowMa[-1]) and (fastMa[-2]>=slowMa[-2]) # 死叉下穿
  63. # 构建进出场逻辑-------------------------------------------------
  64. # 如果金叉时手头没有多头持仓
  65. if (crossOver) and (self.posDict[symbol+'_LONG']==0):
  66. # 如果没有空头持仓,则直接做多
  67. if self.posDict[symbol+'_SHORT']==0:
  68. self.buy(symbol, bar.close*1.01, self.lot) # 成交价*1.01发送高价位的限价单,以最优市价买入进场
  69. # 如果有空头持仓,则先平空,再做多
  70. elif self.posDict[symbol+'_SHORT'] > 0:
  71. self.cancelAll() # 撤销挂单
  72. self.cover(symbol, bar.close*1.01, self.posDict[symbol+'_SHORT'])
  73. self.buy(symbol, bar.close*1.01, self.lot)
  74. # 如果金叉时手头没有空头持仓
  75. elif (crossBelow) and (self.posDict[symbol+'_SHORT']==0):
  76. if self.posDict[symbol+'_LONG']==0:
  77. self.short(symbol, bar.close*0.99, self.lot) # 成交价*0.99发送低价位的限价单,以最优市价卖出进场
  78. elif self.posDict[symbol+'_LONG'] > 0:
  79. self.cancelAll() # 撤销挂单
  80. self.sell(symbol, bar.close*0.99, self.posDict[symbol+'_LONG'])
  81. self.short(symbol, bar.close*0.99, self.lot)
  82. # 发出状态更新事件
  83. self.putEvent()
  84. #----------------------------------------------------------------------
  85. def onOrder(self, order):
  86. """收到委托变化推送"""
  87. # 对于无需做细粒度委托控制的策略,可以忽略onOrder
  88. pass
  89. #----------------------------------------------------------------------
  90. def onTrade(self, trade):
  91. """收到成交推送"""
  92. symbol = trade.vtSymbol
  93. if trade.offset == OFFSET_OPEN: # 判断成交订单类型
  94. self.transactionPrice[symbol] = trade.price # 记录成交价格
  95. #----------------------------------------------------------------------
  96. def onStopOrder(self, so):
  97. """停止单推送"""
  98. pass
  1. # 在引擎中创建策略对象
  2. parameterDict = {'symbolList':['EOSUSDT:binance']} # 策略参数配置
  3. engine.initStrategy(DoubleMaStrategy, parameterDict) # 创建策略对象
  4. engine.runBacktesting()
  1. import pandas as pd
  2. tradeReport = pd.DataFrame([obj.__dict__ for obj in engine.tradeDict.values()])
  3. tradeDf = tradeReport.set_index('dt')
  4. tradeDf.tail()

查看绩效回测绩效

  1. # 显示逐日回测结果
  2. 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

output_10_1.png-48.7kB

  1. # 显示逐笔回测结果
  2. 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

output_11_1.png-38.1kB

  1. df = engine.calculateDailyResult()
  2. df1, result = engine.calculateDailyStatistics(df)
2018-11-27 16:38:30.473799  计算按日统计结果
  1. 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
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注