3、低波动因子的度量方法:波动率的计算方式与预测模型

波动率这东西,说白了就是资产价格的「心跳」。心跳太快,你拿不住;心跳太慢,收益又不够看。低波动因子之所以能赚钱,核心就在于我们得先搞清楚——到底什么是「低波动」?

我个人习惯把波动率的度量分成两派:一派是「回头看」的,比如历史波动率、已实现波动率;另一派是「向前看」的,比如隐含波动率、GARCH预测。今天咱们就把这些家伙挨个捋一遍。

3.1 历史波动率:最朴素的算法

历史波动率,说白了就是过去N天收益率的标准差。你打开Excel,用STDEV函数算一下,就是这个东西。但这里有个坑——你算的是对数收益率还是简单收益率?

我建议用对数收益率。为什么呢?因为对数收益率在时间上可加,而且更符合正态分布的假设。简单收益率算出来的波动率,在价格波动大的时候会偏大。

import numpy as np
import pandas as pd

def historical_volatility(prices, window=20, trading_days=252):
    """
    计算历史波动率
    prices: 价格序列
    window: 滚动窗口天数
    trading_days: 年化交易日数
    """
    # 计算对数收益率
    log_returns = np.log(prices / prices.shift(1))
    # 滚动标准差
    rolling_std = log_returns.rolling(window=window).std()
    # 年化
    annualized_vol = rolling_std * np.sqrt(trading_days)
    return annualized_vol

# 举个栗子
prices = pd.Series([100, 102, 101, 103, 105, 104, 106, 108])
vol = historical_volatility(prices, window=5)
print(vol)
避坑指南:我曾经在回测时直接用20日历史波动率排序,结果发现换手率高得吓人。后来加了中位数平滑,才把换手率降下来。记住:原始波动率序列噪声很大,建议做一下平滑处理。

3.2 已实现波动率:高频数据的魅力

历史波动率用的是日频数据,但如果你有日内数据呢?比如5分钟K线。这时候就可以算已实现波动率(Realized Volatility)了。

已实现波动率的公式很简单:把一天内所有高频收益率的平方加起来,再开根号。你想想看,这比只用收盘价算出来的波动率要精确得多。

def realized_volatility(intraday_returns):
    """
    计算已实现波动率
    intraday_returns: 日内收益率序列(比如5分钟收益率)
    """
    # 平方和开根号
    rv = np.sqrt(np.sum(intraday_returns ** 2))
    return rv

# 假设一天有48个30分钟收益率
intraday_ret = np.random.randn(48) * 0.01
rv = realized_volatility(intraday_ret)
print(f"今日已实现波动率: {rv:.4f}")
重要提醒:已实现波动率对微观结构噪声很敏感。比如买卖价差、数据缺失都会导致估计偏差。我一般会先用5分钟数据,再做个去噪处理。

3.3 隐含波动率:市场预期的温度计

隐含波动率是从期权价格反推出来的。市场觉得未来会波动大,隐含波动率就高;觉得风平浪静,它就低。这东西有个特点——它自带前瞻性。

我记得在2018年做低波动策略时,发现一个有趣的现象:当隐含波动率远高于历史波动率时,低波动因子往往表现更好。为什么?因为市场在过度恐慌,低波动股票被错杀了。

计算隐含波动率需要用到BS公式的反函数,这里给个简单示例:

from scipy.stats import norm
from scipy.optimize import brentq

def bs_call_price(S, K, T, r, sigma):
    """BS公式计算看涨期权价格"""
    d1 = (np.log(S/K) + (r + 0.5*sigma**2)*T) / (sigma*np.sqrt(T))
    d2 = d1 - sigma*np.sqrt(T)
    return S*norm.cdf(d1) - K*np.exp(-r*T)*norm.cdf(d2)

def implied_volatility(market_price, S, K, T, r):
    """用二分法反推隐含波动率"""
    objective = lambda sigma: bs_call_price(S, K, T, r, sigma) - market_price
    return brentq(objective, 0.01, 2.0)

