跳到正文

最短回测长度(MBL):需要多少年数据?

需要多少年的回测数据,才能对报告出来的夏普比率有足够把握?最短回测长度公式会给出答案。本文从概率夏普比率设定出发完整推导,并说明偏度和峰度的作用。

第 6 篇 · 共 12 篇 约 11 分钟

两年的回测数据不够。五年处在边缘。十年通常才算最低要求。最短回测长度(MBL)公式会准确告诉你:在指定的置信水平下,需要多少个观测,才能让报告出来的夏普在统计上和目标基准区分开。

本文从 PSR 公式推导 MBL。我们从这个要求倒推:“我希望目标夏普为 SR^\widehat{SR} 时,PSR(SRb)≥0.95PSR(SR_b) \ge 0.95”,然后解出 TT。

MBL 回答什么问题

你准备回测一个策略。你有一个目标基准 SRbSR_b(通常是 0,有时是 0.5,也可能更高)。你想知道:如果真实夏普等于预期夏普 SR^\widehat{SR},需要多少个观测 TT,才能让 PSR 至少达到 0.95?

换句话说:假设估计值是对的,需要多大的样本量,才能有 95% 的把握认为真实夏普超过基准?

MBL 公式会给出满足这个要求的最小 TT。在回测之前就应该算它。如果所需的 TT 超过了可用历史数据,你就没有足够的数据,回测结果的噪声太大,不能据此行动。

从 PSR 推导

回忆本模块上一篇文章中的 PSR 公式:

PSR(SRb)=Φ(SR^−SRbσSR)PSR(SR_b) = \Phi\left(\frac{\widehat{SR} - SR_b}{\sigma_{SR}}\right)

其中,σSR\sigma_{SR} 是夏普估计量的标准误:

σSR2=1T−1(1−γ3SR^+γ4−14SR^2)\sigma_{SR}^2 = \frac{1}{T-1}\left(1 - \gamma_3 \widehat{SR} + \frac{\gamma_4 - 1}{4} \widehat{SR}^2\right)

我们希望 PSR(SRb)=0.95PSR(SR_b) = 0.95。于是 Φ\Phi 的参数必须等于 Φ−1(0.95)≈1.645\Phi^{-1}(0.95) \approx 1.645:

SR^−SRbσSR=1.645\frac{\widehat{SR} - SR_b}{\sigma_{SR}} = 1.645

解 σSR\sigma_{SR}:

σSR=SR^−SRb1.645\sigma_{SR} = \frac{\widehat{SR} - SR_b}{1.645}

现在代入方差公式:

1T−1(1−γ3SR^+γ4−14SR^2)=SR^−SRb1.645\sqrt{\frac{1}{T-1}\left(1 - \gamma_3 \widehat{SR} + \frac{\gamma_4 - 1}{4} \widehat{SR}^2\right)} = \frac{\widehat{SR} - SR_b}{1.645}

两边平方:

1T−1(1−γ3SR^+γ4−14SR^2)=(SR^−SRb1.645)2\frac{1}{T-1}\left(1 - \gamma_3 \widehat{SR} + \frac{\gamma_4 - 1}{4} \widehat{SR}^2\right) = \left(\frac{\widehat{SR} - SR_b}{1.645}\right)^2

解 TT:

T=1+(1−γ3SR^+γ4−14SR^2)⋅(1.645SR^−SRb)2T = 1 + \left(1 - \gamma_3 \widehat{SR} + \frac{\gamma_4 - 1}{4} \widehat{SR}^2\right) \cdot \left(\frac{1.645}{\widehat{SR} - SR_b}\right)^2

这就是 MBL 公式。对高斯收益率(γ3=0\gamma_3 = 0、γ4=3\gamma_4 = 3):

TGaussian=1+(1+SR^22)⋅(1.645SR^−SRb)2T_{Gaussian} = 1 + \left(1 + \frac{\widehat{SR}^2}{2}\right) \cdot \left(\frac{1.645}{\widehat{SR} - SR_b}\right)^2

怎么读这个公式

