前言
作为一名非全日制研究生,我在完成课程作业的过程中,将研究过程中使用到的代码进行了开源,旨在为金融和经济专业的同学们提供一个学习和借鉴的机会。通过分享这些代码,希望能够促进学术交流,激发更多的创新思维。
事件研究法简介
事件研究法(Event Study)是一种广泛应用于金融领域的分析方法,主要用于评估某一特定事件的发生或信息的发布是否会影响投资者的决策,从而导致股票价格或交易量的变化。这种方法的核心在于考察特定事件前后市场反应的变化,特别是关注是否存在超常收益(Abnormal Returns)。超常收益是指超出市场预期的回报,它的出现往往意味着市场对某一事件的过度反应或是信息未能完全被市场吸收。
事件研究法的理论基础是市场有效性假设。这一假设认为,如果市场是有效的,那么任何新的信息都会迅速而准确地反映在资产价格上。因此,通过分析特定事件前后股票价格的变化,我们可以判断市场对该事件的反应速度及其强度,进而评估该事件对相关公司价值或整个市场的影响。
案例研究:浑水做空中概股事件
在本案例研究中,我采用事件研究法来分析浑水做空中概股事件对公司股价的影响。具体而言,我关注的是该事件发生后一个月内股价的变化情况。
研究设计
估计窗口:为了准确捕捉事件发生前的市场常态,我将估计窗口设定为事件发生前60个交易日。
事件窗口:考虑到浑水报告发布前,这些公司的股价就已经出现了异常波动,这表明部分信息可能已提前泄露给市场。因此,我将事件窗口设定为报告发布前10个交易日加上事件后20个交易日,共计30个交易日。
建模方法:我采用单变量线性回归模型进行建模,其中因变量为个股当日涨跌幅,自变量为市场指数(标普500)的当日涨跌幅。尽管这种模型较为简单,但在初步分析中仍能提供有价值的信息。
我把代码开源如下:
# coded by LY(伊玛目的门徒)
import pandas_datareader as pdr
import datetime
# 获取公司
start=datetime.datetime(2021,6,1)
end= datetime.datetime(2022,6,1)
df = pdr.get_data_tiingo('BEKE', start,end,api_key='你的tlingo key')
#轴向转化函数 解决分组索引问题
df1=df.stack(0)
df1=df1['BEKE'].unstack()
#市场收益率Rm
# 获取标普五百
start=datetime.datetime(2019,1,1)
end= datetime.datetime(2022,4,1)
dfzs = pdr.get_data_tiingo('SPY', start,end,api_key='你的tlingo key')
#轴向转化函数 解决分组索引问题
dfzs1=dfzs.stack(0)
dfzs1=dfzs1['SPY'].unstack()
#计算收益率
dfzs1['pct_chg'] = (dfzs1['adjClose'] - dfzs1['adjClose'].shift(1)) / dfzs1['adjClose'].shift(1)
df_index = dfzs1[['pct_chg']].copy()
df_index['trade_date'] = df_index.index
#计算收益率
df1['return'] = (df1['adjClose'] - df1['adjClose'].shift(1)) / df1['adjClose'].shift(1)
#企业收益率Ri
d0 = df1[['return']].copy()
d0['trade_date'] = d0.index
# 指数DF和公司DF合并
df_final = d0.merge(df_index, how='left',on='trade_date')
# 避免第一天空值Nan影响建模
df_final.ix[0,'return']=0
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression #线性回归
import csv
import numpy as np
#计算预期收益率
def get_OLS(X, y, pre_X):
linear_m = LinearRegression().fit(X, y)
r_2 = linear_m.score(X, y) #值越接近1拟合优度越好
pre_y=linear_m.predict(X)
Residual = sum((y - pre_y)**2)
L_xx = len(X) * np.var(X)
sigma = np.sqrt(Residual / (len(X)-2))
t = linear_m.coef_ * np.sqrt(L_xx) / sigma
t=round(float(t),4)
print(f"构建模型,拟合优度为{round(r_2*100, 2)}%")
print(f"Ri = {round(linear_m.intercept_,3)} + {round(linear_m.coef_[0],3)}Rm + e")
if 1.65<=abs(t)<1.96:
print(f'回归模型的t值为{t},回归系数在10%的置信水平下显著')
elif 1.96<=abs(t)<2.58:
print(f'回归模型的t值为{t},回归系数在5%的置信水平下显著')
elif abs(t)>=2.58:
print(f'回归模型的t值为{t},回归系数在1%的置信水平下显著')
else:
print(f'回归模型的t值为{t},回归系数不显著')
return linear_m.predict(pre_X)
#计算AR,CAR
def get_data(event):
print("事件日为: ", event)
#q,h = df_final[df_final['trade_date'] == event].index[0]-10, df_final[df_final['trade_date'] == event].index[0]+20 #事件窗口[-15,15]
# 30天窗口期
q,h = df_final[df_final['trade_date'] == event].index[0]-10, df_final[df_final['trade_date'] == event].index[0]+20 #事件窗口[-10,20]
target = df_final.loc[q:h].copy()
#estimate = df_final.loc[q-195:q-6].copy() #估计窗口[-210,-21]
# 60天估计期
estimate = df_final.loc[q-60:q].copy() #估计窗口[-210,-21]
#print (estimate)
#估计期 指数涨幅
X = estimate[['pct_chg']]
#估计期企业回报率
y = estimate['return']
# 窗口期实际指数市场回报率
predict_X = target[['pct_chg']]
target['E(Rt)'] = get_OLS(X, y, predict_X) # #窗口期的指数涨幅企业预期收益率
#企业异常收益率
target['ARt'] = target['return']-target['E(Rt)']
#累计异常收益率 = 异常收益率在窗口期的求和
target['CARt'] = target['ARt'].cumsum()
return target
#绘制图像
def main(e):
a = get_data(e)
print(a)
a.set_index('trade_date')[['ARt', 'CARt']].plot()
#结果
events = ['2021-12-16']
for e in events:
main(e)
plt.rcParams['font.sans-serif'] = ['SimHei'] # 中文字体设置-黑体
plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
plt.title('IQ CARt累计异常收益率,ARt单日异常收益率 ')
plt.savefig('.\爱奇艺.jpg',bbox_inches='tight')
事件日为: 2021-12-16 构建模型,拟合优度为0.77% Ri = -0.002 + 0.564Rm + e 回归模型的t值为0.6749,回归系数不显著
结论
通过对浑水做空中概股事件的详细分析,我得出了以下结论:
- 事件日:2021年12月16日
- 模型构建:我们构建了单变量线性回归模型,模型的形式为 ��=−0.002+0.564��+�Ri=−0.002+0.564Rm+e,其中 ��Ri 表示个股当日涨跌幅,��Rm 表示市场指数(标普500)的当日涨跌幅。
- 拟合优度:模型的拟合优度(R²)为0.77%,表明模型对数据的解释能力较弱。
- 回归系数显著性:回归模型的t值为0.6749,表明回归系数不显著,即市场指数的变动对个股涨跌幅的影响在统计上不显著。