# 示例
iv = implied_volatility(market_price=5.2, S=100, K=105, T=30/365, r=0.03)
print(f"隐含波动率: {iv:.2%}")
注意:隐含波动率不是直接拿来用的。它包含了很多情绪因素,比如恐慌、贪婪。我建议把它和历史波动率做个差值,这个差值才是真正的「波动率溢价」。

3.4 波动率预测模型:GARCH与EWMA

前面讲的都是「已经发生」的波动率。但做量化投资,我们更关心「未来」的波动率。这时候就需要预测模型了。

3.4.1 EWMA:指数加权移动平均

EWMA的思路很简单:越近的数据权重越大。它只有一个参数λ(衰减因子),通常取0.94(RiskMetrics的标准)。

def ewma_volatility(returns, lambda_=0.94):
    """
    EWMA波动率估计
    returns: 收益率序列
    lambda_: 衰减因子
    """
    n = len(returns)
    vol = np.zeros(n)
    # 初始方差用样本方差
    vol[0] = np.var(returns)
    
    for t in range(1, n):
        vol[t] = lambda_ * vol[t-1] + (1-lambda_) * returns[t-1]**2
    
    return np.sqrt(vol)

# 使用示例
returns = np.random.randn(100) * 0.02
ewma_vol = ewma_volatility(returns)

EWMA的好处是计算快、参数少。但有个问题——它对极端事件的反应不够灵敏。我曾在2015年股灾时用EWMA做风控,结果波动率上升的速度跟不上市场暴跌的速度。

3.4.2 GARCH:更精细的波动率建模

GARCH模型比EWMA多了一个东西——它考虑了「波动率的波动率」。简单说,GARCH(1,1)有三个参数:ω(长期均值)、α(新信息的影响)、β(旧波动的影响)。

from arch import arch_model

def garch_volatility(returns, p=1, q=1):
    """
    GARCH(p,q)波动率预测
    """
    model = arch_model(returns, vol='Garch', p=p, q=q)
    res = model.fit(disp='off')
    
    # 预测未来5天的波动率
    forecasts = res.forecast(horizon=5)
    predicted_vol = np.sqrt(forecasts.variance.values[-1])
    
    return predicted_vol, res

# 示例
returns = np.random.randn(500) * 0.015
pred_vol, model_result = garch_volatility(returns)
print(f"未来5天预测波动率: {pred_vol}")
我的经验:GARCH模型在正常市场下表现不错,但遇到极端行情容易失效。我一般会结合GARCH和已实现波动率做一个混合模型,效果比单独用任何一个都好。

3.5 知识体系总览

说了这么多,咱们用一张图把整个脉络串起来:

低波动因子度量方法体系 历史波动率 已实现波动率 隐含波动率 对数收益率标准差 高频收益率平方和 BS公式反推 EWMA指数加权 GARCH(p,q)模型 应用场景 低波动因子构建 | 风险平价策略 | 波动率择时 | 期权定价 组合优化 | 尾部风险对冲 | 波动率套利 注:虚线表示跨类别关联,实线表示直接推导关系

3.6 实战中的选择建议

说了这么多方法,到底用哪个?我个人的经验是:

场景 推荐方法 理由
日频因子构建 历史波动率(60日窗口) 简单稳定,数据易得
高频交易策略 已实现波动率 反应快,精度高
期权策略 隐含波动率 包含市场预期
风险预测 GARCH(1,1) 能捕捉波动率聚集效应
快速风控 EWMA (λ=0.94) 计算快,参数少
一个小技巧:我建议把多种波动率指标结合起来用。比如用历史波动率做因子排序,用GARCH预测做风险控制,用隐含波动率做择时信号。三个维度互相验证,胜率会高很多。

嗯,波动率的度量方法就聊到这儿。记住一点:没有完美的波动率指标,只有最适合你策略的指标。多试试不同的组合,找到那个让你睡得着觉的度量方式。

专注资料整理