Skip to content

Instrument identity

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

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) records CUDISUSDT-SPOT.BYBIT as retired at manifest version 6 — yet the separately tracked CURRENT_PRODUCTION record cites that same instrument as part of the mv5-epoch1 production 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.json
  • backend@efa38e04:python/src/onix_engine/venues/profile.py
  • backend@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.