Skip to content

Execution runtime

VerifiedOwner Backend / platformLast verified backend@efa38e04e2db37a444e9f17100323c2ad4b83647 nautilus@2.0.0rc3

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:

  1. Code existence. Nautilus itself ships add_simulated_exec_client/SandboxExecutionClient in the pinned wheel, and ONIX's PublicDataNodeBuilder guard (Layer 2, above) deliberately leaves that one call reachable while blocking add_exec_client. The simulated-execution mechanism genuinely exists in the dependency this backend runs.
  2. Activation. At this pin, no ONIX process wires that mechanism up. spine.service's own SpineService.sandbox_start/sandbox_stop/sandbox_status do not start, stop, or poll a SandboxExecutionClient at 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 tools sandbox_start_revision, sandbox_stop / spine_sandbox_stop, and sandbox_status are real, enumerable tool specs (see ../mcp.md) that call this same route — calling one returns the refusal below, not a running sandbox.
  3. Availability, on the wire. POST /v2/sandbox/start, POST /v2/sandbox/stop, and GET /v2/sandbox/status answer HTTP 501 with a capability block naming status: "UNAVAILABLE", reason: "DEFERRED_PAPER_PRODUCT" on the core spine and on the Binance product node — never a 200 carrying sandbox state. On the IBKR node the same three operations answer HTTP 404 NOT_SUPPORTED_ON_THIS_NODE (UNSUPPORTED, not UNAVAILABLE): 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.py
  • backend@efa38e04:python/src/onix_engine/spine/service.py
  • backend@efa38e04:python/src/onix_engine/spine/deferred.py
  • backend@efa38e04:python/src/onix_engine/ibkr/execution.py
  • backend@efa38e04:deploy/activation.json
  • backend@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.