Skip to content

11. Capacity, crowding & the size at which the edge stops being yours

Every chapter so far has sized a strategy as if the market would hand you any quantity at the price on your screen. Kelly computes a leverage; vol-targeting scales it; the allocator splits the book by risk; risk of ruin evaluates survival at a deployment weight. Not one of them asks the question that decides whether the edge survives contact with real size: can the market actually absorb the notional this math just produced, without your own trading moving the price against you? It cannot, beyond some size, and that size is the most under-discussed number in retail quant. A "production" book that never asks how much can this take? has a hole exactly where a paper book ramped toward live size is most exposed.

This chapter is about capacity: the size at which your own market impact, or a crowd trading the same signal, consumes the edge you measured at toy size. It has three moving parts — a capacity ceiling you impose on yourself through market impact, the cost-aware re-validation that turns that ceiling into a deploy/no-deploy verdict at deployed size, and crowding, the ceiling other people impose on you by trading the same thing. The unifying identity is simple and ruthless: turnover × size = impact, so capacity is never a property of the edge alone; it is a property of the edge, the turnover, and the liquidity, together.

The capacity ceiling: ADV, participation, and the square-root wall

The execution chapter introduced market impact as a cost term: slippage that grows with participation, where participation is your order size as a fraction of the instrument's average daily volume (ADV). The form is sub-linear — roughly the square root of participation — and that shape is the whole story of capacity:

# from cost_realism.apply_sqrt_impact_slippage: slip GROWS with participation = order / ADV
slip = coef * np.sqrt(np.clip(participation, 0.0, None))   # participation = clip_notional / ADV
cost = turnover * slip                                      # paid every time you trade

At toy size, participation is a rounding error and impact is invisible — which is exactly why a backtest run at notional ≈ 0 reports an edge that looks free. As you scale up, participation rises and the per-unit impact rises with its square root, so the total impact you pay scales faster than linearly with the size you're trying to deploy. Somewhere on that curve, the impact cost equals the gross edge, and every dollar beyond that point trades at a loss. That crossover is your capacity ceiling: the most you can run before your own footprint eats the alpha.

Two consequences follow immediately, and both are routinely missed:

  • Capacity is a function of turnover, not just AUM. Because impact is paid per trade (turnover × slip), a sleeve that turns over weekly hits its ceiling at a far smaller book than one that turns over yearly, even at the same edge and the same ADV. A fast signal is a small-capacity signal, structurally. This is why the allocator's turnover discipline — a no-trade band, a turnover penalty — is not just a cost saving; it is a capacity lever: every basis point of turnover you don't spend is capacity you buy back.
  • The sizing chain has no ceiling in it. Kelly hands back a leverage that can be 75×; vol-targeting converts it to a notional; the allocator weights it — and none of those steps knows the ADV of the thing being traded. The math will cheerfully hand you a clip the market cannot absorb in a day, with no error and no warning. Capacity is the cap the sizing chain is missing.

Turn the ceiling into a verdict: re-run the cost-aware WFO at deployed size

A capacity ceiling is only useful if it gates a decision. The mechanism already exists — the execution chapter's realistic-cost gate re-runs the bootstrap-Sharpe CI on the net-of-cost series and requires the lower bound to stay positive. Capacity makes one change to it: evaluate the impact term at the participation your deployed size actually implies, not at a fixed bps.

# Capacity-aware cost gate: the slippage term is evaluated at the participation
# implied by the DEPLOYED clip, so the verdict becomes size-conditional.
for clip in [size_small, size_target, size_2x]:
    participation = clip / adv
    net = apply_sqrt_impact_slippage(gross_returns, turnover, participation)
    net = apply_cost_model(net, turnover, cost_model)        # spread/commission too
    ci_lo, _ = bootstrap_sharpe_ci(net, periods_per_year)
    print(clip, "deployable" if ci_lo > 0 else "OVER CAPACITY")

