Risk Models
How QuantJourney applies portfolio risk overlays to target weights before rebalancing.
Risk models adjust target weights. They do not inspect pending orders and they do not block order-mode submissions. In the current engine they are a weight-mode overlay between raw weights and rebalancing.
Source
backtester/risk/ + backtester/core.pyLayerPortfolio risk overlay
ModeWeight mode
Inputtarget weights, returns and optional metadata
Outputadjusted target weights
Primary API
risk_model=...Main caveatRisk models adjust weights; order mode still needs a separate pre-trade risk gate.
Engine Contract
Risk models answer: "Should these target weights be modified before they become realized exposure?" They are not stop-losses and they are not broker order checks.
signals -> raw weights -> RiskModel.adjust(weights, returns)
-> adjusted weights -> RebalanceEngine
Level 1: Position Limit
Cap single-name exposure
python
from backtester.risk import PositionLimitModel
strategy = MyStrategy(
...,
execution_mode="weights",
risk_model=PositionLimitModel(
max_weight=0.25,
max_total_leverage=1.0,
),
)Level 2: Volatility Target
Scale portfolio exposure to target vol
python
from backtester.risk import VolTargetModel
strategy = MyStrategy(
...,
risk_model=VolTargetModel(
target_vol=0.15,
lookback=63,
max_leverage=1.5,
rebalance_freq="BMS",
),
)Level 3: Risk Chain
Apply multiple models in sequence.
Vol target then hard caps
python
from backtester.risk import RiskModelChain, VolTargetModel, PositionLimitModel
risk_model = RiskModelChain([
VolTargetModel(target_vol=0.12, lookback=63, max_leverage=1.5),
PositionLimitModel(max_weight=0.20, max_total_leverage=1.0),
])
strategy = MyStrategy(..., risk_model=risk_model)Data Contract
| Item | Meaning |
|---|---|
weights | target weights DataFrame |
returns | asset returns DataFrame aligned to weights |
metadata | optional context such as sectors |
| output | same shape as input weights |
Failure Modes
- Expecting a risk model to reject raw order submissions in order mode.
- Applying leverage caps without checking row gross exposure.
- Forgetting that risk model output still goes through rebalancing and drift.
- Treating a volatility target as a guarantee of realized future volatility.