The Learning Library
Contents

Module 23 — Risk Management & Position Sizing

Part V · Production · Priority 🎯 Core · Status: Draft v0.1 Prerequisites: Module 2, Module 6, Module 16, Module 22


Overview

Position sizing is the discipline that converts an edge into survivable bets: given a signal with positive expectancy, sizing decides whether you compound it or get carried out by an ordinary losing streak. The edge itself explains surprisingly little of the spread in long-run outcomes between traders running the same system — bet size does, because compounding punishes oversized bets far harder than undersized ones reward them. On the other side of every oversized position stands the broker’s margin desk and its stop-out engine, which liquidates leveraged accounts mechanically, without sympathy and without exception.

This module treats sizing as engineering, not taste: the Kelly criterion as a ceiling with a haircut, volatility targeting as the everyday workhorse, drawdown ladders as the circuit breakers, portfolio heat as the aggregate exposure ledger, and stress replays as the reality check. Everything ends in one artifact you can enforce in code — a written risk constitution your supervisor executes line by line.

House position: your research pipeline produces validated candidates; this module is where their size gets decided, bounded, and policed. Signals pick the horse; sizing decides whether you finish the race.


Why Sizing Decides Survival

The arithmetic average of returns lies about compounding. A trader who gains 50% then loses 50% is down 25% overall, despite averaging zero. Sequences multiply, and multiplication has a nasty asymmetry: a −20% drawdown needs +25% to heal, while −50% needs +100%.

That asymmetry creates volatility drag: every unit of additional size adds expected gain roughly in proportion to size, but adds compounding drag roughly in proportion to size squared. Small sizes leave growth on the table; large sizes pay more in drag and tail risk than they collect in edge. Somewhere in between sits an optimum — and past it, a winning system loses money. That single sentence is the entire theory of this module.

It also means sizing explains more of the variance in long-run outcomes than signal accuracy does. Two traders running identical signals at 2% versus 0.5% risk per trade will diverge enormously over a hundred trades; two traders at identical size whose win rates differ by a point or two barely diverge at all. You cannot fix a bad signal by resizing forever — but you can absolutely destroy a good signal by resizing badly.

💡 Idea: Read every sizing rule as insurance pricing. The premium you pay is slower compounding; the insured event is the losing streak that would otherwise end the fund. Under-insuring wastes the edge; going bare is how accounts die.

Losing streaks: the hand-checkable core

Ten consecutive losses is not a freak event — at a 48% loss rate per trade, a 10-loss streak shows up in a few hundred trades. What it costs depends only on size, because losses compound multiplicatively. With risk r per trade, ten losers leave (1 - r)^10 of equity:

Risk per trade Equity after 10 straight losses Gain needed to recover
0.5% −4.9% +5.1%
1.0% −9.6% +10.6%
2.0% −18.3% +22.4%

Hand-check the worst row: 0.98^10 = 0.817, so equity is down 18.3%, and healing requires 1 / 0.817 - 1 = +22.4%. Same signals, same streak — the 2% trader needs four times the recovery of the 0.5% trader. Size is the variable you actually control.


The Kelly Criterion, Practically

The Kelly criterion answers one question: what bet size maximizes long-run compound growth? For a discrete win/lose system, it balances three things — how often you win, what winners pay relative to losers, and nothing else. In plain words: bet the fraction where the marginal gain from betting bigger equals the marginal compounding damage of the extra variance.

Following the house pattern, the derivation lives in code, not algebra:

# Kelly fraction for a discrete win/loss system -- with a haircut parameter
def kelly_fraction(win_prob, payoff_ratio, haircut=1.0):
    """Full Kelly share of capital per trade; haircut scales it down."""
    gross_edge = payoff_ratio * win_prob - (1 - win_prob)
    return haircut * gross_edge / payoff_ratio

print(kelly_fraction(0.52, 1.5))           # -> 0.2000  full Kelly: 20%
print(kelly_fraction(0.52, 1.5, 0.5))      # -> 0.1000  half Kelly: 10%
print(kelly_fraction(0.52, 1.5, 0.25))     # -> 0.0500  quarter:     5%

# Continuous-case twin for a levered book (CFD/FX): optimal leverage is
# expected excess return divided by return variance.
expected_return, risk_free_rate, variance = 0.15, 0.05, 0.20 ** 2
kelly_leverage = (expected_return - risk_free_rate) / variance
print(kelly_leverage)                      # -> 2.5  (worked example below)