The result is the uncomfortable truth a single backtest hides: deploy/no-deploy is not a property of the strategy, it is a property of the strategy at a size. A sleeve can be a clean pass at the minimum size that clears commission and an outright reject at the size someone actually wants to run, because the impact term that was a rounding error at the small clip is the entire edge at the large one. The honest response to "it fails at the size I want" is deploy it smaller — at or below its capacity ceiling — not to wish the impact away. An edge run past its capacity isn't a smaller edge; it's a negative one wearing the backtest's optimism.

Capacity is the sixth decision axis — and it lives at deployment, not research

The decision matrix scores five axes — CI_lo, DSR, Monte-Carlo drawdown, sanctuary, noise — and every one of them is a property of the return series, computed with no reference to how much capital you'll deploy. Capacity is structurally different: it is the one axis you cannot evaluate in research, because it only exists once you fix a size and an ADV. So treat it as a sixth axis evaluated at deployment, a gate that sits alongside the research verdict rather than inside its count-of-best ladder. A strategy can be a five-axis DEPLOY and still fail the capacity axis at your intended size — and that combination means "deploy, but smaller," not "deploy as planned." Check it before every ramp tranche (see paper to live), because participation rises with each step up and a clean small-size replay never guarantees a clean larger one.

Crowding: the capacity ceiling other people impose

ADV-participation is the ceiling your own footprint imposes. Crowding is the ceiling imposed by everyone else trading the same edge, and it is both more dangerous and harder to measure, because you cannot see other people's positions.

Two distinct harms hide under the one word:

  • Alpha decay. When capital crowds into a published or widely-rediscovered signal, the signal is arbitraged down: more money chasing the same forecast compresses the very mispricing the forecast exploits. A real edge has a half-life, and crowding shortens it. You cannot observe the crowd directly, but you can observe the symptom — a live edge decaying against its research baseline — which is why the Learn-loop's edge-decay detection is also a crowding detector.
  • Correlated exit. The more dangerous harm is in the tail. A crowded trade is one where everyone holds the same position and everyone's risk model says "reduce" at the same moment, so the unwind is a stampede: the de-grossing is the crash, the exact mechanism the correlation dial exists to fade. Crowding therefore makes a strategy's drawdowns fatter-tailed and more synchronised with everyone else's precisely when diversification is supposed to save you — the same blindness the stressed joint-ruin sim and the factor-exposure decomposition are built to surface.

The defensive posture is humility about what you can know: assume any edge you found from a public source (a paper, a forum, a popular indicator) is more crowded than your backtest reflects, treat capacity estimates on it as optimistic, and lean on a diversity of low-correlation edges rather than scaling a single crowded one. Crowding is a capacity sibling because it does the same thing capacity does — shrink the size at which the edge is yours — just on a clock you don't control.

War-story: the small-edge sleeve that was deployable only at toy size

A slow cross-asset sleeve cleared every research gate with a positive lower bound and went to paper. Its backtest, like all backtests, was run at negligible notional, so its impact cost was effectively zero and its net edge looked clean. The first time anyone asked "what's the capacity?", the answer was sobering: re-running the cost gate with the slippage term evaluated at the participation a real allocation would imply — a meaningful fraction of the substitute instrument's ADV, on a leg that wasn't especially liquid — pushed the net lower bound toward zero an order of magnitude below the book size someone had in mind. The edge was real; it was just small and shallow-pooled, deployable at a fraction of the intended size and a reject above it. The rule it bought: a backtest's edge is quoted at zero participation; the deployable edge is quoted at your size, and for a small-edge sleeve those are different strategies. Titan models the sqrt-impact slippage and can run the size-conditional cost gate, but it has no explicit capacity-ceiling estimate, no ADV cap in the sizing chain, and no crowding monitor — so this is, as ever, a designed defence the primitives support, not a shipped control.

The Titan example: primitives present, the ceiling absent

Honesty first, as every chapter in this part insists.

