[关闭]
@Channelchan 2018-11-28T18:00:31.000000Z 字数 10881 阅读 64606

2_Optimization


BarGenerator内容

  1. 15分钟Bar更新
  2. 60分钟Bar更新

策略逻辑:

60分钟看长短期MA趋势, 15分钟做均线择时。

配置引擎回测

  1. from __future__ import division
  2. from vnpy.trader.vtConstant import *
  3. from vnpy.trader.app.ctaStrategy import CtaTemplate
  4. import talib as ta
  5. ########################################################################
  6. # 策略继承CtaTemplate
  7. class MultiFrameMaStrategy(CtaTemplate):
  8. className = 'MultiFrameMaStrategy'
  9. author = 'ChannelCMT'
  10. # 策略参数
  11. fastPeriod = 20; slowPeriod = 55
  12. signalMaPeriod = 20
  13. lot = 1
  14. # 策略变量
  15. maTrend = {} # 记录趋势状态,多头1,空头-1
  16. transactionPrice = {} # 记录成交价格
  17. # 参数列表,保存了参数的名称
  18. paramList = [
  19. 'fastPeriod', 'slowPeriod',
  20. 'signalMaPeriod'
  21. ]
  22. # 变量列表,保存了变量的名称
  23. varList = [
  24. 'maTrend',
  25. 'transactionPrice'
  26. ]
  27. # 同步列表,保存了需要保存到数据库的变量名称
  28. syncList = ['posDict', 'eveningDict']
  29. #----------------------------------------------------------------------
  30. def __init__(self, ctaEngine, setting):
  31. super().__init__(ctaEngine, setting)
  32. #----------------------------------------------------------------------
  33. def onInit(self):
  34. """初始化策略"""
  35. self.writeCtaLog(u'策略初始化')
  36. self.transactionPrice = {s:0 for s in self.symbolList} # 生成成交价格的字典
  37. self.maTrend = {s:0 for s in self.symbolList}
  38. self.putEvent()
  39. #----------------------------------------------------------------------
  40. def onStart(self):
  41. """启动策略"""
  42. self.writeCtaLog(u'策略启动')
  43. self.putEvent()
  44. #----------------------------------------------------------------------
  45. def onStop(self):
  46. """停止策略"""
  47. self.writeCtaLog(u'策略停止')
  48. self.putEvent()
  49. #----------------------------------------------------------------------
  50. def onTick(self, tick):
  51. """收到行情TICK推送"""
  52. pass
  53. #----------------------------------------------------------------------
  54. def onBar(self, bar):
  55. """收到Bar推送"""
  56. pass
  57. #----------------------------------------------------------------------
  58. def on60MinBar(self, bar):
  59. """收到60MinBar推送"""
  60. symbol = bar.vtSymbol
  61. am60 = self.getArrayManager(symbol, "60m")
  62. if not am60.inited:
  63. return
  64. # 计算均线并判断趋势
  65. fastMa = ta.MA(am60.close, self.fastPeriod)
  66. slowMa = ta.MA(am60.close, self.slowPeriod)
  67. if fastMa[-1] > slowMa[-1]:
  68. self.maTrend[symbol] = 1
  69. else:
  70. self.maTrend[symbol] = -1
  71. #----------------------------------------------------------------------
  72. def on15MinBar(self, bar):
  73. """收到15MinBar推送"""
  74. symbol = bar.vtSymbol
  75. am15 = self.getArrayManager(symbol, "15m")
  76. if not am15.inited:
  77. return
  78. signalMa = ta.EMA(am15.close, self.signalMaPeriod)
  79. maUp = signalMa[-1]>signalMa[-3] # 均线上涨
  80. maDn = signalMa[-1]<signalMa[-3] # 均线下跌
  81. # 均线上涨, 趋势为多头, 多头没有持仓
  82. if maUp and (self.maTrend[symbol]==1) and (self.posDict[symbol+'_LONG']==0):
  83. if (self.posDict[symbol+'_SHORT']==0):
  84. self.buy(symbol, bar.close*1.01, self.lot) # 成交价*1.01发送高价位的限价单,以最优市价买入进场
  85. elif (self.posDict[symbol+'_SHORT'] > 0):
  86. self.cancelAll() # 撤销挂单
  87. self.cover(symbol, bar.close*1.01, self.posDict[symbol+'_SHORT'])
  88. self.buy(symbol, bar.close*1.01, self.lot)
  89. # 均线下跌, 趋势为空头, 空头没有持仓
  90. if maDn and (self.maTrend[symbol]==-1) and (self.posDict[symbol+'_SHORT']==0):
  91. if (self.posDict[symbol+'_LONG']==0):
  92. # self.cancelAll() # 撤销挂单
  93. self.short(symbol, bar.close*0.99, self.lot) # 成交价*0.99发送低价位的限价单,以最优市价卖出进场
  94. elif (self.posDict[symbol+'_LONG'] > 0):
  95. self.cancelAll() # 撤销挂单
  96. self.sell(symbol, bar.close*0.99, self.posDict[symbol+'_LONG'])
  97. self.short(symbol, bar.close*0.99, self.lot)
  98. self.putEvent()
  99. #----------------------------------------------------------------------
  100. def onOrder(self, order):
  101. """收到委托变化推送(必须由用户继承实现)"""
  102. # 对于无需做细粒度委托控制的策略,可以忽略onOrder
  103. pass
  104. #----------------------------------------------------------------------
  105. def onTrade(self, trade):
  106. """收到成交推送(必须由用户继承实现)"""
  107. # 对于无需做交易信息记录的策略,可以忽略onTrade
  108. pass
  109. #----------------------------------------------------------------------
  110. def onStopOrder(self, so):
  111. """停止单推送"""
  112. pass

