Skip to main content

Overview

BULK’s risk engine runs inline with the matching engine, evaluating every order and position change in real time. It is not a batch process or a background job - risk is assessed at the point of execution, before fills are confirmed. The engine is built on four interconnected systems: regime detection, lambda surfaces, portfolio margin, and cascade adjustment.

Regime Detection

BULK classifies the current market environment into one of 9 regimes using a Hidden Markov Model. Each regime encodes direction and volatility:
RegimeDirectionVolatility
-12BearishHigh
-11BearishMedium
-10BearishLow
0NeutralLow
1NeutralMedium
2NeutralHigh
10BullishLow
11BullishMedium
12BullishHigh
Regime classification is continuous and real-time. The engine also tracks regime duration, which feeds into the time-decay function for margin transitions.

Lambda Surfaces

Lambda (λ\lambda) is BULK’s generalized risk parameter. Instead of static margin tiers, BULK uses lambda surfaces - continuous 3D functions that map to a maintenance margin rate: λi=f(leverage,  impact,  regime)\lambda_i = f(\text{leverage},\; \text{impact},\; \text{regime}) Each asset has its own lambda surface. The surface is interpolated bilinearly, meaning margin requirements change continuously as position size, leverage, or market conditions change - no discrete jumps at tier boundaries.

Time Decay

When a regime change is detected, margin requirements don’t jump instantaneously. They follow a time-decay curve: λ(t)=λoriginpt+λend(1pt)\lambda(t) = \lambda_{\text{origin}} \cdot p^t + \lambda_{\text{end}} \cdot (1 - p^t) Where λorigin\lambda_{\text{origin}} is the rate at the time of the regime transition, λend\lambda_{\text{end}} is the new regime’s target, pp is the decay factor, and tt is time elapsed. This prevents unnecessary liquidation cascades from brief regime flickers. See Margin for the full regime table and how time decay works in practice.

Portfolio Margin

For accounts with multiple positions, BULK computes a correlation-adjusted effective notional that captures diversification and hedging benefits.

Effective Portfolio Notional

For each position ii, the signed notional is sNi=sign(Qi)QiPisN_i = \text{sign}(Q_i) \cdot |Q_i| \cdot P_i. The effective portfolio notional accounts for correlations: Neff2=isNi2+2i<jsNisNjρijN_{\text{eff}}^2 = \sum_i sN_i^2 + 2 \sum_{i \lt j} sN_i \cdot sN_j \cdot \rho_{ij} Where ρij\rho_{ij} is the real-time correlation coefficient between assets ii and jj. When positions hedge each other (correlated assets, opposing directions), the cross terms become negative and NeffN_{\text{eff}} shrinks well below the sum of individual notionals. Hedging discounts of up to 70% are achievable on correlated pairs.

Portfolio Maintenance Margin

For each position, the signed margin component is: Mi=sign(Qi)λiQiPiM_i = \text{sign}(Q_i) \cdot \lambda_i \cdot |Q_i| \cdot P_i The portfolio maintenance margin uses the same correlation structure: Mp=max(0,  iMi2+2i<jMiMjρij)M_p = \sqrt{\max\left(0,\; \sum_i M_i^2 + 2\sum_{i \lt j} M_i \cdot M_j \cdot \rho_{ij}\right)} This produces a single number that captures the true risk of the combined portfolio. See Margin for the step-by-step breakdown.

Marginal Contributions

For each position, the engine computes partial derivatives: MpMijMjρijMp\frac{\partial M_p}{\partial M_i} \propto \frac{\sum_j M_j \cdot \rho_{ij}}{M_p} This tells the liquidation optimizer how much each position contributes to overall portfolio risk, enabling it to selectively reduce positions while preserving hedges. See Liquidations for the full optimizer algorithm.

Cascade Adjustment

The system incorporates liquidation impact feedback into margin computation. When evaluating margin requirements, the engine estimates what would happen if positions needed to be unwound:
  • How much market impact would liquidating each position create?
  • Would that impact cascade into further margin breaches for other accounts?
The cascade adjustment factor increases margin requirements for positions that would create significant market impact if liquidated, preventing scenarios where positions appear well-margined in isolation but would cause systemic risk if unwound. The engine iterates up to 2 rounds: estimate liquidation price from current λ\lambda, compute cascade size from order book depth, then re-fetch λ\lambda with cascade impact included.

Background Risk Recomputation

In addition to inline risk checks at execution time, BULK runs background risk recomputation cycles that:
  • Update portfolio margins as mark prices change (even without new orders)
  • Detect accounts approaching maintenance margin thresholds
  • Trigger liquidation when equity falls below MpM_p
This ensures that risk is managed continuously, not just at the moment of order submission. See Price Indices for how the mark price is computed.

Comparison to Existing Systems

FeatureStatic Tiers (most DEXs)BULK Risk EngineCME SPAN
Margin modelFixed per-notional bracketsContinuous lambda surfacesScenario-based (16 scenarios)
CorrelationNoneFull real-time matrixExplicit inter-commodity spreads
Market regimeIgnored9 regimes, real-time HMMImplied via stress scenarios
Margin transitionsInstant jumpsSmooth time-decayBatch recomputation
LiquidationClose biggest loserImpact-ratio optimizerClearing house default management
ComputationPer-positionPortfolio-levelPortfolio-level
LatencyN/A (batch)Inline with matchingBatch (typically overnight/intraday)
See Margin, Liquidations, and Portfolio Margining for detailed specifications.