波动率管理:历史波动率计算、波动率锥、基于波动率的仓位调整

波动率这东西,说白了就是市场的「脾气」。

我做了这么多年量化,最深的体会就是:你永远无法预测市场往哪走,但你可以衡量它走得有多「颠」。轮动策略里,波动率管理不是锦上添花,而是保命符。今天我们就来聊聊,怎么用波动率这把尺子,量出仓位该下多重。

一、历史波动率计算:别被「历史」两个字骗了

历史波动率,听起来像是翻旧账。其实它是在回答一个问题:过去N天,这个资产每天上蹿下跳的幅度有多大?

我习惯用对数收益率来计算。为什么不用简单收益率?因为对数收益率在时间序列上可加,统计性质更好。你想想看,连续复利的概念,天然适合做波动率建模。

公式其实很简单:

σ = std(ln(P_t / P_{t-1})) * √252

这里有个坑,我曾经踩过——年化因子用252还是365? 股票市场用252个交易日,加密货币用365。别搞混了,否则波动率直接差20%。

来看一段我常用的计算代码:

import numpy as np
import pandas as pd

def calc_historical_volatility(price_series, window=20, annual_factor=252):
    """
    计算历史波动率
    :param price_series: 价格序列(pandas Series)
    :param window: 滚动窗口天数
    :param annual_factor: 年化因子
    :return: 年化波动率序列
    """
    log_returns = np.log(price_series / price_series.shift(1))
    rolling_std = log_returns.rolling(window=window).std()
    annualized_vol = rolling_std * np.sqrt(annual_factor)
    return annualized_vol

# 使用示例
prices = pd.Series([100, 102, 101, 105, 103, 107, 106])
vol = calc_historical_volatility(prices, window=5)
print(vol)
我的小技巧: 窗口期选20天还是60天?做轮动策略,我建议用20天。太长的窗口会钝化反应,等你发现波动率变了,行情早走完了。

二、波动率锥:一眼看穿波动率的「季节」

光算一个历史波动率,其实不够。为什么?因为不同时间尺度下,波动率的表现完全不一样。

举个例子:某只股票过去5天的波动率是30%,但过去60天的波动率只有20%。这说明什么?短期波动在放大,长期趋势还没变。 波动率锥就是用来可视化这种「期限结构」的。

波动率锥的构建方法:

  1. 取不同窗口长度(5天、10天、20天、60天、120天)
  2. 对每个窗口,计算滚动历史波动率
  3. 统计每个窗口的分位数(25%、50%、75%、最大值、最小值)
  4. 把这些分位数连成线,就得到一个「锥形」

我画个图帮你理解:

波动率锥示意图 5天 10天 20天 60天 120天 0% 10% 20% 30% 最大值 75%分位 中位数 25%分位 最小值 当前 窗口长度 →

看到这个锥形了吗?短期波动率的范围比长期宽得多。5天窗口的波动率可以从5%到35%,而120天窗口基本稳定在15%-25%之间。这就是波动率回归的特性。

核心用法: 如果当前波动率处于锥体的上沿(比如超过75%分位),说明市场情绪极端,后续大概率会回落。这时候减仓,胜率很高。

三、基于波动率的仓位调整:让仓位跟着「路况」走

好了,现在我们知道怎么算波动率,也知道了当前波动率在历史中的位置。下一步就是——怎么用它来调仓位?

我常用的方法叫「目标波动率仓位调整」。核心思想很简单:让每笔交易承担的风险(波动率)保持恒定

公式:

目标仓位 = 基准仓位 × (目标波动率 / 当前波动率)

举个例子:

  • 你设定的目标波动率是20%(年化)
  • 当前资产的历史波动率是40%
  • 那么仓位应该降到基准仓位的50%

反过来,如果当前波动率只有10%,仓位可以翻倍。

来看完整实现:

def position_sizing_by_volatility(current_vol, target_vol=0.20, base_position=1.0, 
                                  min_position=0.1, max_position=2.0):
    """
    基于波动率的仓位调整
    :param current_vol: 当前年化波动率
    :param target_vol: 目标年化波动率(默认20%)
    :param base_position: 基准仓位(默认1.0表示全仓)
    :param min_position: 最小仓位限制
    :param max_position: 最大仓位限制
    :return: 调整后的仓位比例
    """
    if current_vol <= 0:
        return base_position
    
    # 核心公式
    raw_position = base_position * (target_vol / current_vol)
    
    # 仓位限幅
    adjusted_position = np.clip(raw_position, min_position, max_position)
    
    return adjusted_position

# 实战场景
vol_scenarios = [0.10, 0.20, 0.30, 0.40, 0.50]
for vol in vol_scenarios:
    pos = position_sizing_by_volatility(vol)
    print(f"当前波动率: {vol:.0%} → 建议仓位: {pos:.0%}")
注意! 仓位调整不能太频繁。我曾经犯过这个错——每天根据波动率调仓,结果手续费吃掉了所有超额收益。建议至少持有3-5天再调整一次。

四、完整的波动率管理流程

把上面三块串起来,就是一个完整的闭环:

  1. 计算历史波动率:用20天滚动窗口,年化到252天
  2. 构建波动率锥:对比当前波动率在历史分位中的位置
  3. 判断市场状态:波动率处于锥体上沿 → 高风险;下沿 → 低风险
  4. 调整仓位:高风险减仓,低风险加仓
  5. 定期再平衡:每周或每两周检查一次

我自己的经验是,这套流程在震荡市中特别有效。趋势行情里反而容易踏空——因为波动率放大时你减仓了,结果行情继续猛涨。所以我会加一个条件:如果趋势指标(比如均线)显示强势,波动率仓位调整的权重降低一半

避坑指南: 我曾经在2020年3月美股熔断时,看到波动率飙到80%,按公式把仓位降到几乎空仓。结果后面反弹20%完全踏空。后来我加了「波动率衰减因子」——波动率越高,仓位调整的敏感度越低。说白了,极端行情下,波动率指标会失效,这时候要靠经验。

五、写在最后

波动率管理不是万能药,但它能让你在市场发疯的时候保持清醒。记住一句话:波动率是市场的体温计,不是天气预报。它告诉你现在有多热,但没法告诉你明天会不会降温。

用好波动率锥和仓位调整公式,你的轮动策略至少能活过大多数熊市。剩下的,就看你对市场的理解了。


公众号:蓝海资料掘金营,微信deep3321