跟我学VNPY 中基于Talib的KDJ量化交易策略实现 -探索更真实的量化交易世界


VNPY的回测过程

新版本的VNPY已经提供了KDJ指标策略,策略文件就存储在strategyfile目录下面,

VNPY开源项目网址:

https://gitee.com/vnpypro/vnpy

  1 # KDJ策略
  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 = [['fastk_period', 3, 5, 1], ['slowk_period', 15, 30, 1], ['slowd_period', 15, 30, 1]]
 13 
 14 
 15 class MyStrategy(module_backtest.VirtualAccount, QtCore.QThread):
 16     def __init__(self, period, slippoint):
 17         super(MyStrategy, self).__init__(period, slippoint)
 18         self.TradingDay = []
 19         self.klinetime = []
 20         self.open = []
 21         self.high = []
 22         self.low = []
 23         self.close = []
 24         self.volume = []
 25         self.money = []
 26         self.open_interest = []
 27         self.InstrumentID = []
 28     def OnTick(self, marketdata, strategyname):
 29         arg = [5, 20, 0, 0, 0, 0]
 30         InstrumentID = str(marketdata.InstrumentID, encoding="utf-8")
 31         kline = VNKlineData()
 32         kline.InstrumentID = marketdata.InstrumentID
 33         # kline.TradingDay = globalvar.md.GetKline(InstrumentID, 1)[0].TradingDay
 34         kline.TradingDay = int(str(globalvar.md.GetKline(InstrumentID, 1)[0].TradingDay, encoding="utf-8")  )
 35         kline.open = globalvar.md.GetKline(InstrumentID, 1)[0].Open
 36         kline.high = globalvar.md.GetKline(InstrumentID, 1)[0].High
 37         kline.low = globalvar.md.GetKline(InstrumentID, 1)[0].Low
 38         kline.close = globalvar.md.GetKline(InstrumentID, 1)[0].Close
 39         kline.volume = globalvar.md.GetKline(InstrumentID, 1)[0].Volume
 40         kline.klinetime = int(globalvar.md.GetKline(InstrumentID, 1)[0].Minutes)
 41         kline.money = 0
 42         kline.open_interest = 0
 43         print(str(kline.TradingDay) + "," +str(kline.open))
 44         self.OnKline(kline, arg, strategyname)
 45         '''
 46         #(1)marketdata 是 实时Tick数据
 47         #(2)这是从CTP Tick由vnctpmd.dll 在本机生成的K线,可以直接按下标方式取得,速度快vnctptd.dll、vnctpmd.py、vnctptd.ini
 48         #(3)这是从服务器获得当日K线取法,禁止频繁调用  vnklineservice.dll、vnklineservice.py、vnklineservice.ini
 49         #(4)这是当前显示K线图数据暂时,数据来自于(2)和(3),策略计算不用这个
 50         globalvar.data_kline_M1[0][globalvar.OPEN]
 51         globalvar.data_kline_M1[0][globalvar.HIGH]
 52         globalvar.data_kline_M1[0][globalvar.LOW]
 53         globalvar.data_kline_M1[0][globalvar.CLOSE]
 54         globalvar.data_kline_M1[0][globalvar.KLINETIME]
 55         globalvar.data_kline_M1[0][globalvar.VOL]
 56         globalvar.md.GetKline(marketdata.InstrumentID, 0).contents.Minutes
 57         str(globalvar.data_kline_M1[0][globalvar.INSTRUMENT], encoding="utf-8")
 58         str(globalvar.data_kline_M1[0][globalvar.TRADINGDAY], encoding="utf-8")
 59         '''
 60 
 61     def OnKline(self, mddata, arg, strategyname):
 62         if arg[0] <= 0 or arg[1] <= 0:
 63             return
 64         # TradingDay = klinedata.TradingDay.decode()
 65         # klinetime = klinedata.klinetime.decode()
 66         self.InstrumentID = mddata.InstrumentID.decode()
 67         # self.exchange=mddata.exchange.decode()
 68         self.close.append(float(mddata.close))
 69         self.high.append(float(mddata.high))
 70         self.low.append(float(mddata.low))
 71         try:
 72             float_close = [float(x) for x in self.close]
 73             float_high = [float(x) for x in self.high]
 74             float_low = [float(x) for x in self.low]
 75         except Exception as e:
 76             pass
 77         # Talib中的STOCH就是KDJ指标,Talib中的SMA就是通达信中的MA,所以结果稍有区别
 78         # 默认参数 9,3,3
 79         K, D = talib.STOCH(np.array(float_high), np.array(float_low), np.array(float_close), fastk_period=arg[0],
 80                            slowk_period=arg[1],
 81                            slowk_matype=0,
 82                            slowd_period=arg[2],
 83                            slowd_matype=0)
 84         # print('结果1:' + str(self.K))
 85         # print('结果2:' + str(self.D))
 86         # print('结果2:' + str(self.J))
 87         thisK = K[len(K) - 1]
 88         thisD = D[len(D) - 1]
 89         # thisJ =  J[len( J) - 1]
 90         if thisK < 50 and thisD < 50 and thisK > thisD:
 91             # 金叉
 92             if self.sellvol + self.sellvol_history > 0:
 93                 self.InsertOrder(self.InstrumentID, '', THOST_FTDC_D_Buy, THOST_FTDC_OF_Close, VN_OPT_LimitPrice,
 94                                  mddata.close + 1, 1)
 95             if self.buyvol + self.buyvol_history < 10:
 96                 self.InsertOrder(self.InstrumentID, '', THOST_FTDC_D_Buy, THOST_FTDC_OF_Open, VN_OPT_LimitPrice,
 97                                  mddata.close + 1, 1)
 98         elif thisK > 50 and thisD > 50 and thisK < thisD:
 99             # 死叉
