Skip to content

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.

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 refresh
  • is_default — exactly one universe can be marked default; that’s what cents factory run uses when its config says universe = "default"
  • description — free-form
  • timestamps

The four sources sit on a spectrum from “you bring everything” to “the system populates from external data”:

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.

Terminal window
cents universe create thematic --source static \
--symbols NVDA,AMD,AVGO,TSM,ASML \
--description "Semis with material China exposure"

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.

Terminal window
cents universe create my-watchlist --source watchlist

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.

Terminal window
cents universe create sp500 --source fmp_index --index sp500
cents universe refresh sp500 # re-pull constituents

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.

Terminal window
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 screen

Full-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.

Terminal window
cents universe create <NAME> [--source ...] [--symbols ...] [--from-file ...] [--index ...]
cents universe list # marker next to the default
cents universe show <NAME> # full detail + first 20 symbols
cents universe refresh <NAME> # re-resolve dynamic sources
cents universe set-default <NAME> # which one the factory picks up
cents universe delete <NAME> [--force]

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.

Use caseRecommended 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 watchingwatchlist
Run parallel experiments — e.g. factory perf on financials vs. techMultiple named static universes, switch via set-default or --universe
  • 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 refresh is 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.

Not financial advice. Cents is an educational and research tool for tracking your own investment theses. Outputs are model-generated and may be inaccurate. You are solely responsible for your own investment decisions.