The United States tax engine is the most permissive of the four the platform supports — HIFO is allowed, the wash-sale rule is well-codified at §1091, the long/short-term split is a clean 12-month boundary, and the substantially-identical test has decades of administrative practice behind it. This post walks through what each piece means for the optimizer's daily solve, and what data the engine reads to compute it.
HIFO, FIFO, LIFO, average cost — what the rule actually requires
US tax law lets the holder identify which lot is sold on each sale, provided the identification is made at or before the time of sale and recorded on the broker statement. Three flavours practitioners use:
| Method | Picks | When the optimizer prefers it |
|---|---|---|
| HIFO | Highest cost first | Maximises realised loss / minimises realised gain on every sale |
| FIFO | Oldest first | Maximises long-term proportion of realised gain (oldest lots most likely past 12-month gate) |
| LIFO | Newest first | Rare; only useful in narrow contexts |
| Average cost | Pooled basis | Mutual-fund convention; not used for individual stocks |
§1091, the 30-day window, and 'substantially identical'
§1091 disallows a loss on a sale if a substantially identical security is acquired in the 30 days before or after the sale. The disallowed loss is added to the basis of the replacement security and the holding period of the original is tacked on, which means the wash-sale doesn't disappear — it just defers the deduction.
The optimizer's wash-sale layer is conservative on tickers (locks the exact ticker for 30 days) and requires explicit configuration to treat non-identical names as substantially identical. The replacement-security selection routine — which picks the correlated substitute the optimizer rotates into for the lockout period — is documented in the replacement-security post.
12 months, day count, lot-by-lot
Long-term capital gains apply when the holding period exceeds one year. The clock starts on the day after acquisition and ends on the day of sale. The optimizer's tax engine carries the acquisition date on every lot and computes the holding period exactly — no calendar-month approximations. A name acquired Jan 15 2025 crosses to long-term on Jan 16 2026.
Federal headline rates, NIIT, and AMT
| Component | Short-term | Long-term |
|---|---|---|
| Income / capital-gains rate | 37% | 20% |
| NIIT (§1411) | 3.8% | 3.8% |
| Total federal | 40.8% | 23.8% |
Per-account inputs the US tax engine consumes
- Lot history. Per-ticker, per-acquisition-date, with cost basis. The engine carries this from Account.lots in Postgres.
- Marginal-rate set. Three numbers: short-term rate, long-term rate, NIIT. Stored on the Account record.
- Wash-sale lock vector. Per-ticker, per-day, derived from the trailing 30 days of loss-realising sells. The DailyRunner populates this vector before each solve.
- Filing status (optional). Used only if the account elects per-bracket marginal-rate calculation; most accounts pass a flat top-bracket rate.
§1091 is a deferral, not a forfeiture. A wash-sale loss is added to the replacement security's basis and recovered on its eventual sale.
What the US engine doesn't model
- State / local capital-gains tax is passed through as a flat surcharge on realised gains, not modelled with state-specific residency, source, or apportionment rules.
- AMT (§55) interaction with capital-gains income for high-AMT taxpayers is not in the engine; production accounts with AMT exposure should consult a tax advisor before trading on the engine's output.
- §1259 constructive-sale treatment for certain offsetting structures is layered into the long/short and VPF strategies separately; it's not part of the base US tax engine for long-only DI.
- IRC §1091 — Loss from wash sales of stock or securities.
- IRC §1411 — Imposition of net investment income tax.
- IRS Publication 550 — Investment Income and Expenses. The wash-sale chapter is the canonical practitioner reference.
Educational illustration · not advice · jurisdictional rules change.