自己做量化交易軟體(35)小白量化實戰8–事件型回測程式
小白量化第二代程式也提供了一個簡單的事件型回測程式,我們前面的博客文章有介紹這方面的知識,當時用MT5 做的回測演示,見文章:自己做量化交易軟體(26)小白量化事件回測之MetaTrader5自動回測,
這篇文章我簡單的介紹通達信港股行情的回測和A股回測程式,
事件回測程式使用HP_quant模塊,這個模塊定義Context,Data,GlobalVars,
其中GlobalVars存放全域變數,Data存放當前bar或tick的行情資訊,Context存放與賬戶和交易相關資訊,
import HP_quant as hqu #小白量化事件回測
G=hqu.GlobalVars() #用戶全域變數
context = hqu.Context() #創建回測句柄
data = hqu.Data() #創建交易資料
我們利用小白量化HP_tdxex模塊來獲取港股或期貨行情,下面給出港股回測的程式,如果有疑問,可在<零基礎搭建量化投資系統――以Python為工具>讀者群中咨詢,
# encoding:utf-8
'''
## 小白量化事件回測程式--港股回測
#
#購買<零基礎搭建量化投資系統>正版書,送小白量化軟體源代碼,
# https://item.jd.com/61567375505.html
#獨狼荷蒲qq:2775205
#通通python量化群:524949939
#電話微信:18578755056
#微信公眾號:獨狼股票分析
#最后修改日期:2021年01月25日
'''
import datetime
import matplotlib.pyplot as plt
import pandas as pd
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
import HP_global as g
import HP_tdxex as htdxex #小白量化通達信擴展行情
import HP_quant as hqu #小白量化事件回測
import HP_plt as hplt #小白量化指標繪圖模塊
from HP_formula import * #小白公式函式模塊
pd.set_option('display.max_columns', 50) # number of columns to be displayed
pd.set_option('display.width', 1500) # max table width to display
global CLOSE,LOW,HIGH,OPEN,VOL
global C,L,H,O,V
#白底色
g.ubg='w'
g.ufg='b'
g.utg='b'
g.uvg='#1E90FF'
#小白換檔買賣線
def XBHDMMX(N=24,M=2,X=25):
MID =MA(CLOSE,N)
UPPER=MID + 2*STD(CLOSE,N)
LOWER= MID - 2*STD(CLOSE,N)
M1=(UPPER-MID)/2+MID
M2=(MID-LOWER)/2+LOWER
MM1=EMA((OPEN+CLOSE*2+LOW+HIGH)/5,M);
MM2=EMA(IF(MM1>=MID,MM1*(1+X/1000),MM1*(1-X/1000)),3)
MM=MM2
return MID,UPPER,LOWER,M1,M2,MM
G=hqu.GlobalVars() #用戶全域變數
context = hqu.Context() #創建回測句柄
data = hqu.Data() #創建交易資料
code='03690' #回測品種
data.code=code #回測品種
data.price=0.0 #成本價
def initialize(context,df):
print('回測初始化')
context.f1=0.001 #買入傭金
context.f2=0.001 #賣出傭金
context.f3=0.001 #買入印花稅
context.f4=0.00 #賣出印花稅
context.f5=0.00005 #交易費(香港)
context.f6=0.000027 #交易征費(香港)
context.f7=0.00002 #交收費(香港)
context.lot=100 #每手股數
# 定義一個全域變數, 保存要操作的證券
context.stocks = ['03690'] #股票池
context.cash=1000000.00 #初始現金
context.cash2=context.cash #初始現金
context.i=0 #i是起始位置
context.start=0 #i是起始位置
context.end=1500 #i是結束位置
df['date']=[ x for x in df.datetime.astype(str)]
df['time']=[ x[11:16] for x in df.date.astype(str)]
df['mode']=0 #買賣狀態
df['yl']=0 #盈利
df['jz']=context.cash #凈值
print(df)
df2=df[df.minute==0]
df3=df2[df2.hour>=1]
df3=df3.reset_index(level=None, drop=True ,col_level=0, col_fill='')
day=df3.at[len(df3)-1,'day']
context.mydf=df #df資料
context.day= day #當前日期
context.yingli=5.0 #基準盈利
context.kuisun=-10.0 #基準虧損
context.volume=0.00 #持倉量
context.mode=0 #買單狀態0:空倉,1:多單,2:空單
context.end=len(context.mydf) #結束位置
context.start=0 #i是起始位置
context.dc=0.5 #點差
context.price=0.0 #成本價
context.s1=0 #買多次數
context.s2=0 #買空次數
context.s3=0 #平倉次數
context.s4=0 #止損次數
#買
def buy(context, data,volume=0.1):
cash=context.cash
lot=int(cash/(data.close*(1+context.f1+context.f3+context.f5+context.f6+context.f7))/context.lot)
context.volume=lot
context.cash=cash-lot*context.lot*data.close*(1+context.f1+context.f3+context.f5+context.f6+context.f7)
data.price=data.close*(1+context.f1+context.f3+context.f5+context.f6+context.f7)
context.mode=1
context.price=data.price
context.s1=context.s1+1
print('買入',lot,data.price)
#賣
def sell(context, data,volume=0.1):
cash=data.close*(1-context.f1-context.f3-context.f5-context.f6-context.f7)*context.lot*context.volume
context.cash=context.cash+cash
data.price=data.close*(1-context.f2-context.f4-context.f5-context.f6-context.f7)
lot=context.volume
context.price=data.price
context.mode=0
context.volume=0.0
context.s2=context.s2+1
print('賣出',lot,data.price)
#------------------------------------------------------
#開始時間
startTime=datetime.datetime.now()
# 連接行情
global tdxapiex
tdxapiex=htdxex.TdxexInit()
#獲取查詢k線資料
#K線種類
# K 線種類
# 0 - 5 分鐘K 線
# 1 - 15 分鐘K 線
# 2 - 30 分鐘K 線
# 3 - 1 小時K 線
# 4 - 日K 線
# 5 - 周K 線
# 6 - 月K 線
# 7 - 1 分鐘
# 8 - 1 分鐘K 線
# 9 - 日K 線
# 10 - 季K 線
# 11 - 年K 線
KLINE_TYPE_5MIN = 0
KLINE_TYPE_15MIN = 1
KLINE_TYPE_30MIN = 2
KLINE_TYPE_1HOUR = 3
KLINE_TYPE_DAILY = 4
KLINE_TYPE_WEEKLY = 5
KLINE_TYPE_MONTHLY = 6
KLINE_TYPE_EXHQ_1MIN = 7
KLINE_TYPE_1MIN = 8
KLINE_TYPE_RI_K = 9
KLINE_TYPE_3MONTH = 10
KLINE_TYPE_YEARLY = 11
dd2=tdxapiex.get_instrument_bars(KLINE_TYPE_DAILY, 31, "03690", 0, 500)
df2=tdxapiex.to_df(dd2)
#重新建立順序索引
df3=df2.reset_index(level=None, drop=True ,col_level=0, col_fill='')
#對資料做小白量化格式轉換
mydf=df3.copy()
CLOSE=mydf['close']
LOW=mydf['low']
HIGH=mydf['high']
OPEN=mydf['open']
C=mydf['close']
L=mydf['low']
H=mydf['high']
O=mydf['open']
#呼叫自定義指標
MID,UPPER,LOWER,M1,M2,MM=XBHDMMX()
#把指標值添加到mydf資料表中
mydf['MID']=MID
mydf['UPPER']=UPPER
mydf['LOWER']=LOWER
mydf['M1']=M1
mydf['M2']=M2
mydf['MM']=MM
#計算買賣信號
mydf['b1']=CROSS(mydf['MM'],mydf['LOWER'])
mydf['b2']=CROSS(mydf['MM'],mydf['M2'])
mydf['b3']=CROSS(mydf['MM'],mydf['MID'])
mydf['b4']=mydf['b1']+mydf['b2']+mydf['b3']
mydf['B']=IF(mydf['b4']>0,1,0) #買入信號
mydf['s1']=CROSS(mydf['UPPER'],mydf['MM'],)
mydf['s2']=CROSS(mydf['M1'],mydf['MM'],)
mydf['s3']=CROSS(mydf['MID'],mydf['MM'],)
mydf['s4']=mydf['s1']+mydf['s2']+mydf['s3']
mydf['S']=IF(mydf['s4']>0,1,0) #賣出信號
mydf['HL']=0.00 #獲利比例
#策略初始化
initialize(context,mydf)
context.end=len(mydf)
#用戶策略
def handle_data(context,data):
i=context.i
#獲取每個資料的值
df3=context.mydf
day=df3.at[i,'day']
data.day=df3.at[i,'day']
data.high=df3.at[i,'high']
data.low=df3.at[i,'low']
data.open=df3.at[i,'open']
data.time=df3.at[i,'time']
data.close=df3.at[i,'close']
B=df3.at[i,'B']
S=df3.at[i,'S']
#計算買賣
if context.mode==0 and B==1: #買多
buy(context, data)
elif context.mode==1 and S==1: #買空
sell(context, data)
#計算獲利率
context.mydf.at[i,'HL']=(context.cash+context.volume*context.lot*data.close-context.cash2)/context.cash2*100
context.i=i+1 #繼續下一個周期
#開始回測
m=context.end-context.start
#回圈回測
for i in range(context.start,context.end):
context.i=i
handle_data(context,data)
print('當前進度:',(i*100/m),data.day,data.time,'資金: ',context.cash)
print('買多:',context.s1,'買空:',context.s2,'止損:',context.s4,'資金:',context.cash)
print('持倉:', context.volume*context.lot,'現價:',data.close)
print('初始資產:',context.cash2)
print('當前資產:',round(context.cash+context.volume*context.lot*data.close,2))
######下面是繪圖
mydf=context.mydf
#資料裁減
m=1
mydf=mydf.tail(150*m).head(150).copy()
#繪制圖形
plt.figure(1,figsize=(16,12), dpi=80)
#繪制主圖指標
ax1=plt.subplot(311)
hplt.ax_K(ax1,mydf,t=data.code,n=0)
mydf['MID'].plot.line(legend=True)
mydf['UPPER'].plot.line(legend=True,linewidth=3)
mydf['LOWER'].plot.line(legend=True,linewidth=3)
mydf['M1'].plot.line(legend=True)
mydf['M2'].plot.line(legend=True)
mydf['MM'].plot.line(legend=True,linewidth=4)
#繪制副圖指標
ax2=plt.subplot(312)
mydf['MID'].plot.line(legend=True)
mydf['UPPER'].plot.line(legend=True,linewidth=3)
mydf['LOWER'].plot.line(legend=True,linewidth=3)
mydf['M1'].plot.line(legend=True)
mydf['M2'].plot.line(legend=True)
mydf['MM'].plot.line(legend=True,linewidth=4)
ax3=plt.subplot(313)
plt.sca(ax3)
mydf.HL.plot(color='orange', grid='on',legend=True)
mydf.B.plot(color='blue',legend=True)
mydf.S.plot(color='green',legend=True)
#添加標題
plt.title(code+' 獲利')
plt.show()
程式運行結果:
買多: 10 買空: 10 止損: 0 資金: 2342387.8199072722
持倉: 0.0 現價: 399.8000183105469
初始資產: 1000000.0
當前資產: 2342387.82