Worked example: the 2.5x levered book

A strategy targets a 15% annual expected return at 20% annualized volatility; cash earns 5%. The continuous Kelly says what fraction of equity to hold as notional exposure:

Step Computation Result
Excess return 15% − 5% 10%
Return variance 0.20 × 0.20 0.04
Kelly leverage 0.10 ÷ 0.04 2.5x

Full Kelly runs notional at 2.5 times equity; half Kelly runs 1.25x. Note what Kelly does not say: it does not promise this leverage is safe. It says this leverage maximizes growth if every input were exact. They never are — which is the subject of the next section.

Monte Carlo: watch the same edge live or die by size

Nothing teaches this faster than simulation. Five thousand identical accounts take 500 trades with the same 52%-win edge; only their size differs. “Ruined” means the account was cut in half at some point along the way:

# Monte Carlo account paths: the SAME edge at four sizes -- who survives?
import numpy as np

rng = np.random.default_rng(42)
n_sims, n_trades = 5_000, 500             # 5,000 parallel accounts x 500 trades
win_prob, payoff_ratio = 0.52, 1.5        # one edge, shared by every account
kelly_full = (payoff_ratio * win_prob - (1 - win_prob)) / payoff_ratio

for scale in [0.5, 1.0, 1.5, 2.0]:        # half / full / 1.5x / double Kelly
    frac = scale * kelly_full
    wins = rng.random((n_sims, n_trades)) < win_prob
    step = np.where(wins, 1 + frac * payoff_ratio, 1 - frac)   # multiplicative
    equity = np.cumprod(step, axis=1)
    ruined = (equity.min(axis=1) < 0.5).mean()     # halved at some point
    growth = np.median(equity[:, -1]) ** (1 / n_trades) - 1
    print(f"{scale:>4}x Kelly f={frac:.2f}  halved={ruined:5.1%}  "
          f"growth/trade={growth:+.3%}")
 0.5x Kelly f=0.10  halved= 11.3%  growth/trade=+2.235%
 1.0x Kelly f=0.20  halved= 44.5%  growth/trade=+2.975%
 1.5x Kelly f=0.30  halved= 74.4%  growth/trade=+2.225%
 2.0x Kelly f=0.40  halved= 93.0%  growth/trade=-0.079%

Read that table twice. Betting double Kelly turned a genuine winning edge into a money loser — negative growth from positive expectancy, purely from size. And even exact Kelly got halved 44.5% of the time. The fastest grower and the safest grower are different bets, and the gap between them is measured in survival.


Why Fractional Kelly

Estimation error is the enemy, because Kelly output is violently sensitive to the expected-return input. With one year of daily data — roughly 250 observations — the standard error of an estimated mean return is about sigma / sqrt(250), which is sigma / 16. For a 20%-vol strategy that is ±1.26 points per year, so a “15%” estimate is honestly somewhere in 12–18%. Watch what that does to optimal leverage:

True expected return Kelly leverage ((mu - r) / sigma^2)
12% 1.75x
15% (your estimate) 2.50x
18% 3.25x

Your best guess says 2.5x; the truth could justify anywhere from 1.75x to 3.25x — nearly a 2:1 swing driven entirely by ordinary sampling noise, before regime change or fat tails (see the fat-tails section of Module 2). An estimate that noisy cannot be traded at face value.

Fractional Kelly is the standard response: divide the Kelly stake by a constant — usually 2, often 4 — and treat full Kelly strictly as a ceiling. The cost is smaller than intuition suggests:

  • Half Kelly captures about 75% of maximum geometric growth, while cutting typical peak-to-trough drawdowns roughly in half. Growth falls with the square of the size fraction near the optimum; pain falls almost linearly.
  • Quarter Kelly still captures around 44% of max growth — and is dramatically easier to sit through.

🧪 Evidence: Ed Thorp — who ran Kelly-sized positions successfully in markets for decades — recommends in his Kelly paper that practitioners bet half or quarter Kelly in practice, precisely because real edges are estimated from finite, non-stationary samples. The men with the best data still took the haircut.

What the haircut buys, concretely:

Sizing rule Typical max drawdown Growth captured Practice verdict
Fixed 1% per trade ~10–20% modest, steady survival-first retail default
Fixed 2% per trade ~20–30% moderate aggressive but livable
Quarter Kelly ~12–20% ~44% of max strong when edge is uncertain
Half Kelly ~25–35% ~75% of max practitioner norm
Full Kelly / optimal-f 40–60%+ 100% (nominal) academic only — never live

