目录
已知条件:
概念描述:
开始计算:
读入数据
计算复权因子
计算前复权因子
计算后复权因子
计算前复权收盘价
计算后复权收盘价
数据:
本文以恒瑞医药上市以来至2022-07-06的数据作为讲解素材,数据在本文最后会提供下载。
注:本文计算不考虑扣税
1. 恒瑞医药上市以来无复权收盘价数据
文件名:pre_600276_data.csv
字段说明:secID:股票编码,tradeDate:交易日期,closePrice:收盘价
2. 恒瑞医药上市以来分红数据
文件名:pre_600276_bonus.csv
字段说明:registerDate:股权登记日,exDivDate:除权除息日,perCashDiv:每股派息(现金分红),perShareDivRatio:每股送股,perShareTransRatio:每股转增,programmeTxt:分红的文字描述
1. 上市公司在送股后,股票的数量变多,但公司价值不变,股价变低,在K线图上就会出现一个缺口,涨跌幅变得不合理,很多指标通过这样的数据计算出来基本不可用,所以就需要修补这个缺口,这个过程就叫复权。
2. 复权有分前复权和后复权,比较通用的是前复权,一般指标的计算都是使用前复权数据
3. 前复权是以最近一次的除权日为起点,往前回溯对数据进行调整,可以粗糙地理解是把以前的数据往下平移,去除缺口
前复权后价格=(复权前价格-现金红利)/(1+流通股份变动比例)
这里的“复权前价格”是股权登记日的收盘价
4. 后复权要看我们使用的数据以什么时候为起点,可以是上市当日,也可以自己任意取一个开始日期,可以粗糙地理解是从开始日期把往后的数据向上平移,去除缺口
后复权后价格=复权前价格×(1+流通股份变动比例)+现金红利
这里的“复权前价格”是除权除息日的收盘价
import pandas as pd
pd.set_option('display.max_columns',None)
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
plt.figure(figsize=(20,10))
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
df_noright_data = pd.read_csv('pre_600276_data.csv',encoding='utf-8')
df_noright_data.head()
df_bouns = pd.read_csv('pre_600276_bonus.csv',encoding='utf-8')
df_bouns.head()
# 计算复权因子,所有计算都不考虑税费
df_adjust_factor = df_bouns.loc[:,['registerDate','exDivDate','perCashDiv','perShareDivRatio','perShareTransRatio']].copy()
df_adjust_factor['registerDate'] = pd.to_datetime(df_adjust_factor['registerDate'])
df_adjust_factor['exDivDate'] = pd.to_datetime(df_adjust_factor['exDivDate'])
# 将“股权登记日registerDate”对应的未复权收盘价加入 df_adjust_factor 表,字段名为 register_close_price
df_noright_data['tradeDate'] = pd.to_datetime(df_noright_data['tradeDate'])
def input_register_close_price(x):
target_date = x['registerDate']
target_close = df_noright_data[df_noright_data['tradeDate']==target_date].iloc[0]['closePrice']
return target_close
df_adjust_factor['register_close_price'] = df_adjust_factor.apply(input_register_close_price,axis=1)
df_adjust_factor.head()
# 将“除权除息日exDivDate”对应的未复权收盘价加入 df_adjust_factor 表,字段名为 except_close_price
def input_except_close_price(x):
target_date = x['exDivDate']
target_close = df_noright_data[df_noright_data['tradeDate']==target_date].iloc[0]['closePrice']
return target_close
df_adjust_factor['except_close_price'] = df_adjust_factor.apply(input_except_close_price,axis=1)
df_adjust_factor.head()
1. 前复权后价格=(复权前价格-现金红利)/(1+流通股份变动比例)
2. 计算的是“股权登记日”的收盘价
3. 前复权因子 = 前复权后价格/复权前价格
4. 前复权除权因子,为本次股权登记日为起点,往前开始累乘,所得到的数值为“前复权除权因子”,这样历史未复权收盘价乘以前复权除权因子后就是前复权收盘价
# 计算前复权因子
'''
前复权后价格=(复权前价格-现金红利)/(1+流通股份变动比例)
计算的是“股权登记日”的收盘价
前复权因子 = 前复权后价格/复权前价格
前复权除权因子,为本次股权登记日为起点,往前开始累乘,所得到的数值为“前复权除权因子”,这样历史未复权收盘价乘以前复权除权因子后就是前复权收盘价
'''
# 定义前复权因子字段名 pre_single_factor
def caculate_preSingleFactor(x):
perCashDiv = x['perCashDiv'] if not np.isnan(x['perCashDiv']) else 0 # 每股派息
perShareDivRatio = x['perShareDivRatio'] if not np.isnan(x['perShareDivRatio']) else 0 # 每股送股
perShareTransRatio = x['perShareTransRatio'] if not np.isnan(x['perShareTransRatio']) else 0 # 每股转增
ori_price = x['register_close_price']
target_price = (ori_price-perCashDiv)/(1+perShareDivRatio+perShareTransRatio)
target_radio = target_price/ori_price
return target_radio
df_adjust_factor['pre_single_factor'] = df_adjust_factor.apply(caculate_preSingleFactor,axis=1)
df_adjust_factor.head()
# 定义前复权除权因子字段名 pre_accum_factor
df_adjust_factor['pre_accum_factor'] = df_adjust_factor['pre_single_factor'].cumprod()
df_adjust_factor.head()
1. 后复权后价格=复权前价格×(1+流通股份变动比例)+现金红利
2. 计算的是“除权除息日”的收盘价
3. 后复权因子 = 后复权后价格/复权前价格
4. 后复权除权因子,要看你的收盘价数据是以什么时间为起点,你收盘价数据的起点就是后复权除权因子计算的起点,往后开始累乘后复权因子,所得到的数值为“后复权除权因子”,这样历史未复权收盘价乘以后复权除权因子后就是后复权收盘价
# 计算后复权因子
'''
后复权后价格=复权前价格×(1+流通股份变动比例)+现金红利
计算的是“除权除息日”的收盘价
后复权因子 = 后复权后价格/复权前价格
后复权除权因子,要看你的收盘价数据是以什么时间为起点,你收盘价数据的起点就是后复权除权因子计算的起点,往后开始累乘后复权因子,\
所得到的数值为“后复权除权因子”,这样历史未复权收盘价乘以后复权除权因子后就是后复权收盘价
'''
# 定义后复权因子字段名 after_single_factor
def caculate_afterSingleFactor(x):
perCashDiv = x['perCashDiv'] if not np.isnan(x['perCashDiv']) else 0 # 每股派息
perShareDivRatio = x['perShareDivRatio'] if not np.isnan(x['perShareDivRatio']) else 0 # 每股送股
perShareTransRatio = x['perShareTransRatio'] if not np.isnan(x['perShareTransRatio']) else 0 # 每股转增
ori_price = x['except_close_price']
target_price = ori_price*(1+perShareDivRatio+perShareTransRatio)+perCashDiv
target_radio = target_price/ori_price
return target_radio
df_adjust_factor['after_single_factor'] = df_adjust_factor.apply(caculate_afterSingleFactor,axis=1)
df_adjust_factor.head()
# 定义后复权除权因子字段名 after_accum_factor
df_temp = df_adjust_factor.loc[:,['exDivDate','after_single_factor']].copy()
df_temp.sort_values(by='exDivDate',ascending=True,inplace=True)
df_temp.head()
df_temp['after_accum_factor'] = df_temp['after_single_factor'].cumprod()
df_temp.tail()
df_temp.sort_values(by='exDivDate',ascending=False,inplace=True)
df_adjust_factor['after_accum_factor'] = df_temp['after_accum_factor']
df_adjust_factor.head()
前复权收盘价 = 无复权收盘价*前复权除权因子
# 计算前复权收盘价
df_pre_data = df_noright_data.loc[:,['tradeDate','closePrice']].copy()
df_pre_factor = df_adjust_factor.loc[:,['registerDate','pre_accum_factor']].copy()
df_pre_factor.rename(columns={'registerDate':'tradeDate'},inplace=True)
df_pre_factor.head()
df_pre_data = pd.merge(df_pre_data,df_pre_factor,on='tradeDate',how='left')
df_pre_data.head()
df_pre_data.tail()
df_pre_data['pre_accum_factor'] = df_pre_data['pre_accum_factor'].fillna(method='bfill',axis=0)
df_pre_data.tail()
df_pre_data['pre_accum_factor'] = df_pre_data['pre_accum_factor'].fillna(1,axis=0)
df_pre_data.tail()
df_pre_data['adj_close'] = df_pre_data['closePrice']*df_pre_data['pre_accum_factor']
df_pre_data.plot(x='tradeDate',y=['closePrice','adj_close'])
后复权收盘价 = 无复权收盘价*后复权除权因子
# 计算后复权收盘价
df_after_data = df_noright_data.loc[:,['tradeDate','closePrice']].copy()
df_after_factor = df_adjust_factor.loc[:,['exDivDate','after_accum_factor']].copy()
df_after_factor.rename(columns={'exDivDate':'tradeDate'},inplace=True)
df_after_data = pd.merge(df_after_data,df_after_factor,on='tradeDate',how='left')
df_after_data.head()
df_after_data.tail()
df_after_data['after_accum_factor'] = df_after_data['after_accum_factor'].fillna(method='ffill',axis=0)
df_after_data.tail()
df_after_data.head()
df_after_data['after_accum_factor'] = df_after_data['after_accum_factor'].fillna(1,axis=0)
df_after_data['adj_close'] = df_after_data['closePrice']*df_after_data['after_accum_factor']
df_after_data.plot(x='tradeDate',y=['closePrice','adj_close'])
链接:https://pan.baidu.com/s/104dpG734M5kD4cjMsYkGgw
提取码:souj