# Capacity & Stress-Execution Realism — 2026-05-30

**Type:** research note (NON-alpha, no production change). Objective 2 of the
2026-05-30 "harden the apparatus" AFK session.

**Method:** the EXISTING Almgren–Chriss impact model
(`backtest/costs.py:compute_impact_cost`, the production cost model — *not*
rewritten) applied to the real latest book, real per-name ADV/vol, and — for the
crash case — stressed inputs. Analysis layer: `backtest/capacity.py`; CLI:
`thales capacity-report`. Reproduce with that command.

ADV/vol definitions mirror the engine exactly: ADV = 20-day mean share volume,
σ = 63-day annualized return std, spread = 5bps one-way, impact_coeff = 0.1.

## The book being sized

- Latest rebalance: **2026-03-02**, 50 names.
- **Gross exposure ≈ 24.5%** — the half-Kelly × VIX-scaled vol-target shrinks the
  book well below 1.0. This is the single most important capacity fact: a "full
  liquidation" only sells ~24.5% of AUM, so dollar trades — and therefore impact
  — are ~4× smaller than the AUM headline suggests.
- Mean one-way rebalance turnover across all 194 historical rebalances: **13.4%**
  (the BRIEFING's "~27%" is roughly the two-way figure; one-way is what the cost
  model charges). Latest-vs-prior book turnover: 11.3% one-way.

## "Effective bps" and what "breaks the flat assumption" means

Effective bps = modelled cost ÷ one-way dollars traded × 1e4. By construction the
impact model's **spread floor** (5bps on buys + 5bps on sells) equals the
production **flat 10bps round-trip** — that *is* the documented "flat 10bps ≡
Almgren–Chriss at production turnover" calibration. So the flat assumption does
not "break" at the floor; it breaks when the size-dependent **impact** term pushes
total cost *materially* above it. We flag that at **1.5× = 15bps** (impact has
added ≥50% on top of spread).

## (a) Normal monthly rebalance — shortfall by AUM

| AUM | $ traded (1-way) | cost $ | eff bps | flat assumption |
|-----|-----------------:|-------:|--------:|-----------------|
| $100K | $11,275 | $11 | 10.08 | holds |
| $1M | $112,752 | $115 | 10.24 | holds |
| $10M | $1,127,519 | $1,213 | 10.76 | holds |
| $100M | $11,275,195 | $13,982 | 12.40 | holds (+24%) |
| $1B | $112,751,949 | $198,337 | 17.59 | **broken** |
| $10B | $1.13B | $3,833,955 | 34.00 | **broken** |

- **Capacity ceiling (>15bps): ≈ $434M AUM.** Below this the production flat-cost
  assumption is sound for the normal monthly rebalance.
- Cost doubles vs the assumption (>20bps) at **≈ $1.7B**.
- At the realistic near-term AUM ($100K–$10M paper/seed), modelled impact is
  within ~0.7bps of the flat assumption — i.e. **the flat 10bps is honest at the
  size this strategy will actually trade for a long time.**

## (b) Kill-switch full liquidation (book → cash)

This is the tail the 5-window walk-forward misses by construction: the 20%
kill-switch fires *precisely when liquidity evaporates*.

**Calm regime** — almost identical to a rebalance (liquidation turnover ≈ gross
≈ 24.5% one-way): ceiling ≈ **$391M**, eff bps 10.1 ($100K) → 18.0 ($1B).

**Stressed regime** (spreads ×4, ADV ×0.3, σ ×3 — a credible crash):

| AUM | $ traded (1-way) | cost $ | eff bps |
|-----|-----------------:|-------:|--------:|
| $100K | $12,269 | $50 | 40.44 |
| $1M | $122,688 | $508 | 41.38 |
| $10M | $1,226,882 | $5,445 | 44.38 |
| $100M | $12,268,816 | $66,062 | 53.85 |
| $1B | $122,688,159 | $1,027,908 | 83.78 |

- The stress cost decomposes into a **size-independent spread tax ≈ 40bps**
  (the ×4 spread widening — paid regardless of AUM) **plus a size-driven impact
  term** that adds ~43bps more by $1B.