Meaning: Kelly is a ceiling, not a target. Size below it in proportion to how much you distrust your own statistics — and you should distrust them a lot (Module 19).


Volatility Targeting & Constant-Risk Sizing

Fractional Kelly sets the budget; volatility targeting is the day-to-day machinery that spends it evenly. The idea: hold position sizes so each position contributes a roughly constant slice of risk, by scaling inversely with recent realized volatility:

# Volatility targeting: every position scaled by target vol / realized vol
target_annual_vol = 0.15                        # book aims at 15 percent vol
realized_vol = {"XAUUSD": 0.18, "BTCUSD": 0.55}
GEAR_CAP = 2.0                                  # never let the scalar exceed 2x

vol_scalars = {s: min(target_annual_vol / rv, GEAR_CAP)
               for s, rv in realized_vol.items()}
print(vol_scalars)
# {'XAUUSD': 0.83, 'BTCUSD': 0.27}  BTC gets a third of gold's raw weight
#
# Base size per symbol = fractional-Kelly share x its vol scalar:
half_kelly_share = kelly_fraction(0.52, 1.5, haircut=0.5)      # 10%
base_size_xauusd = half_kelly_share * vol_scalars["XAUUSD"]    # 8.3%
base_size_btcusd = half_kelly_share * vol_scalars["BTCUSD"]    # 2.7%

Quiet markets earn bigger positions; violent markets get smaller ones automatically — no forecast required, just measurement. The gear cap exists because realized vol collapsing to nearly zero (a squeeze) would otherwise instruct absurd sizes.

On MT5, constant-risk sizing is native currency: stops defined in ATR multiples convert directly into lot counts, since risk per lot is just tick value times stop distance (Module 1). The complete production chain — risk budget from the ladder, stop from ATR, lots from arithmetic, grid snap from the broker’s own specs:

# Size from stop distance and risk budget -- the MT5-native workflow
import math

def snap_volume_down(lots, vol_min, vol_step, vol_max):
    """Floor onto the broker grid: realized risk stays under budget."""
    steps = max(0.0, math.floor((lots - vol_min) / vol_step + 1e-9))
    return min(vol_min + steps * vol_step, vol_max)

account_equity  = 10_000.0
ladder_scalar   = 1.00                     # from risk_tier(): normal tier
risk_budget_usd = 0.005 * account_equity * ladder_scalar      # $50 at 0.5%

entry_price, stop_price = 2_650.00, 2_647.80     # ATR-scaled stop (M15 idea)
stop_distance = entry_price - stop_price          # 2.20 USD per oz

raw_ounces = risk_budget_usd / stop_distance      # -> 22.7 oz
raw_lots   = raw_ounces / 100.0                   # XAUUSD: 100 oz per lot
lots = snap_volume_down(raw_lots, 0.01, 0.01, 50.0)
print(f"{lots=} -> risk ${lots * 100 * stop_distance:.2f} of "
      f"${risk_budget_usd:.0f}")
# lots=0.22 -> risk $48.40 of $50

Hand-check: $50 ÷ $2.20 = 22.7 oz wanted; the grid only sells whole cent-lots, so we floor to 22 oz (0.22 lots) and actual risk lands at $48.40 — always rounding down on risk, never up.


Drawdown Control Frameworks

Per-trade stops protect individual trades; portfolio-level controls protect the account, and for a systematic book they matter far more. Any single-trade stop is sized in basis points of equity — no single trade can sink you if sizing is right. What sinks systematic accounts is the aggregate: twenty correlated positions all wrong together, or a slow bleed nobody decided to stop. Portfolio-level controls exist because the dangerous failure modes are portfolio-shaped.

The framework has three moving parts: a de-gearing ladder keyed to drawdown depth, hard daily/weekly loss limits enforced mechanically, and a recovery protocol for coming back.

Tier Trigger (DD below high-water) Rule Exit condition
Normal 0–10% Standard sizing: fractional Kelly × vol scalar
Reduced 10% or deeper Cap risk at 0.5% per trade; no adding to losers Recover inside 10%
Halted 15% (circuit breaker) No new entries; existing positions managed toward flat; manual review required Signed restart memo