Piece Status What it does / doesn't
Sqrt-impact slippage model shipped (cost_realism.apply_sqrt_impact_slippage) impact = turnover × coef·√participation; the curve a capacity ceiling reads off
Cost-aware deploy gate shipped (realistic_cost_gate) re-runs net CI_lo > 0; capacity just feeds it a size-dependent slippage
Explicit capacity ceiling (the deployable-size estimate) not built nothing computes "the size at which impact eats the edge"
ADV / participation cap in sizing not built Kelly/vol-target/allocator hand back a notional with no liquidity ceiling
Capacity axis in the decision matrix not built the verdict is size-independent; deployment size is chosen by other means
Crowding / signal-decay monitor partial the Learn-loop edge-decay detector is the nearest tell; no positioning/crowding measure

The honest summary: Titan has the cost primitive (sqrt-impact) and the gate primitive (the realistic-cost CI), so it can answer "is this deployable at size X?" for a given X — but it does not yet estimate the ceiling, cap the sizing chain at it, or score it as an axis, and it has no direct read on crowding. The pieces are in the repo; assembling them into a capacity ceiling that the sizing chain and the deploy gate both respect is the work this chapter specifies.

Exercises

  1. Why deploy/no-deploy depends on size. A sleeve passes the cost gate at minimum size and fails at 10× the size, with an identical edge. What changed? ??? success "Answer" The market-impact cost grows with the √ of participation (clip/ADV), so the impact term that was a rounding error at small size becomes the whole edge at large size. The verdict is size-conditional; the honest fix is to deploy smaller, at or below the capacity ceiling — not to wish the impact away.
  2. Turnover and capacity. Two sleeves share an edge and an ADV; one turns over weekly, one yearly. Which has the smaller capacity, and why? ??? success "Answer" The weekly one — impact is paid per trade (turnover × slip), so a fast sleeve hits its ceiling at a far smaller book. A no-trade band and a turnover penalty are therefore capacity levers: turnover you don't spend is capacity you keep.

Takeaways

  • The sizing chain has no liquidity ceiling in it. Kelly, vol-targeting, and the allocator all hand back a notional with no reference to ADV. Capacity is the cap they're missing: the size at which your own market impact equals the edge.
  • Capacity = edge × turnover × liquidity, not AUM alone. Impact is paid per trade and grows with the √ of participation, so a fast-turnover sleeve hits its ceiling at a far smaller book than a slow one. Turnover discipline (a no-trade band, a turnover penalty) is a capacity lever, not just a cost saving.
  • Deploy/no-deploy is a property of the strategy at a size. Re-run the cost-aware WFO with the slippage term evaluated at your deployed participation; a clean small-size pass can be an over-capacity reject at the size you want. The fix is to deploy smaller, never to wish the impact away.
  • Capacity is the sixth decision axis, and it lives at deployment. The five research axes are size-independent; capacity can only be scored once a size is fixed, so gate it alongside the matrix and re-check it before every ramp tranche.
  • Crowding is the capacity ceiling you don't control. Others trading your edge decays the alpha (watch the live-vs-research drift) and synchronises the exit (fattens the tail, the de-gross-into-the-same-move trap). Treat any public-source edge as more crowded than the backtest shows, and prefer a diversity of edges over scaling one.

All participation coefficients, ADV fractions, and capacity thresholds here are illustrative; the real liquidity of each traded instrument and the deployed sizes are configuration, not edge. The transferable part is the method — read the ceiling off the √-impact curve, turn it into a size-conditional cost gate, score it as a deployment axis, and respect crowding as the ceiling you can't measure.


This chapter put a ceiling on the size the sizing chapters compute. It feeds forward into the allocator, where turnover-aware construction (a no-trade band, a turnover penalty) is the lever that buys capacity back, and into paper to live, where the capacity check gates each ramp tranche. It reads its impact curve from the execution layer and its crowding tell from the Learn loop; next, the sanctuary & decision matrix is where the research verdict this capacity axis sits beside is actually computed.