vike
Tools

market_exit

The panic button — cancel every live order, then flatten every open one-way position (hedge-mode legs are skipped), optionally scoped to one venue; two-call gated like every other write tool, on confirm plus a preview_token.

market_exit is the get-me-out verb. Its own tool description calls it the panic button, and it is the one command that empties the order book and the positions together. It previews unless a call carries both confirm: true and the preview_token its own preview returned, and needs vike-cli mcp --node <host:port> plus VIKE_TRADEHUB_CONTROL_KEY.

The panic button is two calls, and the first one is not one of them

This verb is the one where the two-call gate costs something real: in an incident, a confirm: true sent without the preview_token does not fire the exit and does not complain — it hands back another preview. Take the preview, read preview_token out of it, and send the second call with both fields. Then read will_execute. The token is good for 60 seconds, which is the window this gate was sized for.

Arguments

ParameterTypeRequiredNotes
venuestringnoOmit for every engine
reasonstringnoRationale for the node's audit trail
confirmbooleannoMust be the JSON boolean true and be accompanied by preview_token — either one missing returns a preview
preview_tokenstringnoThe token this tool's preview returned. Fires once, expires after 60s, bound to the command it previewed

Nothing is required. market_exit_preview_allows_an_omitted_venue pins that a call with an empty argument object previews cleanly and produces a MarketExit wire command. venue: None is the global exit across every engine; Some(v) scopes it to that venue's engine alone.

It is a compound verb, expanded on the node

OrderIntent::MarketExit carries no state of its own and mints no orders directly. The runtime expands it at apply time into the primitives that already exist:

  1. one MassCancel, applied first;
  2. then one Flatten per non-flat BOTH-side position, derived from the post-cancel account, in the account's own (venue, symbol, position_side) insertion order.

Hedge-mode LONG/SHORT rows are skipped. Flatten resolves its size at (venue, symbol, "BOTH"), so a hedge leg would expand into a Flatten that resolves 0.0 and no-ops. On an account whose venue reports only hedge buckets — binance perp's positionSide, OKX's posSide, bybit's positionIdx — the mass-cancel still runs but the flatten half mints nothing. Those venues need per-leg closing intents the primitive vocabulary does not carry yet.

Each leg is lowered through the same apply_intent site every other order takes, so mint → RiskGate → client stays structural rather than being a special path for the emergency verb. A flat, order-free book is a no-op beyond the mass-cancel.

It works from a halted core

No precondition — this is the reverse of what the verb documented for years

The RiskGate kill switch admits a position-covered reduce under Halted (vike_model::is_covered_reduce), which is exactly the shape a flatten leg mints: side opposite the position, quantity |position|. So the mass-cancel runs and every flatten leg is submitted, under Active, Reducing and Halted alike — though admission at that arm is all the covered shape buys: RiskGate::check_inner's per-order notional and projected-exposure caps carry no covered-reduce bypass, so a leg over an armed max_notional_per_order or max_total_exposure is denied in any state. And one residual under Halted alone (Reducing trusts the flag): the gate re-takes its halt verdict against the lot-rounded size, so a position sitting off the lot grid (|position| = 1.8 on a 1.0 lot) rounds its own leg up to 2.0, which would flip the position, and that leg comes back OrderDenied with the reason halted. Every size this core mints is already lot-rounded, so reaching that residual takes an externally-sourced position — a venue liquidation, a reconcile fold. The runtime still logs a warning and a recent-events note when the exit runs under a halt — now saying it is proceeding.

The gate used to deny every order under Halted, reduce_only included, so the panic button was disarmed in exactly the situations that reach Halted on their own — both dead-man's switches and the safe-state sweep halt — and an operator had to set the state back to active first, un-halting the strategy that got them there in order to escape it. A kill switch must stop you opening risk, never trap you in it.

Best-effort, not atomic

A resting order can still fill after a flatten leg

Against a real venue the mass-cancel is fire-and-forget over the adapter's actor thread. Its acknowledgements land asynchronously, possibly after the flatten market orders are already on the wire. Ordering the legs is a local best effort, not a venue-side transaction.

OrderIntent::MarketExit's own instruction is the one to follow: re-issue the exit if the board is not flat afterwards. Read the board with node_snapshot rather than assuming the first exit finished the job.

What the node does with it

lower_command maps WireCommand::MarketExit to the core intent with an empty coid — the account-wide-verb convention, since there is no single order id to echo. ControlLimits::vet consumes a rate token and applies no size cap: market-exit sits with cancel, flatten, mass-cancel and trading-state among the risk-reducing verbs its doc says are never size-capped.

The preview's guardrail is Guardrail::NoSize for the same reason a flatten's is — there is no order size on this side to check, and the orders this verb will produce do not exist yet. What the preview can give you is the node's own dry-run (node_verdict, when there is a node to ask) and the preview_token the confirming call has to carry; Live node sets out how that token behaves.

Outcomes

Server::execute awaits this command's own ticket for two seconds. accepted returns sent: true with an empty client_order_id; a refusal is an error result carrying the node's reason; a timeout returns outcome: "unknown"; a dropped control connection is an error result saying the outcome is unknown and it may have executed.

For this verb in particular, the ambiguous answers deserve the snapshot rather than a reflex retry — though a second exit is the documented remedy for a board that is not flat, so the cost of checking first is small and the cost of guessing is not.

mass_cancel is the first half on its own — clear the orders, leave the positions. flatten is the second half for one book. set_trading_state halts new risk without closing anything. The gates each leg passes are described in Risk and arming.

Market exit everything on binance, right now — reason: feed outage.

On this page