历史波动率计算原理:对数收益率计算、标准差计算、年化处理、滚动窗口计算

各位同学,咱们今天来啃一块硬骨头——历史波动率的计算原理。

说实话,我刚入行那会儿,觉得波动率就是个数字,拿Excel一拉就完事了。后来在实盘里吃过亏,才发现这里面门道不少。你想想看,如果连波动率怎么算出来的都不清楚,你怎么敢用它去定价期权?

好,咱们一步步来拆解。

一、对数收益率:为什么不用简单收益率?

先问大家一个问题:你今天赚了10%,明天亏了10%,你的本金变了吗?

算一下:100块 → 110块 → 99块。亏了1块。

这就是简单收益率的陷阱——它不对称。而对数收益率是连续的、可加的,在时间序列分析里更干净。

公式很简单:

r_t = ln(P_t / P_{t-1})

其中P_t是今天的收盘价,P_{t-1}是昨天的。

我个人习惯用对数收益率做波动率计算,原因有三:

  • 正态性更好:对数收益率更接近正态分布,方便后续建模
  • 时间可加性:多期的对数收益率可以直接相加
  • 数值稳定性:避免出现负价格这种荒谬情况
小提示: 如果你用Python,直接用 np.log(price / price.shift(1)) 一行搞定。别自己写循环,慢。

二、标准差计算:波动率的原始形态

有了对数收益率序列,下一步就是算标准差。说白了,就是衡量这些收益率到底有多“散”。

样本标准差公式:

σ = sqrt( (1/(n-1)) * Σ(r_t - μ)² )

这里μ是收益率均值,n是样本数量。

嗯,这里要注意:

  • 样本标准差(分母n-1),不是总体标准差(分母n)
  • 因为我们是拿样本去估计总体,自由度要减1

我曾经见过一个团队,直接用 np.std() 的默认参数,结果分母是n,算出来的波动率系统性偏低。后来回测怎么都跑不赢,查了两天才发现是这里的问题。

避坑指南: Python里 np.std(ddof=0) 是总体标准差,np.std(ddof=1) 才是样本标准差。默认是ddof=0,千万记得改!

三、年化处理:把日波动率“放大”到一年

我们算出来的通常是日波动率。但期权定价、风险度量都需要年化数据。怎么转?

核心逻辑:波动率与时间的平方根成正比

公式:

σ_年化 = σ_日 × sqrt(252)

为什么是252?因为一年大约有252个交易日。

这里有个坑:

  • 美股用252,A股用242-245(扣除节假日)
  • 加密货币市场用365(7×24小时交易)
  • 千万别搞混,否则波动率直接偏掉

你想想看,如果A股你用了252,年化波动率会偏高约2%。做高频可能不明显,但做中长线策略,这点误差足以影响仓位管理。

核心要点: 年化处理不是简单的乘法,而是基于“独立同分布”假设。如果收益率存在自相关,这个假设就不成立。实盘中我一般会先做Ljung-Box检验,确认序列白噪声后再年化。

四、滚动窗口计算:让波动率“活”起来

静态波动率没意义。市场在变,波动率也在变。我们需要一个滚动窗口,不断更新。

常见的窗口长度:

窗口长度 适用场景 特点
20天(约1个月) 短期交易、高频策略 反应快,但噪音大
60天(约1季度) 中期趋势跟踪 平衡了灵敏度和稳定性
252天(1年) 长期投资、风险预算 平滑,但滞后明显

我个人习惯用20天和60天双窗口。20天捕捉短期波动,60天看中期趋势。两者交叉验证,比单一窗口靠谱得多。

代码实现也很简单:

# 假设df是包含收盘价的DataFrame
df['log_return'] = np.log(df['close'] / df['close'].shift(1))
df['vol_20d'] = df['log_return'].rolling(20).std() * np.sqrt(252)
df['vol_60d'] = df['log_return'].rolling(60).std() * np.sqrt(252)

这里有个细节:rolling(20).std() 默认用的是ddof=1,也就是样本标准差。Pandas这点做得比NumPy好,默认就是对的。

注意: 滚动窗口的第一个窗口期是没有值的。比如20天窗口,前19天都是NaN。实盘里要处理好这个边界,别把空值喂给模型。

五、完整流程图:历史波动率计算全流程

下面这张图,把整个计算逻辑串起来了。建议你保存下来,写代码时对照着看。

历史波动率计算流程图 获取收盘价序列 计算对数收益率 滚动窗口标准差 年化处理 ×√252 历史波动率序列 关键参数说明 窗口长度:20/60/252天 年化因子:√252(A股) 标准差:样本标准差 (ddof=1) 常见坑点: 1. 忘记年化 2. 用错交易日数 3. 窗口边界NaN 4. 简单收益率替代 建议:双窗口交叉验证

六、实战中的几个经验

最后,分享几个我在项目中踩过的坑,希望对你有帮助:

  1. 数据频率要统一:别把日线和小时线混在一起算波动率。我见过有人用日线算波动率,却用小时线做交易,结果波动率完全对不上。
  2. 异常值处理:遇到停牌、涨跌停、分红除权,收益率会突变。我一般用MAD(中位数绝对偏差)做异常值过滤,比3σ更稳健。
  3. 不要过度优化窗口:20天就是20天,别为了拟合历史数据去调成19天或21天。过拟合的波动率,在实盘里一文不值。
  4. 波动率聚集效应:高波动率之后往往跟着高波动率。如果你发现滚动波动率突然飙升,别急着加仓,等它稳定下来再说。

好了,历史波动率的计算原理就讲到这里。记住,波动率不是目的,而是工具。怎么用它去定价、去风控、去交易,才是我们后面要深入的内容。