Skip to content

90%的均值回归策略都忽略了这一个成本变量

作者:老余捞鱼

原创不易,转载请标明出处及原作者。

本文约 2400 字 | 预计阅读 5-7 分钟

文中示例仅用于技术讨论,不构成任何操作建议。量化策略开发应以学习和技术交流为目的。本公众号不荐股、不卖课、不承诺收益。市场有风险,请合法合规投资。

均值回归(Mean Reversion)是量化策略里最经典的逻辑之一:价格偏离均值太远,总会回来。但大多数均值回归信号在实盘中都死在同一个地方,价差。

今天聊一个我在量化团队里实际在用的过滤方法:预期回归距离过滤。核心思路很简单,在下单前先算一下,价格预计能回归多少,再跟交易摩擦(spread、手续费、滑点)比一比。回归幅度覆盖不了摩擦成本,就不下单。

图1:信号看着不错,但摩擦成本把它吃掉了

一、为什么回归速度和回归距离一样重要

很多均值回归系统只看一件事:偏离够不够大。Z-score 超过 2 个标准差,触发信号。但这只是一个置信度检查,它没回答一个关键问题:价格多久能回归?

两个完全相同的 Z-score,一个标的 2 天就回归,另一个要磨蹭 20 天。前者的预期收益是正的,后者可能因为持仓成本和滑点累积变成负的。

说白了,偏离大小决定”能赚多少”,回归速度决定”多快能拿到钱”。在扣除交易摩擦后,速度往往比距离更关键。

二、用数学量化回归速度

要量化回归速度,业界标准工具是 Ornstein-Uhlenbeck 过程(OU过程)。它是连续时间下均值回归的标准数学模型,能给出条件期望的封闭解。

图2:theta 大,回归快;theta 小,回归慢

OU 过程的微分方程:

dx_t = θ × (μ - x_t) × dt + σ × dW_t

各参数含义:

参数含义直观理解
θ (theta)回归速度θ 越大,拉回均值的力越强
μ (mu)长期均值价格的”锚点”
σ (sigma)扩散系数(噪声)随机波动的幅度
W_t标准布朗运动市场的随机扰动

关键公式来了。在时间跨度 H 上,条件期望为:

E[x_{t+H} | x_t] = μ + (x_t - μ) × exp(-θ × H)

那么预期回归距离就是:

expected_reversion = (x_t - μ) × (1 - exp(-θ × H))

这里 (1 - exp(-θ × H)) 就是”在今天偏离的基础上,预计到时间 H 能恢复的比例”。θ 越大,恢复比例越高;H 越长,恢复比例也越高。

半衰期和 θ 的换算

如果你习惯用半衰期(Half-life)来理解回归速度,换算关系很简单:

θ = ln(2) / T_half

半衰期 2 天,对应 θ ≈ 0.3466。半衰期 5 天,对应 θ ≈ 0.1386。从历史数据估 θ,用 AR(1) 回归就行,后面代码部分会展示。

三、过滤器规则

有了预期回归距离的公式,过滤规则就一句话:

只有当  | 预期回归距离 | > 摩擦预算 时,才下单。

图3:过滤器像个收费站的闸门,过不了摩擦预算的信号直接拦下

摩擦预算(friction_budget)应该包含:

  • 往返价差成本(round-trip spread cost,以 bps 为单位)
  • 佣金和交易所费用
  • 滑点估计(用历史均值)
  • 安全垫(给偶尔的糟糕成交留余量)

所有量纲统一用 bps(基点),跟成本直接可比。这是整个方法最务实的部分,不跟你谈什么信号优劣,就问一个简单问题:预期赚的钱够不够付手续费?

四、数值一算,体感更清楚

光看公式您可能还没感觉,来个具体数字。假设:

参数
偏离量 x_t – μ20 bps
半衰期2 天
持仓周期 H1 天
摩擦预算8 bps

第一步:θ = ln(2) / 2 ≈ 0.3466

第二步:恢复比例 = 1 – exp(-0.3466 × 1) ≈ 0.293

第三步:预期回归 = 20 × 0.293 ≈ 5.86 bps

第四步:5.86 < 8,不交易。

图4:同样 20 bps 的偏离,扣掉摩擦后净亏 21 刀

换算成美元,以 10 万美元的名义本金计算:

项目金额
1 bps = $10
预期毛收益5.86 × $10 = $58.60
预期摩擦成本8 × $10 = $80.00
预期净收益-$21.40

同样的 Z-score,同样的偏离幅度,扣掉成本后期望是负的。这就是这个过滤器的价值所在。

五、手把手 Python 代码

逻辑不复杂,直接上代码。用 AR(1) 回归估 θ,再算预期回归距离:

import numpy as np
import pandas as pd
from math import log, exp

# 模拟残差序列(单位:bps)
s = pd.Series(np.random.normal(0, 8, 500)).cumsum() * 0.1 + 10.0

# AR(1) 回归:x_{t+1} = a + b * x_t + e
x0, x1 = s[:-1].values, s[1:].values
b = np.cov(x0, x1, ddof=0)[0, 1] / np.var(x0, ddof=0)
theta = -np.log(b) if b > 0 else 0.1

# 持仓周期
H = 1.0

# 预期回归距离
expected_reversion = (s.iloc[-1] - s.mean()) * (1 - exp(-theta * H))

print(f"b={b:.3f}, theta={theta:.3f}")
print(f"expected_reversion={expected_reversion:.2f} bps")

预期输出类似:

b=0.70, theta=0.357
expected_reversion=5.86 bps

拿到 expected_reversion 之后,跟你的 friction_budget 比一下就行。一行 if 语句,就是你的过滤器。

六、这个过滤器到底能改变什么

用了这个过滤之后,最直接的变化是交易次数变少了。一些以前会下的单,现在被拦住了。

其实这是好事。被拦住的那些单,预期收益本来就覆盖不了成本,做了也是给券商打工。少做交易、少犯错,比多找信号更管用。

这个方法还逼着你做一件事:把交易摩擦显式化。你得搞清楚自己的 spread 成本、佣金、滑点分别是多少。很多策略亏钱不是因为信号差,是因为做策略的人根本没认真算过成本。。

提示:OU 过程是对现实市场的简化模型。极端行情下(比如流动性突然枯竭),回归行为可能跟模型预估差很远。过滤器是工具,不是保险。

如果你想更进一步,可以估计 σ 的分布,对 x_{t+H} 做蒙特卡洛模拟,算出预期收益的概率分布。但从简单版开始,先把基本的过滤器跑起来。一个清晰的保守过滤器,比追着边际收益使劲,对 P&L 的贡献更快。

最后总结一下要点:

  • 回归速度和回归距离同样重要,同样的 Z-score,回归慢的可能亏钱。
  • OU 过程给出预期回归距离的封闭解,用 AR(1) 就能估参数。
  • 过滤规则就一行:预期回归距离 > 摩擦预算才下单。
  • 所有量纲统一到 bps,跟成本直接可比,别混用。
  • 交易次数减少是正常表现,拦住的本来就是负期望的单。

均值回归策略的胜负手不在信号本身,在信号和成本的关系。把这个想清楚,你已经比大部分只看 Z-score 的系统强了。

你现在的均值回归策略,有没有认真算过摩擦预算?


#均值回归 #量化策略 #OrnsteinUhlenbeck #交易摩擦 #过滤器 #Zscore #半衰期 #AR1回归 #bps #策略优化 #滑点 

Published inAI&Invest专栏

Be First to Comment

    发表回复