配置引擎回测

  1. if __name__=="__main__":
  2. from vnpy.trader.app.ctaStrategy import BacktestingEngine
  3. # 创建回测引擎对象
  4. engine = BacktestingEngine()
  5. # 设置回测使用的数据
  6. engine.setBacktestingMode(engine.BAR_MODE) # 设置引擎的回测模式为K线
  7. engine.setDatabase('VnTrader_1Min_Db') # 设置使用的历史数据库
  8. engine.setStartDate('20180901 12:00',initHours=200) # 设置回测用的数据起始日期
  9. engine.setEndDate('20181123 12:00') # 设置回测用的数据终止日期
  10. # 配置回测引擎参数
  11. engine.setSlippage(0.002) # 设置滑点
  12. engine.setRate(5/10000) # 设置手续费千1
  13. engine.setCapital(1000000) # 设置回测本金
  14. # # 在引擎中创建策略对象
  15. parameterDict = {'symbolList':['BTCUSDT:binance']} # 策略参数配置
  16. engine.initStrategy(MultiFrameMaStrategy, parameterDict) # 创建策略对象
  17. 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:39:28.106324  计算按日统计结果
2018-11-27 16:39:28.125304  ------------------------------
2018-11-27 16:39:28.125304  首个交易日:  2018-09-01 00:00:00
2018-11-27 16:39:28.125304  最后交易日:  2018-11-23 00:00:00
2018-11-27 16:39:28.125304  总交易日:   84
2018-11-27 16:39:28.125304  盈利交易日   54
2018-11-27 16:39:28.125304  亏损交易日:  29
2018-11-27 16:39:28.125304  起始资金:   1000000
2018-11-27 16:39:28.125304  结束资金:   1,003,343.23
2018-11-27 16:39:28.125304  总收益率:   0.33%
2018-11-27 16:39:28.125304  年化收益:   0.96%
2018-11-27 16:39:28.125304  总盈亏:    3,343.23
2018-11-27 16:39:28.125304  最大回撤:   -308.75
2018-11-27 16:39:28.125304  百分比最大回撤: -0.03%
2018-11-27 16:39:28.125304  总手续费:   230.16
2018-11-27 16:39:28.125304  总滑点:    0.14
2018-11-27 16:39:28.125304  总成交金额:  460,323.2
2018-11-27 16:39:28.125304  总成交笔数:  71
2018-11-27 16:39:28.125304  日均盈亏:   39.8
2018-11-27 16:39:28.125304  日均手续费:  2.74
2018-11-27 16:39:28.125304  日均滑点:   0.0
2018-11-27 16:39:28.125304  日均成交金额: 5,480.04
2018-11-27 16:39:28.125304  日均成交笔数: 0.85
2018-11-27 16:39:28.125304  日均收益率:  0.0%
2018-11-27 16:39:28.125304  收益标准差:  0.01%
2018-11-27 16:39:28.125304  Sharpe Ratio:   4.24

output_7_1.png-52.8kB

  1. # 显示逐笔回测结果
  2. engine.showBacktestingResult()