Around the ladder sit the mechanical limits common practice converges on: daily loss limits of 2–3% of equity and weekly limits of 5–6%, hit-and-flat — when breached, the kill-switch closes discretionary room and suspends the supervisor’s entry logic for the rest of the session. A kill-switch worth the name has three properties: it triggers automatically on measured equity, it requires human ceremony (not a click) to reset, and it has been tested in a rehearsal run before real money depends on it.

Recovery mode completes the loop. After a halt, re-entry happens at half the previous size scalar and restores gradually — a common schedule adds back a quarter of the remaining reduction per week without incident. The psychology this enforces is the point: after a deep drawdown the temptation is to size up and “get it back fast,” which is martingale thinking wearing a suit.

The whole constitution, enforced end to end, looks like this:

Figure: every order request walks the same gauntlet — sizing, broker reality, aggregate exposure, then the ladder’s verdict. Nothing reaches MT5 without passing all four gates, and every outcome feeds telemetry back into the ladder state.

flowchart TD
    sig[Signal fires<br/>a candidate trade]
    base[Compute base size<br/>fractional Kelly x vol scalar]
    grid[Snap to broker<br/>volume grid]
    heat{"Heat plus correlation<br/>under ceiling?"}
    ladder{"DD-ladder:<br/>normal / reduced / halted"}
    gate{"Order passes<br/>all checks?"}
    fill[Send order to MT5]
    veto[Veto or shrink order<br/>and log the reason]
    tele[(Post-trade telemetry<br/>updates ladder state)]

    sig --> base --> grid --> heat
    heat -->|"yes: room in book"| ladder
    heat -->|"no: ceiling breached"| veto
    ladder -->|"normal tier"| gate
    ladder -->|"reduced tier: shrunk size"| gate
    ladder -->|"halted: breaker set"| veto
    gate -->|"yes"| fill
    gate -->|"no"| veto
    fill --> tele
    veto --> tele
    tele -.->|"state feeds next decision"| ladder

    classDef data fill:#e8f0fe,stroke:#4a86e8
    classDef process fill:#f3f3f3,stroke:#888
    classDef decision fill:#fff4d6,stroke:#d6a300
    classDef risk fill:#fde8e8,stroke:#c0392b
    classDef ok fill:#e6f4ea,stroke:#2e7d32

    class tele data
    class sig,base,grid process
    class heat,ladder,gate decision
    class veto risk
    class fill ok

How to read this:

  • The amber diamonds are pure functions of measurable state — heat, correlation, drawdown — never of mood. If a gate cannot be computed from the journal, it does not belong in the constitution.
  • Red nodes are vetoes, and vetoes are logged with reasons: a veto trail is how you audit the constitution later.
  • The dashed feedback edge is the loop that makes this a system: post-trade P&L updates the drawdown state, which changes tomorrow’s tier before tomorrow’s first signal fires.

Correlation & Portfolio Heat

Portfolio heat is the accounting identity of risk management: the sum of open risk if every stop were hit tonight. Each open position contributes position size × stop distance; the naive heat is their simple sum. The ceiling — a number written in the constitution, e.g. 4% of equity — bounds it.

Naive summation understates the danger, because open risks are not independent. Two long gold positions do not behave like two independent bets; in a crash, correlations converge toward one and co-move everything against you simultaneously (Module 16’s correlation web is the data source here). The conservative correction charges correlated exposure extra rather than granting it diversification credit:

# Correlation-aware portfolio heat: risks lost together charge extra
import numpy as np

open_risk_usd = {"XAUUSD trend": 120.0,
                 "XAUUSD reversion": 90.0,
                 "BTCUSD breakout": 150.0}
pairwise_corr = np.array([[1.00, 0.85, 0.35],
                          [0.85, 1.00, 0.30],
                          [0.35, 0.30, 1.00]])
risks = np.array(list(open_risk_usd.values()))
n = len(risks)
avg_pairwise_corr = (pairwise_corr.sum() - n) / (n * (n - 1))

naive_heat     = risks.sum()                        # ignores correlation
effective_heat = naive_heat * (1 + avg_pairwise_corr)

HEAT_CEILING_USD = 400.0
new_trade_risk = 40.0
admit = effective_heat + new_trade_risk <= HEAT_CEILING_USD
print(f"naive ${naive_heat:.0f} vs effective ${effective_heat:.0f}",
      "-> admit" if admit else "-> VETO")
# naive $360 vs effective $540 -> VETO   (naive math would have admitted)

