data_updater_v2.tables.universe
universe.py — the raw universe tables: one per family, one row per ticker era of a
security (id), every era the active pulls have carried, is_active for today’s.
A universe row is a listing’s static facts: who it is, how each vendor spells it, whether it
is active today, where it trades, its ids, what it IS. Nothing that moves daily (price, AUM,
NAV, market cap, supply) lives here; those are metrics. A listing that leaves the active pull
stays, is_active false: the active universe is is_active, and the rows never vanish.
Every table keys on OUR id (identity): global_id the security, minted once from its
first identifier (composite FIGI, ISIN, CUSIP, share-class FIGI, record FIGI; else the ticker)
and kept; id the ticker era, reproduced from the security, the market and the ticker. A
rename is a new row under the same global_id (the old era’s row stays, inactive); a ticker
another security takes later is a new row under a new global_id — so a symbol is unique
only among today’s rows (is_active), and every dataset row carries the id of the era
it was fetched under. symbol is OUR spelling — nc-feeds’ (data_clients/papers.py:
spell_fmp / spell_eodhd / spell_bitstamp): a listing as dashed (BRK-B), an index
without its caret (GSPC), a coin as BASE-USD (BTC-USD), a commodity by its root (GC) — with
each vendor’s own spelling beside it, so any vendor is asked in its own words.
Each table says, per vendor, how it spells the listing (*_symbol) and whether it prices it
(on_*: FMP’s active pull, EODHD’s daily file for the last finished session, Bitstamp’s
enabled pairs), so the price section routes by the row.
What the active pull is, per family (data_clients/fmp.py section 2, and for the two
listed families EODHD’s US ticker list beside it — data_client.EODHD_VENUES: its
listings on the US venues that FMP’s screener does not carry join as EODHD’s, fmp_symbol
null, on_fmp false; 13,298 EODHD lines on the venues against FMP’s ~11,800 on 2026-10-18):
etf_universe the screener per US venue, ETFs, trading only 5,747
equity_universe the screener per US venue, operating companies 6,080
(every paper FMP lists there: security_type says
which are shares — common, ADR, LP units — and which are
notes, preferreds, warrants, units, rights, funds)
index_universe index-list, US index codes in USD, quoted this week 316
crypto_universe USD pairs quoted today with volume (FMP), unioned ~1,860
with Bitstamp’s USD pairs
commodity_universe the commodity list, quoted this week 40
Sources, column by column, are in each comment: screener, profile, etf/info, sec-profile
(FMP), OpenFIGI, EODHD’s ticker lists, Bitstamp, the SEC’s own directories and filings (the
CIK and a fund’s series and class from its ticker directories; a company’s state and SIC
from its submissions; a fund’s adviser, type, expense ratio and objective from its N-CEN and
prospectus — data_clients/sec.py), and the classification of all four (nc-feeds’
readers, papers; the SEC’s fund directory says a listing is a 40-Act fund).
Columns run ids -> identity -> vendors -> status -> listing -> vendor ids -> what it is ->
enrichment. fetch is the one column ours rather than a vendor’s: a listing set false is
skipped by every price and event method (named in the result’s skipped), and kept so on a
rebuild and across a rename. Market facts only: no provider, fetched_at or run columns.
Classes
CommodityUniverse
Bases: _Ids, Base
One continuous US future (FMP carries no venue for them).
CryptoUniverse
Bases: _Ids, Base
One coin priced in US dollars, on FMP, Bitstamp, EODHD, or several (each coin once: EODHD’s code is matched to ours by the coin’s FIGI, else by its code and name).
EquityUniverse
Bases: _Ids, Base
One US exchange-listed paper FMP’s screener calls an operating company: the shares
(common, ADR, LP units) and the papers beside them, security_type saying which.
EtfUniverse
Bases: _Ids, Base
One US exchange-traded product FMP’s ETF screener has listed (ETNs included: FMP marks them ETFs too).
IndexUniverse
Bases: _Ids, Base
One US index (FMP has no index profile: index-list is all there is).