股票量化-双均线策略

炒股的人通常都喜欢各种技术指标,来指定买卖策略,然而我们却经常看到股民们亏钱,难道是这些指标有问题吗?还是专家在忽悠股民朋友们?将以非常简单的均线指标为例,来挖掘其在一只股票上的绩效潜力。

实现流程的简单梳理

1.读取数据,了解数据的结构
2.对读取的数据进行清洗,使数据符合进一步分析
3.计算相应的股票日涨跌幅度
4.通过画图来展示:
a.基于回测资金曲线
b.股票k线图
c.参数优化的热力图

读取数据

注意事项:

pd.read_excel()有两个设置参数,分别是:
1.parse_dates:是指将指定列转化为时间类型格式,注意是列表形式指定列[“交易日期”]
2.index_cel:是指将指定列变为行索引index

# 导包
import pandas as pd
df = pd.read_excel("sz002115",parse_dates=["加油日期"],index_cel="交易日期")

在这里插入图片描述

为什么要设置"交易日期"列为datetime数据类型?

主要是后面的作图,直接传入时间数据为y轴,用str数据类型,有可能不会被识别.

最后我们查看一下数据的基本构造,看数据是否有空值,是否需要填充

df.info()

在这里插入图片描述

股票涨跌幅/涨跌停/复权计算

概念解析

1.股票涨跌幅:股票每天相对的昨日收盘价的涨跌幅
2.股票涨跌停价格:股票每一天的涨停价,跌停价
3.复权:把复权简单理解为就是排除送股,配股,分红等影响因素。

计算股票涨跌幅

df["涨跌幅"] = df["收盘价"]/df["前收盘价"]-1

注意事项

使用前收盘价,而非用开盘价,是为了避免因为送股,配股,分红等影响因素的股价不合理变化.

计算股票涨跌停

df["涨停价"] = df["前收盘价"]*1.1
df["跌停价"] = df["前收盘价"]*0.8

计算股票后复权价格

概念解析

前复权处理:股票最近一天价格不变,之前数据按照真实日涨跌幅做调整;

后复权处理:股票上市第一天价格不变,之后数据按照真实日涨跌幅做调整;(后复权类似于基金净值的统计)

计算股票资金曲线

所谓资金曲线,即把股票上市第一天的净值设为1,之后每天净值随真实日涨跌幅波动的曲线
1+涨跌幅 我们的到的是涨跌比例,我们把每一天的涨跌比例累程起来.我们的到一个1+涨跌幅的累乘数据,在做归一化
在这里插入图片描述
这个是比较难理解的,看图你应该就明白了!!!

