本文使用从20031231到20201113上证50指数对数收益率样本共计4099个。按照每组包含20、40、60…600个样本的分组方式,将数据分别划分为相应的组数。先分别计算每个样本组的均值、标准差、偏度和峰度,再对所有样本组数据进行标准化处理,计算总体均值,标准差,偏度和峰度。
"""计算各种样本分组情况下的,数据标准化统计量平均值"""
import pandas as pd
import numpy as np
import os
import copy
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['simhei']#用于正常显示中文标签
plt.rcParams['axes.unicode_minus']=False#用于正常显示负号
def makepath(path):
"""生成文件目录
:param path:str,文件目录
:return:
"""
if os.path.exists(path)==False:
os.mkdir(path)
def ETF50_log_():
"""计算股价收益率的对数收益率
:return: DataFrame,['交易日期','对数收益率']数据表格
"""
ETF50=pd.read_excel('原始数据/ETF50.xlsx')
ETF50.sort_index(inplace=True,ascending=False)
ETF50.dropna(inplace=True)
ETF50.index=range(len(ETF50))
ETF50['对数收益率']=np.log(ETF50['收盘点位'].shift(1)/ETF50['收盘点位'])
ETF50_log=ETF50.loc[1:,['交易日期','对数收益率']]
return ETF50_log
def sort_(days:int,data):
"""
将数据按照日期划分为等天数的组,并计算所有组统计值的平均值
:param days: int,每组的天数
:param data: DataFrame,所使用的数据
:return:每组天数,组数,[均值,标准差,偏度,峰度]
"""
# days=30
# data = ETF50_log
index_sort=data.index[::days]
data_index=data.loc[index_sort,:]
data['{}天组'.format(days)]=0
times=1
for i in data_index.index:
data.loc[i:(i+days),'{}天组'.format(days)]=times
times+=1
#pd.pivot_table(data,index=['{}天组'.format(days)],values=['对数收益率'],aggfunc=[])
dict_describe={'组次':[],'均值':[],'标准差':[],'偏度':[],'峰度':[]}
for time in data['{}天组'.format(days)].unique():
#time=1
data_time=data.loc[data['{}天组'.format(days)]==time]
dict_describe['组次'].append(time)
dict_describe['均值'].append(data_time['对数收益率'].mean())
dict_describe['标准差'].append(data_time['对数收益率'].std())
dict_describe['偏度'].append(data_time['对数收益率'].skew())
dict_describe['峰度'].append(data_time['对数收益率'].kurt())
data_describe=pd.DataFrame(dict_describe)
list_describe=data_describe.iloc[:,1:].mean().tolist()
return days,len(data['{}天组'.format(days)].unique()),list_describe
def main():
"""
计算每组分组情况下的平均统计量和标准化统计量,并绘制图形
:return: 平均统计量,标准化统计量
"""
makepath('原始数据')
makepath('生成数据')
dict_all={'每组天数':[],'组数':[],'平均均值':[],'平均标准差':[],'平均偏度':[],'平均峰度':[]}
ETF50_log = ETF50_log_()
for days in np.arange(20,601,10):
size,numbers,describe=sort_(days, ETF50_log)
dict_all['每组天数'].append(size)
dict_all['组数'].append(numbers)
dict_all['平均均值'].append(describe[0])
dict_all['平均标准差'].append(describe[1])
dict_all['平均偏度'].append(describe[2])
dict_all['平均峰度'].append(describe[3])
print(days)
data_all=pd.DataFrame(dict_all)
#标准化的统计结果
data_all_standard=copy.deepcopy(data_all)
data_all_standard.iloc[:,2:]=(data_all.iloc[:,2:]-data_all.iloc[:,2:].mean())/data_all.iloc[:,2:].std()
#绘制标准化统计结果折线图
plt.figure(figsize=(10,8))
for label in data_all_standard.columns[2:]:
plt.plot(data_all_standard['每组天数'],data_all_standard.loc[:,label],label=label)
plt.legend()
plt.xlabel('每组天数',fontsize=15)
plt.ylabel('标准化平均统计量',fontsize=15)
plt.title('标准化平均统计量',fontsize=15)
plt.savefig('生成数据/标准化平均统计量.jpg')
print(data_all)
print(data_all_standard)
return data_all,data_all_standard
if __name__=='__main__':
data_all,data_all_standard=main()
最终可以获得标准化后的统计量均值,部分结果如下图所示:
很显然,随着每组的样本数量越来越多,平均偏度和平均峰度在变得越来越大!具体如图所示:
所使用的数据: