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'sleveragenote) — 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
OrderSubmittedsynchronously at submit; the venue emitsOrderAccepted / Rejected / Canceled / (Partially)Filled." - No silent vanish — "a dead venue path MUST synthesize a terminal
OrderRejected." - Exactly one terminal — the
ManagedOrderFSM "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.
| class | what it means |
|---|---|
live-exec-recon | an ungated arm mounts a real client from credentials; the venue is in the default reconcile set |
feature-gated | the live arm compiles only under a vike-mount cargo feature; a default build has no arm and falls through to paper |
sidecar-exec-no-recon | exec runs through an owned child process, and no arm wires that venue's recon factory |
paper-only | only 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.
surface
Writes vike-cli's own backtest-plane command surface as the cli.json asset the docs site renders this reference from.
Alpaca
Alpaca on Vike Trader: capabilities, order kinds, time-in-force handling, margin, fees, amend semantics and how the bridge is wired — rendered from the venue tables the runtime consults.