df["资金曲线"] = (1+df["涨跌幅"].cumprod()  
df.loc[:,"资金曲线"] = df["资金曲线"]/df["资金曲线"].iat[o]  #进行数据归一化

iat只能访问单个元素

df[“xxx”].iat[x]
当前"xxx"这一列的第x值

loc与iloc

loc是标签名,不带i的是名字
iloc是位置号,带i的就是index位置
取数据都遵循:左行右列loc[左行,有列] iloc[左行,右列]

计算后复权价格

格式:
收盘后复权 = 第一天的当日收盘价(固定值) * 资金曲线的值 (一直在变动反应股票涨跌变化情况的值)
其他后复权,求出对于收盘价的涨跌幅后乘上收盘价后复权
涨跌幅 * 收盘价后复权

df["收盘价_后复权"] = df["资金曲线"] * df["收盘价"].iat[0] # 股票第一天的价格不变作为基准价

df["开盘价_后复权"] = df["开盘价"]/df["收盘价"]*df["收盘价_后复权"]
df["最高价_后复权"] = df["最高价"]/df["收盘价"]*df["收盘_后复权"]
df["最低价_后复权"] = df["最低价"]/df["收盘价"]*df["收盘_后复权"]

# 生成新的4个字段
df[["开盘价_后复权","最高价_后复权","最低价_后复权","收盘价_后复权"]]

在这里插入图片描述

绘制股票历史价格变动图、k线图

绘制股票历史价格变动图

df["资金曲线"].plot(figsize=(20,8),
					grid=True,
					alpha=0.8,
					rot=45,
					title="股票历史价格变动图")

在这里插入图片描述

绘制不复权k线图

# 导入pyecharts工具包,用pe作为简写
import pyecharts as pe

# 提取x轴数据,即交易日期,同时转换为字符串形式
x = df.index.astype('str')

# 提取y轴数据,即绘制股票k线所必须的4个价格字段
y = df[['开盘价','收盘价','最低价','最高价']].values

# 创建k线图对象,并设置大标题
kline = pe.Kline('不复权K线图_三维通信')

# 绘制图表
kline.add('日K', x, y,                          #图例名称,x轴数据,y轴数据
          is_datazoom_show=True,                #使用区域缩放组件
          datazoom_range=[97,100],              #设置区域缩放的范围,这里设置为末尾3%的k线数据
          mark_point=['max','min'],             #标记可视范围内开盘价最大值,最小值
          is_xaxislabel_align = True,           #设置x轴刻度与标签对齐
          tooltip_trigger ='axis',              #坐标轴触发弹窗提示
          tooltip_axispointer_type ='shadow')   #设置tooltip指示器

在这里插入图片描述

标记双均线策略信号

计算均线

df["MA50"] = df["收盘价_后复权"].rolling(50).mean()
df["MA200"] = df["收盘价_后复权"].rolling(200).mean()

注意事项

pandasSeries.rolling(n)是表示对一列的n个数据做滚动处理,rolling(3).mean()表示
对滚动的数据做均值计算,并且记录在最后一行
在这里插入图片描述

双均线策略信号标记

在这里插入图片描述
在这里插入图片描述

总结一句话就是:

对于短周期均线前天小后天大是上传买入信号,前天大后天小是下穿卖出信号

## 1位买入信号
df.loc[(df["MA50"]<df["MA200")&
		(df["MA50"].shift(1)>df["MA200"].shift(1)),
		"交易信号"]=1
# 0卖出信号
df.loc[(df["MA50"]>df["MA200"])&
		(df["MA50"].shift(1)<df["MA200"].shift(1)),
		"交易信号"]=0
# 去除掉空值
df["交易信号"].dropna()

注意事项:

df.loc[(条件1)&(条件2), ‘交易信号’] = 1找到了同时满足2个条件的所有行,并且索引到交易信号这一列,当这一列最开始不存在的时候,pandas会帮我们自动新建一列空值的交易信号,然后对这一列满足2个条件的所有行赋值为1,这就完成了买入信号的标记,卖出信号标记则同理

涨跌停信号屏蔽

当股票涨停是无法买入的,跌停也是无法卖出的,如果我们策略中有这样的情况,则需要把交易信号屏幕掉(即设置为空值)

df.loc[(df["收盘价"]>=df["涨停价"])&
		(df["交易信号"]==1),
		"交易信号"]=None
df.loc[(df["收盘价"]<=df["跌停价"])&
		(df["交易信号"]==0),
		"交易信号"]=None
df["交易信号"].dropna()

持仓信号标记

我们需要根据 交易信号 来标记出,在股票历史中,我们买入持仓的期间,以及卖出空仓状态的期间。这是为了之后能回测双均线策略的优劣所必须的步骤

df["持仓信息"] = df["持仓状态"].fillna(method="ffill").shift().fillna(0)

df[‘交易信号’].fillna(method=‘ffill’) 函数会填充 “交易信号” 字段的空值,这里用到的参数 method=‘ffill’ 代表向前填充。假设交易信号只有4行 [NaN , 1 , NaN , NaN],每一行空值都会按之前最近的一个非空值来填充自己,ffill填充结果为 [NaN , 1 , 1 , 1],首行找不到之前的非空数据就不会被填充
pandas里的方法是可以连续调用的,在填充空值后,连续调用 .shift() 移位,沿用上面例子的假设,[NaN , 1 , 1 , 1] 将变为 [NaN , NaN , 1 , 1, 1],最后调用 .fillna(0) 将剩余空值填充为 0 [0 , 0 , 1 , 1]
在这里插入图片描述
这样子做的目的是为了实现,当日建仓因为是T+1的,当日是不可以买卖的持仓数量应为0,次日才应该有持仓
在这里插入图片描述

构建函数分析

持仓的计算,都是基于50日均线,200日均线来标记生成的。如果我想测试其他的均线组合呢?我要一行行去改代码中出现MA50,MA200的位置嘛?–这里我们总结上述信息封装一个函数

def Ma_mark(dfr,n,m):
"
dfr股票原始数据
n短周期
m长周期
"
# 制作数据备份
df = dfr.copy()
# 计算双均线
df["{}日均线".format(n)] = df["收盘价_后复权"].rolling(n).mean()
df["{}日均线".format(m)] = df["收盘价_后复权"].rolling(n).mean()

# 计算交易信号
#买入
df.loc[df["{}日均线".format(n)]<df["{}日均线".format(m)]&
		df["{}日均线".format(n)].shift()>df["{}日均线".format(m)].shift(),
		"交易信号"]=1
# 卖出
df.loc[]=0

注意事项

1.DataFrame.shape可以拿到数据的(行数,列数),索引取0即取数据的行数
2.assert语句包含两部分,assert 条件,不满足条件时报错并弹出对应提示 ,用来限制大家对函数参数的传入

持仓分组标记及涨跌幅分析

绩效指标计算及调参方法

用循环调整周期参数

绘制各绩效指标参数热力图

最优参数绩效及资金曲线

发布了23 篇原创文章 · 获赞 9 · 访问量 2848

猜你喜欢

转载自blog.csdn.net/weixin_45154559/article/details/105008526