This week on Nexus 08.26.26
A fired reduce-only trigger is clamped into the price band, maker fills reach /orders/history, and liquidation_price answers null with a reason instead of a zero. Auto-deleveraging screens its candidates against the settlement price, a cross cascade closes every leg, and a retried order carrying the same client id is admitted once. A market listing is journaled and carried in the snapshot, journaled market parameters win over config on restore, and price_band_bps becomes the first parameter the engine changes while it runs. Order placement and eight public market-data routes are served on the host a client already reads from, recovery fails closed on a log segment lost at either end, and the clients now offer only operations the contract serves. Here is what shipped.
Trading and orders
- A fired reduce-only trigger is clamped into the price band. The limit price a reduce-only trigger fires with is clamped into the market’s price band, so the order it produces cannot be priced outside the band the market is already enforcing.
- Maker fills are recorded in
/orders/history. The indexer records the maker side of a fill, so an order’s history shows the fills it received and not only the ones it took. liquidation_priceis null with a reason, not a0sentinel. When there is no liquidation price to report, the field is null and carries the reason it is absent, so a client no longer has to read a zero as “none”.- Order placement is served on the host a client already reads from. An order can be submitted to that host and is relayed on, so placing an order does not mean a second base URL.
Risk and funding
- Auto-deleveraging candidates are screened against the settlement price. Risk-margin screens ADL candidates on the settlement price, so the accounts it selects are measured against the price the position would settle at.
- A cross cascade closes every leg. The cross-margin cascade is forced to close all of an account’s legs, so it cannot stop partway and leave one open.
- The funding premium is taken from impact bid and ask, with a dead zone. Risk-margin computes the premium from the impact bid and ask prices and holds a dead zone around them, so a premium inside the dead zone does not move the funding rate.
- A retry carrying the same
client_idis admitted once. Risk deduplicates onclient_id, so resubmitting a request that may already have landed does not produce a second one.
The engine, markets and parameters
MarketListedis journaled, and the snapshot carries the market set. The engine journals the listing event and versioned snapshots carry the set of listed markets, so the market set is recovered from state rather than reassembled from config.- Journaled market parameters win over config on restore. When the restored journal and the config disagree about a market’s parameters, the journal decides, so a parameter change applied at runtime survives a restart.
price_band_bpsis the first parameter the engine changes while it runs. The parameter is applied actor-side through the engine’s apply seam, so a market’s price band can move without a restart.- The market-parameter mutation path has a server-side allowlist and typed refusals. A parameter mutation is checked against an allowlist held by the service and refused with a typed error, so an unpermitted change is rejected by the server rather than trusted from the caller.
Accounts and credentials
The account layer took plumbing rather than product this window: sessions moved to Postgres, the at-risk read is gated on the admin secret, and the shared client signs only the writes it lists rather than signing on a caller’s behalf.
Market data and the interface
GET /market-statscarriestotal_open_interest. The field is added to the market-stats response, so open interest arrives with the rest of a market’s statistics instead of being fetched separately.- Eight public market-data routes are served on the host a client already reads from. Eight public market-data routes are reachable there, so those reads sit alongside the rest of a client’s calls.
- The blotter comes back composed. A composed blotter view is served, so the blotter arrives assembled rather than stitched together by the caller.
- The chart takes MA and EMA overlays, an RSI pane and a mark-price line. The trading chart draws moving-average and exponential-moving-average overlays over the price, an RSI pane, and a line at the mark.
- Deposit and withdrawal history is shown. The interface lists past deposits and withdrawals, so a transfer can be looked up in the product that made it.
- A truncated margin-health figure no longer reads Safe. Margin health is computed in one extracted place and a truncated value no longer lands in the Safe band, so the label matches the account it describes.
State, recovery and the write-ahead log
- A corrupt live-tail record is resynced past, not trusted. The log resynchronises past a corrupt record at the live tail instead of trusting the length it declares, so one bad record does not carry the reader into the bytes after it.
- A log segment lost at either end fails closed. Exchange-state refuses to continue when a segment is missing from the head or the tail of the log, so a gap stops recovery instead of being replayed around.
Events also moved off the commit path and onto their own log, so recording an event no longer sits inside the commit.
Oracle
- Markets listed after boot are discovered, observe-only. The oracle picks up markets listed after it started and observes them without posting, so a new listing does not wait on an oracle restart to be seen.
- Failover freshness ages on value change, not delivery. A feed’s freshness is measured from the last time its value changed rather than the last time a message arrived, so a feed repeating an unchanged value is not counted as fresh.
Bridge and deposits
- A positive reconciliation delta has a remediation path. The eth-watcher can remediate a delta found in the positive direction, so a surplus at reconciliation has a defined way to be settled.
- A failed tombstone write no longer opens a double-credit window. When the dead-letter tombstone write fails, the eth-watcher closes the window in which the same item could be credited twice.
The API contract
- Nine
Orderfields the API already served are documented. The spec describes nine fields the endpoint was already returning and drops one it never returned, so the documented order matches the one a client receives. - 104 operations under one published spec. The spec published from this repository describes 104 HTTP operations.
Client SDKs
- The Rust client offers only operations the contract describes. Code-only operations the spec never carried are deleted and the allowlist that admitted them is sealed, so every operation the client exposes is one the API serves.
- The TypeScript client’s drift check runs without an allowlist. Any entry that differs from the spec now fails the check, and the funds surface is sent at the paths the spec declares.
Behind the scenes
The sandbox and the bots took most of the plumbing this window: the exchange port binds on both interfaces with the default unchanged, a market is held until a client actually trades, an agent can see its own resting orders, and the Observer’s export cap is configurable and says when it binds, with a whole run downloadable through /export/run and /export/manifest. The bots fail closed on positions they cannot read, and one gated reference-price table unsticks GOLD, OIL and SPX. Demo mode is wired through, with /demo/account/portfolio-history mounted behind it. The API docs withhold Try-It from write operations.
Alongside all of that, work landed on how changes are built and rolled out, and on how traffic is routed.