登录  | 立即注册

游客您好!登录后享受更多精彩

QQ登录

只需一步,快速开始

查看: 8593|回复: 0

2022年1月2日新版策略自动生成回测文件功能代码解析

[复制链接]

65

主题

110

帖子

1380

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1380
发表于 2022-1-2 06:24:35 | 显示全部楼层 |阅读模式
VNPY精华帖子列表:https://q.vnpy.cn/comm/thread-18-1-1.html
项目地址: https://gitee.com/vnpypro/vnpy
VNPY官网:https://www.vnpy.cn
快速入门: https://q.vnpy.cn/comm/thread-13-1-1.html

其他参考文章
《快速入门教程》
https://q.vnpy.cn/comm/thread-13-1-1.html
《新版策略自动生成回测文件功能代码解析》
https://q.vnpy.cn/comm/thread-22-1-1.html
《VNPY3.0以后的版本为什么不用数据库设计架构?》
https://q.vnpy.cn/comm/thread-21-1-1.html
《VNPY3.0行情数据调用的5种方式 》
https://q.vnpy.cn/comm/thread-24-1-1.html
《VNPY新手常见问题说明》
https://q.vnpy.cn/comm/thread-3-1-1.html

VNPY官网
https://www.vnpy.cn
VNTA 证券和期货方案
http://www.vnta.cn
《用户福利》
https://www.vnpy.cn/kaihu/

图1 回测效果图

图1 回测效果图


图1: 回测过程



2022年1月2日版本,实现了策略文件生成模块,本文就是介绍回测机制。

在VNPY3.0项目目录下有strategyfile和strategyfilebacktest目录。

strategyfile 是实盘策略文件目录
strategyfilebacktest  是量化回测策略文件目录


在VNPY主界面点击红圈中的“回测”按钮,即可打开图3界面


回测是由module_backtest.py文件实现的


33p.png



图2

图2


图2:VNPY窗口界面


图3

图3



图3:进入到回测界面



其中我们开发策略的时候是修改strategyfile下的策略文件,回测时会自动生成回测专用的策略文件,存在strategyfilebacktest 目录下。



点击上图中的“开始回测”按钮 就会触发转换函数

  1. class DialogBackTest(QtWidgets.QDialog) 类的 GenerateBackTestFile(self)这个方法
复制代码
这样就由strategyfile下的talib_MA.py(实盘策略文件)生成了strategyfilebacktest 目录下的talib_MA.py(量化回测策略文件)



我们看一下这2个策略文件结构上有什么不同,我们以最简单的TALIB MA策略为例,来说明实盘策略代码和量化回测用的代码的区别。

(1)在def __init__(self, period, slippoint):方法内增加了以下代码:

  1.         self.TradingDay = []
  2.         self.klinetime = []
  3.         self.open = []
  4.         self.high = []
  5.         self.low = []
  6.         self.close = []
  7.         self.volume = []
  8.         self.money = []
  9.         self.open_interest = []
  10.         self.InstrumentID = []
复制代码

(2)将

  1. def OnKline(self, mddata, arg, strategyname):
复制代码

改为

  1. def OnKline(self, reportpath1, reportpath2, mddata, arg, strategyname):
复制代码



(3)在def OnKline(self, mddata, arg, strategyname):方法内增加了以下代码:

  1. super(MyStrategy, self).OnKline(reportpath1, reportpath2, arg, mddata)
复制代码


通过以上3处代码自动修改生成了strategyfilebacktest下的同名文件,就实现了量化交易的虚拟账号类来进行仿真柜台结算了,
下面这句表示,该类的父类是module_backtest.py文件里的VirtualAccount类,该类功能就是实现了一个量化回测用的仿真柜台。
  1. class MyStrategy(module_backtest.VirtualAccount, QtCore.QThread):
复制代码


这是实盘用的策略文件代码如下:



  1. # MA策略
  2. import talib
  3. import module_backtest
  4. from vnctptdType661 import *
  5. from PyQt5 import QtCore
  6. # CTP行情库
  7. from vnctpmd import *
  8. import numpy as np
  9. import globalType
  10. import globalvar
  11. # 策略参数定义 '名称,开始值,结束值,步长'
  12. parlist = [['short', 3, 10, 1], ['long', 10, 30, 1]]

  13. class MyStrategy(module_backtest.VirtualAccount, QtCore.QThread):
  14.     def __init__(self, period, slippoint):
  15.         super(MyStrategy, self).__init__(period, slippoint)

  16.     def OnKline(self, mddata, arg, strategyname):
  17.         if arg[0] <= 0 or arg[1] <= 0:
  18.             return
  19.         # TradingDay = klinedata.TradingDay.decode()
  20.         # klinetime = klinedata.klinetime.decode()
  21.         self.InstrumentID = mddata.InstrumentID.decode()
  22.         # self.exchange=mddata.exchange.decode()
  23.         self.close.append(float(mddata.close))
  24.         try:
  25.             float_close = [float(x) for x in self.close]
  26.         except Exception as e:
  27.             pass
  28.         self.MA_A = talib.MA(np.array(float_close), arg[0])
  29.         self.MA_B = talib.MA(np.array(float_close), arg[1])
  30.         # print('结果1:' + str(self.MA5))
  31.         # print('结果2:' + str(self.MA20))
  32.         if self.MA_A[len(self.MA_A) - 1] > self.MA_B[len(self.MA_B) - 1]:
  33.             if self.sellvol + self.sellvol_history > 0:
  34.                 self.InsertOrder(self.InstrumentID, '', THOST_FTDC_D_Buy, THOST_FTDC_OF_Close, VN_OPT_LimitPrice,
  35.                                  mddata.close + 1, 1)
  36.             if self.buyvol + self.buyvol_history < 10:
  37.                 self.InsertOrder(self.InstrumentID, '', THOST_FTDC_D_Buy, THOST_FTDC_OF_Open, VN_OPT_LimitPrice,
  38.                                  mddata.close + 1, 1)
  39.         elif self.MA_A[len(self.MA_A) - 1] < self.MA_B[len(self.MA_B) - 1]:
  40.             if self.buyvol + self.buyvol_history > 0:
  41.                 self.InsertOrder(self.InstrumentID, '', THOST_FTDC_D_Sell, THOST_FTDC_OF_Close, VN_OPT_LimitPrice,
  42.                                  mddata.close - 1, 1)
  43.             if self.sellvol + self.sellvol_history < 10:
  44.                 self.InsertOrder(self.InstrumentID, '', THOST_FTDC_D_Sell, THOST_FTDC_OF_Open, VN_OPT_LimitPrice,
  45.                                  mddata.close - 1, 1)

