2026年九月5日 · 风险

你的回测从未被强平:保证金、标记价格,以及你忽略的杠杆边界

你的回测从未被强平:保证金、标记价格,以及你忽略的杠杆边界

上个月,一条生成策略的权益曲线出现了 63% 的回撤。跌得深,难看,但随后在接下来的 6 周里干净利落地恢复——这种走势会让研究员眯起眼睛盘算,只要缩小仓位,或许还能承受。我把它重新放进一个知道什么是维持保证金档位的保证金引擎里跑了一遍。账户在第 41 天、回撤进行到一半时就被强平了;第 41 天之后的一切都是虚构的。

这是我所知道代价最高的一类回测错误,因为它造成的偏差不只是几个基点。它把一种不可逆的终止状态从模拟中删掉了。能归零的策略和不能归零的策略是两种不同的策略,而从不检查保证金的回测无法告诉你自己拿着的是哪一种。

我反复看到的 3 种错误做法。

错误做法一:把杠杆当作一个乘数去放大收益

最常见的模式是这样:根据你的信号计算收益序列,决定用 10x 杠杆交易,然后把收益乘上去。有时做法会稍微复杂一点——仓位大小设为 equity * leverage / price——但账户状态仍然只是一个上下波动的数值。没有保证金余额,没有名义价值上限,也没有失败条件。

问题不易察觉,所以这种错误能躲过审查。Sharpe 不随规模变化,因此把杠杆从 3x 调到 30x,醒目的指标数字也不会变,研究员便得出结论:杠杆只是一个免费旋钮,可以用波动率换收益。最大回撤按线性比例放大,却因算术上的偶然而一直低于 100%:因为一串被放大的收益复利后只会渐近于零,永远不会跌穿零。把一个 -9% 的交易日乘以 12,在严谨的版本里结果是 -108%;在天真的版本里则是“-108%,但权益曲线仍为正”,这取决于你用的是复利还是求和。我两种都见过。

缺失的关键在于,杠杆并不是作用于你的收益,而是作用于你的抵押品;抵押品数量有限,交易所每秒都在监控。一旦它低于维持保证金要求,这个仓位就不再属于你。

判断标准:如果你的模拟在任何杠杆下都不可能产生全部亏损,那它就没有在模拟杠杆。

错误做法二:仅凭杠杆推导强平价格

第二种稍微复杂的做法加入了强平检查,通常像这样:20x 杠杆下,5% 的不利价格变动会耗尽保证金,因此做多时在入场价 × 0.95 处强平。看起来简洁直观,却在 4 个方面同时出错。

永续合约平台不会根据你设置的杠杆来决定何时结束你的交易。它们使用随仓位名义价值阶梯上升的维持保证金率,并将其列在档位表中。以下是 BTCUSDT USDⓈ-M 档位的大致情况;平台修订时可能会调整:

仓位名义价值(USDT)维持保证金率最高杠杆
0 – 50,0000.40%125x
50,000 – 600,0000.50%100x
600,000 – 3,000,0001.00%50x
3,000,000 – 12,000,0002.50%20x
12,000,000 – 70,000,0005.00%10x

因此,逐仓多头能承受的不利价格变动大约是 1/L − MMR,而不是 1/L。在第二档使用 20x 杠杆时,就是 5% − 0.5% = 4.5%。半个百分点听起来像是四舍五入误差。但 BTC 价格为 84,000 时,这相当于 420 美元的价格差;剧烈波动的一小时里,这 420 美元决定了一根影线会不会把你扫出场。每根影线都像一次抛硬币,而你把每次结果都偏向了对自己有利的一面。

接下来是手续费。入场 taker 手续费在成交瞬间就从保证金中扣除:500,000 名义价值按 0.045% 收取 225 USDT 手续费,相对于 25,000 的保证金余额,这会在仓位还没发生任何变化之前就推动强平价格。资金费率也有同样的影响,而且会持续发生;按杠杆后的名义价值计算,其影响远超研究员的预期:

4.55%20x 杠杆下的实际强平不利变动幅度,含入场手续费
0.60%20x 杠杆下每日资金费率损耗,占保证金的比例,资金费率为 0.01%/8h
18%平静的一个月里损失的保证金比例