下面看看A股的回測程式:
# -*- coding: utf-8 -*-
"""
## 小白量化事件回測程式--A股回測
#購買<零基礎搭建量化投資系統>正版書,送小白量化軟體源代碼,
# https://item.jd.com/61567375505.html
#獨狼荷蒲qq:2775205
#通通python量化群:524949939
#電話微信:18578755056
#微信公眾號:獨狼股票分析
#最后修改日期:2021年01月25日
"""
from HP_view import * #選單欄對應的各個子頁面
import pandas as pd
import numpy as np
import datetime as dt
import time
import matplotlib.pyplot as plt
from matplotlib import dates as mdates
from matplotlib import ticker as mticker
#from matplotlib.finance import candlestick_ohlc
from mpl_finance import candlestick_ohlc
from matplotlib.dates import DateFormatter, WeekdayLocator, DayLocator, MONDAY,YEARLY
from matplotlib.dates import MonthLocator,MONTHLY
import matplotlib
from numpy import arange, sin, pi
#from matplotlib.backends.backend_tkagg import FigureCanvasTk,NavigationToolbar2Tk #matplotlib 2.0.2
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk) ##matplotlib 3.0.2
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure
import math
import HP_tdx as htdx
import HP_lib as mylib
from HP_sys import *
import tkinter as tk
import HP_global as g
import HP_data as hp
from HP_formula import *#小白量化仿通達信庫模塊
import HP_tdx as htdx #小白量化通達信莫開
import HP_plt as hplt #小白量化指標繪圖模塊
import HP_quant as hqu #小白量化事件回測
global CLOSE,LOW,HIGH,OPEN,VOL
global C,L,H,O,V
#小白換檔買賣線
def XBHDMMX(N=24,M=2,X=25):
MID =MA(CLOSE,N)
UPPER=MID + 2*STD(CLOSE,N)
LOWER= MID - 2*STD(CLOSE,N)
M1=(UPPER-MID)/2+MID
M2=(MID-LOWER)/2+LOWER
MM1=EMA((OPEN+CLOSE*2+LOW+HIGH)/5,M);
MM2=EMA(IF(MM1>=MID,MM1*(1+X/1000),MM1*(1-X/1000)),3)
MM=MM2
return MID,UPPER,LOWER,M1,M2,MM
htdx.TdxInit(ip='183.60.224.178',port=7709)
#獲取股票行情資料
code='603260'
df2 = htdx. get_security_bars(nCategory=4,nMarket = 0,code=code)
df3=df2
##資料規格化
df3.dropna(inplace=True)
#對資料做小白量化格式轉換
mydf=df3.copy()
CLOSE=mydf['close']
LOW=mydf['low']
HIGH=mydf['high']
OPEN=mydf['open']
VOL=mydf['volume']
C=mydf['close']
L=mydf['low']
H=mydf['high']
O=mydf['open']
V=mydf['volume']
#呼叫自定義指標
MID,UPPER,LOWER,M1,M2,MM=XBHDMMX(34,4,32)
#把指標值添加到mydf資料表中
mydf['MID']=MID
mydf['UPPER']=UPPER
mydf['LOWER']=LOWER
mydf['M1']=M1
mydf['M2']=M2
mydf['MM']=MM
#成交量過濾條件,成交量持續大于113均量線
MAV113=MA(V,113);
T1=IF(REF(V,1)>REF(MAV113,1),1,0);
T2=IF(REF(V,2)>REF(MAV113,2),1,0);
T3=IF(V>MAV113,1,0);
T=IF((T1+T2+T3)>=2,1,0);
mydf['T']=T
mydf['b1']=CROSS(mydf['MM'],mydf['LOWER'])
mydf['b2']=CROSS(mydf['MM'],mydf['M2'])
mydf['b3']=CROSS(mydf['MM'],mydf['MID'])
mydf['b4']=mydf['b1']+mydf['b2']+mydf['b3']
mydf['B']=IF(mydf['b4']>0,1,0) #買入信號
mydf['s1']=CROSS(mydf['UPPER'],mydf['MM'],)
mydf['s2']=CROSS(mydf['M1'],mydf['MM'],)
mydf['s3']=CROSS(mydf['MID'],mydf['MM'],)
mydf['s4']=mydf['s1']+mydf['s2']+mydf['s3']
mydf['S']=IF(mydf['s4']>0,1,0) #賣出信號
G=hqu.GlobalVars() #用戶全域變數
context = hqu.Context() #創建回測句柄
data = hqu.Data() #創建交易資料
data.code=code #回測品種
data.price=0.0 #成本價
def initialize(context,df):
print('回測初始化')
context.f1=0.001 #買入傭金
context.f2=0.001 #賣出傭金
context.f3=0.001 #買入印花稅
context.f4=0.00 #賣出印花稅
context.f5=0.00005 #交易費(香港)
context.f6=0.000027 #交易征費(香港)
context.f7=0.00002 #交收費(香港)
context.lot=100 #每手股數
# 定義一個全域變數, 保存要操作的證券
context.stocks = [] #股票池
context.cash=1000000.00 #初始現金
context.cash2=context.cash #初始現金
context.i=0 #i是起始位置
context.start=0 #i是起始位置
context.end=1500 #i是結束位置
df['mode']=0 #買賣狀態
df['yl']=0 #盈利
df['jz']=context.cash #凈值
context.mydf=df #df資料
context.yingli=5.0 #基準盈利
context.kuisun=-10.0 #基準虧損
context.volume=0.00 #持倉量
context.mode=0 #買單狀態0:空倉,1:多單,2:空單
context.end=len(context.mydf) #結束位置
context.start=0 #i是起始位置
context.dc=0.5 #點差
context.price=0.0 #成本價
context.s1=0 #買多次數
context.s2=0 #買空次數
context.s3=0 #平倉次數
context.s4=0 #止損次數
#買
def buy(context, data,volume=0.1):
cash=context.cash
lot=int(cash/(data.close*(1+context.f1+context.f3))/context.lot)
context.volume=lot
context.cash=cash-lot*context.lot*data.close*(1+context.f1+context.f3+context.f5+context.f6+context.f7)
data.price=data.close*(1+context.f1+context.f3)
context.mode=1
context.price=data.price
context.s1=context.s1+1
print('買入',lot,data.price)
#賣
def sell(context, data,volume=0.1):
cash=data.close*(1-context.f2-context.f4)*context.lot*context.volume
context.cash=context.cash+cash
data.price=data.close*(1-context.f2-context.f4)
lot=context.volume
context.price=data.price
context.mode=0
context.volume=0.0
context.s2=context.s2+1
print('賣出',lot,data.price)
mydf['HL']=0.00 #獲利比例
#策略初始化
initialize(context,mydf)
context.end=len(mydf)
print(mydf)
#用戶策略
def handle_data(context,data):
i=context.i
#獲取每個資料的值
df3=context.mydf
data.high=df3.at[i,'high']
data.low=df3.at[i,'low']
data.open=df3.at[i,'open']
data.close=df3.at[i,'close']
B=df3.at[i,'B']
S=df3.at[i,'S']
#計算買賣
if context.mode==0 and B==1: #買多
buy(context, data)
elif context.mode==1 and S==1: #買空
sell(context, data)
#計算獲利率
context.mydf.at[i,'HL']=(context.cash+context.volume*context.lot*data.close-context.cash2)/context.cash2*100
context.i=i+1 #繼續下一個周期
#開始回測
m=context.end-context.start
#回圈回測
for i in range(context.start,context.end):
context.i=i
handle_data(context,data)
print('當前進度:',(i*100/m),'資金: ',context.cash)
print('買多:',context.s1,'買空:',context.s2,'止損:',context.s4,'資金:',context.cash)
print('持倉:', context.volume*context.lot,'現價:',data.close)
print('初始資產:',context.cash2)
print('當前資產:',round(context.cash+context.volume*context.lot*data.close,2))
######下面是繪圖
mydf=context.mydf
#資料裁減
m=1
mydf=mydf.tail(150*m).head(150).copy()
#繪制圖形
plt.figure(1,figsize=(16,12), dpi=80)
#繪制主圖指標
ax1=plt.subplot(311)
plt.title(code+' 日線圖')
hplt.ax_K(ax1,mydf,t=data.code,n=0)
mydf['MID'].plot.line(legend=True)
mydf['UPPER'].plot.line(legend=True,linewidth=3)
mydf['LOWER'].plot.line(legend=True,linewidth=3)
mydf['M1'].plot.line(legend=True)
mydf['M2'].plot.line(legend=True)
mydf['MM'].plot.line(legend=True,linewidth=4)
#繪制副圖指標
ax2=plt.subplot(312)
mydf['MID'].plot.line(legend=True)
mydf['UPPER'].plot.line(legend=True,linewidth=3)
mydf['LOWER'].plot.line(legend=True,linewidth=3)
mydf['M1'].plot.line(legend=True)
mydf['M2'].plot.line(legend=True)
mydf['MM'].plot.line(legend=True,linewidth=4)
ax3=plt.subplot(313)
plt.sca(ax3)
mydf.HL.plot(color='orange', grid='on',legend=True)
mydf.B.plot(color='blue',legend=True)
mydf.S.plot(color='green',legend=True)
#添加標題
plt.title(code+' 獲利')
plt.show()
程式運行結果:
買多: 6 買空: 5 止損: 0 資金: 2788.6329580013407
持倉: 27500 現價: 46.81
初始資產: 1000000.0
當前資產: 1290063.63
顯示圖形如下:

購買《零基礎搭建量化投資系統――以Python為工具》(https://item.jd.com/61567375505.html)一書,就能得到小白量化第二代全部源代碼,
請持續關注我的博客,我的進步,就是你的進步!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/253043.html
標籤:AI
