Tax-aware backtesting

Tax-aware backtesting adds account type, tax profile, lot tracking, wash-sale handling, annual tax settlement, and tax diagnostics to a historical portfolio simulation.

On this page

Use this when

Use tax-aware mode when the question is about a real taxable account. It models lot-level sales, wash sales, capital-gains netting, and annual settlement so the after-tax line tells you what remains under the configured tax assumptions.

Good for

  • Comparing turnover-heavy strategies against buy-and-hold on an after-tax basis.
  • Estimating wash-sale and lot-method impact on a realistic taxable account.
  • Showing the gap between pre-tax CAGR and after-tax CAGR over long horizons.

Reach for a different tool when

  • Tax-deferred or tax-free accounts, where annual tax events are zero.
  • Forecasting your real tax bill. It is a portfolio tax model, not a complete return.

Tax-aware backtesting walkthrough

Walkthrough
  1. Start from the same portfolio you would test pre-tax.

  2. Enable the tax-aware engine and set filing status, income, state, account type, and lot method.

  3. Compare pre-tax and after-tax results, then inspect diagnostics before trusting the ranking.

First run

Quickstart
  1. Run the pre-tax version

    Establish the historical result before adding tax accounting.

  2. Enable tax-aware mode

    Set identity, account type, lot method, and carryforward assumptions.

  3. Compare after-tax value

    Check whether taxes change the portfolio ranking.

  4. Inspect diagnostics

    Use drag drivers, high-impact trades, and wash-sale notes to explain the result.

Run the comparison with saved assumptions

Signed-in users can run tax-aware backtests with saved household assumptions. Pro workflows add deeper exports and adjacent advanced tools for taxable-account comparisons.

Pro workflow
What each plan includes, tool by tool

Configuration guide

Tax settings define the taxpayer and account that the run models. They do not describe the investment thesis. They describe the tax treatment of realized activity.

The tax profile appears at the top of Portfolio Backtest after sign in. Rebalancing, date range, and price mode remain in the main portfolio configuration.

ConfigurationWhat It MeansWhy It Matters
Filing statusThe tax bracket table and annual capital-loss deduction limit.The same trades can produce different federal tax bills under different bracket thresholds.
Annual incomeOrdinary income used to locate the marginal tax bracket and NIIT applicability.Higher income can turn realized gains and ordinary dividends into a larger tax drag.
Resident stateThe state tax treatment applied to portfolio investment income.State choice can materially change after-tax results, especially for high-turnover strategies.
Account typeTaxable, tax-deferred, or tax-free treatment for the simulated account.Account type determines whether annual trades create current tax drag or deferred/tax-free results.
Lot methodThe rule that chooses which tax lots to sell when the engine disposes of shares.Lot choice changes realized gain character, loss harvesting, and embedded unrealized gains.
Loss carryforwardPrior capital losses available before the simulation starts.A carryforward can offset future gains and make early tax drag look lower than a fresh account.
Rebalancing settingsThe portfolio-level trading schedule and drift trigger used by both pre-tax and tax-aware paths.Tax-aware mode prices the tax impact of the same trading rule. It does not create a separate rebalance policy.

What is tax-aware backtesting?

Standard backtests report pre-tax returns, which overstate what a taxable account keeps. Tax-aware backtesting models the impact of taxes on portfolio returns. It covers capital gains realization at each modeled sale, wash-sale disallowance, cost-basis lot tracking, and annual tax settlement with loss carryforward.

The engine runs a day-by-day simulation that mirrors a taxable brokerage account under the configured assumptions. Sales trigger gain or loss recognition, and each year nets gains and losses. The engine settles annual tax at the selected federal and state rates, and unused losses carry forward to offset future gains. It is a portfolio tax model, not a full individual tax return.

Getting started

To enable tax-aware backtesting:

  1. (Optional) Open Household, Tax, & Accounts and review the household tax context: filing status, ordinary income, resident state, carryforwards, and TLH substitutes. Portfolio Backtest can load those defaults, and each run can still override them.
  2. Navigate to the Portfolio Backtest page and toggle on "Tax-Aware" mode.
  3. Configure the tax-specific fields for your simulation.

