3. 低波动因子构建:波动率的计算、排序与回测框架
各位同学,咱们今天聊点实在的。低波动策略的核心,说白了就是找到那些「涨得慢、跌得也慢」的股票。那怎么量化这个「慢」呢?答案就是——波动率。
我个人习惯把波动率比作股票的「心跳」。心跳太快,容易猝死;心跳太慢,可能是个僵尸。我们要找的,就是那种心跳平稳、长期健康的股票。
3.1 历史波动率:最朴素的度量
历史波动率,就是看过去一段时间股价的「上蹿下跳」程度。计算方式很简单:
- 取对数收益率:ln(Pt / Pt-1)
- 计算标准差:对收益率序列求标准差
- 年化处理:乘以 sqrt(252)(一年约252个交易日)
嗯,这里要注意一点。我见过很多新手直接拿收盘价算波动率,结果被分红、送股搞得数据全是坑。一定要用复权价格,最好是后复权。
历史波动率 = std(ln(Pt/Pt-1)) × sqrt(252)
代码实现也很直接:
import numpy as np
import pandas as pd
def calc_historical_vol(price_series, window=20):
"""
计算历史波动率
:param price_series: 复权价格序列
:param window: 滚动窗口,默认20天
"""
log_ret = np.log(price_series / price_series.shift(1))
hist_vol = log_ret.rolling(window).std() * np.sqrt(252)
return hist_vol
你想想看,为什么用20天?其实没有标准答案。我在做A股回测时,20天刚好覆盖一个月的交易天数,能较好地捕捉短期波动特征。但如果你做的是高频策略,可能用5天更合适。
3.2 已实现波动率:更精细的度量
历史波动率有个问题——它只用了收盘价。但一天之内,股价可能上蹿下跳好几次。这时候就需要已实现波动率了。
已实现波动率,说白了就是把一天内的分钟收益率平方加起来。公式长这样:
RVt = sqrt( Σ ri² ) × sqrt(252)
其中 ri 是第 i 分钟的收益率。
我曾经在实盘中吃过亏。用5分钟数据算RV,结果发现和用30分钟数据算出来的结果差异巨大。后来才意识到,采样频率越高,噪声越大。我个人建议:A股用5分钟或15分钟数据比较合适,既能捕捉日内波动,又不会引入太多微观结构噪声。
def calc_realized_vol(minute_returns, freq=5):
"""
计算已实现波动率
:param minute_returns: 分钟收益率序列
:param freq: 采样频率(分钟)
"""
# 重采样到指定频率
resampled = minute_returns.resample(f'{freq}min').sum()
rv = np.sqrt((resampled ** 2).sum()) * np.sqrt(252)
return rv
3.3 波动率排序与分组
算完波动率,下一步就是排序和分组。这一步很关键,直接决定了你的因子是否有效。
我的做法是:
- 每月末,计算每只股票过去20天的波动率
- 按波动率从小到大排序,分成10组(Decile)
- 做多最低波动组,做空最高波动组
你可能会问:为什么是10组?不是5组或20组?
嗯,这里有个经验之谈。分组太少,组内股票差异不够大;分组太多,每组股票太少,统计意义下降。10组是个折中方案,也是学术界常用的做法。
| 分组 | 波动率范围 | 预期表现 |
|---|---|---|
| 第1组(最低波动) | 0% - 15% | 低收益、低风险 |
| 第5组(中等波动) | 15% - 30% | 中等收益、中等风险 |
| 第10组(最高波动) | 30%以上 | 高收益、高风险 |
3.4 低波动因子的回测框架搭建
好了,现在因子有了,分组也做好了。接下来就是搭建回测框架,验证这个因子到底能不能赚钱。
我习惯用事件驱动型回测框架。核心逻辑是这样的:
class LowVolBacktest:
def __init__(self, data, rebalance_freq='M'):
self.data = data # 包含价格、波动率的数据
self.rebalance_freq = rebalance_freq
def run(self):
# 1. 在每个调仓日计算波动率
# 2. 按波动率排序分组
# 3. 买入最低波动组,卖出最高波动组
# 4. 计算组合收益
# 5. 统计绩效指标
pass
具体实现时,有几个关键点要注意:
- 避免前视偏差:计算波动率时只能用历史数据,不能用未来数据
- 考虑交易成本:低波动策略换手率不高,但也不能忽略
- 市值中性化:低波动股票往往是大盘股,要剔除市值影响
我曾经犯过一个低级错误——用当天的收盘价计算波动率,然后当天就买入。结果回测收益高得离谱,实盘却一塌糊涂。后来才发现,这是典型的前视偏差。
下面这张图,是我整理的低波动因子构建与回测的完整流程:
这张图把整个流程串起来了。从数据获取到绩效评估,每一步都有坑。但只要你按照这个框架来,至少能保证回测结果不会太离谱。
最后说一句:回测只是起点,不是终点。我见过太多人回测收益翻倍,实盘却亏得底裤都不剩。原因无他——回测框架太理想化。所以,在搭建框架时,尽量把现实因素考虑进去,比如交易成本、流动性限制、冲击成本等。
• 历史波动率:简单但粗糙,适合快速筛选
• 已实现波动率:精细但数据要求高,适合深度分析
• 排序分组:10组是黄金标准,兼顾统计意义和可操作性
• 回测框架:事件驱动型最灵活,但要注意前视偏差