Skip to main content

Simulating PM Risk

Every number described in Portfolio Margin can be read back for your account, and every trade can be previewed before you send it. The simulator is not a separate model: it runs the same margin code, on the same policy and the same engine snapshot, that checks your orders and runs the liquidation watcher.

In the app​

The Portfolio margin page (/risk/span) shows, for a PM account:

  • equity, IM, MM, buying power and maintenance buffer
  • scanning risk, option floor and gamma overlay separately
  • the scenario grid for each underlying, with the P&L of every scenario and every leg
  • Simulate positions: add hypothetical legs to your book, or replace it, and compare current against simulated IM and MM. A simulation never places an order or changes account state.

The page refreshes every 5 seconds.

Endpoints​

EndpointWhat it answersAuth
GET /portfolio?wallet=Current equity, IM, MM and positionsNone
GET /risk/grid?wallet=Current scanning risk, floor, overlay, and the per-underlying scenario matrixNone
POST /risk/simulate/portfolioIM and MM if your positions were differentNone
POST /risk/simulate/ordersWhether an order or package would pass the margin check, and its IM costNone
GET /liquidation/status?wallet=Liquidation state and shortfallNone

All of them take your manager wallet as wallet; Hypercall resolves it to your PM account. GET /risk/grid answers only for PM accounts.

Risk grid​

GET /risk/grid returns the account's current requirement and, per underlying, the scenarios that underlying is scored on (its own grid, including any extra scenarios) with:

  • scenarios[]: id, spot_shock_pct, vol_shock_pct, pnl_weight, is_tail and the underlying's total_pnl in that scenario
  • extended_risk_matrix.instruments[]: per-leg scenario_pnls, aligned with scenarios

scanning_risk at the top level is the charged number: each underlying's worst weighted loss, summed. The matrix's worst_scenario_index is a diagnostic for one underlying's grid and does not drive margin across underlyings.

Portfolio simulation​

curl -X POST https://api.hypercall.xyz/risk/simulate/portfolio \
-H 'Content-Type: application/json' \
-d '{
"wallet": "0xYourManagerWallet",
"add_positions": true,
"positions": [
{"symbol": "BTC-20261231-100000-C", "quantity": "-1"},
{"symbol": "BTC-20261231-110000-C", "quantity": "1"},
{"symbol": "BTC-PERP", "quantity": "0.25"}
]
}'
  • add_positions: true (the default) adds each signed quantity to your current position. false replaces your book with exactly the list.
  • Up to 50 symbols, each listed once. Option and perp symbols are both accepted.
  • Positions are valued at current marks. No premium is charged and no order book is consulted.

The response has current, simulated and delta. In each summary, read:

FieldMeaning
equityEquity as defined on the methodology page
position_initial_marginIM on positions: max(scanning risk, floor) + overlay
position_maintenance_marginMM, 0.85 × position IM
open_orders_initial_marginReservation for your live resting orders
total_initial_marginPosition IM plus open-order IM
initial_margin_availableEquity minus total IM. Negative means new risk is refused
maintenance_margin_availableEquity minus MM. Negative means liquidation
scanning_risk, option_floor, gamma_overlayThe three components
underlyings[]The per-underlying scenario matrix, as in GET /risk/grid
venue_liquidationPresent when you hold Hyperliquid perps: whether each Hyperliquid compartment survives the grid (hedge_survives), the collateral that would be lost, and the venue-aware IM and MM

metadata identifies the engine snapshot the simulation ran on (l2_seq, evaluated_at_ms).

Live pending inventory​

Both simulation responses include live_pending, captured from the same snapshot as current, before any requested changes:

  • orders contains outright option and perp orders, including those with a zero current margin charge. Each entry has order_id, symbol, side, price, remaining_size, is_perp, and reduce_only.
  • combo_orders keeps each atomic parent together, with its canonical combo symbol, order_id, side, signed net price, remaining_size, reduce_only, and legs. Each leg has an instrument_id, symbol, and signed integer ratio, relative to buying the parent. Selling reverses those ratios. A parent price may be zero or negative.
  • perp_directives contains managed perp reservations with directive_id, symbol, side, price, remaining_size, and fill_evidence_timestamp_ms. A non-null fill-evidence timestamp means the reservation holds observed fills awaiting position reconciliation; it is not an independently executable unfilled order.

Units are explicit: prices and quantities are decimal strings. Quantities are human contract, combo, or base-asset units, never raw micro units. Order IDs, instrument IDs, and ratios are exact strings. side is "Buy" or "Sell".

All three arrays are required, including when empty. Missing inventory on an older server is unavailable evidence, not an empty portfolio. Entries are not truncated and are ordered by their exact numeric order ID or directive UUID. The inventory covers the node's order and managed reservation stores. It does not enumerate outstanding RFQ quotes or orders placed directly on an external venue outside the managed flow; track those commitments separately.

Do not add these entries again as hypothetical_open_orders: they already belong to the current snapshot and are included by the applicable margin model. Hypothetical orders are additional orders you have not placed. Snapshot revisions identify the observation; they do not guarantee the inventory remains unchanged after the response.

Order simulation​

POST /risk/simulate/orders runs the financial part of order admission without placing anything:

  • execution_mode: "resting" takes exactly one order and charges it as a resting order.
  • execution_mode: "atomic" evaluates the legs as a package that fills together, the way a combo is margined.
  • hypothetical_open_orders lets you add resting orders you have not placed yet, evaluated before orders.

The response adds admissible and, when false, a rejection_reason. The delta block shows the IM the order would consume. Request examples are in Authentication.

The order simulator answers the margin question only. Matching, price bands, RPI, nonces, rate limits and trading halts are not simulated, and engine state can move before you send the real order.

Errors​

StatuserrorWhat it means
400invalid_simulationMalformed request, unknown or expired symbol, duplicate symbol, or more than 50 items
429risk_simulation_saturatedSimulation capacity is shared and limited; retry with backoff
503risk_inputs_unavailableAn input is missing or stale, for example no IV mark for an option, or a stale HyperCore snapshot. The real order would be refused for the same reason

Rate limits for simulations are listed in Rate Limits.