The hedge ledger
Why the xEMM's only inventory authority holds two signed positions and derives what is owed, so a retried hedge can never double the position.
Every fill the cross-exchange maker takes on the maker venue creates a directional exposure that only an order on the taker venue can close. crates/vike-mm/src/xemm/hedge.rs's HedgeLedger is the one place that exposure is accounted for — the xEMM's only inventory authority — and its defining choice is that it is a target, not a delta.
Built, tested, and mounted by nothing
XemmMaker is reached by no binary — crates/vike-run/src/xemm.rs's build_live_xemm_core has no caller, and crates/vike-strategy/src/registry.rs's strategy_by_name has no xemm arm — and it has never quoted on a venue. Keeping the code rather than deleting it was a deliberate verdict, not an oversight. Read this page as the design constraints a future mount must not break; see the xEMM overview.
Why a delta ledger is wrong
The obvious ledger adds the owed hedge on a maker fill and subtracts it on a hedge fill. The module doc names its silent, unbounded failure: a hedge whose ack is lost — the ordinary case hedge_timeout_ms exists for — is re-fired, and if the original then fills too, a delta ledger has subtracted once and sent twice. The position doubles while the maker believes it is flat.
The ledger instead holds the two legs' signed positions — maker_pos folded from maker-leg fills, hedge_pos from hedge-leg fills, + long in both — and derives everything else:
target = −hedge_qty(maker_pos, hedge_ratio) // the hedge position we WANT
residual = target − hedge_pos // what still has to be sent
naked = maker_pos + hedge_pos // the exposure actually carriedcrates/vike-mm/src/xemm/pricing.rs's hedge_qty is net_filled_base · hedge_ratio, linear in both. A retry re-sends residual, which a late original fill has already shrunk — so a retry can never double the position, whatever order the acks arrive in. The in-file test a_retry_never_doubles_the_position drives the sequence a delta ledger fails — fire, time out, re-fire, then the original lands — and if the retry then fills too, the residual reports an over-hedge to be unwound rather than "flat". Sign convention: side is +1 buy / −1 sell, size unsigned, and a maker buy of 5 owes a hedge sell of 5.
Why the broker seam is never read for inventory
Broker::position(hedge_symbol) would be the natural source for hedge_pos. Two of the three reasons the module doc used to give against it are history — the runtime defects in declared_views and dispatch_applied_fills are fixed, with crates/vike-core/tests/wiring/multi_symbol_reads.rs as the proof. What survives is narrower and still decisive: HftBroker::position, the verb this maker's own trait bound gives it, takes no symbol and returns the dispatching engine's scalar, so reading a hedge leg through it is wrong by signature; and a broker read answers about settled state while this ledger exists for the in-flight hedge — no Broker::position can see a sent-but-unacked order, and a ledger derived from one would re-fire the full residual and double the position on a late ack. So the fill stream stays the authority, needs zero plumbing, and crates/vike-mm/src/tests/xemm_guards.rs's the_maker_never_reads_position_price_or_equity_through_the_broker pins the maker's output bit-identical against a broker whose every read surface is poisoned.
Residual, dust, and the deliberate naked position
HedgeLedger::residual(hedge_ratio, dust) returns the owed order as (side, qty), or None when the hedge is complete within dust. Dust forgives a residual smaller than the taker venue's min_qty: a sub-minimum order is rejected by the venue, and a rejected hedge is an unhedged position that would be retried forever. The bound is inclusive, so a residual exactly at it settles rather than oscillating; a negative dust is clamped to zero; a non-finite residual is treated as settled, there being no order to name. XemmParams::hedge_dust's doc says to set it to the taker venue's min_qty (symbol properties); the default is 0.0.
naked() is not the residual. With hedge_ratio < 1.0 a fully executed hedge still leaves a deliberate naked position — a_partial_ratio_leaves_a_deliberate_residual_exposure hedges 6 of a 10-unit fill at ratio 0.6 and reports 4 naked — and that is exactly what the naked bands measure, so "deliberate" never means "invisible". hedge_ratio == 0.0 owes nothing and fires no order rather than a zero-size one. XemmParams::hedge_ratio's doc calls 1.0 the only defensible v1 setting, and it is the default.
In flight, attempts, and exhaustion
InFlight { ts } records the event timestamp a hedge was sent at — the timeout clock. fire(ts) sets it and increments attempts; settle() clears both, so a new maker fill after a completed hedge starts with the full budget rather than inheriting the last cycle's. timed_out(now, timeout_ms) is true once a sent hedge has been outstanding for at least timeout_ms of event time; timeout_ms <= 0 disables the timeout, and with it any consumption of the budget past the first send.
attempts_exhausted needs all three: something still owed, attempts >= max_attempts, and the last send timed out — a hedge merely in flight is not a fault. When all three hold, HaltReason::HedgeUnfilled is raised, because continuing to quote past that point grows an exposure the taker venue has demonstrably refused to close. XemmParams::default times the hedge out at 3 s with 3 attempts. The budget counts sends, the first included — XemmMaker::with_hedge_discipline's doc spells 0 as "never hedge at all".
Where it fires from
crates/vike-mm/src/xemm/mod.rs's drive_hedge is the target-residual discipline in one place: nothing owed settles the ledger; a hedge in flight and not yet timed out, or a spent budget, sends nothing; otherwise the residual goes out as Broker::submit_market(hedge_symbol, side, qty) and the send is recorded. That verb is a hard contract — the only venue-routable one, because the runtime's resolve_intent_venue finds a declared leg by symbol and a tagged submit carries symbol: None. A tagged verb here would place the hedge on the maker venue, doubling the exposure it was sent to close.
crates/vike-mm/src/xemm/strategy_impl.rs's on_fill routes by Fill::symbol, the only leg discriminator a fill carries, which is why XemmMaker::new panics on equal leg symbols. On the maker leg it folds the fill, hedges first and re-quotes second — the exposure just created is the urgent thing. On the hedge leg, a dispatch that drains on the taker venue's series, it folds and calls drive_hedge only: never a tagged verb, never requote or pull_all. on_schedule calls drive_hedge too, so an owed hedge gets its retry even when both feeds are silent. Hedge-leg fills never reach the one-sided-fill breaker: they are the maker's own mechanical offset, and netting them would cancel every real signal to exactly zero.
A rejected hedge is handled by the clock, not by an event
on_order_event is deliberately not implemented: how a rejected or externally cancelled hedge leg folds back into HedgeLedger and InFlight is a hedge-accounting question strategy_impl.rs's module doc says is undesigned, and "no reaction is better than a guessed one". Until then a lost or refused hedge is the in-flight marker aging past hedge_timeout_ms and the residual being re-sent — the path the ledger was built to make safe.
Persistence and observables
XemmStateV1 persists maker_pos, hedge_pos, hedge_attempts and the in-flight timestamp across a restart, because an unhedged position is real money at risk on two venues and a maker that forgets it restarts believing it is flat; load_state is fail-open and can only make the maker more cautious (mounting covers strategy-state persistence). XemmMaker::naked_exposure and leg_positions read the owned ledger for the operator. A hot re-tune through apply_params never touches it — the ledger is a sibling of the tunable bag, and the two leg symbols live outside that bag as identity, so a re-tune cannot repoint a leg while an unhedged position is open. The test module is crates/vike-mm/src/tests/xemm_hedge.rs, whose header calls it the #997 regression surface and the most dangerous code in the crate.
Basis
The event-time EWMA of the maker-versus-reference basis — a diagnostic and a halt band, never a term in a quote price, folded from paired market touches only.
Guards
The xEMM's pure safety verdicts — the freshness bounds, the soft and hard naked-inventory bands, and the halt vocabulary every stop is named in.