halo 的技术博客

返回

「指数涨了 1%,我的对冲头寸怎么反而亏了?」——这是用固定对冲比做配对/对冲交易的人,最常在 regime 切换时遇到的问题。根子在哪儿?你用来对冲的那个 β,它自己就在变。

本文不堆公式,直接给你一套能跑的代码:把对冲比放进状态空间模型,用卡尔曼滤波(Kalman Filter)从价格序列里实时「学」出动态 β,再和静态 OLS、滚动 OLS 做硬碰硬的对比。你会发现,光是「让对冲比动起来」这一步,就能把对冲残差的方差砍掉一个数量级。

动态对冲比 β_t 随时间演化:固定对冲比会系统性偏离真实值

一、为什么固定对冲比会失效#

最朴素的对冲思路是最小二乘:用一段历史窗口回归 y = β·x + ε,拿到一个 β 后,长期持有「多 y、空 β 份 x」的中性组合。问题在于——这个 β 是历史的平均值,而市场不是静止的

真实世界里,对冲比会变的原因至少有三:

  • Regime 切换:比如股指期货和现货的基差结构在升水/贴水之间切换,对冲比会跳变;
  • 结构性漂移:标的的基本面关系缓慢变化(如两只股票从强相关走向分化);
  • 流动性与微观结构:成交量、买卖价差变化会改变两者的最优对冲比例。

下图第一根线就是「真实 β_t」:它在中段有一个正弦慢漂移,在 t=950 附近还有一个阶跃(模拟一次 regime 切换)。后面三条线分别是三种估计方法——你能直观看到,红色虚线(静态 OLS)在最右侧已经系统性偏离,橙色(滚动 OLS)能跟上但噪声大、滞后明显,而蓝色(卡尔曼)既跟得住又平滑。

二、卡尔曼滤波:一句话直觉#

卡尔曼滤波干的事,就是在「信任模型预测」和「信任新观测」之间,按不确定性动态加权

想象你蒙眼往前走(状态预测),每隔几秒有人告诉你真实位置(观测)。如果你走得很稳(预测不确定小),你就更信自己的估计;如果观测噪声很小(测量很准),你就更信那个读数。卡尔曼滤波用严格的数学,把这两种「信任度」量化成每一步的卡尔曼增益(Kalman Gain),自动求出最优折中。

放到对冲场景,我们把「对冲比 β」当作隐藏状态——它看不见,但能通过 yx 的关系推断出来。

三、动态对冲比的状态空间模型#

把对冲关系写成:

观测方程:  y_t = β_t · x_t + μ_t + ε_t,    ε_t ~ N(0, R)      ← R 是观测噪声方差
状态方程:  [β_t, μ_t]^T = [β_{t-1}, μ_{t-1}]^T + w_t,  w_t ~ N(0, Q)  ← Q 是状态演化方差
plaintext

这里 β_t 是我们要的动态对冲比,μ_t 是缓慢漂移的截距(吸收价差、基差等水平项),Q 控制 β 变化的「快慢」,R 控制我们对价格噪声的容忍。整套逻辑就是含时变系数的线性回归,用卡尔曼滤波在线估计

下面是从零实现的卡尔曼滤波(不依赖 pykalman,纯 numpy,方便你嵌进回测):

注意 QR 这两个旋钮:Q 调大,滤波更「跟手」但更抖;R 调大,滤波更「平滑」但更滞后。实战里通常用一段样本做极大似然或网格搜索来定,下文会讲。

四、实证对比:静态 OLS vs 滚动 OLS vs 卡尔曼#

我们用一段合成数据(x 为标的物、y 为其可套利对手,真实 β_t 含慢漂移 + 一次阶跃)跑三种方法,看对冲后的残差有多干净。对照组代码:

把对冲残差的累计轨迹画出来(下图),结论很直观:卡尔曼动态对冲的净值线明显更扁、更贴着 0 轴,说明它把绝大部分共同波动都对冲掉了,剩下的是真正的 idiosyncratic 噪声。

