滚动CAPM贝塔的代码示例和分析
2026/9/14 18:10:57 网站建设 项目流程

以下代码是在计算每只股票相对等权股票池的多日滚动CAPM beta

def compute_market_beta(returns, window=BETA_WINDOW, minp=BETA_MINP): """60d trailing CAPM beta of each stock vs the equal-weight universe.""" r_mkt = returns.mean(axis=1) var = r_mkt.rolling(window, min_periods=minp).var() cov = returns.rolling(window, min_periods=minp).cov(r_mkt) return cov.div(var, axis=0)

实现了如下功能:

1. 用等权股票池的横截面平均收益作为市场收益;

2. 计算市场收益的滚动方差;

3. 计算每只股票与市场收益的滚动协方差;

4. 协方差除以方差,得到每只股票的滚动 beta。

金融上,它度量的是个股对“等权市场组合”的系统性风险暴露。核心公式是:

其中是个股收益,是市场组合收益。

代码用 pandas 的滚动协方差除以滚动方差,得到随时间变化的 beta。

这里进一步分析其计算逻辑,适应场景,以及可能需要注意或修正的事项。

1 代码逻辑

1.1 输入假设

这里先对输入假设进行分析

returns是一个DataFrame:

- 行:日期或时间序列

- 列:股票

- 值:收益率,不是价格

window=BETA_WINDOW:滚动窗口,例如 60 个交易日。

minp=BETA_MINP:窗口内最少需要的有效观测数,用于控制 NaN。

1.2 计算逻辑

这里进一步分析代码的计算逻辑

r_mkt = returns.mean(axis=1)

按行求均值,得到每一天的市场收益。

如果 returns有 N 只股票,那么:

这相当于一个每日再平衡的等权组合。

注意它不等于市值加权指数,也不是真正的市场组合。

var = r_mkt.rolling(window, min_periods=minp).var()

对市场收益 r_mkt做滚动方差:

pandas 默认ddof=1,即样本方差。

min_periods控制窗口内至少有多少个非 NaN 值才计算。

cov = returns.rolling(window, min_periods=minp).cov(r_mkt)

对每一只股票收益与市场收益 r_mkt做滚动协方差:

返回结果通常是一个DataFrame,列与原returns相同,表示每只股票在每个日期的滚动协方差。

return cov.div(var, axis=0)

把每只股票的滚动协方差除以市场滚动方差:

axis=0表示按行索引对齐,也就是按日期对齐。

因为var是Series,索引为日期,所以每一行所有股票都除以当天的市场方差。

最终返回一个 beta 矩阵:
- 行:日期
- 列:股票
- 值:该股票当天的滚动 CAPM beta

2. 金融相关

这里从金融的角度,分析以上计算逻辑。

2.1 CAPM与beta

CAPM 的基本形式:

或者:

其中:

-:无风险利率;

-:市场风险溢价;

-:股票 i 对市场风险的暴露。

beta 的定义:

也可以写成:

含义说明如下

-:股票与市场同步波动;

-:进攻型、周期型,市场涨跌时波动更大;

-:防御型,波动小于市场;

-:与市场反向;

-:理论上无系统性风险暴露。

2.2 beta 是OLS回归斜率

如果把个股收益对市场收益做单变量回归:

那么 OLS 估计的斜率就是:

这正是代码中cov / var做的事。

因此,这段代码本质上是在做滚动单因子回归,但没有显式估计alpha。

2.3 滚动beta的意义

rolling(window=60)表示用过去 60 个交易日的数据估计beta,即:

这叫做时变beta或滚动历史beta。

金融含义:

- 短窗口:对近期市场变化更敏感,但噪声大;

- 长窗口:更稳定,但对结构变化反应慢;

- 60 日约等于一个季度,是常见折中。

2.4 市场组合代理

理论上,CAPM 中的市场组合应包括所有可投资资产,并按市值加权。

现实中无法直接观测,所以常用指数代理。

这段代码用:

r_mkt = returns.mean(axis=1)

即等权股票池作为市场代理。

这意味着:

- 每只股票权重相同;

- 小盘股、波动大的股票权重可能被高估;

- 与真实市值加权市场组合有差异;

- 如果股票池本身就是当前股票池,还可能存在幸存者偏差。

2.5 beta的用途

beta经常可能用于如下用途。

计算股权资本成本:

组合风险管理:组合 beta 是成分股 beta 的加权平均;

市场中性策略:根据 beta 调整多空敞口;

对冲:用股指期货对冲时,合约数量与组合 beta 有关;

绩效归因:区分 alpha 和市场 beta 收益;

因子模型:作为市场因子暴露。

3. 潜在问题

3.1 等权假设问题

等权市场包含个股自身,可能造成偏差

因为:

所以:

个股与市场协方差中包含了自身方差项。

若股票池很小,beta 会被高估。更严谨的做法是:

- 使用外部市场指数;

- 或计算市场收益时排除该股票自身;

- 或使用市值加权。

3.2 缺失值处理可能不一致

returns.mean(axis=1)

默认skipna=True,所以某天某些股票缺失时,市场收益由剩余股票平均得到。

但 returns.rolling(...).cov(r_mkt)对每只股票与市场收益计算协方差时,会忽略该股票自身的 NaN。

这样可能出现:

- 市场方差var使用了某些日期;

- 个股协方差cov使用了另一些日期;

- 分子分母样本不完全一致。

更严谨的做法是:

对每只股票,

先把该股票收益与市场收益对齐、dropna(),

再计算同一组样本上的协方差和方差。

3.3 无风险利率问题

CAPM 严格使用超额收益:

代码直接使用原始收益。

若日频无风险利率变化很小,近似可以接受;但严谨的资产定价应使用超额收益。

3.4 历史beta不等于未来beta

滚动 beta 是历史估计。

beta 会随公司杠杆、行业、宏观环境变化。实际中常用:

- Blume 调整:

- 贝叶斯收缩;

- 多因子模型;

- DCC-GARCH、Kalman 滤波等动态 beta 方法。

3.5 非同步交易与微观结构

不同市场、不同时区、停牌、涨跌停、流动性差,

都会导致收益率不同步,从而低估或高估 beta。

3.6 异常值与窗口选择

极端收益会显著影响协方差和方差。可考虑:

- winsorize;

- 使用稳健回归;

- 调整窗口长度;

- 使用指数加权

3.7 beta不需要年化

beta 是斜率,频率一致时,日频、周频、月频估计的理论 beta 相同。

把收益年化不会改变 beta,因为协方差和方差同比例缩放。

4 更严谨实现

如果希望分子分母使用完全相同的样本,可以这样写:

import pandas as pd def compute_market_beta(returns, window=60, minp=30): r_mkt = returns.mean(axis=1) betas = {} for col in returns.columns: sub = pd.concat([returns[col], r_mkt], axis=1).dropna() sub.columns = ['stock', 'mkt'] cov = sub['stock'].rolling(window, min_periods=minp).cov(sub['mkt']) var = sub['mkt'].rolling(window, min_periods=minp).var() betas[col] = cov / var return pd.DataFrame(betas)

如果要排除自身影响,可以计算除该股票外的等权市场收益:

sum_ret = returns.sum(axis=1) count = returns.notna().sum(axis=1) for col in returns.columns: r_mkt_ex = (sum_ret - returns[col]) / (count - returns[col].notna()) # 再用 r_mkt_ex 与 returns[col] 计算滚动 beta


reference

---

滚动单因子回归的计算和代码示例

https://blog.csdn.net/liliang199/article/details/165297581

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询