有三个项要看:

  1. 非正态因子 (1−γ3SR^+γ4−14SR^2)\left(1 - \gamma_3 \widehat{SR} + \frac{\gamma_4 - 1}{4} \widehat{SR}^2\right)。高斯收益率下,它是 1+SR^2/21 + \widehat{SR}^2/2。收益率偏度为负(γ3<0\gamma_3 < 0)时,这一项更大,也就需要更多数据。

  2. 夏普差距 SR^−SRb\widehat{SR} - SR_b。差距越小,需要的数据越多。两者是平方关系:差距减半,数据需求增加 4 倍。

  3. 置信水平 1.645(对应 95%)。99% 置信度用 2.326,90% 用 1.282。

这是一个可以直接解出的 TT 公式,不需要迭代。

完整例子

例 1:日频股指期货趋势跟踪。

目标夏普:1.0。基准:0。偏度:γ3=0\gamma_3 = 0(为简单起见,假设高斯)。超额峰度:γ4=0\gamma_4 = 0。时间步长:日频。

T=1+(1+0.5)⋅(1.645/1.0)2=1+1.5⋅2.706=1+4.06=5.06T = 1 + (1 + 0.5) \cdot (1.645/1.0)^2 = 1 + 1.5 \cdot 2.706 = 1 + 4.06 = 5.06

所以 T=6T = 6 个观测?这看起来太小了。问题在于:公式给出的 TT 使用的是收益率频率单位。对日频数据来说,T=6T = 6 天不可能支持任何真正的结论。答案的单位就是你输入的收益率频率。

转换成年数,要除以每年的观测数:

Tyears=TobsfT_{years} = \frac{T_{obs}}{f}

对 f=252f = 252 的日频数据:

Tyears=6252=0.024 yearsT_{years} = \frac{6}{252} = 0.024 \text{ years}

等等,这意味着总共只有 T=6T = 6 个观测,也就是 6 个交易日或 0.024 年。这和前面说“五年处在边缘”矛盾。

重新仔细算一遍。公式中的夏普必须和观测使用相同频率。所以 SR^=1.0\widehat{SR} = 1.0 是年化夏普,但公式使用的是收益率频率单位。用日频夏普重算:

SR^daily=1.0/252=0.063\widehat{SR}_{daily} = 1.0 / \sqrt{252} = 0.063。那么:

T=1+(1+0.0632/2)⋅(1.645/0.063)2=1+1.002⋅681.6=683T = 1 + (1 + 0.063^2/2) \cdot (1.645 / 0.063)^2 = 1 + 1.002 \cdot 681.6 = 683

所以需要 683 个日频观测,也就是 683/252≈2.7683 / 252 \approx 2.7 年。

因此,一个年化夏普为 1.0 的趋势策略,要有 95% 的把握超过 SRb=0SR_b = 0,需要 2.7 年数据。

重新用正确单位写一遍例 1。

例 1(修正后):日频股指期货趋势跟踪。

年化目标夏普:1.0。日频夏普:1.0/252=0.0631.0/\sqrt{252} = 0.063。基准(日频):0。高斯假设:γ3=0\gamma_3 = 0、γ4=0\gamma_4 = 0。

Tdaily=1+(1+0.06322)⋅(1.6450.063)2=1+1.002⋅681.6=683T_{daily} = 1 + \left(1 + \frac{0.063^2}{2}\right) \cdot \left(\frac{1.645}{0.063}\right)^2 = 1 + 1.002 \cdot 681.6 = 683

所以需要 683 个交易日,也就是大约 2.7 年。

如果基准 SRb=0.5SR_b = 0.5(年化),日频基准为 0.5/252=0.03150.5/\sqrt{252} = 0.0315:

Tdaily=1+1.002⋅(1.645/0.0315)2=1+1.002⋅2727=2733T_{daily} = 1 + 1.002 \cdot (1.645/0.0315)^2 = 1 + 1.002 \cdot 2727 = 2733

所以需要 2733 天,也就是大约 10.8 年。想以 95% 的把握区分夏普 1.0 和 0.5,需要超过十年的日频数据。

例 2:SPX 日频空波动率策略。

年化目标夏普:1.5。日频夏普:1.5/252=0.09451.5/\sqrt{252} = 0.0945。偏度:γ3=−1.5\gamma_3 = -1.5(空波动率策略的典型情况)。超额峰度:γ4=3\gamma_4 = 3。

