Compare commits
3
Commits
4135946cb3
...
3df36a9bfb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3df36a9bfb | ||
|
|
98793925ef | ||
|
|
2e083d3bb9 |
@@ -426,8 +426,9 @@ workstream B — Alpaca remains the price source throughout.
|
||||
API values across the tracked universe, report per-field deltas and resulting
|
||||
fundamental-score/ranking changes, require explicit approval. Definition
|
||||
changes (e.g. TTM vs provider convention) called out, not averaged away.
|
||||
The read-only report job and Admin summary/download are implemented; production
|
||||
observation and explicit cutover approval remain pending.
|
||||
**Status 2026-07-24: the gate has been exercised and the evidence supports
|
||||
approval** — see the handoff section below. What remains of A5 is the
|
||||
activation itself: implementing step (c) and flipping it on.
|
||||
- A6. Remove FMP/Finnhub/Alpha Vantage; keep monitoring + manual fallback.
|
||||
|
||||
**Workstream B (independent, start when wanted):**
|
||||
@@ -479,6 +480,47 @@ workstream B — Alpaca remains the price source throughout.
|
||||
- Score-parity diff reviewed and approved before `fundamental_data` cutover.
|
||||
- Scheduled imports never block the API event loop.
|
||||
|
||||
## Handoff — remaining work after the A5 parity investigation (2026-07-24)
|
||||
|
||||
The 2026-07-23 parity report surfaced coverage gaps and wrong values; a nine-pass
|
||||
investigation traced every one to parser/identity bugs (not source data), fixed them,
|
||||
and reparsed production twice. Full evidence trail:
|
||||
`reports/fundamentals-parity-20260723-findings.md` (root causes, decisions, validation)
|
||||
plus the before/after reports (`fundamentals-parity-20260723T…` / `…20260724T….json`).
|
||||
Post-fix: candidate scores 504 of 511 vs legacy's 507 (gap = PSKY/Q new registrants +
|
||||
FITB, all explained); revenue-growth agreement 0.0038 median abs delta where both exist.
|
||||
Dennis reviewed the evidence 2026-07-24 and directed proceeding to cutover.
|
||||
|
||||
**Task 1 — A5 activation (implement step (c) above, ~line 207).** The post-activation
|
||||
local refresh of `fundamental_data` does not exist yet. Per the spec: `pe_ratio` and
|
||||
`market_cap` from newest valid snapshots × latest PostgreSQL close, `revenue_growth`
|
||||
from snapshots, `earnings_surprise`/`next_earnings_date` from `earnings_events`; mark
|
||||
affected cached fundamental scores stale; must run identically when SEC is unreachable.
|
||||
Implementation notes from the parity work: consume `fundamentals_derivation.derive()`
|
||||
outputs, NOT raw snapshot fields — that path carries the split guard (`ttm_diluted_eps`
|
||||
nulls when contaminated, with `ttm_diluted_eps_caveat`) and the multi-class share
|
||||
fallback (`shares_outstanding` + `shares_outstanding_estimated`). Activation should be
|
||||
an explicit switch (SystemSetting, like `sec_cik_overrides`), default off.
|
||||
|
||||
**Task 2 — A6 decommissioning.** After a short observation window: remove
|
||||
FMP/Finnhub/Alpha Vantage providers, config and env keys; keep monitoring + manual
|
||||
fallback. Gated by the acceptance criteria above — especially forward-calendar
|
||||
timeliness from `dolt_earnings` (its `source_max_date` ran ~5 weeks ahead as of
|
||||
2026-07-23, which passes).
|
||||
|
||||
**Known caveats to carry (documented in the findings report, not bugs to fix):**
|
||||
- KLAC-class post-filing splits: P/E wrong until the next 10-Q; undetectable from
|
||||
snapshots. Workstream B's `corporate_actions` table is the natural future fix.
|
||||
- BRK-B: no share count exists anywhere in companyfacts → no market cap, correctly.
|
||||
- FITB: unscored (split guard + no taggable revenue) — the one name that lost its
|
||||
score relative to legacy; composite renormalises.
|
||||
- Share-change guard at 25% nulls P/E for stock-funded M&A too (COF, WAT…);
|
||||
revisit only if the ~3% universe hit-rate proves painful.
|
||||
- `sec_cik_overrides` SystemSetting pins XOM → 34088 (applied in prod); the
|
||||
`no_xbrl_filings` SystemEvent says when a new pin is needed.
|
||||
- After any future parser change, stored rows need `scripts/reparse_fundamentals.py`
|
||||
(dry-run default; `--apply` rewrites) — snapshots are otherwise immutable.
|
||||
|
||||
## Deferred (explicitly, until a concrete need appears)
|
||||
|
||||
- Workstream B itself is deferred relative to A and blocks nothing in A.
|
||||
|
||||
@@ -853,3 +853,73 @@ track the parser's `SnapshotRow`, and only one of them is now enforced by a test
|
||||
|
||||
PSKY and Q need nothing — they are new registrants without enough filing history, which is
|
||||
correct behaviour.
|
||||
|
||||
---
|
||||
|
||||
# Closing — post-reparse verification (2026-07-24)
|
||||
|
||||
## Production reparse
|
||||
|
||||
Two apply runs against prod (`scripts/reparse_fundamentals.py --apply`):
|
||||
|
||||
- **Run 6** (all fixes through the seventh pass): 262 inserted, 28,664 rewritten —
|
||||
99.4% of which was backfilling the new `weighted_avg_diluted_shares` column; the
|
||||
behavioural churn matched the dry run exactly. The five duration facts clustering at
|
||||
190–234 changed rows each is the 4-4-5 Q3 recovery signature. `accepted_at` changed on
|
||||
only 76 rows (0.25%), confirming the tz-comparison fix works against real Postgres.
|
||||
- **Run 7** (after the fiscal-year-end fix below): 3 inserted, 322 rewritten — BEN, DELL,
|
||||
and boundary-year relabels for 53-week filers whose derived MMDD shifted a few days.
|
||||
|
||||
`cik_updates: 1` on run 6 was the XOM pin taking effect; XOM now has 68 snapshot rows,
|
||||
latest period end 2026-03-31.
|
||||
|
||||
## Regression caught by the collision check — and its fix
|
||||
|
||||
The before/after key-collision query (~130 rows max 6 → 44 rows all 2) surfaced one real
|
||||
regression: **BEN**. `submissions.fiscalYearEnd` declares `1231` while every Franklin
|
||||
Resources 10-K ends 09-30, so `_period_identity` — which trusted the declared value — put
|
||||
BEN's real fiscal Q1 zero days from the claimed year end (no band matched) and labelled its
|
||||
fiscal Q2 as Q1. The collision discarded a period and BEN lost TTM EPS and revenue growth it
|
||||
had before the branch. Fixed in `3d42ca7`: `resolve_fiscal_year_end()` prefers the issuer's
|
||||
own most recent 10-K reportDate (which *is* the fiscal year end by definition) and treats
|
||||
the declared field as fallback. Full-universe scan: 2 of 506 issuers mis-declare (BEN 91d,
|
||||
DELL 29d); both now derive correctly (BEN rg 3.8243 vs legacy 3.82; DELL 38.5735 vs 38.57).
|
||||
|
||||
Residual collisions after run 7: 36 rows, all count-2, **latest year 2023** — the 53-week
|
||||
drift class (AVY/CDNS/RVTY/JNJ/TDY/DPZ at 5–6-year intervals). Newest-wins degrades one
|
||||
historical FY row; no current period is affected. Left alone deliberately: eliminating them
|
||||
means modelling each filer's actual 52/53-week calendar per year, for rows feeding no
|
||||
current metric.
|
||||
|
||||
## The verdict: 2026-07-24 parity report vs the 2026-07-23 baseline
|
||||
|
||||
| metric | baseline | after | |
|
||||
|---|---|---|---|
|
||||
| candidate scored | 482 | **504** | legacy scores 507; gap = PSKY, Q (new registrants) + FITB |
|
||||
| revenue_growth candidate available | 442 | **489** | banks, REITs, 4-4-5 recovered |
|
||||
| pe_ratio candidate available | 432 | **452** | net of the split-guard nulls |
|
||||
| revenue_growth median abs delta | 0.0038 | **0.0038** | 47 names added at unchanged agreement |
|
||||
| pe_ratio median / p95 abs delta | 0.5883 / 7.73 | **0.5576 / 6.03** | corrupted outliers gone |
|
||||
|
||||
Revenue `material_differences` rose 84 → 96: the newly compared names include the cases
|
||||
where **legacy is the wrong side** (JPM 108.98% vs 3.34%, PPL −58.81% vs 8.34%, FCX −24.23%
|
||||
vs +5.44%). Material is symmetric; these flag the provider being corrected.
|
||||
|
||||
The split guard is visible in the report: BKNG (1.10), COF, TPL, AMCR, WAT all null P/E now.
|
||||
**KLAC (6.19) is the one known-wrong value left** — the post-filing split documented as
|
||||
unfixable without a corporate-actions source.
|
||||
|
||||
**Correction to the seventh pass:** the claim that guard-tripped issuers "keep their
|
||||
fundamental score, losing one of three inputs" fails for **FITB**, the one name that also
|
||||
lacks revenue growth (its recent filings tag only ASC-606 fee-income fragments, then nothing)
|
||||
— nulling its contaminated P/E (Comerica merger, 661M → 902M shares) drops it to one metric
|
||||
and no score. Accepted: the composite renormalises, and legacy's 58% "revenue growth" for a
|
||||
bank was itself junk.
|
||||
|
||||
## Recommendation
|
||||
|
||||
The A5 gate evidence now supports approving the cutover: coverage within 3 of legacy with
|
||||
every gap explained, agreement essentially exact where both sides exist, every corrupted
|
||||
value either fixed or deliberately nulled with a caveat, and the remaining score deltas are
|
||||
documented definition differences — called out, not averaged away, as the plan requires.
|
||||
Carry KLAC as the one known caveat in the approval note.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user