Agentic Trading
Decisions

ADR-0013: Paper broker — isolated-margin leverage + liquidation accounting

  • Status: superseded by ADR-0014
  • Date: 2026-06-02
  • Affects: packages/brokers/paper, packages/shared/src/broker.ts, packages/agent-runtime/src/context.ts

Superseded. This ADR introduced an isolated-margin liquidation model as the MVP step. It was correct that some leverage modeling was needed, but the isolated approach overstates liquidation risk for multi-position accounts and diverges from Hyperliquid (which is cross-margin). The follow-up ADR-0014 replaces the paper broker model with cross-margin and codifies that live brokers source margin + liquidation from the exchange. Keep this ADR for the historical reasoning trail; do not implement from it.

Context

The paper broker had no leverage modeling. leverage: 1 was hardcoded on every position; margin used equaled notional regardless of what the agent proposed. Leveraged positions in the schema (ProposedAction.leverage) were accepted by the engine — the cap was checked — but the broker silently dropped the leverage value, so a 10x proposal behaved identically to a 1x.

Consequences before this fix:

  • The agent could not learn how leverage affects margin usage, since margin and notional were the same number.
  • No liquidation price existed on any position. The paper broker could not force-close positions on mark moves. Sim backtests with leveraged strategies didn't model the real downside (forced closure with most/all margin lost).
  • Strategies that rely on leverage for capital efficiency couldn't be evaluated honestly. A momentum strategy at 5x that should have been liquidated mid-drawdown instead survived to the end of the sim.
  • The recent risk-caps surfacing (## Risk caps section, ADR-0012 family) and the leverage-as-strategic-dial framing in the system prompt were both pointing at a feature that didn't exist downstream.

Decision

Implement leverage + liquidation accounting in the paper broker using an isolated-margin model. Each position carries:

  • its own leverage (set from propose_order, weighted-averaged on blends)
  • its own liquidationPrice, recomputed on every state change

Liquidation formula (isolated margin, per-position):

long:  liqPrice = entry * (1 - 1/leverage + maintMarginRate)
short: liqPrice = entry * (1 + 1/leverage - maintMarginRate)

maintMarginRate is a single broker-wide constant (default 50 bps ≈ Hyperliquid tier-1 majors). Real Hyperliquid uses tiered rates per symbol; the paper broker accepts a constant for MVP simplicity.

Liquidation trigger fires inside setMarkPrice: when the new mark crosses the stored liquidation price, the broker force-closes the position at the liquidation price (not at the new mark — this keeps PnL deterministic and matches the formula). A synthetic LiquidationFill record (reason: 'liquidation') is appended to fill history.

placeOrder adds a broker-side margin guard: rejects when the order's notional / leverage exceeds the account's free margin. The engine's R3/R4 caps still run first and catch most cases; the broker's check is the final word on its own ledger.

The Position type in @repo/shared gains liquidationPrice: number. formatPortfolio in agent-runtime/src/context.ts surfaces it to the agent along with a "% to liquidation" shorthand, so the agent can size and manage positions with awareness of distance-to-wipe.

Alternatives considered

Alt A — Cross-margin accounting matching Hyperliquid exactly

  • All collateral cross-margins all positions; tiered maintenance margin per symbol; liquidation is account-level when total maintenance margin > total equity.
  • Faithful to live behavior; sim results would translate directly.
  • Requires per-symbol tier tables and an account-level liquidation pass.
  • Not picked for MVP. Significant scope, and the isolated-margin model already lets us evaluate strategies' leverage choices on a per-position basis — which is the lift the agent and the trader actually need for authoring. Live trading on Hyperliquid uses Hyperliquid's broker adapter, which delegates liquidation to the exchange entirely. The paper broker only needs to be plausible enough for sim authoring confidence. Cross-margin is a follow-up.

Alt B — Skip liquidation, just track margin

  • Compute marginUsed = notional / leverage but never force-close.
  • Cheaper to implement; preserves backtest results' completeness.
  • Fundamentally dishonest about leverage's risk. A strategy proposing 10x leverage during a drawdown would survive ticks it would have been wiped in. Backtests become misleadingly optimistic for leveraged strategies. Not picked.

Alt C — Liquidate at the new mark instead of the liquidation price

  • More "realistic" in one sense (you're closed at where the market was, not where the formula said).
  • Makes PnL nondeterministic with respect to bar choice (a bar that closes below liq triggers a liquidation deep in the loss; the same liq-event with closer marks triggers a smaller loss).
  • We close at the liquidation price for determinism. The error is small (the gap between liq price and the bar's close), and it's biased in the trader's favor — slightly understates worst-case loss. Acceptable for sim; the live broker doesn't use this code path.

Alt D — Defer until we have testnet broker traffic

  • Don't model liquidation in paper; rely on testnet for risk realism.
  • Testnet runs aren't reproducible; sim is the only fast-iteration loop. Without liquidation in sim, the loop is blind to leverage's downside. Not picked.

Consequences

Positive

  • Leverage is now a real decision. Margin used scales correctly with leverage; the agent can verify that high-leverage proposals consume less margin and free room for more positions, with the corresponding tightening of liquidation distance.
  • Backtests reflect leverage risk. A 10x strategy that bottoms out on a -10% drawdown will now be liquidated in sim, not just show a -10% unrealized PnL.
  • Distance-to-liquidation in context. The ## Portfolio section now shows liq=PRICE (X% below/above) per position. The agent reads this directly when deciding to add to a position or stand down.
  • Engine + broker share margin responsibility. Engine caps proposals against deployer-set risk; the broker rejects orders that overdraw its ledger. Two checks, different concerns, both cheap.
  • One-line liquidation model. The formula is auditable. The constant maintenanceMarginRate is a single knob to tune sim realism against historical Hyperliquid liquidation outcomes.

Negative / trade-offs

  • Not faithful to cross-margin Hyperliquid. An account with one losing leg and one winning leg gets liquidated on the loser in our model; on Hyperliquid the winner's PnL would cushion the loser and possibly avert liquidation. We overstate liquidation risk for multi-position accounts. Documented; cross-margin is the next refinement.
  • Single maintenance margin rate. Hyperliquid's tier-1 majors are ≈ 0.5%; smaller caps run higher (≈ 1-2%). Strategies on alt symbols will see softer liquidations in sim than they'd get live. Mitigated by configuring maintenanceMarginRate higher for sim runs targeting smaller-cap symbols.
  • Bar-aware liquidation not implemented. A bar with a low that crossed liq price but a close that recovered will not trigger in sim (we only see the bar's close via setMarkPrice). The simulator could pass intra-bar high/low into a markRange() broker call to fix this; deferred.
  • Liquidation event not surfaced in ## Last decision. When a position is force-closed between ticks, the agent sees a vanished position and a dropped equity, but no explicit "you were liquidated on X" signal. The fill history records it; the agent context layer could expose it. Deferred until we see whether agents actually struggle to infer it from portfolio diff.

Things we'll need to revisit

  • If sim results diverge meaningfully from testnet runs for leveraged strategies, build a cross-margin paper broker mode and switch the default.
  • Add a per-tick "## Liquidations since last tick" section to context if the agent commonly fails to identify a liquidation from the portfolio diff.
  • Add bar-range liquidation in the simulator (high/low aware) once we have a strategy where intra-bar liquidation realism matters.

References

On this page