【C0031】事件研究法python实现
·
1.概述
事件研究法是一种统计方法,用于评估特定事件(如财报发布、并购公告、政策变更等)对资产价格(通常是股票收益率)的影响。其核心逻辑是将实际观测到的收益率与“如果没有发生该事件”情况下的预期正常收益率进行比较,两者的差额即为异常收益率 (Abnormal Return, AR)。其核心步骤如下:
-
1. 定义事件与窗口:
-
• 事件日 (Event Date):消息公开的那一天。
-
• 估计窗口 (Estimation Window):用于估算股票正常表现参数的时间段(通常在事件前较远处,如 [-120, -21] 天)。
-
• 事件窗口 (Event Window):用于观察事件影响的时间段(如 [-5, +5] 天)。
-
-
2. 建立期望收益模型:
-
• 常用市场模型 (Market Model):通过回归分析 ,利用估计窗口的数据计算出 和 。
-
• 是个股收益, 是市场收益。
-
-
3. 计算异常收益 (AR):
-
•
-
• 即:实际收益减去模型预测的正常收益。
-
-
4. 计算累计异常收益 (CAR):
-
•
-
• 将事件窗口内的异常收益累加,以衡量事件的总体影响。
-
-
5. 统计检验:
-
• 对 AR 和 CAR 进行 t 检验,判断其是否显著异于零,从而确定事件是否具有统计学意义上的影响。
-
2.代码实现
import pandas as pd
import numpy as np
import statsmodels.api as sm
def run_event_study(data, event_date, ticker_col='ticker', date_col='date', return_col='return', window=(-5, 5)):
# 1. 数据预处理:计算市场平均收益作为基准模型 (简化版 Market Model)
# 假设数据中已包含市场收益率或在此处计算等权市场收益
if 'market_return' not in data.columns:
data['market_return'] = data.groupby(date_col)[return_col].transform('mean')
results = []
# 获取唯一股票列表
tickers = data[ticker_col].unique()
for ticker in tickers:
stock_data = data[data[ticker_col] == ticker].copy()
stock_data = stock_data.sort_values(by=date_col)
# 确定事件日在时间序列中的位置
if event_date not in stock_data[date_col].values:
continue
event_idx = stock_data[stock_data[date_col] == event_date].index[0]
all_indices = stock_data.index.tolist()
event_pos = all_indices.index(event_idx)
# 定义估计窗口 (例如事件前 120 天到前 20 天) 和 事件窗口
est_start_pos = max(0, event_pos - 120)
est_end_pos = max(0, event_pos - 21)
if est_end_pos <= est_start_pos:
continue
est_window_data = stock_data.iloc[est_start_pos:est_end_pos+1]
# 2. 估计正常收益 (使用 OLS 回归: R_i = alpha + beta * R_m + epsilon)
X = sm.add_constant(est_window_data['market_return'])
y = est_window_data[return_col]
model = sm.OLS(y, X).fit()
# 3. 计算事件窗口内的异常收益 (AR)
event_start_pos = max(0, event_pos + window[0])
event_end_pos = min(len(stock_data)-1, event_pos + window[1])
event_window_data = stock_data.iloc[event_start_pos:event_end_pos+1].copy()
if len(event_window_data) == 0:
continue
X_event = sm.add_constant(event_window_data['market_return'])
predicted_return = model.predict(X_event)
event_window_data['abnormal_return'] = event_window_data[return_col] - predicted_return
event_window_data['relative_day'] = range(window[0] + (event_start_pos - (event_pos + window[0])),
window[0] + (event_start_pos - (event_pos + window[0])) + len(event_window_data))
# 4. 计算累计异常收益 (CAR)
event_window_data['car'] = event_window_data['abnormal_return'].cumsum()
event_window_data[ticker_col] = ticker
results.append(event_window_data[[ticker_col, date_col, 'relative_day', 'abnormal_return', 'car']])
if not results:
return pd.DataFrame()
final_result = pd.concat(results)
# 按相对日期聚合平均 CAR
avg_car = final_result.groupby('relative_day')[['abnormal_return', 'car']].mean().reset_index()
return avg_car
3.结果展示

更多推荐


所有评论(0)