The configurable fields are:

  • Filing status: Single, Married Filing Jointly, Married Filing Separately, or Head of Household. Determines tax bracket thresholds and the annual loss deduction limit.
  • Annual income: your ordinary income from wages and other sources. Used to determine your marginal federal bracket and whether the Net Investment Income Tax applies.
  • State: your resident state. The backtest engine uses resident state only for portfolio investment tax drag. Household work-state inputs support earned-income summaries in household views, but work state does not change portfolio backtest tax drag.
  • Lot method: how the engine chooses shares when selling: optimized, FIFO, LIFO, or HIFO.
  • Account type: Taxable, tax-deferred (traditional IRA/401k), or tax-free (Roth).
  • Portfolio rebalancing settings: set frequency, mode, threshold, and offset in the main portfolio controls, not inside the tax profile. Both pre-tax and tax-aware runs use the same values.
  • Loss carryforward: any prior capital loss carryforward from, for example, real tax returns that you want to add to the simulation.

How the engine works

The tax-aware engine runs in two layers. An execution layer emits deterministic trade events from your portfolio settings. A tool-agnostic tax accounting layer replays those events with lot tracking, wash sale logic, and annual settlement.

Rebalancing cadence, mode, threshold, and offset come from the portfolio configuration itself. The tax profile controls tax identity (filing status, income, lot method, account type, TLH settings), not rebalance scheduling.

  1. Price alignment and initial purchase: on the first day of the backtest, the engine invests the portfolio according to target allocations. Each purchase creates initial tax lots with the acquisition date and cost per share recorded.
  2. Daily loop: the engine updates portfolio values with current prices and then checks drift and calendar conditions. In either mode, either condition is sufficient. In and mode, the engine requires both conditions. Signal allocation changes cause an immediate rebalance. Sales realize gains or losses, and purchases create lots.
  3. Year-end settlement: the engine performs capital gains netting at each year-end and at the end of the backtest. It applies wash-sale adjustments, computes the tax bill, and carries unused losses forward.

The engine works with any strategy that produces target allocations. This includes buy-and-hold and signal strategies. Each backtest year repeats trade execution, wash-sale detection, and tax netting.

Cost basis & lot tracking

Every purchase of shares creates a distinct tax lot that records the acquisition date, number of shares, and cost per share. When shares are sold, the engine selects which lots to dispose of based on your chosen lot method:

  • Optimized: minimizes total tax impact by considering both the gain/loss amount and the holding period of each lot. The engine sorts lots into four priority buckets and sells them in this order:
    • Short-term losses (biggest loss first), harvested first because they offset short-term gains taxed at the highest rates.
    • Long-term losses (biggest loss first), harvested next to offset long-term gains, or cross-character to offset short-term gains.
    • Long-term gains (smallest gain first): when a sale must realize gains, prefer long-term, which carries the lower capital gains rate (0-20%).
    • Short-term gains (smallest gain first): the most expensive gains from a tax perspective, deferred as long as possible.
  • FIFO (first in, first out): sells the oldest lots first. This is the deterministic fallback when you do not identify a specific lot. It tends to realize long-term gains sooner.
  • LIFO (last in, first out): sells the newest lots first. Tends to realize short-term gains or losses.
  • HIFO (highest in, first out): sells the highest-cost lots first, which minimizes realized gains (or maximizes realized losses).

When a sale does not consume an entire lot, the engine splits the lot proportionally. The sale recognizes a gain or loss on the sold portion. The remaining portion retains its original acquisition date and cost basis. Each purchase also retains a stable identity across partial-sale and wash-sale fragments. A specific-lot sale consumes only fragments from that purchase. Separate purchases remain separate even when their acquisition date and price match.

The holding period determines the tax character of each gain or loss. Shares held for more than one year (366+ days) qualify as long-term, which carries preferential rates. Shares held for one year or less are short-term and taxed as ordinary income.

Capital gains netting (IRS rules)

At year-end, the engine follows IRS netting rules to determine your taxable gains:

  1. Separate netting: the engine nets short-term gains against short-term losses, and long-term gains against long-term losses. The result is a net short-term amount and a net long-term amount.
  2. Cross-character netting: if one character (short-term or long-term) has a net loss, that loss offsets the other character's net gain. For example, a net short-term loss of $5,000 can offset $5,000 of net long-term gains.
  3. Annual loss deduction: you can deduct a remaining net capital loss against ordinary income. The limit is $3,000, or $1,500 for Married Filing Separately. This gives a benefit at the marginal ordinary rate.
  4. Loss carryforward: any remaining net capital loss beyond the $3,000 annual limit carries forward indefinitely to future tax years. The engine applies carryforward losses to the same character first (short-term carryforward offsets short-term gains first, then long-term).

The engine applies prior-year carryforward losses at the start of each year's netting process, same character first. These losses come from the seed value you enter or from previous simulation years. Cross-character netting occurs after that step.

