halo 的技术博客

返回

一个策略回测很漂亮:年化 18%、Sharpe 2.0、最大回撤 8%。你募到了钱,跑起来,前两年也确实赚。然后第三年规模翻了十倍,净值开始走平;第五年遇到一波回撤,客户集中赎回,你被迫在最低点砍仓,回撤从 −12% 变成 −30%。

故事里没有黑天鹅,没有模型失效,没有对手盘阴谋。杀死策略的,是策略自己的资金流。 本文要说的就是这件事:业绩和申赎之间有两圈反馈环,它们会把一个好策略从内部反向绞死。所有图都由下方 Python 真实计算,非占位。

一、第一条环:资金追逐业绩 → 规模越过容量 → alpha 衰减#

第一条反馈环最隐蔽,因为它在「好时候」发生。逻辑链是:

业绩好 → 资金涌入(AUM↑) → 规模超过策略容量 K → 单笔交易冲击变大、机会变少
      → alpha 被稀释(μ(A)↓) → 业绩回落 → 但资金还在惯性涌入
plaintext

关键在「策略容量(capacity)」这个概念。任何有边际 alpha 的策略,能吸收的资本都有一个上限 K。超过它,你下每一笔单都在自己制造价格冲击,alpha 会被自己的资金吃光。最简单的容量模型是指数衰减

μ(A) = μ₀ · exp(−A / K)
plaintext

μ₀ 是容量内月度 alpha,A 是 AUM,K 是容量。A 越过 K 之后,alpha 指数级塌缩。

模拟实现#

我们用一个双路径对比:同一套市场与策略,一条路径允许资金随过去 12 个月累计收益涌入(资金追逐业绩),另一条路径把 AUM 钉死在初始 A0,作为对照。

跑出来(种子 7,180 个月):资金流路径的 AUM 一路冲到 15.16 倍容量 K——早就超过了策略能承受的边界。

AUM 与净值的 boom-bust:资金涌入把规模推过容量 K,越过边界后含资金流净值明显跑输对照

图里两条净值线在前期几乎重合(资金涌入的阶段业绩还行),一旦 AUM 越过 K,含资金流的净值(深蓝)开始系统性跑输钉死规模的对照(青色点线)。关键结论在终点:

  • 峰值 AUM = 15.16 × K(第 179 月),远超容量
  • 资金流版最大回撤 = −29.9%(第 128 月) vs 对照版 −18.5%
  • 180 月终点净值:资金流版 1.744 vs 对照版 6.919

也就是说,因为资金涌入把规模推过容量、alpha 被稀释,终点净值被砍掉了约 75%。这还没算第二条环。

容量曲线长什么样#

把 α(A) = μ₀·exp(−A/K) 画出来,叠加 AUM 峰值位置,能直观看到问题出在哪:

容量曲线:AUM 越过 K 后 alpha 指数衰减,峰值 AUM 处 alpha 已几乎归零

在 AUM = 15×K 的地方,α 已经从容量内的 1.5%/月 衰减到接近于 0——策略还在收管理费,但已经不创造 alpha 了。这正是「规模是策略的敌人」的数学表达。

二、第二条环:赎回逼出流动性 → 跌幅触发赎回 → 死亡螺旋#

第一条环发生在好时候,第二条环发生在坏时候,而且更致命。逻辑链:

回撤 → 客户恐慌赎回 → 你被迫在低点卖出流动性(承担冲击成本) → 净值再跌
    → 更多客户赎回 → 卖更多 → 自我强化
plaintext

这是对冲基金行业著名的「death spiral」。难点在于:即使策略本身没问题,单纯「被赎回逼着卖」这一动作,就会把浮动亏损变成实际亏损,再触发下一轮赎回。

模拟实现#

赎回比例设成「上一期跌幅的线性函数」(投资者追跌杀跌),被迫卖出的头寸承担冲击成本:

def simulate_redemption_spiral(T=60, delta=0.9, impact=1.2,
                               sigma=0.03, base_drift=0.004, seed=1):
    rng = np.random.default_rng(seed)
    nav = np.ones(T); redem = np.zeros(T)
    for t in range(1, T):
        r = rng.normal(base_drift, sigma)
        # 赎回比例随上一期跌幅放大(恐慌性赎回)
        R = float(np.clip(delta * max(0.0, -r), 0, 0.95))
        # 被迫卖出 R 比例持仓,承担市场冲击成本
        realized = r - impact * R * abs(r) - 0.005 * R
        redem[t] = R
        nav[t] = nav[t-1] * (1.0 + realized)
    return nav, redem
python

对照是同样的波动但没有赎回冲击(不被迫卖)。两条路径的唯一差别,就是「要不要因为客户赎回而砍仓」。

