自己做量化交易软件(34)小白量化实战7–投资理念与通达信公式回测(2)
投资通俗地讲就是“财富变压器”。投资是使资本和财富生长的源泉。没有证券市场和期货市场时投资者当投出一元钱时,这一元钱资本压死在资产中。但是有了证券市场和期货市场后,这一元钱不仅容易变现流通,而且可以以市盈率的倍数放大。这样搞活和加速了投资频率,因而产生了财富效应。
下面我举个例子,假定一个村庄有10户人家,每户都有一只鸡蛋,鸡蛋的市场价格为1元(原始股),因此每只鸡蛋财富为1元。甲户认为自己的鸡蛋没有用处,以2元价格卖给乙户,2元是市场价,此时每只鸡蛋财富均为2元。丙户以3元价格将鸡蛋卖给丁户,3元是市场价,此时每只鸡蛋财富均为3元。因此鸡蛋持有人能以市场价格3元卖出鸡蛋,乙户卖出自己的2只鸡蛋,获得6元,减去投资成本3元,获利3元。乙户可以认为是投资者,这里的“鸡蛋”,我们可以理解为房子,黄金,或者股票,期货、外汇品种等等。
无论是投资实体物品房产或黄金等,或者虚拟资产证券、期货、外汇等,都是投资。
能不能赚钱,还要看你的眼光和判断,很多投资君子兰、普洱茶等一些方面的投资者都亏损累累,如果他们用那些钱投资房产和茅台酒等,结果将会获利丰厚。
同样投资证券和期货、外汇,也要靠你的眼光和技术判断。现择什么板块?选择什么品种?选择什么时间买卖等等。
前面文章介绍过,投资赚钱的前提要有正确的投资理念,投资方法。我们的投资技术能不能赚钱,我们可以把我们的投资理念和投资技术,用程序实现,用历史行情模拟一遍“真实交易”,这个过程称为"回测"。
下面我们接上一篇文章,我们选出一只股票603260。
我们写出603260的Python回测代码。程序中HL表示原始买点的回测获利结果,HL2表带增量过滤后的买点回测获利结果。
# -*- coding: utf-8 -*-
# 小白量化自编指标回测程序
'''
独狼荷蒲qq:2886002
通通小白python量化群:524949939
tkinter,pyqt,gui,Python交流2群:517029284
微信公众号:独狼股票分析
'''
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import HP_global as g #小白量化全局变量库
from HP_formula import *#小白量化仿通达信库模块
import HP_tdx as htdx #小白量化通达信莫开
import HP_plt as hplt #小白量化指标绘图模块
import HP_sys as hs #小白量化回测系统库
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
#白底色
g.ubg='w'
g.ufg='b'
g.utg='b'
g.uvg='#1E90FF'
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'
df = htdx. get_security_bars(nCategory=4,nMarket = 0,code=code)
#对数据做小白量化格式转换
mydf=df.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['BT']=IF(mydf['b4']>0,1,0)*T #增量买入信号
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) #卖出信号
##回测1
tt=hs.hpQuant() ##初始化类
#下面是用户可设置信息。
#tt.money2=1000000.00 #总资金
#tt.stamp_duty=0.001 #印花税 0.1%
#tt.trading_Commission=0.0005 #交易佣金0.05%
tt.stop_loss_on=True #允许止损
#tt.stop_loss_max=50 #止损3次,就停止交易
tt.stop_loss_range=0.05 #止损幅度
tt.code=code #证券代码,必须输入
tt.stop_loss_on=False #关闭自动止损
#参数表说明:股票数据表,买点序列名称,卖点序列名称,返回获利序列名称
df2=tt.Trade_testing(mydf,'B','S','HL') #开始回测
print('\n打印交易过程')
tt.PrintTrade() #打印交易过程
print('\n打印持仓信息')
tt.PrintSecurity() #打印持仓信息
print('\n 打印内部交易记录信息')
print(tt.text) #打印交易信息
##回测2
tt=hs.hpQuant() ##初始化类
tt.stop_loss_on=True #允许止损
tt.stop_loss_range=0.05 #止损幅度
tt.code=code #证券代码,必须输入
tt.stop_loss_on=False #关闭自动止损
mydf=tt.Trade_testing(df2,'BT','S','HL2') #开始回测
######下面是绘图
#数据裁减
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=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.HL2.plot(color='red', grid='on',legend=True)
mydf.B.plot(color='blue',legend=True)
mydf.S.plot(color='green',legend=True)
#添加标题
plt.title(code+' 获利')
plt.show()
程序运行结果如下:
打印交易过程
date time mode code amount price money
0 2020-05-15 15:00 14:45:01 1 603260 41300.0 24.16 1.693096e+03
1 2020-05-25 15:00 14:45:02 2 603260 41300.0 22.79 9.415083e+05
2 2020-05-28 15:00 14:45:01 1 603260 37300.0 25.20 1.078276e+03
3 2020-06-08 15:00 14:45:02 2 603260 37300.0 24.74 9.224961e+05
4 2020-09-10 15:00 14:45:01 1 603260 32300.0 28.50 1.485798e+03
5 2020-10-22 15:00 14:45:02 2 603260 32300.0 28.34 9.154947e+05
6 2020-10-30 15:00 14:45:01 1 603260 30400.0 30.09 3.013565e+02
7 2020-11-18 15:00 14:45:02 2 603260 30400.0 41.16 1.249688e+06
8 2020-12-21 15:00 14:45:01 1 603260 30600.0 40.80 5.842205e+02
9 2020-12-29 15:00 14:45:02 2 603260 30600.0 32.81 1.003064e+06
10 2021-01-07 15:00 14:45:01 1 603260 27700.0 36.08 3.148534e+03
打印持仓信息
code amount price money
0 603260 27700.0 36.09804 999915.708
打印内部交易记录信息
----开始回测-----
日期:2020-05-15 15:00 买入:41300.0股, 价格:24.16
日期:2020-05-25 15:00 卖出:41300.0股, 价格:22.79获利:-5.85%
日期:2020-05-28 15:00 买入:37300.0股, 价格:25.2
日期:2020-06-08 15:00 卖出:37300.0股, 价格:24.74获利:-7.75%
日期:2020-09-10 15:00 买入:32300.0股, 价格:28.5
日期:2020-10-22 15:00 卖出:32300.0股, 价格:28.34获利:-8.45%
日期:2020-10-30 15:00 买入:30400.0股, 价格:30.09
日期:2020-11-18 15:00 卖出:30400.0股, 价格:41.16获利:24.97%
日期:2020-12-21 15:00 买入:30600.0股, 价格:40.8
日期:2020-12-29 15:00 卖出:30600.0股, 价格:32.81获利:0.31%
日期:2021-01-07 15:00 买入:27700.0股, 价格:36.08
总投入1000000.0,最终获利幅度33.0%
回测图中 橘黄HL曲线不带成交量过滤,红色HL2曲线,含有成交量增量条件,明显过滤掉一些假买点信号。
113均量成交量过滤是不是对所有股票有效呢?不见得,因为主力高度控盘的股票不会有很大成交量的,为证实这些问题,我们可以在小白量化第二代上写成回测代码看看结果。下面代码保存为文件[回测面板_自编指标回测.py],把这个程序放到[xb2/user]目录中。这样,这个文件名会出现在小白量化软件导航树上。
我们可以在回测面板中修改回测参数,例如股票代码和回测开始时间等等。
# -*- coding: utf-8 -*-
"""
#功能:通通股票分析软件框架 回测工具
#版本:Ver1.00
#设计人:独狼荷蒲
#电话:18578755056
#QQ:2775205
#百度:荷蒲指标
#开始设计日期: 2018-07-08
#公众号:独狼股票分析
#使用者请同意最后<版权声明>
#最后修改日期:2021年01月24日
"""
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_sys as hs #小白量化回测系统库
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
ds=g.hcdate_s.get()
de=g.hcdate_e.get()
stockn=g.hcstock.get()
code=stockn
df2=htdx.get_k_data(stockn,ktype='D',start=ds,end=de,index=False,autype='qfq')
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['BT']=IF(mydf['b4']>0,1,0)*T #增量买入信号
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) #卖出信号
##回测1
tt=hs.hpQuant() ##初始化类
#下面是用户可设置信息。
#tt.money2=1000000.00 #总资金
#tt.stamp_duty=0.001 #印花税 0.1%
#tt.trading_Commission=0.0005 #交易佣金0.05%
tt.stop_loss_on=True #允许止损
#tt.stop_loss_max=50 #止损3次,就停止交易
tt.stop_loss_range=0.05 #止损幅度
tt.code=code #证券代码,必须输入
tt.stop_loss_on=False #关闭自动止损
#参数表说明:股票数据表,买点序列名称,卖点序列名称,返回获利序列名称
df2=tt.Trade_testing(mydf,'B','S','HL') #开始回测
print('\n打印交易过程')
tt.PrintTrade() #打印交易过程
print('\n打印持仓信息')
tt.PrintSecurity() #打印持仓信息
print('\n 打印内部交易记录信息')
print(tt.text) #打印交易信息
##回测2
tt=hs.hpQuant() ##初始化类
tt.stop_loss_on=True #允许止损
tt.stop_loss_range=0.05 #止损幅度
tt.code=code #证券代码,必须输入
tt.stop_loss_on=False #关闭自动止损
mydf=tt.Trade_testing(df2,'BT','S','HL2') #开始回测
#数据裁减
m=1
mydf=mydf.tail(150*m).head(150).copy()
g.tabControl.select(g.tab5)
if g.UserCanvas!=None:
g.UserPlot.cla()
g.UserPlot.close()
g.UserCanvas._tkcanvas.pack_forget()
g.UserCanvas=None
######下面是绘图
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
# 开启一个双图例的窗口,定义为211和212
fig=plt.figure(2, figsize=(12,8), dpi=80)
g.UserFig=fig
g.UserPlot=plt
ax1 = plt.subplot(211)
ax2 = plt.subplot(212)
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
# ax1(211窗口)
plt.sca(ax1)
ax_K(ax1,mydf,stockn,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(212窗口)
plt.sca(ax2)
mydf.HL.plot(color='orange', grid='on',legend=True)
mydf.HL2.plot(color='red', grid='on',legend=True)
mydf.B.plot(color='blue',legend=True)
mydf.S.plot(color='green',legend=True)
#添加标题
plt.title(stockn+' 获利')
plt.legend() # 显示图中右上角的提示信息。
ax2.grid(True)
ax2.axhline(0, color='blue')
plt.close()
canvas =FigureCanvasTkAgg(fig, master=g.UserFrame)
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
g.UserCanvas=canvas
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
程序在小白量化中回测结果如下:
是不是与开始的程序结果一样,我们修改股票代码为000155,回测图如下:
输出的信息,要在[工作台]输出窗口看。参见下图。
购买《零基础搭建量化投资系统――以Python为工具》(https://item.jd.com/61567375505.html)一书,就能得到小白量化第二代全部源代码。
请持续关注我的博客,我的进步,就是你的进步!