Tdaily=1+(1−(−1.5)(0.0945)+(3/4)(0.0945)2)⋅(1.645/0.0945)2T_{daily} = 1 + (1 - (-1.5)(0.0945) + (3/4)(0.0945)^2) \cdot (1.645/0.0945)^2 =1+(1+0.142+0.0067)⋅(17.41)2= 1 + (1 + 0.142 + 0.0067) \cdot (17.41)^2 =1+1.149⋅303.0= 1 + 1.149 \cdot 303.0 =1+348.1=349= 1 + 348.1 = 349

所以需要 349 个交易日,也就是大约 1.4 年。这个结果看起来很短,但夏普差距很大(1.5 对 0)。

如果基准为 1.0(年化),日频基准为 0.063:

Tdaily=1+1.149⋅(1.645/(0.0945−0.063))2=1+1.149⋅(1.645/0.0315)2T_{daily} = 1 + 1.149 \cdot (1.645/(0.0945-0.063))^2 = 1 + 1.149 \cdot (1.645/0.0315)^2 =1+1.149⋅2727=3135= 1 + 1.149 \cdot 2727 = 3135

需要 3135 天,也就是 12.4 年。要有 95% 的把握认为夏普 1.5 超过基准 1.0,需要 12.4 年日频数据。

教训是:说“我的夏普不是零”,远比说“我的夏普超过一个激进基准”容易。

MBL 为什么重要

MBL 在你相信回测结果之前,先回答“回测够不够长?”如果可用数据短于 MBL,就不应该根据这次回测做决策。

实际工作流可以这样走:

  1. 决定目标夏普 SR^\widehat{SR},也就是你希望策略实现的水平。
  2. 决定基准 SRbSR_b,也就是你需要超过的水平。
  3. 决定置信水平(95% 是惯例;90% 偏宽松;99% 偏保守)。
  4. 计算 MBL。
  5. 把 MBL 和可用数据比较。
  6. 如果 MBL > 可用数据,不要相信这次回测。要么降低置信要求,要么寻找更多数据,要么接受这个样本量无法完成统计验证。

MBL 还会告诉你什么时候根本不值得做回测。如果目标夏普是 0.5、基准是 0.4,就需要 13 年以上的日频数据。很少有策略能有这么长的有效历史,而且还覆盖多个状态、没有结构断点。所以你只能提高目标夏普、降低基准,或者接受较低的置信度。

低夏普目标的诅咒

量化研究中一个常见错误是:开发一个目标夏普为 0.3 的策略,准备逐步放大规模,然后做 3 年回测。SR^=0.3\widehat{SR} = 0.3 相对于 SRb=0SR_b = 0 的 MBL 是:

Tdaily=1+(1+0.32/2/252)⋅(1.645/(0.3/252))2T_{daily} = 1 + (1 + 0.3^2/2/252) \cdot (1.645/(0.3/\sqrt{252}))^2 =1+1.0002⋅(1.645/0.0189)2=1+1.0002⋅7575=7576= 1 + 1.0002 \cdot (1.645/0.0189)^2 = 1 + 1.0002 \cdot 7575 = 7576

需要 7576 个交易日,也就是 30 年。换句话说,想以 95% 的把握证明夏普 0.3 超过零,需要 30 年日频数据。

这就是低夏普策略很难通过统计验证的原因。随着 SR^\widehat{SR} 逼近 SRbSR_b,MBL 按平方增长。即使是看起来不低的夏普,也可能需要几十年数据才能统计验证,而大多数回测只有 5 到 10 年。因此,低夏普策略可能是:

  1. 真实存在、但无法用现有数据统计验证的优势。
  2. 在 5 年回测里看起来真实的统计假象。

你分不清是哪一种。诚实的做法是在拿到更多数据前,先按第二种处理。

非高斯收益率

对偏度或超额峰度不为零的策略,MBL 会通过非正态因子进行修正:

MBLfactor=1−γ3SR^+γ4−14SR^2MBL_{factor} = 1 - \gamma_3 \widehat{SR} + \frac{\gamma_4 - 1}{4} \widehat{SR}^2