Hand-check: naive heat is $360; the three pairwise correlations average 0.50, so effective heat is 360 × 1.5 = $540. A fresh $40-risk trade fits the naive ceiling exactly ($400) and gets vetoed anyway — because during a crash, that “exactly at ceiling” book behaves like one $540 position. During stress, expect effective heat to approach twice the naive figure; size ceilings accordingly.


Stress Testing: Replaying the Horrors

Backtests sample history; stress tests interrogate specific nightmares. Three documented episodes belong in every leveraged trader’s replay set, because each killed real firms that had “stops”:

Scenario When What happened Sizing lesson
CHF flash crash Jan 2015 SNB scrapped the EURCHF 1.20 floor; CHF gapped ~20–30% intraday; Alpari UK went insolvent, FXCM needed a $300M rescue loan FX “small pip moves” is a fair-weather claim; gaps skip stops entirely
COVID liquidity crash Mar 2020 Everything sold at once — even Treasuries; spreads blew out; stops filled far through their levels Diversification reads zero exactly when drawdown control matters most
Yen carry unwind Aug 2024 BoJ hike plus soft US data sank USDJPY ~12% in weeks; Nikkei fell ~12% in one day; crypto sold with equities Carry dies by gap, not drift; cross-asset correlation spiked instantly

For CFD traders there is a fourth, recurring scenario: the weekend gap. Brokers reopen Monday through your stop and beyond — fills land at the market’s price, not your stop’s price. Any position held across a weekend carries an effectively unbounded tail; the constitution either forbids the exposure or reserves explicit capital for it.

Two tail-risk numbers complete the toolkit, in plain words: VaR says “how bad is a bad day” — e.g., 95% one-day VaR of −$800 means one day in twenty is worse than −$800. Expected shortfall (ES) says “how bad is the average of the worst days” — the mean loss across that worst 5%. Fat tails (Module 2) make VaR systematically lie about crash severity, because it is blind to how much worse than −$800 the tail goes; ES respects the tail. Set portfolio limits on ES-style thinking, and treat any VaR computed under a normal-distribution assumption as decorative.


Never Martingale

Law: never increase risk to recover losses. Not as style preference, not “usually,” not “except after a bad week” — never.

Martingale sizing doubles stakes after losses so one winner erases the streak. The mathematics is unforgiving: after ten straight losses the next stake is 1,024× the base unit, and the cumulative commitment exceeds 2,000 base units. With a 1%-of-equity base unit, that is bankruptcy several times over — reached without ever violating the per-trade stop, because every individual bet was “reasonable.” The edge never changed; only the size did, and the size alone guarantees eventual ruin. Every account blow-up story that ends with “then he started doubling up” is this law being discovered experimentally. The drawdown ladder’s Reduced tier exists partly to outlaw its quieter cousin: adding to losers, raising size “to make back the month,” or post-win size escalation beyond plan.


Testing It Honestly

Sizing code is risk code, and risk code earns trust the way any ledger does: fixtures with known answers and boundary tests on every threshold.

Simulator fixture with an analytic answer. The Monte Carlo path simulator has a closed-form target: per-trade expected log-growth at fraction f equals p·ln(1 + f·b) + (1 - p)·ln(1 - f). For p=0.52, b=1.5 the analytic values are +2.21%, +2.93%, +2.20% and −0.08% at f = 0.10, 0.20, 0.30, 0.40 — the simulator’s medians must match those within a stated tolerance (a few basis points at 5,000 sims). The half-Kelly capture ratio is a second fixture: 0.754 measured against the theoretical 75%. A simulator that reproduces both is calibrated; one that doesn’t has a bug worth finding before it manages money.

Ladder boundary tests. Thresholds are exactly where off-by-one bugs live, so test the boundaries themselves: DD of 9.99% → normal, 10.00% → reduced, 14.99% → reduced, 15.00% → halted — plus a monotonicity property test (larger DD never grants a higher tier) and an idempotence check (same input, same tier, always).

# Boundary tests: the ladder must be exact at its own thresholds
assert risk_tier(0.099)[0] == "normal"
assert risk_tier(0.100)[0] == "reduced"
assert risk_tier(0.149)[0] == "reduced"
assert risk_tier(0.150)[0] == "halted"

tiers = [risk_tier(d)[1] for d in [0.0, 0.09, 0.11, 0.16]]
assert tiers == sorted(tiers, reverse=True)   # bigger DD, smaller scalar