一个 30 天内毫无动静的仓位——没有不利变动,也没有交易——已经消耗了接近 1/5 的抵押品,并显著拉近了强平价格。还有第 3 和第 4 个错误之处:随着你加仓,档位会变化;一个起初处于 0.5% 档、后来加仓到 1.0% 档的仓位,其强平价格会比你在入场时算出的更差。逐仓保证金和全仓保证金也有区别:全仓会让多个仓位共享抵押品,因此 BTC 多头能否存活取决于 ETH 空头的表现。如果你把全仓保证金模拟成一组互不相关的逐仓仓位,就把自己账户的相关性结构完全搞反了。

错误做法三:用错误的价格、在错误的时点、以错误的成交价处理强平

假设你算对了触发价。接下来要问:哪个价格越过了它?你在什么时候检查?你的成交价又是多少?

强平由标记价格触发。标记价格是多个现货平台价格的指数,包含平滑处理的基差分量,特意设计成能抵御单个平台上的影线。你的止损则取决于配置方式,很可能由最新成交价触发。只有在最关键的时候,这两个价格才会出现分歧。瀑布行情期间,永续合约的最新成交价可能连续几十秒比标记价格低 1–2%。如果回测用同一根 OHLCV K 线的最低价来触发止损和强平,它模拟的平台根本不存在。

这里这两种错误都存在,而且不会相互抵消。按最新成交价处理,你会因为平台忽略的影线而被强平;按标记价格处理,你又会漏掉标记价格本身发生变动的情况——现货平台上的指数偏离,确实可能让你在一个从未出现在所交易永续合约上的价格被强平。

接下来是成交价。天真的引擎会在强平价格平仓,并像处理止损一样记账。实际情况是:清算引擎会在破产价格接管仓位——也就是保证金恰好归零的价位,比触发价更差——此外还会收取强平清算费,费率取决于档位;在较低档位附近,这笔费用约为名义价值的 1%。20x 杠杆下,名义价值的 1% 相当于剩余保证金的 20%。如果引擎的成交价低于破产价格,保险基金会填补差额;在某些平台上,如果保险基金耗尽,社交化亏损还会波及订单簿中盈利的一方。你的实际亏损不只是到强平价格为止的回撤,而是更大;而在订单簿深度不足、情况最糟的那些日子,超出的部分也最大。

K 线内机制中的时序问题在这里同样适用,而且后果更严重。如果一根 1-minute K 线同时包含你的止盈价和强平价,那么先检查退出条件、后检查保证金的回测会轻轻松松地把盈利记下来。交易平台会在每次标记价格更新时检查保证金,大约每秒一次,优先于你原本希望发生的所有其他事件。

引擎需要追踪哪些状态

这些都不需要多么复杂,关键是要有状态。账户应该是一个包含余额的对象,而不是一串收益序列;每根 K 线上,都要按交易平台更新状态的顺序来处理:

  1. 分别记录钱包余额和未实现 PnL。 维持保证金率等于维持保证金除以保证金余额,而保证金余额包含未实现 PnL。把两者混为一谈,会让亏损中的仓位看起来比实际抵押更充足。
  2. 为每个交易品种维护按日期版本化的档位表。档位会修订。用 2026 年档位跑 2023 年的回测,会引入一种不易察觉的前视偏差——通常会让结果偏好,因为随着时间推移,平台一般放宽了主流交易品种的要求。
  3. 使用标记价格序列,而不只是 K 线数据。如果无法获取历史标记价格,就在结果中明确说明,并使用保守的代理值。绝不要悄悄替换成最新成交价。
  4. 在 K 线事件顺序中优先检查保证金,早于止损、止盈、信号和再平衡。
  5. 以破产价格成交,并计入清算费;费率与 MMR 从同一档位行读取。
  6. 一个不可逆的终止状态。权益归零时,回测就结束。不重置基准,不“假设交易者会追加资金”,也不从新的名义价值继续跑这串数据。

最后一点最容易引发争论。总有人会指出,真实交易团队会追加抵押品,所以结束模拟不切实际,过于严苛。或许吧。但“这个策略在爆仓后只要继续注资就能奏效”是一项值得明确说出来、并专门测试的主张;追加资金应当作为明确输入,而不是偷偷当作默认设置。坦诚地把它写下来之后,大多数人会发现自己其实并不是这个意思。

这样做的实际好处是:当你把同一策略放在实盘平台上纸面运行时,交易所报告的保证金率和模拟器计算的结果应当全天保持在 1 到 2 个基点以内。每分钟、每个未平仓位都可以免费检查这种一致性。这是整个系统里成本最低的对齐测试,却几乎没人做——而当这两个数字出现偏差时,交易所是对的。趁回撤替你发现问题之前,你就有一个值得排查的 bug。

永续合约杠杆强平保证金引擎回测
← 全部文章