halo 的技术博客

返回

核心结论:税收亏损收割(Tax-Loss Harvesting, TLH)的绝大部分产出不是 alpha,是递延。 它今天帮你省下的税,以「成本基准下降」的形式记在账上,清算那天一次性讨回。同一次运行、同一批路径,用行业常用的未清算口径算出来是 15.77 bp/年,用诚实的清算口径算出来只有 10.89 bp/年——虚高 1.45 倍。而这剩下的 10.89 bp 也不全是白捡的:它是递延期的时间价值 + 税率档差,两者都有明确的失效条件。

更反直觉的是它的驱动因子。TLH 的增益随波动率单调上升(σ 从 8% 到 40%,增益从 0.85 涨到 43.16 bp),却随收益率单调下降(μ 从 0% 到 13%,增益从 89.16 塌到 1.48 bp,差 60 倍)。也就是说:它在牛市里最没用,而牛市恰恰是大多数人开始关注它的时候。

左:同一次运行两个口径的差距(未清算 15.77 bp vs 清算 10.89 bp);右:600 条路径的逐路径增益分布,均值 15 bp、5% 分位仅 2 bp

一、问题:省下来的税,和不用交的税,是两件事#

TLH 的机制三句话说得完:组合里某个标的浮亏了,卖掉实现这笔亏损,用它抵扣当年的应税收益,同时立刻买入一个高度相关的替代品,保证市场暴露不变。你少交了税,仓位没动,看起来是纯粹的免费午餐。

问题出在最后一步的会计上。卖出并买回之后,你的成本基准从原来的买入价降到了现在的市价。这意味着未来清算时,应税收益会更大——大多少?恰好等于你这次实现的亏损额。

换句话说:

TLH 不是「免税」,是「延后交税」。它把今天的税单挪到了未来,用降低成本基准作为借条。

那它到底还剩下什么价值?三块,且都有条件:

  1. 递延的时间价值——省下的现金今天就能再投资,这部分是真实的
  2. 税率档差——如果清算时适用税率低于收割时(退休后降档、短期转长期),差额是永久豁免
  3. 永不清算——遗产步升基准(step-up basis)或捐赠,借条可以永远不还

本文的全部工作,就是把这三块从「递延」里剥出来,看看剩多少。

二、受控模拟:真值全部由构造给定#

为了让每一个 bp 的来源可追溯,我构造了一个真值完全已知的世界:

参数设定值说明
税前年化漂移 μ7%真值,由构造给定
年化波动率 σ20%真值
组合标的数40每个标的一个 lot 池
标的间相关系数0.35中等相关,贴近实际股票组合
持有年限20 年252 × 20 = 5040 个交易日
路径数600蒙特卡洛
短期资本利得税率35%持有 < 1 年
长期资本利得税率20%持有 ≥ 1 年
收割阈值浮亏 ≥ 5%触发条件
洗售封锁期30 天wash sale rule
单边交易成本5 bp卖 + 买各一次
递延资金再投资利率3%保守,按无风险利率

核心的对照是同一批路径跑两遍:一遍开收割,一遍不开。差值就是 TLH 的增量,不掺任何基准选择的争议。

关键的实现细节在于两个口径:

final_price = px[-1].astype(np.float64)
gross = (shares * final_price).sum()
unreal_gain = (shares * (final_price - basis)).sum()

# 口径 A:未清算(行业常用,虚高)
net_noliq = gross + cash_saved

# 口径 B:清算(诚实)—— 期末按长期税率结清
taxable = max(unreal_gain - 0.0, 0.0)
tax_end = taxable * tax_lt
net_liq = gross + cash_saved - tax_end
python

cash_saved 是累计税收节省并按无风险利率滚存的部分,tax_end 是清算日一次性讨回的账。两个口径的全部差别就在最后那一行减号。

三、基准结果:虚高 1.45 倍#

600 条路径、20 年、40 标的,中位数结果:

