4.3 KiB
zfin diagnose
Trace one symbol's candle data through every tier -- local cache, shared server, upstream provider -- and say where the chain breaks.
Usage: zfin diagnose SYMBOL
diagnose answers one question: is the provider behind for this
symbol, or is it us? It is the counterpart to
doctor, and deliberately its opposite on both axes --
doctor checks the whole setup and never touches the network, while
diagnose checks a single symbol and queries every tier including the
provider.
It is read-only: no cache writes, and the provider query does not populate the cache. Safe to run while investigating.
What it reports
Seven lines, in the order the data flows:
| Line | Says |
|---|---|
local |
Newest cached bar, TTL state, which provider sourced it, consecutive failures, any Tiingo backoff |
adj basis |
How current the cached adjusted closes are, against the newest dividend or split that has already gone ex |
peers |
Newest bar held by other cached symbols of the same kind (equity vs mutual fund) |
tracked |
Whether a normal run fetches this symbol, or it is only pulled on demand |
server |
What ZFIN_SERVER offers, whether it is ahead or behind you, and whether it refreshes this symbol |
provider |
What the upstream provider actually has right now |
verdict |
Where the chain breaks, and what to do about it |
Example
zfin diagnose SPY
local newest 2026-08-19, TTL still in the future, tiingo
adj basis 2026-08-17 - current through the newest corporate action (2026-06-18)
peers 23 other equity cached, newest 2026-08-19
tracked on demand - a projections benchmark symbol
server offers 2026-08-19 - same as local, written 2026-08-19, tracked: yes
provider tiingo newest 2026-08-19 (8 bars in the last 10 days)
verdict up to date with everything available
Reading the adj basis line
This is the least obvious line, so it is worth spelling out. Cached price history grows by appending, which cannot retroactively correct the adjusted closes of bars already on disk. When a dividend or split goes ex, those earlier bars need marking down, and until they are, total returns spanning that ex-date read low by roughly the missed yield. See Incremental candle updates.
Three forms:
adj basis 2026-08-17 - current through the newest corporate action (2026-06-18)
adj basis 1970-01-01 - STALE, 2026-06-01 went ex behind it; total returns read low until restated
adj basis 2026-08-19 - no dividends or splits cached, nothing to restate
STALE is not something to act on -- the next refresh re-downloads that
symbol's full history on its own. It explains a total return that looks
slightly low in the meantime.
Two things the date is not: it is not when the restatement ran (it is
the newest bar present at the time, which lags when a session's bar has
not posted yet), and it is not an ex-date. 1970-01-01 means "never
restated", which is what a cache predating the feature reads as.
The compared-against date is the newest ex-date that has already passed. A declared-but-not-yet-ex dividend is deliberately ignored: no provider has applied it either, so waiting on it would refetch forever.
Rate limit caveat
The provider query uses its own rate limiter, separate from the budget
the rest of zfin accounts for -- so it is invisible to that budget. On a
free tier close to its cap, diagnose can be the request that trips it.
One request per invocation.
See also
doctor-- whole-setup health check, no network.cache--stalefinds symbols behind their peers;refreshforces a local re-fetch.server-- force a refresh in the shared server's cache instead.- Caching and data freshness -- the tiers and TTLs.