Skip to content

After-tax performance lens: model annual taxation of trading gains (report-layer first) #2006

Description

@dayfine

Motivation

2026-07-19 ad-hoc analysis (session note): applying a naive 35%/yr tax on net MTM gain to the Run D record path compresses terminal wealth $80.1M → $18.8M (no loss carryforward) / $21.8M (with carryforward) — CAGR 18.0% → 11.7-12.3%. The effect is structural (tax paid annually out of compounding capital, ~0.65× log-growth), and it hits short-holding-period strategies (avg hold ~46d ⇒ nearly all gains short-term ordinary-rate) far harder than buy-and-hold, which defers essentially everything and pays LTCG once. Any honest-tradeable comparison of this strategy vs an index arguably needs an after-tax lens: rough after-tax edge estimate is still ~+4.5pp/yr vs after-tax SPY-TR B&H, but the headline multiple changes dramatically.

Why it isn't simple

  • Basis: realized-gains taxation ≠ yearly-MTM (§475 trader election). Needs per-trade realization dates from trades.csv, not the equity curve.
  • ST/LT split: holding period per trade decides ordinary vs LTCG rate; open positions at year-end defer.
  • Loss carryforward across years (capital-loss netting rules).
  • Wash sales: the strategy re-enters names within 30 days routinely (recoverer re-buys) — disallowed losses could be material.
  • Cash-flow realism: tax paid in April from the account is a forced outflow the simulator doesn't model; at full deployment it forces sales (interacts with cash floor / sizing).
  • Comparator fairness: after-tax strategy must be compared to after-tax benchmark (deferral + LTCG + dividend taxation on the TR series), per the total-return-comparator rule.

Proposed shape (incremental)

  1. Phase 1 — report-layer lens (pure, post-run): an exe over an existing run dir (trades.csv + equity_curve.csv) computing after-tax wealth under configurable regimes: mtm_flat (the 35% naive model, reproduces the ad-hoc numbers), realized_st_lt (per-trade holding periods, ST/LT rates, carryforward), optional wash-sale adjustment. All rates/toggles in config (sexp), no simulator changes. Emits a summary table per run for release reports.
  2. Phase 2 (only if Phase 1 shows decisions would change): in-sim April tax outflows (forced-liquidation realism), behind a default-off config flag per experiment-flag-discipline.

Non-goals for now

Not urgent; not blocking the resistance-v2 promotion or margin milestones. No in-sim changes in Phase 1. OCaml only (no-python rule).

Acceptance (Phase 1)

  • Reproduces the 2026-07-19 naive numbers on the Run D dir ($18.8M / $21.8M) under mtm_flat 0.35.
  • realized_st_lt mode agrees with a hand-computed small fixture (unit-tested).
  • Runs against any scenario output dir; wired into the release-report flow as an optional section.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions