提示:文章内容主要来自《金融统计分析》课程的课题作业。
文章目录
前言
一、检验方案简述
二、实现步骤
1.数据获取
2.数据整理
3.一阶回归与个例展示
4、 二阶回归
总结
CAPM模型是由哈里·马科威茨提出的,CAPM中文叫资本资产定价模型,是基于风险资产期望收益均衡基础上的预测模型。模型指出:资产的预期超额收益与市场组合的预期收益在长期内成正比。在上世纪60年代,多位经济学家对该模型进行过验证,这些经济学家运用了不同的方法,却都得到了相同的结论。那么,CAPM模型在中国A股市场的定价表现又如何呢?本文将通过截面回归的方式,来探讨这一问题。
1、以沪深300成分股为样本,以沪深300指数代表市场因子,以shibor利率代表无风险收益率;
2、从tushare数据库获2017年1月·1日至2021年12月31日期间内300只成分股的历史行情数据;
3、数据处理,只保留期间一直存在的成分股,去除其他变动的成分股,并将保留的股票数据转换成月度收益;
4、对每只成分股进行回归,得出所有成分股的βi值和预期超额收益E(ri);
5、用所得β值和预期超额收益E(ri)进行截面回归,得到证券市场线。
代码如下:
import tushare as ts
import time
pro = ts.pro_api('##########################') # tushare数据接口,需个人注册获取
# 获取shibor(1个月)数据作为无风险收益率
shibor_history=pro.shibor(start_date='20170101',end_date='20211231',fields='date,1m')
shibor_history.to_csv('E:\\python_outputs\\CAPM\\shibor_history.csv',index=False)
# 获取沪深300指数月线数据
HS300_history=pro.index_monthly(ts_code='000300.SH',start_date='20161201',end_date='20211231',
fields='ts_code,trade_date,close')
HS300_history.to_csv('E:\\python_outputs\\CAPM\\HS300_history.csv',index=False)
# 获取沪深300指数成份股(2021年12月31日)
cons_HS300=pro.index_weight(index_code='000300.SH',trade_date='20211231',
fields='con_code,trade_date')
cons_HS300.to_csv('E:\\python_outputs\\CAPM\\cons_HS300.csv',index=False)
# 获取沪深300所有成份股的月线数据
# 因为每分钟最多访问该接口120次,需要间隔1分钟分次获取
for i in cons_HS300.truncate(before=0,after=99).con_code:
con=pro.monthly(ts_code=i,start_date='20161201',end_date='20211231',fields='ts_code,trade_date,close')
con.to_csv('E:\\python_outputs\\CAPM\\cons_monthly\\{}_monthly.csv'.format(i),index=False)
time.sleep(61) # 等待61秒
for i in cons_HS300.truncate(before=100,after=199).con_code:
con=pro.monthly(ts_code=i,start_date='20161201',end_date='20211231',fields='ts_code,trade_date,close')
con.to_csv('E:\\python_outputs\\CAPM\\cons_monthly\\{}_monthly.csv'.format(i),index=False)
time.sleep(61) # 等待61秒
for i in cons_HS300.truncate(before=200,after=299).con_code:
con=pro.monthly(ts_code=i,start_date='20161201',end_date='20211231',fields='ts_code,trade_date,close')
con.to_csv('E:\\python_outputs\\CAPM\\cons_monthly\\{}_monthly.csv'.format(i),index=False)
代码如下:
import glob
import numpy as np
import pandas as pd
HS300=pd.read_csv('E:\\python_outputs\\CAPM\\HS300_history.csv',parse_dates=['trade_date'])
HS300.trade_date=HS300.trade_date.apply(lambda x:x.strftime('%Y%m')) # 日期转为年月格式
df=pd.read_csv('E:\\python_outputs\\CAPM\\shibor_history.csv',parse_dates=['date'],index_col='date')
df0=(df.resample('M') # 调整周期,以月为周期
.mean()
.div(12) # shibor利率为单利年利,直接出除以12
.reset_index())
df0.date=df0.date.apply(lambda x:x.strftime('%Y%m'))
shibor=df0.rename(columns={'date':'trade_date','1m':'rf_shibor'}).set_index('trade_date')
shibor.to_csv('E:\\python_outputs\\CAPM\\rf_shibor.csv')
files=glob.glob('E:\\python_outputs\\CAPM\\cons_monthly\\*.csv')
cons_monthly=pd.concat([pd.read_csv(j,parse_dates=['trade_date']) for j in files])
cons_monthly.trade_date=cons_monthly.trade_date.apply(lambda x:x.strftime('%Y%m'))
data=(pd.concat([cons_monthly,HS300])
.set_index('trade_date')
.pivot(columns='ts_code',values='close')
.dropna(axis=1)
.apply(np.log)
.diff()
.dropna()
.mul(100))
regression_data_set=(data.T-shibor.T.loc['rf_shibor']).T # regression_data_set为成分股和沪深300的历史超额收益率
regression_data_set.to_csv('E:\\python_outputs\\CAPM\\regression_data_set.csv')
一阶回归基于每只成分股的月度超额收益和指数月度超额收益数据,得出股票的βi值和预期超额收益E(ri)。并以个例(贵州茅台)绘出证券特征线。代码如下:
import statsmodels.api as sm
import matplotlib.pyplot as plt
regression_data_set=pd.read_csv('E:\\python_outputs\\CAPM\\regression_data_set.csv',index_col='trade_date')
print(regression_data_set)
X=sm.add_constant(regression_data_set['000300.SH'])
params_list=[]
r2_adj_list=[]
cons=regression_data_set.columns
for a in cons:
y=regression_data_set[a]
model=sm.OLS(y,X)
result=model.fit()
param = result.params.to_list()
r2_adj = result.rsquared_adj
params_list.append(param)
r2_adj_list.append(r2_adj)
r2_adj = pd.DataFrame(r2_adj_list, index=cons, columns=['rsquared_adj'])
params = pd.DataFrame(params_list, columns=['const', '000300.SH'], index=cons)
regression_result = pd.concat([params, r2_adj], axis=1)
regression_result.to_csv('E:\\python_outputs\\CAPM\\regression_result.csv')
# 个例展示(贵州茅台)
X1=sm.add_constant(regression_data_set['000300.SH'])
y1=regression_data_set['600519.SH']
model1=sm.OLS(y1,X1)
result1=model1.fit()
print(result1.summary())
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
regression_data_set1=regression_data_set.assign(observes_month=range(1,61))
plt.figure(figsize=(9,5))
plt.plot(regression_data_set1.observes_month,[0]*60,color='black')
plt.plot(regression_data_set1.observes_month,regression_data_set['600519.SH'],label='贵州茅台',linestyle='--')
plt.plot(regression_data_set1.observes_month,regression_data_set['000300.SH'],label='沪深300')
plt.title('沪深300和贵州茅台的超额收益')
plt.xlabel('观察样本(月)')
plt.ylabel('超额收益(%)')
plt.legend()
plt.savefig('E:\\python_outputs\\CAPM\\沪深300和贵州茅台的超额收益.png')
X1=regression_data_set['000300.SH']
Y1=result1.predict()
plt.figure(figsize=(9,6))
plt.scatter(X1,y1,label='观测值')
plt.plot(X1,Y1,label='预测值',color='orange')
plt.title('贵州茅台证券特征线')
plt.xlabel('沪深300超额收益(%)',position=(1,1))
plt.ylabel('贵州茅台超额收益(%)',position=(-5,0.95),rotation=0)
plt.legend()
ax=plt.gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines['bottom'].set_position(('data',0))
ax.spines['left'].set_position(('data',0))
plt.savefig('E:\\python_outputs\\CAPM\\贵州茅台证券特征线.png')
二阶回归基于一阶回归的结果,得出证券市场线。代码如下:
regression_result=pd.read_csv('E:\\python_outputs\\CAPM\\regression_result.csv',index_col='Unnamed: 0')
regression_result.rename(columns={'000300.SH':'beta'},inplace=True)
df1=regression_data_set.div(100).add(1).apply(np.cumprod)
mean_return=df1.loc[202112].apply(lambda s:np.power(s,1/60)).sub(1).mul(100).rename('mean_Return')
X2=sm.add_constant(regression_result['beta'])
y2=mean_return
model2=sm.OLS(y2,X2)
result2=model2.fit()
print(result2.summary())
s=regression_data_set.mean()
rf=pd.read_csv('E:\\python_outputs\\CAPM\\rf_shibor.csv',index_col='trade_date')
mean_rf=rf.rf_shibor.mean()
print('mean_rf:','{:.4f}'.format(mean_rf))
X3=regression_result['beta']
Y3=pd.Series(result2.predict()).add(mean_rf)
y3=y2.add(mean_rf)
plt.figure(figsize=(6,6))
plt.scatter(X3,y3,label='observes')
plt.plot(X3,Y3,label='CML',color='orange')
plt.title('证券市场线')
plt.xlabel('beta',position=(1,1))
plt.ylabel('E(R)',position=(-5,0.95),rotation=0)
plt.legend()
ax=plt.gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines['bottom'].set_position(('data',0))
ax.spines['left'].set_position(('data',0))
plt.savefig('E:\\python_outputs\\CAPM\\证券市场线.png')
plt.show()
最后的结果显示,贵州茅台又一个正的α值,而证券市场线显示在2017年到2021年的五年中,A股的资产的预期超额收益与市场组合的预期收益不成成正比。本该为正的无风险收益在证券市场线上则不然。故我们得出:CAPM在A股的定价效果不佳。这一点在A股指数上也不到了一定的印证:217年1月3日1沪深300指数为3342.23点,2021年12月31日为3769.57点。整整5年,上涨了点427.34点,涨幅12.79%,年均(几何平均)2.43%的收益率……
抑郁……
关注获取完整代码和数据库