口径买入持有TLH增益
未清算(行业常用)6.4781%6.6552%+15.77 bp
清算(诚实)5.6596%5.7844%+10.89 bp

虚高倍数 1.4481。

同时值得注意的几个数字:

  • 中位收割次数:173.5 次(20 年,40 标的)
  • 中位累计实现亏损:占初始净值的 22.10%
  • 中位累计交易成本:占初始净值的 0.34%
  • 增益为正的路径占比:100.0%

最后一条需要解释:TLH 在这个设定下确实是稳健为正的——它不是一个赌博,而是一个小而确定的改进。但「稳健为正」和「值得为它重构整个投资流程」是两回事,后面的持有期和税率扫描会说明为什么。

四、安慰剂检验:拆掉柱子看它塌不塌#

一个数值实验最容易骗人的地方是:你搭了一个复杂机器,它吐出一个正数,你就相信这个正数是你想要的那个东西。安慰剂的作用是把机制柱子逐根抽掉,看结果是否按预期塌陷。

安慰剂检验:零波动世界增益精确为 0.0000 bp 且收割次数精确为 0;零税率世界增益转负 −1.64 bp

安慰剂 A:零波动(σ = 1e-9)。 价格确定性上行,永远不会出现 5% 的浮亏,因此收割次数必须精确为 0,增益必须精确为 0。

实测:收割次数 0 次,增益 0.0000 bp

这条检验的意义在于确认没有实现 bug——如果代码里有任何「凭空产生收益」的路径,这里会暴露。

安慰剂 B:零税率(短期 = 长期 = 0%)。 税收节省必须精确为 0,只剩交易成本,因此增益必须 ≤ 0。

实测:−1.64 bp

负号是对的。在一个不收资本利得税的世界里,TLH 就是纯粹的换手损耗。这个数字同时给出了 TLH 的成本基线:你付出的 1.64 bp 是确定的,换回来的税收好处是有条件的。

对照 C:零交易成本。 把成本设为 0,增益从 11.43 涨到 13.64 bp

这说明基准情形下,交易成本吃掉了 2.21 bp,约占毛增益的 16.2%

五、燃料会耗尽:这是一个衰减资产#

TLH 最容易被忽略的性质是:它是一次性资源,不是永续收益流。

每收割一次,那个标的的成本基准就被重置到当前市价。随着组合整体上涨,基准被不断抬高,可供收割的浮亏越来越少。

左:收割次数逐年衰减,第 20 年只有第 1 年的 0.031 倍;右:累计实现亏损的消耗曲线,前 3 年吃掉 63.3%

逐年平均收割次数(200 条路径):

年份1235101520
收割次数62.1929.1818.6710.314.433.471.95

第 20 年是第 1 年的 0.031 倍。前 3 年贡献了 63.3% 的累计实现亏损。

这直接决定了年化增益随持有期的衰减:

持有年限清算口径未清算口径
3 年57.38 bp131.92 bp
5 年46.98 bp104.68 bp
10 年25.97 bp46.76 bp
15 年17.67 bp28.68 bp
20 年13.09 bp19.88 bp
30 年7.68 bp9.24 bp

左:两个口径的裂口随年限扩大;右:组合标的数量对收割机会的影响

有两点值得停下来看:

第一,营销材料里的「TLH 每年增加 1% 收益」通常是短窗口 + 未清算口径的组合。 3 年期未清算口径 131.92 bp——这个数字确实接近 1%,但它同时用了两个最宽松的假设。同一个模型,20 年清算口径给出 13.09 bp,差 10 倍

第二,两个口径的裂口随年限反而收窄(3 年 2.30 倍 → 30 年 1.20 倍)。原因是:持有越久,递延期越长,时间价值累积越多,真实成分占比越高。这是 TLH 唯一一个「越久越诚实」的维度。

六、它是波动率的函数,不是收益率的函数#

这是本文最反直觉的一节。