对偏度为 γ3=−1\gamma_3 = -1、夏普为 1 的策略,假设 γ4=3\gamma_4 = 3,这个因子是 1+1+0=21 + 1 + 0 = 2。所以 MBL 是高斯 MBL 的 2 倍。验证负偏度策略所需的数据,是验证同夏普高斯策略的两倍。

这很反直觉:策略的收益分布形状更难描述,夏普标准误更大,所以需要更多数据。实际含义是:除非有更长的历史数据,否则不要轻易选择负偏度策略。

对偏度为 γ3=1\gamma_3 = 1、夏普为 1 的正偏度策略,因子是 1−1+0=01 - 1 + 0 = 0。所以 MBL 看起来会下降一个因子的幅度,但这个因子有下界 γ4/4⋅SR2\gamma_4/4 \cdot SR^2,始终为正。典型 γ4=3\gamma_4 = 3 时,下界为 3/4⋅1=0.753/4 \cdot 1 = 0.75。因此,MBL 至少是高斯 MBL 的 75%。

对长尾、正偏度策略(买入期权、困境债务),MBL 更短。这也是选择正偏度策略的一个理由:它们更容易通过统计验证。

年化陷阱

一个常见误用是:使用年化夏普计算 MBL,却把 T=5T = 5 直接当成年数代入。这是错的。MBL 公式使用的是收益率频率单位。如果使用年化夏普,必须把算出来的 TT 转换成年数。

正确的单位转换是:

Tobs=Tannualized⋅fT_{obs} = T_{annualized} \cdot f

其中 ff 是每年的收益率观测数。日频数据取 f=252f = 252。所以 3 年的 MBL 对应 Tobs=756T_{obs} = 756 个观测。

大多数实现都会在这里出错。不要犯同样的错。

import numpy as np

def minimum_backtest_length(sr_target, sr_benchmark, 
                             gamma3=0, gamma4=3, 
                             confidence=0.95, freq=252):
    """Compute the Minimum Backtest Length in observations.
    
    Parameters
    ----------
    sr_target : float
        Annualized target Sharpe ratio
    sr_benchmark : float
        Annualized benchmark Sharpe ratio
    gamma3 : float
        Skewness of returns (annualized)
    gamma4 : float
        Excess kurtosis of returns (annualized)
    confidence : float
        Confidence level (e.g., 0.95)
    freq : int
        Return observations per year
    
    Returns
    -------
    int
        Minimum number of observations required
    float
        Equivalent years
    """
    from scipy.stats import norm
    
    # Convert to return-frequency units
    sr_target_daily = sr_target / np.sqrt(freq)
    sr_benchmark_daily = sr_benchmark / np.sqrt(freq)
    
    # Z-score for confidence
    z = norm.ppf(confidence)
    
    # Non-normality factor
    factor = 1 - gamma3 * sr_target_daily + (gamma4 - 1) / 4 * sr_target_daily**2
    
    # MBL in observations
    T_obs = 1 + factor * (z / (sr_target_daily - sr_benchmark_daily))**2
    
    return int(np.ceil(T_obs)), T_obs / freq

# Examples
T, years = minimum_backtest_length(1.0, 0.0)
print(f"SR=1.0 vs 0:    T = {T} obs ({years:.2f} years)")

T, years = minimum_backtest_length(1.0, 0.5)
print(f"SR=1.0 vs 0.5:  T = {T} obs ({years:.2f} years)")

T, years = minimum_backtest_length(0.3, 0.0)
print(f"SR=0.3 vs 0:    T = {T} obs ({years:.2f} years)")

T, years = minimum_backtest_length(1.5, 0.0, gamma3=-1.5, gamma4=3)
print(f"SR=1.5 (skew):  T = {T} obs ({years:.2f} years)")

实际结论

对大多数夏普合理的量化策略(0.5 到 2.0),在常见置信度(95%)下,MBL 是 5 到 15 年日频数据。大多数回测只有 3 到 10 年。大多数已发表的策略夏普,无法在统计上与它们需要超过的基准区分开。

回测之前先运行 MBL。如果答案是“需要 12 年”,而你只有 6 年有效数据,那这次回测就没有信息量。要么换策略,要么换基准,要么换置信要求。没有诚实的第四个选项。