Wash sale rules

The IRS wash sale rule can disallow a loss after a substantially identical purchase. The window includes 30 days before and after the sale, plus the sale date. The engine models these security-level mechanics:

  • Loss disallowance: when a wash sale applies, you cannot deduct the disallowed loss in the current year.
  • Basis adjustment: the engine adds the disallowed loss amount to the cost basis of the replacement lot. This preserves the economic loss for future recognition.
  • Holding period tacking: the engine adds the holding period of the original (washed) lot to the replacement lot's holding period. A short-term lot can then qualify for long-term treatment.
  • Partial wash sales: assume you sell 100 shares at a loss but repurchase only 60 replacement shares within the window. The rule disallows only 60 shares' worth of the loss. The remaining 40 shares' loss stays fully deductible.
  • Cross-year wash sales: a wash sale that spans December and January can force a re-calculation of a previously settled prior-year tax bill. Losses from December may become disallowed based on January purchases.

Tax Rates

The engine applies federal, state, and Net Investment Income Tax rates based on your profile:

  • Short-term capital gains: taxed as ordinary income at your marginal federal rate. The 2026 federal brackets range from 10% to 37% depending on taxable income and filing status.
  • Long-term capital gains: taxed at 0%, 15%, or 20%, depending on total income. Most taxpayers pay 15%. Lower incomes can pay 0%, and the highest incomes pay 20%.
  • Net Investment Income Tax (NIIT): an additional 3.8% tax on investment income above the applicable MAGI threshold. It applies in addition to short-term and long-term rates.
  • State capital gains tax: modeled with progressive state income-tax brackets (2025 table) and applied incrementally on top of your ordinary income baseline. Rates still range from 0% in states like Florida, Texas, and Nevada to 13.3% top marginal in California.
  • Tax benefit from losses: capital losses that offset ordinary income (up to the $3,000 annual limit) generate a tax benefit. The engine calculates that benefit at your marginal ordinary income rate, which is a partial refund of the tax drag.

Account types

The tax treatment depends entirely on the account type you select:

  • Taxable brokerage: the full tax simulation runs, including capital gains on every sale, wash sale tracking, annual netting, and loss carryforward. This is the default and most detailed mode.
  • Tax-deferred (traditional IRA/401k): no annual tax events occur during the backtest. All gains grow tax-deferred. Upon withdrawal, the entire amount counts as ordinary income at your marginal rate. The engine models the deferred tax liability at the end of the simulation.
  • Tax-free (Roth IRA/401k): no tax events at all. Qualified withdrawals are completely tax-free. The after-tax and pre-tax lines will be identical.

Reading the results

When tax-aware mode is active, the results page expands with several additional visualizations and data points:

  • Tax diagnostics: translates the raw ledgers into main drag drivers, high-impact years, high-impact trades, concentrated unrealized gains, implementation warnings, and confidence flags. You can then see why a strategy is tax-inefficient before drilling into raw lot rows.
  • Pre-tax and after-tax chart: the solid line shows pre-tax portfolio growth. The dashed line shows after-tax growth. The shaded area shows cumulative tax drag during the backtest.
  • Cumulative tax paid chart: a running total of all taxes paid over the backtest period, showing how the tax burden accumulates year by year.
  • Tax summary cards: at-a-glance figures for total tax paid, total short-term and long-term gains and losses, and total wash sale disallowances. The cards also show remaining loss carryforward at the end of the simulation.
  • Annual tax bills table: a yearly breakdown of short-term tax, long-term tax, NIIT, dividend tax, state tax, loss benefit, and total tax.
  • After-tax metrics in summary tab: adds rows for after-tax ending value, after-tax CAGR, tax drag percentage, and total taxes paid.
  • Non-taxable account state: tax-deferred and tax-free accounts render an explicit not-applicable diagnostics state instead of implying zero tax drag from annual taxable events.
  • Degraded diagnostics state: if dividend or other attribution inputs are incomplete, the diagnostics remain visible. They mark the run as degraded and surface confidence flags instead of reporting the attribution as fully precise.