左:增益随波动率单调上升;右:增益随收益率单调下降,从 89 bp 塌到 1.5 bp

波动率扫描(μ 固定 7%):

σ8%12%16%20%25%30%40%
增益 (bp)0.853.166.7910.7716.5122.6443.16
收割次数14.554107.5168.5253.5361551

收益率扫描(σ 固定 20%):

μ0%3%5%7%10%13%
增益 (bp)89.1634.5919.9411.154.311.48

μ = 0% 时的 89.16 bp 和 μ = 13% 时的 1.48 bp,相差 60 倍

机制很清楚:TLH 的燃料是浮亏,而浮亏的供给由「波动率制造、漂移消灭」。高波动创造更多穿越 −5% 阈值的机会;高漂移让价格快速离开成本基准上方,浮亏窗口迅速关闭。

实践含义是刺眼的:

TLH 在你最需要安慰的年份(熊市、震荡市)产出最高,在你最志得意满的年份(大牛市)几乎归零。 而后者恰恰是财富管理机构最容易把 TLH 当卖点推销的时候——因为客户账户里有大量已实现收益需要抵扣。

这不是说牛市里做 TLH 是错的,而是说:用历史牛市回测出来的 TLH 收益,会系统性低估它的价值;用历史熊市回测出来的,会系统性高估。 这个方向性偏差在任何单一样本回测里都无法自我暴露。

七、最优阈值不在 0,成本是硬约束#

直觉上「只要有浮亏就收割」应该最优——毕竟每一笔实现的亏损都是税收资产。但成本改变了这个结论。

左:阈值扫描,最优在 5% 而非 1%;中:交易成本敏感性,40bp 时增益塌到 0.71 bp;右:洗售封锁期的真实代价

阈值扫描:

阈值1%2%3%5%8%12%20%
增益 (bp)10.6411.1911.2311.4310.718.975.45
收割次数345288244179.512277.538

最优在 5%。1% 阈值的收割次数是 5% 的 1.92 倍,增益反而低 0.79 bp——多出来的 165 次交易全是给券商打工。

这里有个容易被忽略的细节:曲线在 2%–8% 之间非常平坦(11.19 ~ 11.43,极差 0.24 bp)。也就是说阈值调优的实际收益极小,把它当成一个需要精细优化的参数是在优化噪声。真正陡峭的是两端——1% 太勤快,20% 太保守(少了 5.98 bp)。

成本扫描:

单边成本0 bp2 bp5 bp10 bp20 bp40 bp
增益 (bp)13.6412.8111.439.246.340.71

40 bp 成本时 TLH 基本失效。 这个数字对流动性差的标的(小盘股、部分 ETF、部分债券基金)不是危言耸听——买卖价差加冲击成本很容易到这个量级。TLH 在流动性好的大盘 ETF 上是好主意,在流动性差的持仓上可能是净负贡献。

洗售封锁期:

封锁天数015306090
增益 (bp)11.5211.5411.4311.2810.97

这是一个诚实的负面结果:洗售规则的成本比想象中小得多(0 → 90 天只损失 0.55 bp,4.8%)。原因是本模拟允许买入高度相关的替代品维持暴露,封锁期只限制对同一标的的再次收割,而衰减本来就让后续收割机会稀少。

需要说明边界:如果找不到合格的替代品(比如个股,或税务规则更严格的辖区),真实成本会显著高于这里的 0.55 bp——那时封锁期意味着 30 天的暴露缺口,而不只是延后收割。

八、税率档差:唯一的永久豁免来源#

前面反复强调 TLH 主要是递延。那什么情况下它变成真正的永久收益?答案是:清算时的税率低于收割时。

收割税率 / 清算税率增益 (bp)
短期 35% / 长期 20%11.43
短期 35% / 长期 15%12.30
短期 35% / 长期 0%14.43
短期 20% / 长期 20%3.27
短期 15% / 长期 20%0.72

