Top bracket, California, about $900k taxable income
Mar 2006 to Aug 2026, 20.4 years, $1M at the start, nothing added.

+$1.01M more after tax over 20 years, +0.7 pts a year.

S&P 500 fund, after tax$7.77M10.6% a year
Tax-aware strategy, after tax$8.78M11.2% a year
Difference+$1.01M+0.7 pts a year
Tax paid along the way$398K vs $834KLosses harvested: $1.77M
Tax-aware strategy, after taxS&P 500 fund, after tax
$0$2.5M$5.0M$7.5M2006200920122015201820212024

Account value at each month end, after that year’s tax has been paid out of it. Ending values above are .

How the result is built

Five steps, repeated for twenty years

Start. Both accounts buy on the same day. The fund holds the S&P 500. The strategy holds the largest 1,000 stocks with a tilt toward value and growth.

Year by year

Losses harvested, and tax paid

This scenario, at this tax rate
Losses harvested each year
$0$100K$200K2006200920122015201820212024
Tax paid each yearS&P 500 fundTax-aware strategy
$0$50K$100K$150K2006200920122015201820212024

Harvesting is richest when prices fall and when the account is young. The banked losses are what keep the strategy’s tax bill down.

Where the difference comes from

Every combination, this scenario. “Kept” is after-tax as a share of before-tax: the cleaner measure of tax efficiency, since harvesting also changes what is held.

Plain, after taxPlain, keptWith harvesting, after taxWith harvesting, kept
S&P 500 fund$7.77M84%$8.34M81%
Tax-aware strategy$8.12M74%$8.78M74%
Every scenario

Ahead in 14 of 16 scenarios

After tax, at this tax rate
  1. +0.7 pts+$1.01M
  2. +1.5 pts+$264K
  3. +1.7 pts+$331K
  4. +1.4 pts+$311K
  5. +0.4 pts+$127K
  6. +0.1 pts+$21K
  7. +0.5 pts+$157K
  8. +0.3 pts+$101K
  9. +0.2 pts+$46K
  10. +0.3 pts+$71K
  11. -0.1 pts−$13K
  12. +0.2 pts+$73K
  13. +3.0 pts+$168K
  14. +0.4 pts+$127K
  15. +1.6 pts+$146K
  16. -0.1 pts−$6K

Right: strategy ahead. Left: S&P 500 fund ahead. Each window starts with a fresh $1M. Click a scenario to load it above.

How to read this

After tax
Every December the account pays tax on dividends and realized gains. The lines show what is left.
As held / if sold
As held keeps deferring tax on unrealized gains. If sold pays it too.
Harvesting
Sell a losing position, bank the loss against gains, reinvest in the same sector. Details in the tax article.
Scenarios
The same simulation started on different dates. A strategy that only wins in bull markets is not worth much.

Method

  • Strategy: the largest 1,000 US stocks, cap-weighted, 40% tilt to a value-and-growth score. Benchmark: cap-weighted S&P 500. Both rebalanced each March.
  • Tax lots, holding periods, the wash-sale rule, and yearly tax payments simulated position by position over 20 years.
  • No trading costs or fees deducted for either portfolio.
All assumptions
  • Tax rates are the 2025 statutory stacks from tax_efficient_eq/charts/05_rate_stack.csv (federal + NIIT + state), held constant across the whole 2006-2026 history; no attempt to model the actual rates in force in each year.
  • All dividends are treated as qualified and taxed at the long-term rate.
  • Harvest threshold: a lot is harvested when its price is at least 5% below its cost basis. Positions are checked twice a month (mid-month and month end).
  • Wash-sale block: any name sold at a loss cannot be re-bought for 31 calendar days. A blocked name's rebalance target weight is capped at its current value and the freed weight is spread pro rata (by target weight) over the unblocked target names.
  • Wash-sale de-minimis on the sell side: a lot is still harvestable if the only purchases of that name in the prior 30 days total less than 10% of the shares currently held. Without this, the monthly pro-rata dividend reinvestment (about 0.02% of each position) would block essentially all harvesting; the real rule only disallows the loss on the number of replacement shares bought, which at that size is negligible.
  • Harvest is capped at 20% of NAV per month end (largest percentage losses first), so a broad drawdown such as 2008 is harvested over several months rather than in one.
  • Substitutes: the proceeds of a harvested position are put straight into the other holdings in the same sector, in proportion to their target weights, so the portfolio stays close to its design. At the first check after the 31-day wash window the harvested name is bought back to its target weight, funded by trimming same-sector holdings that sit above target (highest-cost lots first). Real programs use a correlated proxy security for this; the sector basket is the stand-in.
  • Tax-aware trading (harvesting runs only): a lot held under a year that sits at a gain is never sold to rebalance or to swap back; it waits until the gain is long-term. The no-harvesting runs are the naive baseline and sell highest-cost lots first regardless.
  • Delisting: a held name whose price goes NaN is sold at its last available close, booked on the first event date (month end or rebalance) at or after the price disappears.
  • Cash held between events earns no interest.
  • Trading is frictionless: no commissions, no spread, no market impact, executed at the close.
  • Losses carry forward indefinitely keeping their short/long character; the $3,000 ordinary-income offset is ignored.
  • Year-end tax is paid from cash first, then by selling pro rata across holdings (HIFO within each name) at the last December close; those sales are realised in the following tax year.
  • The pre-tax path is a separate run of the identical trade logic with taxes switched off, so it never sells to pay tax. With harvesting on it still makes the harvest trades, so the pre-tax paths for harvest-on and harvest-off are not identical.
  • No trading happens on a scenario's final event date; the terminal values are struck on that day's close.
  • Series start at the scenario start date with NAV 1.0, then one point per month end, ending at the scenario end date.
  • Turnover is (buys + sells) / 2 divided by average NAV and by the number of years; the opening purchase and the hypothetical final liquidation are excluded, tax-payment and delisting sales are included.
  • Prices are split-adjusted closes; dividends per share are derived as (1 + total return) * previous close - close, with tiny negatives clipped to zero.

Sources: te_strategy: alphalab enhanced_longonly/annual/vg04_blend (CVM 3103cf9); sp500: alphalab enhanced_longonly/annual/ref_sp500; prices: Sharadar SEP derived panels. Generated 2026-09-08. Script: scripts/taxsim/run.py.

A method demonstration on historical data. Not a track record, not a forecast, not an offer. Simulated results do not predict future returns.