Tips for tax-efficient investing

  • Use optimized lot selection: the default method uses gain or loss and holding period to reduce tax impact. It harvests losses first. For gains, it prefers long-term lots over short-term lots. This can reduce cumulative tax drag compared with FIFO or HIFO.
  • Favor longer holding periods: Gains on shares held for more than one year qualify for long-term capital gains rates. Short-term gains use ordinary income rates. Less frequent rebalancing can increase holding periods.
  • Monitor tax-loss harvesting opportunities: the wash sale and loss data in the results reveal how much harvesting occurred naturally during rebalancing. Significant wash sale amounts suggest the engine detected loss-generating sales followed by repurchases.
  • Loss carryforward is a tax asset: accumulated loss carryforward reduces future tax bills dollar for dollar. If your simulation shows a large carryforward balance, that balance is a deferred tax saving that you can still use.

Limitations & assumptions

The tax-aware engine models capital gains, wash-sale disallowances, and short-term versus long-term rates. It has these additional boundaries:

  • Federal brackets can use current 2026 tables, historical annual tables, a custom progressive schedule, or a flat rate. Historical annual aggregate requests fail closed for unsupported years or unsupported aggregate capital-gain cases instead of reusing the latest table.
  • State tax modeling uses progressive brackets for Single and Married Filing Jointly. Other statuses use top marginal rates. Only the resident state affects portfolio investment tax. Work state affects household earned-income summaries.
  • No Alternative Minimum Tax (AMT) modeling. Taxpayers subject to AMT may see different effective rates than the simulation suggests.
  • The engine does not include local or city taxes, such as New York City's additional income tax.
  • Extended history .SIM series carry no income component. They model a price path only, and they have no dividend, distribution, or interest stream. A taxable account therefore has no income to tax, so the engine refuses the after-tax replay and reports why. Run the same allocation with the live ETF ticker for an after-tax result, or read the .SIM series pretax. A tax-deferred or tax-free account computes no tax, so it still accepts a .SIM series.
  • The same refusal covers a live ticker that borrows extended history through a fill-backward (FB) modifier. Cash proxies are the exception. The engine derives their interest from the series itself and taxes it as ordinary income.
  • The engine models dividend events, including DRIP. Some tickers and date ranges have degraded or unavailable upstream dividend data. When this happens, the UI shows a warning, and the model may understate tax drag.
  • Qualified dividend treatment uses asset-level eligibility plus a per-lot holding-period check around the ex-dividend date. The engine still does not model issuer-reported yearly qualified-dividend percentages. An example is an ETF that is 85% qualified and 15% ordinary in a specific tax year.
  • Wash sale matching includes conservative "substantially identical" groups (for common ETF pairs) plus TLH substitute mappings. It is not a complete legal classifier for every possible ETF/security pair.
  • If a simulation ends mid-year, the engine settles taxes at the end date as if the tax year closed there. This is useful for comparability, but real tax filing occurs only at year-end.
  • Tax simulation starts from the initial investment. It threads portfolio cashflow entries into tax accounting as taxable buy/sell events when the engine applies those cashflows.
  • Rebalancing Comparison + tax: tax-aware cells are 10-15× slower than pretax cells. Thus, the tool uses a lower default run-count cap. Enable the full sweep only for denser grids. Tax-aware sensitivity runs do not support cash flows. Remove contributions or disable the tax profile before you run the sweep.

Common pitfalls

  1. Treating after-tax CAGR like pre-tax CAGR

    Tax-aware mode is a different experiment. Compare two tax-aware runs to each other, not a tax-aware run to a pre-tax one.

  2. Frequent rebalancing with tight thresholds

    Tight bands plus a taxable account often trigger wash sales and short-term gains. Widen the band, lengthen the cadence, or move to a tax-deferred account.

  3. Ignoring carryforward seeding

    If your real account has a loss carryforward, seed it. A fresh account without one understates the tax benefit you have available.

  4. Choosing FIFO out of habit

    Optimized lot selection considers both gain size and holding period. On long horizons it often beats FIFO and HIFO.

Glossary

Tax lot
A specific batch of shares with its own acquisition date and cost basis. Sales pick from lots according to the chosen method.
Short-term vs long-term
Held one year or less is short-term (taxed at ordinary income rates). Held more than one year is long-term (taxed at preferential rates).
Wash sale
A loss the IRS disallows when a repurchase of a substantially identical security falls within 30 days before or after the sale.
NIIT
Net Investment Income Tax. A 3.8% surtax on investment income above MAGI thresholds ($200K Single, $250K MFJ).
Loss carryforward
Net capital losses beyond the annual deduction limit carry forward indefinitely to offset future gains.
Lot method
The rule that selects which lots are sold first. Optimized, FIFO, LIFO, and HIFO produce different realized gain and loss patterns.
Tax drag
The cumulative wealth lost to taxes. The gap between the pre-tax and after-tax growth lines.