这张表是整篇文章实践含义最强的部分:

  • 35%/20%(有档差):11.43 bp
  • 20%/20%(无档差):3.27 bp——只剩纯递延的时间价值,掉了 71.4%
  • 15%/20%(反向档差,清算税率更高):0.72 bp——几乎归零

当收割税率低于清算税率时,TLH 接近失效。 因为你在用低税率消耗一笔本可以在高税率时使用的税收资产——这是一笔亏本的时间套利。

对应到真实场景:如果你今年收入很低(适用低档税率),而预期退休后或未来收入更高,那么今年不该激进收割,应该把浮亏留到高税率年份。这与「有亏就收」的机械做法完全相反。

九、分散度:标的数量的非单调影响#

标的数1510204080
增益 (bp)14.6912.179.268.659.3010.71
收割次数4.5254076.5164341

这条曲线是 U 形的,最低点在 20 只左右。我不打算过度解读它——两端的机制不同:

  • 单标的(14.69 bp):整个组合是一个 lot,一旦跌破阈值就整体收割,单次收割的名义金额最大。但收割次数只有 4.5 次,全靠少数几次大额收割,路径依赖极强。
  • 80 标的(10.71 bp):收割次数 341 次,机会多但每次名义金额小(1/80 仓位),且交易成本按次累积。

诚实的边界:这条 U 形曲线在本模拟的相关系数设定(ρ = 0.35)下成立,换一个相关结构形状会变。 我没有做相关系数的二维扫描,因此不建议把「20 只最差」当作可迁移的结论。可迁移的部分只有一条:标的数量通过「收割机会数」和「单次金额」两个相反方向影响结果,不是越分散越好。

十、样本量与稳健性#

逐路径分布(600 条路径,清算口径):

  • 单路径增益标准差:16.88 bp
  • 均值:15.29 bp
  • 5% 分位:2.00 bp,95% 分位:42.15 bp
  • 达到 |t| = 2 需要:5 条路径

这是本文少数几个「好消息」:TLH 的信噪比相对不错(SD/均值 ≈ 1.10),5 条独立路径就能统计显著。对比之下,很多因子策略需要几千个观测。

原因也简单:TLH 不是一个方向性押注,它是一个每次都往同一个方向走的小额确定性改进。这也是为什么 600 条路径里 100% 为正。

多宇宙检验(12 个独立随机种子,10 年窗口):

增益范围 18.06 ~ 31.35 bp,均值 24.26 bp,CV = 0.1312

CV 在 0.13 量级说明结论对随机种子不敏感,这个数值实验是可复现的。

十一、对抗式审查:我怀疑过并排除的点#

按流程,这里列出自检阶段真正怀疑过的问题,以及如何排除的。

怀疑 1:清算口径是不是把税算重了? 期末按长期税率对全部未实现收益征税,会不会对买入持有方也不公平?

排除方式:两个口径都对两个策略施加了完全相同的期末处理。买入持有的清算后年化 5.6596% 与 TLH 的 5.7844%,用的是同一个 tax_end 公式。如果这里有偏差,它会同时影响两边,差值不受影响。零波动安慰剂给出精确 0.0000 bp 也佐证了这一点——如果口径不对称,那里会出现非零残差。

怀疑 2:100% 路径为正是不是太好了,有没有 look-ahead? 收割决策只依赖 t 时刻的价格与成本基准,不使用任何未来信息:

pct = price / basis - 1.0
cand = (pct <= -thresh) & (lock == 0)
python

price = px[t]basis 只在过去被更新。没有未来信息泄漏。100% 为正的真实原因是零税率安慰剂揭示的:在有税的世界里,实现亏损的期权价值恒为正,而交易成本(中位 0.34%,20 年累计)不足以在中位路径上把它翻负。5% 分位仅 2.00 bp 说明确实存在接近盈亏平衡的路径。

