Components
Every component is independent — use one or all six. When you want all of them
working together, reach for the RiskManager façade rather than wiring them up
yourself.
RiskManager
The façade over the other six. Build it from a single RiskConfig (which carries
two promoted knobs — base_risk_pct, max_notional_pct — plus a pass-through
dict of keyword arguments for each component), then:
on_equity(equity)— refresh drawdown and session state as the account moves.evaluate(TradeIntent(...))— size and validate one trade, returning aRiskDecision(ok,units,stop,risk_pct, andreasonslisting every gate that vetoed it, plus the full component results for auditing).on_fill(decision)/on_close(trade)— keep the open book and the session's streak/cooldown state current.
decision.ok is the AND of the pre-trade validator passing and the session
manager permitting an entry — the latter catches behavioural blocks (tilt,
cooldowns, profit target hit) that have no dedicated validator flag. The
underlying components are exposed as attributes (.sizer, .drawdown, .stops,
.correlation, .session, .validator) when you need to reach past the façade.
Because the manager tracks the open book, it enforces portfolio-level caps as you
trade: total open notional (max_notional_pct extended across positions),
total open heat — the capital actually at risk if every stop is hit
(max_portfolio_heat_pct, off by default), and per-sector / asset-class
concentration (max_exposure_per_sector_pct, off by default) so no single
sector can dominate the book. Tag a trade's sector with TradeIntent(sector=...);
untagged trades are never sector-capped. Read any of these live with
exposure_pct() / portfolio_heat_pct() / sector_exposure_pct(sector) (or
sector_exposure() for the full per-sector breakdown).
PositionSizer
Volatility-adjusted fixed-fractional sizing. You pick a base risk fraction; the sizer scales it down when volatility is above baseline, applies an optional half-Kelly ceiling, runs a reduction ladder (losing streaks, drawdown tiers, daily loss), and enforces a hard notional cap. Returns the units and every multiplier that fired.
When the stop-distance model isn't what you want, three standalone sizing helpers stand on their own (pure functions, no dependencies):
kelly_fraction(win_rate, avg_win, avg_loss, fraction=1.0)— the edge-optimal risk fraction; passfraction=0.5for half-Kelly. Clamps to 0 with no edge.volatility_target_size(equity, price, return_volatility, target_volatility_pct, max_notional_pct=100)— units sized so a position's expected volatility hits a target % of equity (calmer instrument → larger position), capped by notional.inverse_vol_weights({symbol: volatility})— naive risk-parity weights (∝ 1/σ) that sum to 1.0, so every position contributes equal risk.
DrawdownManager
Tracks high-water-mark drawdown and maps it onto tiers: normal → 0.75x → 0.5x → 0.25x → halt. A recovery ramp steps the tier back down one level at a time once equity recovers, and a rolling weekly-loss guard pauses new entries for 24h.
StopEngine
Each position carries a stack of stops — initial, break-even (armed at 1R),
ATR trailing, EMA trailing, chandelier (ATR from the highest high / lowest low
since entry), structure (ratchets to a swing level you pass), PSAR (ratchets to a
Parabolic SAR value you pass), time, and volatility. The tightest stop relative to
price is active, and stops only ever move closer. Call update() once per bar;
it returns an exit reason or None.
CorrelationGuard
Allows at most one open position per correlation group. Groups can be static
(you define them) or computed dynamically from a rolling return-correlation
matrix (install the pandas extra).
SessionManager
Behavioural guardrails: daily trade/loss caps, profit-taking stops, minimum spacing between trades, escalating cooldowns after losing streaks, and tilt detection (shrinking hold times, size-up after losses, rapid-fire entries, weak signals).
PreTradeValidator
The composable final gate. Assemble a TradeProposal and validate() runs every
rule across market quality, sizing, risk limits, signal quality, and timing —
returning a pass/fail line for each and an overall veto.
Metrics
Standalone risk metrics over a return series: value_at_risk(returns, confidence)
and conditional_value_at_risk(returns, confidence) (historical VaR and expected
shortfall), both reported as positive loss magnitudes. Pure standard library.