3. 案例03

案例03:计算波动率因子并进行横截面标准化 学习卡片

任务说明

本案例基于多只股票的日线收盘价,计算每只股票过去20个交易日的收益率标准差作为波动率因子,再对同一交易日所有股票的波动率因子做横截面 Z-score 标准化,最后输出标准化结果。

环境与依赖

  • Python 3.8+
  • pandas、numpy

安装命令:pip install pandas numpy

实现思路

  1. 构造宽表:行索引为交易日,列名为股票代码,值为收盘价。
  2. 用 pct_change() 计算日收益率。
  3. 用 rolling(20).std() 得到20日收益率标准差,即波动率因子。
  4. 按行(axis=1)做 Z-score:(x - mean) / std,得到横截面标准化结果。

完整代码

import numpy as np
import pandas as pd

np.random.seed(0)

# 1. 构造示例数据:5只股票、60个交易日的收盘价
dates = pd.date_range("2024-01-01", periods=60, freq="B")
codes = ["A", "B", "C", "D", "E"]
prices = pd.DataFrame(
    np.cumprod(1 + np.random.normal(0, 0.02, size=(60, 5)), axis=0) * 100,
    index=dates, columns=codes,
)

# 2. 日收益率
returns = prices.pct_change()

# 3. 20日收益率标准差 = 波动率因子
vol = returns.rolling(window=20).std()

# 4. 横截面 Z-score 标准化(按行)
cs_mean = vol.mean(axis=1)
cs_std = vol.std(axis=1, ddof=0)
vol_z = vol.sub(cs_mean, axis=0).div(cs_std, axis=0)

# 5. 输出结果
result = vol_z.dropna(how="all")
print(result.tail(5).round(4))

# 校验:每个有效交易日的横截面均值≈0、标准差≈1
check = pd.DataFrame({
    "mean": result.mean(axis=1),
    "std": result.std(axis=1, ddof=0),
})
print(check.tail(5).round(6))

运行方式

将代码保存为 vol_factor.py,执行:python vol_factor.py。

验证方法与通过条件

  • 输出末尾5行应为一个 5×5 的标准化矩阵,数值量级大致在 -2 到 2 之间。
  • 校验表中每个有效交易日的 mean 应接近 0(浮点误差范围内),std 应接近 1。
  • 满足以上两点即说明波动率因子计算与横截面 Z-score 标准化均正确。

常见问题

  • 若某交易日有效股票数少于2,std 为 NaN,标准化结果也为 NaN,属正常现象。
  • 若需按行业或市值分组标准化,可将 mean/std 替换为 groupby 分组统计后再做减法与除法。