把 MBL 作为回测前门槛

MBL 最有用的用法,是把它当作回测前门槛。在花几个小时运行回测前,先算 MBL。如果 MBL 超过可用数据,直接跳过回测。这样既省时间,也不会陷入运行一个统计功效不足的研究、最后得到无法下结论结果的陷阱。

典型的量化研究工作流是:

  1. 定义策略假设和预期夏普范围。
  2. 定义要超过的基准。
  3. 定义置信水平(95% 是惯例;99% 偏保守)。
  4. 计算 MBL。
  5. 如果 MBL > 可用数据,放弃这个假设,或者降低假设。
  6. 否则继续回测。

量化研究中不常见这套流程,因为研究员想直接跑回测。但这才是诚实的流程。统计功效不足的研究只会产生噪声,结论不可靠。

MBL 与多状态问题

MBL 公式假设收益率平稳。如果回测包含状态变化(例如 2008 年危机、2020 年 COVID、2022 年通胀),这个假设就被破坏了。非平稳下的夏普标准误会大于公式给出的结果。

一个实用修正是:把 MBL 乘以状态因子,通常取 1.5 到 2.0。对包含 3 个明显状态的回测,MBL × 1.5 是合理调整。

更严格的方法是:把数据按状态切开,计算每个状态内的夏普,再用跨状态方差作为夏普标准误。这就是“block bootstrap”或“状态修正 MBL”。

对大多数量化回测,简单的 MBL × 1.5 规则已经是不错的近似。研究论文通常使用状态修正 MBL。

MBL 与前视偏差

MBL 假设回测是诚实的。如果回测有前视偏差(例如用未来信息做当前决策),报告出来的夏普就被抬高了。MBL 检测不出这个问题。

解决办法是:先去掉前视偏差,计算“诚实”夏普,再用诚实夏普计算 MBL。诚实夏普通常低于报告夏普,所以 MBL 会更长。

如果回测有严重前视偏差,诚实夏普可能接近零。这时 MBL 实际上趋于无穷。现有数据无法验证这个策略。

这也是 MBL 经常比研究员预期长很多的最常见原因。回测藏着前视偏差,诚实夏普很小,MBL 变得极大。诚实结论是:这次回测没有信息量。

不同资产类别的 MBL

MBL 公式是通用的。资产类别会影响输入参数:

  • 股票:宽基指数日波动率 1%–2%,单只股票 2%–4%。目标夏普为 1.0 的策略,MBL 为 2–4 年。
  • 外汇:日波动率 0.5%–1%。MBL 为 1–3 年。
  • 加密货币:日波动率 3%–10%。MBL 为 1–5 年,但高波动会让高夏普更难实现。
  • 固定收益:日波动率 0.1%–0.5%。MBL 为 0.5–2 年,较低的波动率会让高夏普更容易出现。
  • 大宗商品:日波动率 1%–3%。MBL 为 2–4 年。

对多资产策略,分散化会降低组合波动率,但不会改变每种资产自身的 MBL。策略层面的 MBL 取决于策略波动率,不是各资产的波动率。

MBL 与容量

MBL 不考虑容量限制。名义本金 100 万美元时有效的策略,规模到 1 亿美元可能就不行了。夏普会随规模衰减,而基于小资金回测的报告夏普被抬高了。

容量修正后的 MBL 做法是:先估计目标容量下的夏普,再用容量修正夏普计算 MBL。对大多数策略,容量修正夏普只有小资金夏普的 30%–70%,因此 MBL 会相应变长。

一个常见错误是:根据小资金回测计算 MBL,然后以大容量部署,最后发现夏普远低于回测预期。容量是独立于统计显著性的另一个问题。

MBL 与多重检验问题

MBL 假设你只测试了一个策略。如果你测试了 mm 个策略,实际 MBL 会因为多重检验修正而增加。去膨胀夏普比率(DSR)公式把这一点纳入了:

TDSR=1+factor⋅(z1−αSR^−SR∗‾)2T_{DSR} = 1 + \text{factor} \cdot \left(\frac{z_{1-\alpha}}{\widehat{SR} - \overline{SR^*}}\right)^2

