Ordinary market history comes from two providers, and every ordinary ticker can pin its own:
- Yahoo Finance (via the bundled Python sidecar): the broadest fund coverage, and the source for profile/metadata, including a fund's category and expense ratio, a stock's sector and core stats alike. Its feed is unofficial and intended for personal use, so in the commercial edition it is off until you opt in.
- Tiingo: a documented API with a free key, the recommended default. The key is stored locally on your machine, never in the database or its backups.
Namespaced TSP:* funds use the official TSP CSV lane instead of either market
provider. Cash-like local rows and Treasury-curve data are also source-specific;
none of those symbols is sent to Yahoo as a fallback. Ticker Metadata therefore
hides Yahoo profile fetch for TSP:*, locks its source and download-enabled state,
and repairs stale metadata when saved. The main-process provider boundary rejects
the namespace too, so a stale screen or crafted request still cannot reach Yahoo
or Tiingo.
Tickers without a pin follow the global default on Settings; a per-ticker override exists because each source has tickers the other covers badly. Turning Yahoo on with no Tiingo key saved, whether in first-run setup or in Settings, also makes Yahoo the default; otherwise every download would still wait on a key you haven't added. In first-run setup the rule also runs the other way: unticking Yahoo there while a Tiingo key is already saved flips the default to Tiingo, so the wizard never finishes with the default pointed at the source you just turned off. In Settings you change the default yourself.
The wizard's Price data step
A commercial-edition guided setup asks this right after About you, before any account exists. It presents the same Yahoo checkbox and an inline Tiingo key field, no separate Save. Continue stays disabled until the resolved configuration can actually fetch, naming the reason inline when it can't. Landing on a Tiingo default runs a live key check first. A saved-but-revoked key fails here instead of failing silently later, once per ticker. Skip for now writes nothing at all, including a ticked Yahoo box: the install leaves with whatever was already saved, unchanged, and you can finish the setup later in Settings → Price data.
"Set up price data"
A new commercial install has neither feed ready: Tiingo is the default but has no key yet, and Yahoo is off until you opt in. Until one of them works, the top bar's Update Prices button becomes Set up price data and takes you to Settings → Price data, where a notice names what's missing. This is deliberate. Running a download in that state fails once per ticker rather than telling you the one thing that's wrong.
Two ways out, either is enough: paste a Tiingo key (their free tier covers a personal portfolio), or tick Enable Yahoo Finance.
On the Screener, tickers without a usable trailing-return period are excluded from rankings while working results remain. The compact summary gives the excluded count and links to this same Update/Setup action; a full recovery message appears only when the current comparison has no usable result.
Recovery from an empty history
The Dashboard's empty value chart evaluates the whole-library price setup: it offers a rebuild only when the default route is usable, otherwise it opens the specific Price data or License prerequisite.
Ticker Metadata evaluates one ticker more precisely. A ticker pin takes precedence over the default; cash-like local history and the official TSP feed do not require a market provider; Skip DL routes to the ticker editor; Tiingo without a key routes to Tiingo setup; and Yahoo without personal-use consent routes to the Yahoo consent control. An expired commercial trial routes to License before any of those write actions. These recovery paths never change a source, grant consent, or download more than the action names.
Why downloads are slow on purpose
Yahoo has two lanes, paced differently on purpose.
Profile and metadata fetches run strictly one at a time. Measured against a few thousand real tickers, any concurrency above one trips Yahoo's per-IP rate limiting (HTTP 429) somewhere past roughly 600 requests, and the backoff that follows makes the whole job slower than never having hurried. Going faster was the thing making it slow. That's why a bulk profile fetch shows a steady ticker-by-ticker progress line rather than finishing in one burst.
Price history is fetched in batches of about 25 tickers, downloaded together. The batch size is the progress cadence, not a throttle. It is still a lot of requests: a full rebuild over a thousand-ticker universe takes minutes and can still brush a limit.
Failures are recoverable: a bulk download reports which tickers failed and can retry just those. If one ticker's history is persistently wrong at one source, pin it to the other. If a split looks missing, see manual splits rather than re-downloading in a loop.