100             if self.buyvol + self.buyvol_history > 0:
101                 self.InsertOrder(self.InstrumentID, '', THOST_FTDC_D_Sell, THOST_FTDC_OF_Close, VN_OPT_LimitPrice,
102                                  mddata.close - 1, 1)
103             if self.sellvol + self.sellvol_history < 10:
104                 self.InsertOrder(self.InstrumentID, '', THOST_FTDC_D_Sell, THOST_FTDC_OF_Open, VN_OPT_LimitPrice,
105                                  mddata.close - 1, 1)

点击回测,会自动生成回测用的策略文件,在strategyfilebacktest目录下

  1 # KDJ策略
  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 = [['fastk_period', 3, 5, 1], ['slowk_period', 15, 30, 1], ['slowd_period', 15, 30, 1]]
 13 
 14 
 15 class MyStrategy(module_backtest.VirtualAccount, QtCore.QThread):
 16     def __init__(self, period, slippoint):
 17         super(MyStrategy, self).__init__(period, slippoint)
 18         self.TradingDay = []
 19         self.klinetime = []
 20         self.open = []
 21         self.high = []
 22         self.low = []
 23         self.close = []
 24         self.volume = []
 25         self.money = []
 26         self.open_interest = []
 27         self.InstrumentID = []
 28     def OnTick(self, marketdata, strategyname):
 29         arg = [5, 20, 0, 0, 0, 0]
 30         InstrumentID = str(marketdata.InstrumentID, encoding="utf-8")
 31         kline = VNKlineData()
 32         kline.InstrumentID = marketdata.InstrumentID
 33         # kline.TradingDay = globalvar.md.GetKline(InstrumentID, 1)[0].TradingDay
 34         kline.TradingDay = int(str(globalvar.md.GetKline(InstrumentID, 1)[0].TradingDay, encoding="utf-8")  )
 35         kline.open = globalvar.md.GetKline(InstrumentID, 1)[0].Open
 36         kline.high = globalvar.md.GetKline(InstrumentID, 1)[0].High
 37         kline.low = globalvar.md.GetKline(InstrumentID, 1)[0].Low
 38         kline.close = globalvar.md.GetKline(InstrumentID, 1)[0].Close
 39         kline.volume = globalvar.md.GetKline(InstrumentID, 1)[0].Volume
 40         kline.klinetime = int(globalvar.md.GetKline(InstrumentID, 1)[0].Minutes)
 41         kline.money = 0
 42         kline.open_interest = 0
 43         print(str(kline.TradingDay) + "," +str(kline.open))
 44         self.OnKline(kline, arg, strategyname)
 45         '''
 46         #(1)marketdata 是 实时Tick数据
 47         #(2)这是从CTP Tick由vnctpmd.dll 在本机生成的K线,可以直接按下标方式取得,速度快vnctptd.dll、vnctpmd.py、vnctptd.ini
 48         #(3)这是从服务器获得当日K线取法,禁止频繁调用  vnklineservice.dll、vnklineservice.py、vnklineservice.ini
 49         #(4)这是当前显示K线图数据暂时,数据来自于(2)和(3),策略计算不用这个
 50         globalvar.data_kline_M1[0][globalvar.OPEN]
 51         globalvar.data_kline_M1[0][globalvar.HIGH]
 52         globalvar.data_kline_M1[0][globalvar.LOW]
 53         globalvar.data_kline_M1[0][globalvar.CLOSE]
 54         globalvar.data_kline_M1[0][globalvar.KLINETIME]
 55         globalvar.data_kline_M1[0][globalvar.VOL]
 56         globalvar.md.GetKline(marketdata.InstrumentID, 0).contents.Minutes
 57         str(globalvar.data_kline_M1[0][globalvar.INSTRUMENT], encoding="utf-8")
 58         str(globalvar.data_kline_M1[0][globalvar.TRADINGDAY], encoding="utf-8")
 59         '''
 60 
 61     def OnKline(self, mddata, arg, strategyname):
 62         if arg[0] <= 0 or arg[1] <= 0:
 63             return
 64         # TradingDay = klinedata.TradingDay.decode()
 65         # klinetime = klinedata.klinetime.decode()
 66         self.InstrumentID = mddata.InstrumentID.decode()
 67         # self.exchange=mddata.exchange.decode()
 68         self.close.append(float(mddata.close))
 69         self.high.append(float(mddata.high))
 70         self.low.append(float(mddata.low))
 71         try:
 72             float_close = [float(x) for x in self.close]
 73             float_high = [float(x) for x in self.high]
 74             float_low = [float(x) for x in self.low]
 75         except Exception as e:
 76             pass
 77         # Talib中的STOCH就是KDJ指标,Talib中的SMA就是通达信中的MA,所以结果稍有区别
 78         # 默认参数 9,3,3
 79         K, D = talib.STOCH(np.array(float_high), np.array(float_low), np.array(float_close), fastk_period=arg[0],
 80                            slowk_period=arg[1],
 81                            slowk_matype=0,
 82                            slowd_period=arg[2],
 83                            slowd_matype=0)
 84         # print('结果1:' + str(self.K))
 85         # print('结果2:' + str(self.D))
 86         # print('结果2:' + str(self.J))
 87         thisK = K[len(K) - 1]
 88         thisD = D[len(D) - 1]
 89         # thisJ =  J[len( J) - 1]
 90         if thisK < 50 and thisD < 50 and thisK > thisD:
 91             # 金叉
 92             if self.sellvol + self.sellvol_history > 0:
 93                 self.InsertOrder(self.InstrumentID, '', THOST_FTDC_D_Buy, THOST_FTDC_OF_Close, VN_OPT_LimitPrice,
 94                                  mddata.close + 1, 1)
 95             if self.buyvol + self.buyvol_history < 10:
 96                 self.InsertOrder(self.InstrumentID, '', THOST_FTDC_D_Buy, THOST_FTDC_OF_Open, VN_OPT_LimitPrice,
 97                                  mddata.close + 1, 1)
 98         elif thisK > 50 and thisD > 50 and thisK < thisD:
 99             # 死叉
100             if self.buyvol + self.buyvol_history > 0:
101                 self.InsertOrder(self.InstrumentID, '', THOST_FTDC_D_Sell, THOST_FTDC_OF_Close, VN_OPT_LimitPrice,
102                                  mddata.close - 1, 1)
103             if self.sellvol + self.sellvol_history < 10:
104                 self.InsertOrder(self.InstrumentID, '', THOST_FTDC_D_Sell, THOST_FTDC_OF_Open, VN_OPT_LimitPrice,
105                                  mddata.close - 1, 1)