复制代码


转换后的回测用的策略文件代码如下:

  1. # MA策略
  2. import talib
  3. import module_backtest
  4. from vnctptdType661 import *
  5. from PyQt5 import QtCore
  6. # CTP行情库
  7. from vnctpmd import *
  8. import numpy as np
  9. import globalType
  10. import globalvar
  11. # 策略参数定义 '名称,开始值,结束值,步长'
  12. parlist = [['short', 3, 10, 1], ['long', 10, 30, 1]]

  13. class MyStrategy(module_backtest.VirtualAccount, QtCore.QThread):
  14.     def __init__(self, period, slippoint):
  15.         super(MyStrategy, self).__init__(period, slippoint)
  16.         self.TradingDay = []
  17.         self.klinetime = []
  18.         self.open = []
  19.         self.high = []
  20.         self.low = []
  21.         self.close = []
  22.         self.volume = []
  23.         self.money = []
  24.         self.open_interest = []
  25.         self.InstrumentID = []
  26.     def InsertOrder(self, InstrumentID, exchangeid, direction, offside, VN_OPT_LimitPrice, price, vol):
  27.         self.InsertOrder_backtest(InstrumentID, exchangeid, direction, offside, VN_OPT_LimitPrice, price, vol)

  28.     def OnKline(self, reportpath1, reportpath2, mddata, arg, strategyname):
  29.         super(MyStrategy, self).OnKline(reportpath1, reportpath2, arg, mddata)
  30.         if arg[0] <= 0 or arg[1] <= 0:
  31.             return
  32.         # TradingDay = klinedata.TradingDay.decode()
  33.         # klinetime = klinedata.klinetime.decode()
  34.         self.InstrumentID = mddata.InstrumentID.decode()
  35.         # self.exchange=mddata.exchange.decode()
  36.         self.close.append(float(mddata.close))
  37.         try:
  38.             float_close = [float(x) for x in self.close]
  39.         except Exception as e:
  40.             pass
  41.         self.MA_A = talib.MA(np.array(float_close), arg[0])
  42.         self.MA_B = talib.MA(np.array(float_close), arg[1])
  43.         # print('结果1:' + str(self.MA5))
  44.         # print('结果2:' + str(self.MA20))
  45.         if self.MA_A[len(self.MA_A) - 1] > self.MA_B[len(self.MA_B) - 1]:
  46.             if self.sellvol + self.sellvol_history > 0:
  47.                 self.InsertOrder(self.InstrumentID, '', THOST_FTDC_D_Buy, THOST_FTDC_OF_Close, VN_OPT_LimitPrice,
  48.                                  mddata.close + 1, 1)
  49.             if self.buyvol + self.buyvol_history < 10:
  50.                 self.InsertOrder(self.InstrumentID, '', THOST_FTDC_D_Buy, THOST_FTDC_OF_Open, VN_OPT_LimitPrice,
  51.                                  mddata.close + 1, 1)
  52.         elif self.MA_A[len(self.MA_A) - 1] < self.MA_B[len(self.MA_B) - 1]:
  53.             if self.buyvol + self.buyvol_history > 0:
  54.                 self.InsertOrder(self.InstrumentID, '', THOST_FTDC_D_Sell, THOST_FTDC_OF_Close, VN_OPT_LimitPrice,
  55.                                  mddata.close - 1, 1)
  56.             if self.sellvol + self.sellvol_history < 10:
  57.                 self.InsertOrder(self.InstrumentID, '', THOST_FTDC_D_Sell, THOST_FTDC_OF_Open, VN_OPT_LimitPrice,
  58.                                  mddata.close - 1, 1)


复制代码
















回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|VNPY官方Python开源量化社区 ( 沪ICP备17025576号 )

GMT+8, 2025-2-5 17:39 , Processed in 0.077633 second(s), 26 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表