Universes
A universe is a named collection of symbols that the factory iterates on each run. It’s stored in its own SQLite table, has a pluggable source, and can be refreshed independently.
The shape
Section titled “The shape”A Universe has:
name— primary key, case-insensitive (stored lowercased)source— one of three pluggable sources (see below)source_config— JSON blob for source-specific params (e.g.{"index": "sp500"})symbols— the resolved list at the time of last refreshis_default— exactly one universe can be marked default; that’s whatcents factory runuses when its config saysuniverse = "default"description— free-form- timestamps
Sources
Section titled “Sources”The four sources sit on a spectrum from “you bring everything” to “the system populates from external data”:
static
Section titled “static”Explicit symbol list. Symbols come from --symbols A,B,C or
--from-file path.txt (one symbol per line, # comments allowed).
Refresh is a no-op unless you re-supply symbols. The cheapest, least
clever option — you know exactly what’s in scope.
cents universe create thematic --source static \ --symbols NVDA,AMD,AVGO,TSM,ASML \ --description "Semis with material China exposure"watchlist
Section titled “watchlist”Mirrors the existing cents watch list. The watchlist is what you’ve
been manually monitoring; this lets the factory iterate the same set.
Refresh re-reads the watchlist at call time.
cents universe create my-watchlist --source watchlistfmp_index
Section titled “fmp_index”Pulls index constituents from FMP’s /stable/{index}-constituent
endpoint. Currently supported keys: sp500, nasdaq, dowjones.
Requires FMP_API_KEY. Refresh fetches the current constituent list —
handles index reconstitutions on the next cents universe refresh.
cents universe create sp500 --source fmp_index --index sp500cents universe refresh sp500 # re-pull constituentsscreener
Section titled “screener”Runs one of the built-in screener strategies (value,
growth, momentum, mean_reversion, insider_cluster) against a
parent universe. The output is the symbols that pass the screen; the
parent universe is the input set.
cents universe create cheap_sp500 --source screener \ --strategy value --over sp500
cents universe create momo_watch --source screener \ --strategy momentum --over my-watchlist
cents universe refresh cheap_sp500 # re-run the screenFull-market scans (no --over) are gated behind
CENTS_SCREENER_ALLOW_FULL_UNIVERSE=1 to prevent accidental
5,000-symbol queries. The constrained form (--over <parent>) is the
intended default. See Screeners for the strategy
catalog and tuning.
cents universe create <NAME> [--source ...] [--symbols ...] [--from-file ...] [--index ...]cents universe list # marker next to the defaultcents universe show <NAME> # full detail + first 20 symbolscents universe refresh <NAME> # re-resolve dynamic sourcescents universe set-default <NAME> # which one the factory picks upcents universe delete <NAME> [--force]How the factory uses it
Section titled “How the factory uses it”The factory iterates the resolved symbols in their stored order. For each symbol it skips if the symbol is in the held-symbol set (already has a factory thesis, is the hedge leg of an existing paired thesis, or was just invalidated this run). The remaining symbols pass through orchestrator → entry-threshold gate → premise classification → concentration cap → budget / preemption gate → open.
Order is preserved, not shuffled. Deterministic and easy to reason
about, but it does mean if your universe is alphabetical and signals
are evenly distributed, A-named symbols get systematically more chances
to open when max_new_per_run is binding.
Patterns by use case
Section titled “Patterns by use case”| Use case | Recommended source |
|---|---|
| Iterate something stable and known (S&P 500 baseline) | fmp_index with sp500 |
| Try a thematic cut (semis basket, energy basket) | static with --from-file |
| Mirror your manual workflow — let the factory consider whatever you’re already watching | watchlist |
| Run parallel experiments — e.g. factory perf on financials vs. tech | Multiple named static universes, switch via set-default or --universe |
What it deliberately doesn’t do
Section titled “What it deliberately doesn’t do”- No automatic filters (market cap, sector, liquidity) — universe is whatever you give it
- No symbol blacklist — if you don’t want NVDA, don’t put it in
- No automatic refresh schedule —
cents universe refreshis manual or via cron - No universe composition (union/intersection of others) — copy-paste for v1
For most use cases the watchlist or a static list is the right answer.
The fmp_index source exists for when you want a sustainably-large
universe that auto-handles constituent changes without you tracking
them.