其中,SR∗‾\overline{SR^*} 是 mm 次试验的零假设下的期望最大夏普。m=10m = 10 时,SR∗‾≈0.5σSR\overline{SR^*} \approx 0.5 \sigma_{SR}。MBL 会增加一个 (SR^/(SR^−SR∗‾))2(\widehat{SR} / (\widehat{SR} - \overline{SR^*}))^2 的因子。

当 SR^=1.0\widehat{SR} = 1.0、SR∗‾=0.5\overline{SR^*} = 0.5、m=10m = 10 时,因子是 (1.0/0.5)2=4(1.0/0.5)^2 = 4。MBL 变成原来的 4 倍。因此,如果你测试了 10 个策略,最优策略的 MBL 是单次试验 MBL 的 4 倍。

对 100 次试验:SR∗‾≈0.7σSR\overline{SR^*} \approx 0.7 \sigma_{SR}。若 SR^=1.0\widehat{SR} = 1.0、σSR=0.4\sigma_{SR} = 0.4,则 SR∗‾=0.28\overline{SR^*} = 0.28。因子为 (1.0/0.72)2=1.93(1.0/0.72)^2 = 1.93,MBL 大约增加到 2 倍。

实际含义是:测试越多,数据需求越大。诚实的工作流是提前声明试验次数,并计算经过试验次数修正的 MBL。

诚实的 MBL 工作流

假设目标夏普为 1.0、基准为 0.5、做 50 次试验、日频数据、95% 置信度,且收益率高斯:

  1. 单次试验 MBL(由上面的公式得到):2.7 年。
  2. 试验次数修正后的 MBL(DSR 修正):2.7 × 1.93 ≈ 5.2 年。
  3. 状态修正(1.5 倍):5.2 × 1.5 = 7.8 年。
  4. 容量修正(假设夏普衰减 30%):需要提高目标夏普,重新计算 MBL,结果超过 12 年。

诚实的总 MBL:12 年以上。大多数研究项目只有 5–8 年数据。诚实结论是:现有数据无法统计验证这个策略。

这其实是大多数量化研究项目的标准答案:数据不够,策略无法验证。诚实的做法是承认这一点,不要部署策略。大多数研究项目没有这样的纪律。

MBL 说明无法验证时

如果 MBL 超过可用数据,你有三个选择:

选择 1:降低置信度要求。 从 95% 降到 80%,MBL 大致会减半。代价是更多假阳性。早期研究可以接受,资本配置不能接受。

选择 2:提高目标夏普。 夏普越高,越容易验证。但高夏普也更少见,策略可能根本不存在。

选择 3:降低基准。 基准越低,越容易超过。但基准应该反映机会成本,而不是为了方便。故意把基准设得很低是不诚实的。

没有第四个选项。数据不够,结论就是数据不够。

更深一层的教训

MBL 是量化研究中最少被使用的工具之一。大多数回测报告不包含 MBL,大多数策略选择也不考虑 MBL。结果是,大多数“验证过”的策略其实没有被验证。

如果你只采用本文的一条实践,那应该是:任何严肃回测之前,先计算 MBL。如果 MBL > 可用数据,就不要跑回测。如果 MBL ≤ 可用数据,就带着 MBL 这个约束去回测,把它当成设计条件,而不是缺陷。

诚实的 MBL 是量化研究的硬约束。大多数项目忽略它,结果就是大多数已发表策略没有验证。解决办法很简单:提前计算 MBL,并尊重结果。

参考文献

  • Bailey, D. H. and López de Prado, M. (2014). “The Deflated Sharpe Ratio: Correcting for Selection Bias, Non-Normality, and Multiple Testing.” Journal of Portfolio Management, 40(5), 94–107。§3 推导了 MBL。
  • López de Prado, M. (2018). Advances in Financial Machine Learning, 第 14 章。Wiley. ISBN 978-1-119-48208-6。实现。
  • Ardia, D., Boudt, K., and Catania, L. (2018). “Generalized Sharpe Ratios and Portfolio Performance Evaluation Under Autocorrelation and Non-Normality.” SSRN。非独立同分布收益率的相关框架。