Commit Graph

5 Commits

Author SHA1 Message Date
e20b2e30cb Double-listing: layout-agnostic invariants, whole-dump sweep, bulk corrections
Yahoo changed the shape of its event feed between downloads: a 2026-08
re-download of CVIX/JLPSX shows it no longer returns capitalGain events at
all (the dividend stream still carries the year-end rows), while stale
tickers now return no events at all. File-specific remove ops therefore
break silently on the next re-download, so the double-listing fix is now
expressed as layout-agnostic invariants applied at bundle assembly
(idempotent, hold for full and incremental builds):

  dedup: [[date, amount]]      keep at most one copy of a same-date/
      same-amount cross-file pair (the capitalGain copy when both present)
  drop_capg_copy: [date]       the capitalGain row on that date is the
      spurious copy of the dividend row

- data.py: apply_invariants() at bundle assembly + pure dedupe_event_rows()
  shared with verify_official and tests (8 new test cases, 22 passing)
- JLPSX/CVSIX corrections rewritten with the invariants (2019-08-08 now
  keeps the dividend amount per the verified same-date pattern)
- scripts/scan_double_listing.py: whole-dump sweep -> reports/double_listing/
  6,421 symbols scanned: 1,218 with same-amount pairs (6,589), 1,631 with
  differing-amount pairs (12,366, reported only - not distinguishable from
  legitimate same-day div+capg without per-fund official data), 83 with
  repeated within-file rows (ingest keep-last already collapses them)
- scripts/apply_dedup_corrections.py: bulk 'dedup' corrections for the
  1,218 same-amount symbols (1,212 new files; the 6 verified funds keep
  their explicit, official-verified corrections)
- scripts/check_corrections.py: integrity check for every correction op
  against the actual (frozen) files - caught a mis-filed CVSIX entry
2026-08-31 21:00:36 -04:00
e15cb51390 Corrections: resolve the 7 stale mismatches via the Yahoo double-listing pattern
Scanning the verified funds for same-date div/capg pairs showed the Yahoo
double-listing mechanism in every one of the 7 'mismatch' stale funds, and
the official fiscal-year totals pin down which amount is true:

- identical-amount pairs (JLPSX, GDEUX, GSOUX, FAEVX, CVSIX, FZAGX): the
  year-end distribution is in both files; keep the capitalGain copy,
  remove the dividend copy (GDEUX: FY2021-08 1.73 = 1.625+0.115 and
  FY2022-08 0.39 = 0.348+0.036 after; JLPSX/GSOUX/FAEVX/CVSIX same)
- differing-amount pairs (OTCRX, SHXIX, FZAGX, FGIZX, CVSIX): the
  dividend-file amount is the true one in every officially-verified case
  (OTCRX FY2023 0.85 = 0.852488, SHXIX FY2023 1.01 = 1.0078, FZAGX all
  four FYs exact); the capitalGain row is the spurious copy

After corrections GDEUX/SHXIX/CVSIX/JLPSX verify 'ok' against their
filings. The same pattern is extended to these funds' pre-2021 history
(marked mechanism-inferred in the correction notes). Remaining residuals:
FAEVX and FGIZX are also missing regular quarterly dividend rows in the
Yahoo dump (official FY totals exceed local even after dedup) - needs the
funds' per-date distribution archives; FIKAX's official extraction is
ambiguous (systematic ~0.12/yr offset = wrong class table in the
500-fund consolidated Fidelity N-CSRS).
2026-08-31 19:50:18 -04:00
1f5720d7db verify_official: 497/497K forms, per-share layout, candidate re-ranking
- EFTS queries now include 497/497K (many fund families publish their
  per-fund highlights there, not in the consolidated N-CSR) and re-rank
  hits by registrant name match (ticker/brand words), newest first,
  capped at 2 filings per CIK
- new parse_per_share_blocks for the JPMorgan-style 'Per share operating
  performance' table (per-class value blocks; dashes = zero)
- parse_highlights now tolerates row labels split across table cells
  (modernized N-CSRS format, e.g. Calamos 2026)
- region finders: word-flexible name patterns (US vs U.S., class letters),
  self-validating per-share regions (a candidate block must match the
  local series, so a name mention in notes doesn't attribute another
  fund's tables in a combined 58 MB report)
- main() keeps the best result across candidate filings (N-CSRS vs 497
  can round differently) and stops early on 'ok'
- local_series applies the corrections overlay so corrected funds verify
  against their filing

Results: JLPSX and CVSIX now 'ok' (all bounded fiscal years agree with
the official filings); CVSIX also gets a 2023-12-21 0.510 capital-gain
correction. bnd/pmaix still ok (no regression).
2026-08-31 18:10:39 -04:00
9263283995 Corrections overlay: per-symbol distribution fixes survive re-downloads
overrides/corrections/{SYM}.json (git-tracked, with as_of/source/note)
holds remove/replace/add ops on the dividend and capital-gain series.
data.py applies them on top of whatever the data root (or the frozen
snapshot) provides, in both the full build and the incremental refresh
path, and the corrections dir joins the cache manifest so a change
invalidates the cache. A goget re-download of the base CSV can never
clobber a confirmed correction. Format and usage documented in data.py.
2026-08-31 14:49:39 -04:00
02aa750a06 Freeze stale (Yahoo-empty) tickers: snapshot final series in overrides/frozen/
230 tickers whose Yahoo chart responses now come back without a timestamp
array (terminated/merged funds): goget overwrites the .json on every pass
while ohlc.Conv skips the write, leaving the old CSVs as the last known
series. Snapshot them into overrides/frozen/ (git-tracked, audited in
reports/stale-funds.md) and make data.py prefer the frozen copies and
ignore any future data-root rewrite/delete for those symbols, so the
final series survives future goget runs. The cache manifest now covers
the overrides dir too; incremental refresh skips data-root files of
frozen symbols.
2026-08-31 13:23:24 -04:00