怀疑 3:初版的 μ 扫描图标题写着「对收益率几乎不敏感」,但数据是 89 → 1.5 bp。 这是自检抓到的一个真实标注 bug——图表标题与数据矛盾。已修正为「收益率越高,增益越小」。之所以会写错,是因为最初预期 TLH 应主要由波动率驱动、对漂移不敏感,结果数据推翻了预期而标题没跟上。这类「标题写的是假设、图画的是数据」的错误,是数值文章里最危险的一种,因为读者通常只看标题。

怀疑 4:递延资金按 3% 无风险利率滚存,是不是低估了? 是的,且是刻意的保守选择。如果按股票收益率(7%)滚存,增益会更高。我选择无风险利率是因为:省下的税款在实际操作中通常直接留在组合里,其收益已部分体现在 gross 中,按股票收益率二次计入有重复计算风险。这个选择让本文的结论偏保守,不偏乐观。

怀疑 5:40 标的共用同一批相关路径,会不会塌缩有效样本量? 这正是我在配套的另一篇文章里踩到的坑。这里的检查是:多宇宙 CV = 0.1312,且 600 条路径的 SD/均值 = 1.10 属于健康量级。如果有效样本量被塌缩,CV 会显著高于 0.3 且扫描曲线会出现非单调抖动——本文的波动率、收益率、持有期三条扫描全部单调,阈值曲线也只有一个平滑峰,没有塌缩迹象。

十二、结论与适用边界#

TLH 是真实的,但它比营销材料小一个量级,且方向性依赖被系统性忽略。

可以带走的:

  1. 报数字必须说口径。 未清算 15.77 vs 清算 10.89 bp,1.45 倍差距全在最后一个减号。看到任何 TLH 收益数字,第一个问题应该是「清算了吗」。
  2. 它是波动率产品,不是收益率产品。 高波动年份产出高(σ=40% 时 43.16 bp),高收益年份产出低(μ=13% 时 1.48 bp)。用牛市样本评估会低估,用熊市样本会高估。
  3. 它是衰减资产。 前 3 年吃掉 63.3% 的燃料,3 年期年化 57.38 bp 到 30 年期只剩 7.68 bp。「每年稳定贡献 X bp」的表述是错的。
  4. 税率档差是唯一的永久豁免。 无档差时只剩 3.27 bp,反向档差时 0.72 bp。低税率年份激进收割是亏本的时间套利。
  5. 成本是硬约束。 40 bp 单边成本时增益塌到 0.71 bp。流动性差的持仓上做 TLH 可能是净负贡献。

本文不覆盖的(诚实边界):

  • 税制细节被大幅简化。 实际的洗售规则、亏损结转上限、短期/长期分桶抵扣顺序、州税,各辖区差异巨大。本文的税率档差结论在定性方向上稳健,但具体 bp 数不能直接搬到任何真实税务情形。
  • 未建模遗产步升基准。 如果假设永不清算,未清算口径反而是正确的口径,TLH 的价值会显著高于本文数字。这是一个真实存在的场景(高净值家族),本文的清算口径对它过于保守。
  • 替代品被假设为完美相关。 真实的替代品有跟踪误差,这部分成本未建模。它会朝降低 TLH 价值的方向修正结论。
  • 单一资产类别、对数正态路径。 没有厚尾、没有波动率聚集、没有 regime 切换。厚尾世界里浮亏机会更多,本文可能低估。
  • 这不是税务建议。 本文是一个数值实验,展示的是机制和量级关系,不是任何具体情形下的操作方案。

最后一句,也是最重要的一句:TLH 值得做,但它的产出量级是 10 bp 而不是 100 bp,且它在你最不需要的时候最慷慨。 把它当作一个纪律性的小改进是对的,把它当作一个策略是错的。

税收亏损收割:你以为的 alpha,其实是一笔要还的账
https://blog.halo26812.eu.org/blog/capital-gains-tax-loss-harvesting
Author halo
Published at 2026年8月7日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