Master
instrument
Canonical identity, keyed (symbol, venue). Asset/instrument class,
microstructure, FIGI. Option legs in instrument_derivative.
Execution
broker_instrument
Tradable mapping — one row per instrument per broker: broker_symbol,
native_id, limits. Written by sync-broker from the adapter's
InstrumentProvider. Its existence means tradable.
Market data
FeedSymbology
Pricing mapping, 1:n — and a pure function, not a table. candidates()
picks the catalog slice a feed covers, to_feed_symbol() renames it; one
symbol can price the pair on several venues. Evaluated at subscribe time.
End to end
One catalog in the middle, an adapter at each end. Brokers write it:
sync-broker asks each broker's InstrumentProvider what it
lists and stores that as instrument plus a broker_instrument
routing row. Feeds only read it: at subscribe time
FeedSymbology.candidates() picks the slice of the catalog that feed
covers and to_feed_symbol() renames each hit into whatever that feed
calls it.
That second mapping is computed, not stored — there is no feed table anywhere. It is rebuilt from the catalog on every subscription, which is why a broker sync that adds instruments needs no follow-up step to make them priceable, and why nothing can go stale. Each adapter owns its own symbology, so neither end knows the other exists.
Tables & relationships
Foreign keys shown. broker_instrument references the master instrument.
There is no feed table: the pricing mapping is derived in code. Two soft links by code
(no FK): broker_code → broker_connection, and
feed_code is ranked for failover in provider_feed_policy.
Runtime — the two paths
Pricing derives its symbols through FeedSymbology; order routing reads
broker_instrument. They never cross — a feed can price an instrument no
broker trades, and vice versa.
Reflects migrations 0016–0020 and the sync-broker flow. See also
API docs.