⚠️ Pitfall: Stops wider than tested silently break sizing. If the backtest assumed 1×ATR stops and live logic drifts to 1.5×ATR, every position carries 50% more risk than the budget intends — the sizing formula is only honest if the stop model matches the tested one. Wire stop distance from the same config the backtest consumed.


Pitfalls Checklist

Symptom Why it lies Defense
Full Kelly on estimated edges The formula assumes exact inputs; sampling noise makes true optima swing ~2:1 (table above) Half or quarter Kelly; full Kelly is a ceiling, never a setting
Ignoring correlation stacking Naive heat says $360 while crash behavior is $540+ Correlation-adjusted heat charge; cluster-aware ceilings
Stops wider than tested Sizing drifts as live stops stretch beyond backtest assumptions Stop distance sourced from the same config the backtest used
Raising size after wins beyond plan Hot-hand sizing buys maximum exposure at maximum regime risk Size is a function of equity, vol, and ladder tier — never of streak
No written max-DD line before going live An unwritten tolerance gets negotiated emotionally at 3am, mid-drawdown Constitution signed, dated, and machine-enforced before first order

Hands-On Project

Deliverable: src/risk/ (Monte Carlo path simulator + ladder/heat modules with tests) and docs/research/risk-constitution.md — your signed, dated risk constitution — wired into the live supervisor’s config.

Tasks:

  1. Build the account-path simulator parameterized by your real trade distribution (pull the actual win rate, payoff ratio, and trade frequency from your journal, not the toy 52/1.5).
  2. Locate your Kelly boundary empirically: sweep size fractions from quarter to double Kelly, report median growth and ruin/halving probability per fraction, and mark where growth peaks and where it turns negative.
  3. Implement risk_tier(), the correlation-aware heat checker, and the volume-grid snapper as importable modules with the boundary tests from Testing It Honestly.
  4. Draft the risk constitution: max drawdown circuit breaker, daily/weekly loss limits, per-tier size scalars, heat ceiling, correlation treatment, weekend-exposure policy, and the restart protocol after a halt.
  5. Wire the constitution into supervisor config so every gate in the enforcement diagram executes in code, then rehearse: trigger the halt tier deliberately on the demo account and verify the kill-switch behavior end to end.
  6. Sign and date the constitution. A document without a signature is a draft; the signature is what makes the 15% line binding at 3am.

Acceptance criteria:

  • Simulator reproduces the analytic growth figures within stated tolerance, including the negative-growth zone beyond 2x Kelly.
  • Empirical Kelly boundary located and reported next to the analytic value for your own trade distribution.
  • Ladder unit tests pass at all four boundaries plus monotonicity and idempotence properties.
  • Heat checker demonstrably vetoes at least one trade the naive sum would have admitted (fixture included).
  • Risk constitution signed and dated, covering breaker, loss limits, scalars, heat ceiling, weekend policy, and restart protocol.
  • Supervisor config consumes the constitution; a rehearsed halt on demo flat-and-suspends exactly as written.

Key Takeaways

  • Sizing determines survival: the same edge at 2% versus 0.5% risk diverges into ruin versus compounding, and sizing explains more variance in long-run outcomes than signal accuracy does.
  • Kelly is a ceiling derived from estimates you cannot trust: with ~250 observations, a “15%” expected return is honestly 12–18%, swinging optimal leverage between 1.75x and 3.25x.
  • Half Kelly captures ~75% of geometric growth at roughly half the drawdown pain — Thorp’s own recommendation, and the practitioner norm.
  • Over-betting flips signs: at double Kelly, a proven 52% winning edge produced negative growth in 93% of simulated paths.
  • Constant-risk machinery beats forecasts: scale positions by target-vol-over-realized-vol, derive lots from stop distance and risk budget, and floor to the broker grid downward.
  • Per-trade stops cannot sink a correctly sized account; portfolio-level controls — heat ceilings, daily 2–3% and weekly 5–6% limits, the 15% breaker — are what actually save systematic books.
  • Effective risk exceeds naive sums precisely during crashes: charge correlated exposure extra, and stress-test against 2015-CHF, Mar-2020, and Aug-2024 before trusting any leverage number.
  • Never increase risk to recover losses — the one absolute law in this curriculum, because its violation guarantees ruin regardless of edge.
  • A risk constitution that is not written, signed, and executed by the supervisor is not a constitution; it is a mood.

References