vike
Venues

Venues

What a venue bridge is, the emitter split every one of them obeys, and the two gates — the arming ceiling first, then absent credentials — that decide whether a mount is real.

Vike Trader has a bridge crate for fourteen venues, one directory each under crates/bridges/. vike_model::VENUES (crates/vike-model/src/venues.rs) is the canonical roster and calls itself "THE authority on every venue vike has a bridge crate for". Every per-venue capability table's completeness test iterates it, "so adding a venue here fails EVERY table's tests until its rows land" — and a roster venue's row is always named even where its value equals the registry fallback, because "the named row is the declaration that the venue was CLASSIFIED, not forgotten". That is why the per-venue pages here are generated: their rows are the rows the runtime consults.

What a bridge is

vike-bridge-core is "the shared plumbing every venue bridge is built from: blocking REST transport

  • signers, the venue-neutral WS user-data pump with reconnect/backoff/keepalive/resync, the ExecActor command thread, credentials (the absent-credentials-is-the-live-gate authority), and the pinned Decimal wire-format site" (crates/vike-bridge-core/src/lib.rs). A venue crate supplies its own signer, its wire strings and a pure event mapper; the reliability machinery is shared. A shared rule lives in bridge-core rather than in each bridge so the venue arms "cannot drift from each other" (crates/vike-bridge-core/src/lib.rs's leverage note) — which is why a shared home is consumed, not modified in passing: a missing knob is a stop-and-report, and the extension lands as one coordinated change informed by every consumer.

At the top of every bridge sits one trait. vike_exec::ExecutionClient is "the venue-client seam: submit/cancel are the ONLY order-mutating calls that leave the core; every state change comes back as venue events through the ingest channel" (crates/vike-exec/src/execution_engine/client.rs). Everything else on it has a default — see the ExecutionClient seam.

The emitter split, machine-checked

crates/vike-bridge-core/tests/bridge_conformance.rs runs one scenario table against every covered venue's real event mapper, and states the contract it checks:

  • Emitter split — "Rust emits OrderSubmitted synchronously at submit; the venue emits OrderAccepted / Rejected / Canceled / (Partially)Filled."
  • No silent vanish — "a dead venue path MUST synthesize a terminal OrderRejected."
  • Exactly one terminal — the ManagedOrder FSM "must reach exactly one terminal state (Filled | Canceled | Rejected | Denied | Expired); illegal/out-of-order events are dropped idempotently, never corrupting the single terminal."

The oracle is the real FSM the live core folds through, not a model of it. Ten venues are covered — binance, bybit, okx, deribit, aster, hyperliquid, oanda, ig, alpaca and fxcm; polymarket, dukascopy, ibkr and ctrader are deferred with a recorded reason each. Which column a venue sits in is not optional: conformance_roster_is_exhaustive checks both lists exhaustive against VENUES, so a new bridge "fails the gate until it is either wired in or deliberately deferred-with-reason". market_data_conformance.rs is the market-data twin over each covered venue's real route_frame normalizer, with its own roster gate.

Two gates, and the order between them

vike_mount::make_engine turns a venue name into a client, and its module doc is blunt about the sequence: "the LIVE GATE is TWO gates now, and the order between them is the point". The deployment's per-venue arming ceiling — policy.venues.<venue>, paper < demo < live — is consulted first, above the credential read, and "a paper venue returns the paper client having loaded no credential, fetched no instrument grid and opened no socket". Only then does the older rule apply: absent credentials are the live gate, and a venue whose keys are missing stays on vike_paper::PaperExecutionClient.

The ceiling can only ever refuse. vike_config::VenueMode::cap is "min, never max" — its own doctest asserts that a live ceiling over a demo-credentialled venue stays demo, and that a paper ceiling over a live-credentialled venue is refused down to paper. Writing live arms nothing by itself; it declines to stop something else arming it. Arm one venue for demo is the task-shaped version; policy.toml is the key reference.

A box with no [venues] table mounts all paper

vike-mount's venue_arming_migration_message warns once at startup rather than refusing, naming the credentialled venues that are now paper and the settings paths that restore them — because "a node that will not start cannot flatten a position either". It self-silences the moment any venue is declared, and prints venue slugs only, never a credential key name: "this text is designed to be pasted, and a paste-ready block that carries key names invites the reply that carries values."

How each venue is wired

vike_ops::docs_data's Wiring is the one docs-facing axis no capability table encodes, "because it is a property of make_engine arms rather than of any adapter". Each generated venue page opens with its class.

classwhat it means
live-exec-reconan ungated arm mounts a real client from credentials; the venue is in the default reconcile set
feature-gatedthe live arm compiles only under a vike-mount cargo feature; a default build has no arm and falls through to paper
sidecar-exec-no-reconexec runs through an owned child process, and no arm wires that venue's recon factory
paper-onlyonly the paper fallback mounts it; no roster venue is in this class today

WIRING carries one named row per roster venue behind a completeness gate, and an unclassified venue panics the renderer rather than exporting a guess. A ReconClient existing "is not the same as being in the live reconcile set".

What the shared plumbing guarantees

The halt boundary. submit and modify consult the halt file sentinel before touching the command channel, and the refusal is conditional. A submit that OPENS or ADDS is refused with a synthesized terminal OrderRejected (never a silent vanish); a submit that REDUCES is allowed — crates/vike-bridge-core/src/halt.rs's halt_admits_submit "is the whole of that rule", and every such admission is logged, because that boundary holds no position book and can only trust the caller's reduce_only flag. A modify is blocked so the resting order keeps its terms, and cancel is never gated. The reducing arm exists because a cancel alone never discharged "a kill switch must never trap you in a position": "a cancel removes a resting ORDER, while getting OUT of a position means SENDING one", and until that arm landed market-exit under a halt file cancelled everything and could then close nothing. It works when the runtime is wedged: an operator touches the file over ssh (crates/vike-bridge-core/src/exec_actor.rs). See halt.

The restart law. Every venue's resync closure replays a window of venue history bounded by a row count and nothing else, so the first gap-sentinel after a restart once folded the venue's whole retained execution history through the non-idempotent fill path — measured on the production box, "each unexplained equity step equalled the sum of PRIOR sessions' costs, exactly". run_loop now samples its own spawn instant and never forwards a resync event stamped before it; run_resync_supervisor carries the same floor on the user-data lane.

Polymarket carries operational rules no table can hold — they are in Polymarket operations. The rest of the arming picture is in risk and arming.

On this page