2018-11-27 16:39:29.634764  计算回测结果
2018-11-27 16:39:29.637760  ------------------------------
2018-11-27 16:39:29.638759  第一笔交易:  2018-09-05 22:00:00
2018-11-27 16:39:29.638759  最后一笔交易: 2018-11-23 11:58:00
2018-11-27 16:39:29.638759  总交易次数:  36
2018-11-27 16:39:29.638759  总盈亏:    3,341.06
2018-11-27 16:39:29.638759  最大回撤:   -254.65
2018-11-27 16:39:29.638759  平均每笔盈利: 92.81
2018-11-27 16:39:29.638759  平均每笔滑点: 0.0
2018-11-27 16:39:29.638759  平均每笔佣金: 6.45
2018-11-27 16:39:29.638759  胜率      36.11%
2018-11-27 16:39:29.638759  盈利交易平均值 339.84
2018-11-27 16:39:29.638759  亏损交易平均值 -46.82
2018-11-27 16:39:29.638759  盈亏比:    7.26

output_8_1.png-37.5kB

  1. df = engine.calculateDailyResult()
  2. df1, result = engine.calculateDailyStatistics(df)
  3. print(pd.Series(result))
2018-11-27 16:39:30.319064  计算按日统计结果
annualizedReturn               0.955208
dailyCommission                 2.74002
dailyNetPnl                     39.8003
dailyReturn                  0.00384366
dailySlippage                0.00169048
dailyTradeCount                0.845238
dailyTurnover                   5480.04
endBalance                  1.00334e+06
endDate             2018-11-23 00:00:00
lossDays                             29
maxDdPercent                 -0.0308648
maxDrawdown                    -308.747
profitDays                           54
returnStd                     0.0140566
sharpeRatio                     4.23614
startDate           2018-09-01 00:00:00
totalCommission                 230.162
totalDays                            84
totalNetPnl                     3343.23
totalReturn                    0.334323
totalSlippage                     0.142
totalTradeCount                      71
totalTurnover                    460323
dtype: object
  1. from vnpy.trader.app.ctaStrategy.ctaBacktesting import OptimizationSetting
  2. # 优化配置
  3. setting = OptimizationSetting() # 新建一个优化任务设置对象
  4. setting.setOptimizeTarget('sharpeRatio') # 设置优化排序的目标是夏普
  5. setting.addParameter('fastPeriod', 20, 40, 10) # 增加第一个优化参数,起始30,结束50,步进10
  6. setting.addParameter('slowPeriod', 40, 80, 20) # 增加第二个优化参数,起始60,结束30,步进10
  7. # setting.addParameter('signalMaPeriod', 10, 20, 5) # 增加第二个优化参数,起始10,结束30,步进5
  8. setting.addParameter('symbolList', ['BTCUSDT:binance'])
  9. import time
  10. start = time.time()
  11. # 执行单线程优化
  12. resultList = engine.runOptimization(MultiFrameMaStrategy, setting)
  13. # 执行多进程优化一般会改写成py文件然后用多线程运行,提高优化速度。
  14. # resultList = engine.runParallelOptimization(MultiFrameMaStrategy, setting)
  15. print('耗时:%s' %(time.time()-start))
2018-11-27 16:42:45.230052  计算按日统计结果
2018-11-27 16:42:45.247034  ------------------------------
2018-11-27 16:42:45.247034  优化结果:
2018-11-27 16:42:45.247034  参数:["{'fastPeriod': 20, 'slowPeriod': 40, 'symbolList': ['BTCUSDT:binance']}"],目标:3.8373178980181555
2018-11-27 16:42:45.247034  参数:["{'fastPeriod': 20, 'slowPeriod': 60, 'symbolList': ['BTCUSDT:binance']}"],目标:3.7506375116750355
2018-11-27 16:42:45.247034  参数:["{'fastPeriod': 30, 'slowPeriod': 40, 'symbolList': ['BTCUSDT:binance']}"],目标:3.6425674453940045
2018-11-27 16:42:45.247034  参数:["{'fastPeriod': 20, 'slowPeriod': 80, 'symbolList': ['BTCUSDT:binance']}"],目标:3.5332416281547103
2018-11-27 16:42:45.247034  参数:["{'fastPeriod': 40, 'slowPeriod': 40, 'symbolList': ['BTCUSDT:binance']}"],目标:3.117938276707989
2018-11-27 16:42:45.247034  参数:["{'fastPeriod': 30, 'slowPeriod': 80, 'symbolList': ['BTCUSDT:binance']}"],目标:2.9456588639684242
2018-11-27 16:42:45.247034  参数:["{'fastPeriod': 30, 'slowPeriod': 60, 'symbolList': ['BTCUSDT:binance']}"],目标:2.919579847922548
2018-11-27 16:42:45.247034  参数:["{'fastPeriod': 40, 'slowPeriod': 60, 'symbolList': ['BTCUSDT:binance']}"],目标:2.6339188082989096
2018-11-27 16:42:45.247034  参数:["{'fastPeriod': 40, 'slowPeriod': 80, 'symbolList': ['BTCUSDT:binance']}"],目标:2.458459639228935
耗时:160.99369764328003

