如何在Python中实现虚拟变量回归估计非危机/危机时段的Alpha与Beta
分时段虚拟变量回归(危机/非危机时段Alpha、Beta估计)Python实现全流程
核心模型逻辑
对应拆分式回归模型形式为:
$$R_{i,t} - R_{f,t} = \alpha_{NC} D_{NC,t} + \alpha_C D_{C,t} + \beta_{NC} (R_{m,t} - R_{f,t}) D_{NC,t} + \beta_C (R_{m,t} - R_{f,t}) D_{C,t} + \varepsilon_t$$
变量定义:
- $D_{NC,t}$:非危机时段取1,其余时段取0
- $D_{C,t}$:危机时段取1,其余时段取0
- 回归输出的每个系数直接对应分时段的Alpha、Beta值,无需额外换算
全流程实现步骤
环境准备
安装所需依赖库:pip install pandas statsmodels numpy数据格式要求
需提前整理2000-2020年的时序数据,至少包含以下字段:- 日期列:标记每个收益率观测的对应时间
- 被解释变量列:个股/投资组合的超额收益(组合收益减无风险收益)
- 风险因子列:市场(或其他多因子)的超额收益
- 时段标记列:标记每个观测属于非危机(NC)还是危机(C)时段
变量构造
- 基于时段标记生成两个0/1虚拟变量:
D_NC(非危机时段赋值为1)、D_C(危机时段赋值为1) - 构造风险因子与时段的交互项:将风险因子超额收益分别与两个虚拟变量相乘,生成对应时段的风险敞口列
- 关键注意点:由于模型通过两个虚拟变量的系数捕捉不同时段的Alpha项,不存在统一的全局截距,后续回归时严禁额外添加常数截距项,否则会因
D_NC + D_C = 1的恒等关系触发完全多重共线性,导致回归失败。
- 基于时段标记生成两个0/1虚拟变量:
回归拟合与参数提取
可直接运行以下完整代码完成全流程,示例中已内置模拟的2000-2020年月度数据,实际使用时替换为自身数据集即可:import pandas as pd import numpy as np import statsmodels.api as sm # ---------------------- # 替换为自身数据部分:读取2000-2020年时序收益率数据 # ---------------------- # 生成示例时间范围(2000-01至2020-12月度频率) dates = pd.date_range(start="2000-01-01", end="2020-12-31", freq="M") # 构造示例字段 df = pd.DataFrame({ "excess_ret_i": np.random.normal(loc=0.01, scale=0.05, size=len(dates)), # 组合超额收益 "excess_ret_m": np.random.normal(loc=0.008, scale=0.04, size=len(dates)) # 市场超额收益 }, index=dates) # 标记危机时段(示例:2008金融危机、2020疫情阶段为危机时段) df["period"] = "NC" df.loc[((df.index >= "2008-01-01") & (df.index <= "2009-12-31")) | ((df.index >= "2020-02-01") & (df.index <= "2020-12-31")), "period"] = "C" # ---------------------- # 构造回归所需变量 # ---------------------- df["D_NC"] = (df["period"] == "NC").astype(int) df["D_C"] = (df["period"] == "C").astype(int) df["mkt_DNC"] = df["excess_ret_m"] * df["D_NC"] df["mkt_DC"] = df["excess_ret_m"] * df["D_C"] # 组装解释变量矩阵 X = df[["D_NC", "D_C", "mkt_DNC", "mkt_DC"]] y = df["excess_ret_i"] # ---------------------- # 拟合回归(不添加常数项!) # ---------------------- reg_results = sm.OLS(y, X).fit() # ---------------------- # 整理输出分时段参数 # ---------------------- param_label = { "D_NC": "非危机时段Alpha", "D_C": "危机时段Alpha", "mkt_DNC": "非危机时段Beta", "mkt_DC": "危机时段Beta" } for col in X.columns: print(f"{param_label[col]}: 系数={reg_results.params[col]:.4f}, " f"t值={reg_results.tvalues[col]:.3f}, " f"p值={reg_results.pvalues[col]:.4f}")
常见问题排查
- 若回归报错提示“完全多重共线性”,优先检查是否误调用了
sm.add_constant()为解释变量添加了全局截距 - 若需扩展至多因子模型(如Fama-French三因子/五因子),只需对每个风险因子分别与两个时段虚拟变量构造交互项,替换原有市场因子的交互列即可,整体回归逻辑不变
- 虚拟变量的危机时段标记可根据实际研究定义调整,只需保证每个观测仅属于一个时段(即D_NC与D_C不会同时为1、同时为0)即可保证模型可识别
内容的提问来源于stack exchange,提问作者Gemma Caruso
相关产品推荐
相关产品推荐