对冲残差轨迹:动态对冲把波动压得更扁、更稳

更硬的指标看分布。把日度残差(即对冲组合的每日 PnL)画成直方图:

对冲后 PnL 分布:动态对冲显著收窄方差、削减尾部

在我跑的这组样本里,静态 OLS 对冲残差的标准差约 18.8,而卡尔曼动态对冲只有 1.9,方差下降约 99%。这不是「魔法」——静态方法在 regime 切换后,用的是过时的 β,等于对冲了一半「错误的方向」,残差里混入了大量本可对冲掉的系统性波动。

提醒:99% 是合成数据刻意放大了 regime 切换的演示效果。真实市场里削减幅度没这么夸张,但「动态对冲显著优于静态」的结论是稳健的,尤其在基差/价差结构易变的产品上。

五、另一战场:动态 Delta 对冲#

卡尔曼滤波不止能对冲「两只标的的关系」,也能对冲「期权与标的的关系」。期权 Delta 本质就是对标的的局部对冲比,而它会随价格、时间、波动率一起变。

思路完全通用:把期权价格当 y、标的当 x,用卡尔曼滤波在线估计「隐含 Delta」——它甚至不依赖 BS 模型的波动率假设,是从 tick 数据里直接「反」出来的经验 Delta。对波动率曲面扭曲、临近到期的合约,这种数据驱动的 Delta 往往比解析公式更贴实际。本质上,这就是把上一节的 β_t 换成 Δ_t,其余代码一行都不用改。

六、滤波器直观:它到底在权衡什么#

下图把卡尔曼滤波的「灵魂」单独拎出来演示:一条被重噪声淹没的绿色真实信号,灰色是含噪观测,蓝色是滤波估计,蓝色阴影是 95% 置信带。

卡尔曼滤波对含噪信号的跟踪:自动在「跟得住」与「抗噪声」间权衡

你能看到:在信号平稳段,置信带很窄、估计很稳;在信号快速变化时,滤波会「试探性」跟随但保留安全裕度。这正是 Q(状态敢不敢变)和 R(敢不敢信观测)两个旋钮在起作用——不是猜测,而是每一步都用不确定度算出来的最优权衡

七、实战三大陷阱#

  1. Q/R 调参即模型风险:滤波质量高度依赖 QR。调得太「跟手」会过拟合噪声、制造假信号;太「平滑」又滞后。务必在样本外或用滚动窗口重估,别把全样本最优参数当圣旨。
  2. 假设线性高斯:标准卡尔曼滤波假设状态方程和观测方程都是线性、噪声是高斯的。跳空缺口、涨跌停、流动性黑洞会让这些假设瞬间崩塌,此时需要扩展卡尔曼(EKF)或无迹卡尔曼(UKF),甚至粒子滤波。
  3. 别忽略交易成本:动态对冲意味着更频繁调仓。β_t 每变一点就 rebalance,手续费和冲击成本可能吃掉全部方差削减收益。实务上要加「死区」(β 变化超过阈值才调仓)或在目标函数里直接计入成本。

八、小结#

卡尔曼滤波给动态对冲提供了一套在线、自适应、带不确定度量的框架:它把「对冲比」从「历史平均值」升级成「随市场实时演化的状态」,在 regime 切换和高噪声环境里,比静态/滚动 OLS 更跟手、更干净。它的真正价值不在「预测」,而在「在信模型还是信数据之间,每一步都做出数学最优的取舍」。

下一篇,我们把镜头从「估计一个参数」转向「在几千种组合里搜索最优解」——遗传算法如何在大约束下做组合优化。

卡尔曼滤波在动态对冲中的应用
https://blog.halo26812.eu.org/blog/kalman-dynamic-hedging
Author halo
Published at 2026年7月11日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