打印最优结果排序的DataFrame

  1. import pandas as pd
  2. print(pd.DataFrame(resultList).sort_values(1, ascending=False))
                                                   0         1  \
0  [{'fastPeriod': 20, 'slowPeriod': 40, 'symbolL...  3.837318   
1  [{'fastPeriod': 20, 'slowPeriod': 60, 'symbolL...  3.750638   
2  [{'fastPeriod': 30, 'slowPeriod': 40, 'symbolL...  3.642567   
3  [{'fastPeriod': 20, 'slowPeriod': 80, 'symbolL...  3.533242   
4  [{'fastPeriod': 40, 'slowPeriod': 40, 'symbolL...  3.117938   
5  [{'fastPeriod': 30, 'slowPeriod': 80, 'symbolL...  2.945659   
6  [{'fastPeriod': 30, 'slowPeriod': 60, 'symbolL...  2.919580   
7  [{'fastPeriod': 40, 'slowPeriod': 60, 'symbolL...  2.633919   
8  [{'fastPeriod': 40, 'slowPeriod': 80, 'symbolL...  2.458460   

                                                   2  
0  {'startDate': 2018-09-01 00:00:00, 'endDate': ...  
1  {'startDate': 2018-09-01 00:00:00, 'endDate': ...  
2  {'startDate': 2018-09-01 00:00:00, 'endDate': ...  
3  {'startDate': 2018-09-01 00:00:00, 'endDate': ...  
4  {'startDate': 2018-09-01 00:00:00, 'endDate': ...  
5  {'startDate': 2018-09-01 00:00:00, 'endDate': ...  
6  {'startDate': 2018-09-01 00:00:00, 'endDate': ...  
7  {'startDate': 2018-09-01 00:00:00, 'endDate': ...  
8  {'startDate': 2018-09-01 00:00:00, 'endDate': ...  
  1. # 显示优化的所有统计数据
  2. for result in resultList:
  3. print('-' * 30)
  4. print('参数:%s,目标:%s' %(result[0], result[1]))
  5. print('统计数据:')
  6. for k, v in result[2].items():
  7. print('%s:%s' %(k, v))
  ------------------------------
参数:["{'fastPeriod': 20, 'slowPeriod': 40, 'symbolList': ['BTCUSDT:binance']}"],目标:3.8373178980181555
统计数据:
startDate:2018-09-01 00:00:00
endDate:2018-11-23 00:00:00
totalDays:84
profitDays:43
lossDays:40
endBalance:1002162.8486499999
maxDrawdown:-800.1604799999623
maxDdPercent:-0.0802844900912358
totalNetPnl:2162.8486499999967
dailyNetPnl:25.748198214285676
totalCommission:366.11134999999996
dailyCommission:4.358468452380952
totalSlippage:0.23000000000000015
dailySlippage:0.00273809523809524
totalTurnover:732222.7000000001
dailyTurnover:8716.936904761906
totalTradeCount:115
dailyTradeCount:1.369047619047619
totalReturn:0.21628486500000488
annualizedReturn:0.617956757142871
dailyReturn:0.009231223526044257
returnStd:0.037268087692137686
sharpeRatio:3.8373178980181555
------------------------------
参数:["{'fastPeriod': 20, 'slowPeriod': 60, 'symbolList': ['BTCUSDT:binance']}"],目标:3.7506375116750355
统计数据:
startDate:2018-09-01 00:00:00
endDate:2018-11-23 00:00:00
totalDays:84
profitDays:50
lossDays:32
endBalance:1002955.52815
maxDrawdown:-312.15648999996483
maxDdPercent:-0.031176176911619793
totalNetPnl:2955.528149999998
dailyNetPnl:35.1848589285714
totalCommission:216.72784999999996
dailyCommission:2.580093452380952
totalSlippage:0.13400000000000006
dailySlippage:0.001595238095238096
totalTurnover:433455.70000000007
dailyTurnover:5160.186904761906
totalTradeCount:67
dailyTradeCount:0.7976190476190477
totalReturn:0.29555281499999975
annualizedReturn:0.8444366142857136
dailyReturn:0.0033835644182150003
returnStd:0.013975745298525763
sharpeRatio:3.7506375116750355
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注