- **In absolute portfolio terms it is small at realistic AUM:** a stressed full
  liquidation costs **~0.05% of the portfolio at $10M** (only ~24.5% of AUM is
  sold, and these are liquid large-cap Russell names). It only becomes a material
  drag (>0.1% of portfolio) above ~$1B.
- **The single-day assumption is the ACTUAL modeled behavior, not a conservative
  upper bound.** Verified in code: the kill-switch BYPASSES the daily turnover cap
  in both paths. In the backtest engine the cap is applied (`engine.py` ~L631)
  *before* `if in_cash: new_weights = {}` (~L660), and the live path
  (`daily.py:_liquidate_to_cash`) submits orders for `positions -> {}` with no cap.
  So when the kill-switch fires the entire book is dumped in one session — by
  design (get out fast in a crash), but it means the figures above are what the
  system would really pay, at the worst possible moment (peak illiquidity).
  Staging the exit WOULD lower impact, but the system does not stage; that is the
  untested tail this study quantifies.

## What binds capacity — the smallest-ADV names, not the book average

Capacity is not set by the portfolio as a whole; it is set by a handful of
thin-ADV holdings that hit a high ADV participation first. Per-name participation
(trade shares ÷ ADV) for the normal rebalance at the **$434M ceiling**:

| name | Δw | participation (% of ADV) | ADV $ |
|------|----|--------------------------|-------|
| MLI | 1.57% | **9.2%** | $74M |
| ENS | 0.72% | 4.3% | $72M |
| BWA | 1.45% | 3.7% | $169M |
| EA | 2.65% | 2.4% | $479M |
| VAL | 0.72% | 2.3% | $137M |
| ORA | 0.44% | 2.2% | $88M |

Only **8 of 62 traded names exceed 1% ADV participation** at the ceiling; the
median name is **0.23% of ADV**. So the ceiling is a *few-names* phenomenon —
MLI ($74M ADV) alone drives it. **Implication:** an ADV floor in the universe
filter, or a per-name participation cap on the thinnest holdings, would extend
capacity well beyond $434M without touching the rest of the book. (`thales
capacity-report` prints this binding-names table; `per_name_participation()` is
the reusable function.)

## Capacity ceiling — summary

| Scenario | Flat assumption materially breaks (>15bps) |
|----------|--------------------------------------------|
| Normal monthly rebalance | **≈ $434M** |
| Kill-switch liquidation, calm | ≈ $391M |
| Kill-switch liquidation, stressed | spread tax dominates (~40bps fixed) at all sizes; size adds materially above ~$1B |

**Realistic capacity ceiling for the strategy as configured: a few hundred
million AUM** (~$400M), driven by the normal rebalance. Above that, the flat
10bps cost assumption understates reality and the backtest's net Sharpe is
optimistic. The low gross exposure (24.5%) is what buys this headroom.

## Hard caveat — paper TCA is NOT a capacity signal

The live paper-trade TCA reads ≈ **0 bps**. This says **nothing** about capacity:
Alpaca paper fills at NBBO/mid at trivial size, so zero market impact is
*simulated*, not *measured*. Do not infer "costs are negligible" from paper
fills. The only honest capacity estimate is the model above; the only honest
live-cost estimate will come from real fills at real size.

## Conclusion (no production change)

- Flat 10bps is sound up to ~$400M AUM — far above any near-term plan.
- The kill-switch-into-a-crash tail is real but, at realistic AUM, modest in
  portfolio terms (~5bps of equity at $10M) because the book is only ~24.5% gross
  and holds liquid names. It grows dangerous only at ≫ $100M.
- The kill-switch dumps the whole book in one session (verified: it bypasses the
  turnover cap in both engine and live). Fine at current scale; revisit if AUM
  grows.
- Action items (out of session): when AUM approaches $100M, switch the backtest
  to the impact model (`costs.model: impact`) and re-validate; and decide
  deliberately whether the kill-switch should STAGE its liquidation (lower impact,
  slower exit) vs. the current single-session dump (higher impact, fast exit) —
  currently it does not stage. A speed-vs-impact tradeoff, not a bug.