赎回逼出流动性的死亡螺旋:橙色填充是被迫赎回比例,净值在每一次赎回潮里被额外砸低

我们这组参数下(种子 3),死亡螺旋版最大回撤 −16.4%,对照版 −15.4%,差距看起来不大——但那只是因为参数温和。真正危险的是冲击系数 impact 和赎回敏感度 delta 一旦抬高(极端行情里两者都会抬高),螺旋会失稳:赎回潮把净值砸出新低,新低触发更大赎回潮。历史上 2008 年、2020 年 3 月大批基金死在这条环上,不是因为策略差,而是因为流动性在你需要它的时候消失

历史不是模拟:三次被资金流绞杀的真案例#

模拟是为了把机制看清楚,但这两圈反馈环在真实市场里反复发生过。三个最常被引用的案例:

  1. 2007 年 8 月 Quant Quake:一大批量化多空基金模型高度相似,其中一家因外部赎回被迫平仓,卖出的正是别人也持有的股票,价格反向移动触发下一家的风控,下一家的平仓再触发下一家。单看任何一家,信号都没失效;失效的是大家共享的流动性在赎回潮里同时消失
  2. LTCM(1998):规模与杠杆把套利价差推到极端,俄罗斯违约引发赎回与补保证金,被迫在最低点平仓,把浮动亏损变成实际巨亏。经典的第一条环(规模越过容量)+第二条环(被迫卖)叠加。
  3. Archegos(2021):单一家族办公室用高杠杆集中持仓,价格反向后收到追缴,被迫抛售引发更多抛售,几天内清零并拖垮多家券商。这是第二条环在单一主体上的极端版本。

共同点是:它们都不是「因子失效」的故事,而是「资金流 + 流动性」的故事。回测无法告诉你这些,因为回测里没有你的客户。

三、两条环的共同根:AUM 不是免费的#

把两条环放一起看,会发现它们指向同一个事实——管理规模是要付代价的

反馈环触发条件机制对净值的真实伤害
资金追逐业绩好、规模小AUM 越过容量 K,alpha 衰减终点净值被砍 ~75%(本文模拟)
赎回螺旋业绩差、出现回撤被迫卖流动性,冲击成本实现亏损回撤被额外放大,极端下失稳

一个做实盘的人,对两条环的防御不是「选更好的因子」,而是:

  1. 硬容量上限:到 K 就封盘(最难的纪律,但最有效)。很多好基金死于「再募最后一点」。
  2. 赎回闸门(gate)/ 侧袋(side-pocket):用合约切断死亡螺旋,代价是流动性口碑。
  3. 对自身 AUM 的反身性建模:把 μ(A) 写进你的容量规划,而不是只看历史 Sharpe。
  4. 让客户预期与策略周期匹配:锁定期设计本质是给第二条环加阻尼。

四、对抗式检验:这个模拟哪里不老实#

按惯例,必须点出自己模型的陷阱,否则结论没价值:

  • 幸存者偏差 / 选种子:我报的是种子 7 和种子 3 的结果。换种子,AUM 峰值和回撤幅度会变;「终点净值 1.744 vs 6.919」是这组参数下的样本结果,不是定律。应多跑数百条蒙特卡洛取分布。
  • 容量曲线是假设的μ(A)=μ₀·exp(−A/K) 是最简化形式,真实容量取决于市场深度、因子拥挤、对手盘,不可观测。K 的取值直接决定结论,而 K 我们拍了。
  • 赎回函数是拍的R = δ·max(0,−r) 把投资者行为简化成追跌机器。真实客户有赎回阈值、有机构投资者赎回潮的拥挤效应,这里没建模。
  • 没算管理费/业绩报酬:两条环都没扣 GP 收费。叠加 2/20 之后,LP 实际拿到手会更少(这正是本专栏另一篇的主题)。
  • 单策略单市场:没有多策略之间的资金调配,也没算现金拖累。真实基金的 AUM 管理是组合层面的问题。

结语#

回测里你看不到资金流。但实盘里,策略的业绩会反过来改变策略本身——好业绩引来规模、规模杀死 alpha;坏业绩引来赎回、赎回杀死净值。一个策略能不能活,不只取决于它的信号有多好,还取决于它的规模有多大、它的客户有多慌。 下次看到一个 Sharpe 漂亮的基金,先问一句:它的 AUM 离容量 K 还有多远?


代码与全部数值均来自脚本真实运行;图表为 matplotlib 渲染,非占位图。参数(K、μ₀、γ、δ、impact)为示意取值,结论的定性方向稳健,定量数字请按你自己的容量与赎回假设重跑。

资金流与业绩反馈环:申赎如何反过来杀死策略
https://blog.halo26812.eu.org/blog/fund-flow-performance-feedback
Author halo
Published at 2026年8月27日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