Playbook › Playbook
A partially-empty vendor snapshot is not missing data — pull the statements before calling a name unscorable
Claim
An empty field in a vendor snapshot means that endpoint failed, not that the data does not exist. Check the other endpoints before declaring a position unscorable or escalating to a paid tier.
What happened
FISV returned a snapshot with Price, PE(ttm), PE(fwd), P/B, 52wHigh/Low,
Target(mean) and Recommendation populated — and 26 fields blank: sector, industry,
country, employees, EV, EV/EBITDA, EV/Rev, P/S, EPS(ttm), Beta, DivYield%, PayoutRatio,
5yAvgDivYield%, all four margins, ROE, ROA, RevGrowth, EarnGrowth, D/E, CurrentRatio, Float,
Insider%, Inst%, ShortFloat%.
Because the partial payload looked like a broken ticker rather than a broken endpoint, three
monthly reports (Jul 9, Aug 10, Sep 22 baseline) carried the position with a score carried
forward rather than computed, and the Aug 10 report escalated it to an action item:
"/health FISV via roic.ai (Tier 2), not Yahoo."
Pulling the full statements showed income statement, balance sheet and cash flow all complete. FISV scored immediately on real data: FCF $4.30B, 20.3% FCF margin, D/A 36.3%, share count 630M → 534M. No Tier-2 escalation was needed, and the paid call would have bought nothing the free one already had.
Why it persisted three cycles
The batch path for a portfolio sweep is fin.py --quote — correct by default, because 58 full
statement pulls is the wrong cost for a monthly scan. But --quote is the only thing that
was ever run on the flagged name, so the flag regenerated itself every month. The escalation
ladder in CLAUDE.md was followed as written (Tier 0 → Tier 2); what was skipped was the
cheaper Tier-0 call sitting next to the one that failed.
The ETF/crypto variant — same root, larger blast radius
fin.py --quote returns no Price at all for ETFs and crypto: QQQ, SCHD and BTC-USD all
came back blank. The snapshot price comes from a quoteSummary key that funds and crypto do
not populate. In a portfolio sweep this silently understated the book by 20.6% — the
positions still appear, valued at $0, and the total is simply wrong rather than obviously wrong.
Fix: read those from get_historical_stock_prices (Yahoo MCP) and patch them in. A total that
does not move when a 16% position moves is the tell.
The rule
- A blank field is a failed endpoint, not an absent fact.
- Before writing "unscored", "data unavailable", or escalating a tier: run the full
fin.py TICKERonce on that single name. It costs one call. - In any portfolio-wide
--quotesweep, assert that every position has a non-null price before computing a total. ETFs and crypto will fail this assertion by construction. - A flag that regenerates identically every cycle is evidence about the method, not about the ticker. Related: [[pitfall-kb-find-never-searched-the-reports]], where a repeated finding also turned out to be tooling rather than substance.
Related
Distinct from [[principle-primary-source-beats-vendor]], which governs the case where the vendor returns a number and the number is wrong. This note covers the case where the vendor returns nothing and the nothing is mistaken for a fact about the company. Both were live on the same 2026-09-22 run — INTC for the first (Yahoo reported +$4.87B in August and −$4.95B in September for the same fiscal year, against a filed −$8.4B), FISV for the second.
What would falsify this
A name where the statements are genuinely empty and the snapshot is partial, making the extra call wasted. That is fine — it is one call, and it converts "unknown" into "confirmed unavailable", which is a different and more useful state.
History
- 2026-07-09 — FISV snapshot first returns a partial payload; score carried forward.
- 2026-08-10 — second consecutive occurrence; recorded as "reproducible, not noise" and escalated to a roic.ai action item. Diagnosis was the ticker or the vendor as a whole.
- 2026-09-22 — third occurrence; statements pulled for the first time and found complete.
Flag closed, diagnosis corrected, note written.
FIalso tested as an alternate symbol and returned a Yahoo 404 — the ticker was never the problem.