Execution runtime¶
This page states ONIX's execution capability as precisely and conservatively as the pin allows. Nothing here should be read as a claim that this deployment currently places real-money orders on a live venue — the evidence below points the other way, at multiple independent layers.
Layer 1: the market-data spine registers no execution client at all¶
Every venue market-spine process — the process that ingests live data for Bybit, and, in the development roster, Hyperliquid and Binance — builds its Nautilus node with default data/portfolio/risk engine configuration and attaches zero execution or risk clients. This is stated directly by the module that composes the node: "no exec/risk client is added here; the market spine node runs no execution engine at all." A process with no execution client attached cannot place an order on any venue, real or simulated, because Nautilus has nothing registered to route the order to.
Layer 2: a structural guard on the one call that would register real execution¶
Independent of layer 1, a dedicated wrapper (PublicDataNodeBuilder) around Nautilus's own
LiveNode.builder(...) intercepts add_exec_client(...) — the single Nautilus method that
registers a real venue execution client — and raises immediately, before the wrapped official
builder's method is ever called. Every other builder method, including Nautilus's own
add_simulated_exec_client (simulated/sandbox execution — explicitly authorized and left
reachable), is delegated unchanged. This is a caller that tries to register real execution being
refused by a typed error, not merely a convention of "the code just never happens to call it" — and
it is paired with a second guard (EnvAccessGuard) that raises the instant any code path reads a
credential-shaped environment variable while it is active, catching a dynamically-constructed key
name a static grep could miss.
The one honestly-stated limit of this guard: it is a Python-level structure, not a language-level
sandbox — it can be stepped around by deliberate closure/reflection tricks, and the released
Nautilus LiveNode exposes no way to enumerate registered execution clients for an independent
post-build check. That limitation is recorded rather than papered over.
Layer 3: sandbox execution — code exists, activation does not, availability is refused¶
Nautilus publishes an ExecutionEnvironment vocabulary — BACKTEST, SANDBOX, PAPER, LIVE —
and ONIX's own wire contract adopts it (target-contract: a declared enum, not evidence that any
tagged execution path is active). Three separate claims matter here, and this documentation
previously ran them together:
- Code existence. Nautilus itself ships
add_simulated_exec_client/SandboxExecutionClientin the pinned wheel, and ONIX'sPublicDataNodeBuilderguard (Layer 2, above) deliberately leaves that one call reachable while blockingadd_exec_client. The simulated-execution mechanism genuinely exists in the dependency this backend runs. - Activation. At this pin, no ONIX process wires that mechanism up.
spine.service's ownSpineService.sandbox_start/sandbox_stop/sandbox_statusdo not start, stop, or poll aSandboxExecutionClientat all — every one of the three raises a typed deferred refusal (onix_engine.spine.deferred.deferred("spine.sandbox.start"/"...stop"/"...status")) before any sandbox node could be constructed. The MCP toolssandbox_start_revision,sandbox_stop/spine_sandbox_stop, andsandbox_statusare real, enumerable tool specs (see../mcp.md) that call this same route — calling one returns the refusal below, not a running sandbox. - Availability, on the wire.
POST /v2/sandbox/start,POST /v2/sandbox/stop, andGET /v2/sandbox/statusanswer HTTP 501 with acapabilityblock namingstatus: "UNAVAILABLE",reason: "DEFERRED_PAPER_PRODUCT"on the core spine and on the Binance product node — never a200carrying sandbox state. On the IBKR node the same three operations answer HTTP 404NOT_SUPPORTED_ON_THIS_NODE(UNSUPPORTED, notUNAVAILABLE): IBKR is a real-broker connection service with no backtest-job store or simulated-execution concept to defer in the first place — the two statuses answer different questions ("this release doesn't ship it yet" versus "this node has no such concept"), and a client must not collapse them.
This is a deliberate deferral, corrected from a worse prior state, not a silent gap. The
module's own comment records why: the previous behavior for this whole execution/account
observability lane was not a decision — the routes stayed wired and fabricated an answer.
/v2/portfolio returned 200 with a zeroed portfolio, /v2/orders//v2/fills//v2/positions
returned 200 [], and the capability registry reported every one of them READY. To a client,
"200, no orders" was indistinguishable from "this account has done no trading." Refusing loudly
with a named, typed reason — rather than answering with plausible-looking empty state — is the
fix, and it is why this documentation states UNAVAILABLE rather than describing the surface as
merely "empty" or "not yet used." A future paper-execution milestone is expected to start from a
native Nautilus LiveNode/SandboxExecutionClient under ordinary systemd supervision, not from
the removed bespoke HTTP process supervisor sandbox execution previously used.
Layer 4: real broker execution code exists for Interactive Brokers — and is disabled¶
Interactive Brokers is architecturally different from every other integration ONIX profiles: it is
a real, multi-account broker, and ONIX's ibkr package contains genuine execution-projection
code that reads an official Nautilus IBKR execution client's account/order/fill/position state —
code that only produces real data when a real IBKR account id has been configured and the exec
client has connected. Unconfigured or unconnected states are reported honestly by name
(execution_ready: false, reason ACCOUNT_NOT_CONFIGURED or EXEC_CLIENT_NOT_CONNECTED), never
masked as empty-but-successful. At the pin, this is the only place in the backend that
constructs execution code capable of touching a real (non-simulated) account.
This capability is currently disabled in the deployment activation roster
(deploy/activation.json: ibkr.enabled: false) and does not appear at all in the tracked
CURRENT_PRODUCTION record. Its status here is verified (the code exists and is real, not
simulated) combined with private-test-stage at most for its activation state — there is no
evidence in this repository of it being live-activated in any tracked deployment.
The sole runtime, its lifecycle, and how it stops¶
Every venue-market-data process in this fleet — including the ones this page documents as having
no execution client attached — is the one runtime kind this backend hosts:
../runtime/index.md documents NautilusRuntimeHost (the object that
drives Nautilus's blocking run() over run_async()) in full, including the capture-before-run
contract, the single supervisor thread that converts every stop intent (signal, startup timeout,
run deadline) into one handle.stop() call, and why run_async() was rejected on this pin. Process
isolation is OS-level: each integration is its own process, restarted by systemd
(Restart=always) rather than by an ONIX-owned supervisor — an earlier ONIX supervisor layer was
retired when RC3 removed the LiveNode.start()/poll() methods it was built around. A committed
systemd-unit inventory names one unit per venue integration, the public gateway, the operator
gateway, the screener, and the IBKR preview/display stack (deploy/testing/units/*.service);
exact hosts, ports and mount paths are deliberately not published here (see
../runtime/index.md's scope note). Restart/shutdown behavior for the two
pieces of state this backend does maintain across a process boundary —
scheduling/retry state for catalog hydration, and closed-period consolidation watermarks for the
INTERNAL sibling catalog root — is covered in ../data/catalog.md and is
proven by python/tests/test_runtime_lifecycle.py and python/tests/test_internal_lifecycle.py,
not asserted from prose. Deployed versus observed, stated once more: every fact in this
section is verified against pinned source and tests; whether a given systemd unit is currently
running on any specific host is a production-record-at-best claim — see
../runtime/index.md for the tracked record and its limits.
Summary¶
| Layer | What it proves |
|---|---|
| Market-spine node composition | No venue market-data process has any execution client registered, real or simulated |
PublicDataNodeBuilder guard |
Real execution registration is refused by a typed error, structurally, on that code path |
| Sandbox/paper execution | The simulated-execution mechanism exists upstream and is left reachable by the guard, but no ONIX process activates it at this pin: sandbox_start/sandbox_stop/sandbox_status all raise a typed UNAVAILABLE/501 refusal on the core spine and Binance node (404 UNSUPPORTED on IBKR, which has no such concept) |
| IBKR execution code | Genuine real-broker execution code exists and serves real account/order/fill/position reads when configured and connected, but is disabled in activation and absent from the production record |
No path in the pinned source, the development activation roster, or the tracked production record demonstrates real-money order placement on a live venue by this deployment. This documentation makes no claim beyond what is stated above, and will not describe any future state as current without equivalent evidence.
Evidence and source pins for this page
Verified. Current behaviour, confirmed in source at the pinned commit.
Verified on against the following immutable sources:
backend@efa38e04:python/src/onix_engine/venues/execution_guard.pybackend@efa38e04:python/src/onix_engine/spine/service.pybackend@efa38e04:python/src/onix_engine/spine/deferred.pybackend@efa38e04:python/src/onix_engine/ibkr/execution.pybackend@efa38e04:deploy/activation.jsonbackend@efa38e04:docs/contracts/capability-registry-v1.md
Status tokens are defined on the documentation and status model page. Every pin on this site is listed under versions and source pins.