← ClaudeAtlas

after-tax-backtestinglisted

Attach lot matching, wash sales and section 1256 to an existing backtest and report after-tax Sharpe beside pre-tax - and refuse to report one that does not state its rate, jurisdiction and lot method. TRIGGER - after-tax return, after tax Sharpe, tax drag, tax-aware backtest, tax alpha, tax-managed strategy, turnover penalty, "what does this strategy return after tax", tax cost of rebalancing, taxable account backtest, tax-efficient turnover, pre-tax vs post-tax performance, capital gains netting, loss carryforward, "should I hold this in an IRA". Modelling assumptions for backtests, not tax advice. SKIP for the lot rules themselves (tax-lot-matching-and-cost-basis), for the wash-sale mechanics (wash-sale-rules), for futures and index options (section-1256-and-derivatives-tax), for A-share taxes (china-ashare-trading-taxes), and for transaction costs, which are a different drag entirely (execution-cost-analysis).
howard-lynn-ye/fin-skills · ★ 1 · AI & Automation · score 77
Install: claude install-skill howard-lynn-ye/fin-skills
# After-tax backtesting **An after-tax Sharpe without a rate, a jurisdiction and a lot method is not comparable to anything — including the same strategy next quarter. So `report()` refuses to print one.** These are **modelling assumptions for a backtest, not tax advice.** Confirm current law with a qualified professional before relying on any of it. This is the **assembly** skill. It owns nothing of its own: it wires `../tax-lot-matching-and-cost-basis/SKILL.md`, `../wash-sale-rules/SKILL.md` and `../section-1256-and-derivatives-tax/SKILL.md` onto a return series and reports both Sharpes. Read those three for the rules and their sources; read this one for what happens when they meet a backtest. ✅ Measured comes from `scripts/after_tax.py` — numpy + pandas, seed 20260909, one 4-year path, **3.5 s**. ## 1. The guard, and why refusing is the feature ```python TaxAssumptions(jurisdiction=..., short_rate=..., long_rate=..., lot_method=...) ``` All four are **required positional fields with no defaults**, and `require_assumptions()` raises `MissingAssumptions` on anything less. ✅ Measured — the demo's two refusals, verbatim: ``` guard: after-tax results are not comparable without assumptions. Pass a TaxAssumptions with ['jurisdiction', 'short_rate', 'long_rate', 'lot_method']. guard: after-tax result is missing ['long_rate', 'lot_method']. An after-tax Sharpe without a rate, a jurisdiction and a lot method is not comparable to anything. ``` 🔑 **There is no