Instrument identity¶
Canonical form¶
Every instrument ONIX names uses Nautilus's own canonical instrument_id string, shaped
{raw_symbol}.{venue} — for example BTC-USD-PERP.HYPERLIQUID. This is the identity carried
end to end: in bar types, in coverage rows, in hydration status, in the strategy-authoring demand
model, and on every gateway response that names an instrument.
The one rule every consumer of this contract must follow, stated explicitly in the schema itself:
never split an instrument_id on . to recover its parts. A venue-native symbol can itself
contain a dot, which would silently break a naive splitter — and worse, invite that (slightly
different) splitting logic to be re-implemented independently in Rust, Python and any TypeScript
consumer. The onix.instrument_ref document instead carries venue and raw_symbol as their own
typed fields, alongside base_currency, quote_currency, settlement_currency, product kind,
is_inverse, and precision/increment fields — a consumer reads those fields, never parses the
composite string.
External bar timestamp normalization¶
Venues disagree about whether a candle's own timestamp names the interval's start or its close.
Each ONIX venue profile declares this explicitly (external_bar_stamp: "start" or "close") as
verified against that venue's own pinned adapter behavior — for example, one profile declares its
venue stamps at interval start and is normalized to close on ingestion, while another's pinned
adapter default already close-stamps and is passed through untouched. Getting this wrong in either
direction would shift every external bar by one interval; it is why this is a per-profile,
adapter-verified field rather than a single global assumption.
Sharding¶
For a venue whose full instrument universe is too large for one process's connection budget, an
instrument is deterministically assigned to one of N spine processes by a stable SHA-256 prefix of
its id — never Python's per-process salted hash() — so the assignment is stable across restarts,
hosts, and process re-launches, and no instrument is silently owned by zero or two shards at once.
Identity in transition¶
Because instrument identity is tied to what a venue currently lists, and because ONIX's own
retained-ingestion manifest governs which instruments accumulate durable demand (see
../data/ingestion.md), "the current instrument roster" is not a fixed
fact — it moves with manifest epochs and with what a venue itself lists or delists. Two concrete
consequences worth stating plainly:
- An instrument can be retired between manifest versions read at different pins. The
development-pin manifest committed in this repository (
manifest_version: 8) recordsCUDISUSDT-SPOT.BYBITas retired at manifest version 6 — yet the separately trackedCURRENT_PRODUCTIONrecord cites that same instrument as part of themv5-epoch1production roster. Both are correct at their respective manifest versions; a reader comparing the two without noting the version difference would wrongly conclude one of them is an error. - Discovery and demand are not the same set. A venue can list far more instruments than the
retained-ingestion manifest currently admits into durable demand; an instrument outside the
retained set is enumerable (nothing about it is hidden) but reports
retention_state: "unretained"and accumulates no history.
Any documentation, dashboard, or downstream consumer that hard-codes "the instrument list" from a single snapshot should expect it to be stale relative to the live manifest. The manifest itself, not a cached roster, is the authority.
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:schemas/instrument_ref.schema.jsonbackend@efa38e04:python/src/onix_engine/venues/profile.pybackend@efa38e04:deploy/retained-ingestion.json
Status tokens are defined on the documentation and status model page. Every pin on this site is listed under versions and source pins.