Skip to content

fix(holdings): keep junk sheets and non-numeric weights out of the feed - #84

Merged
daggerok merged 1 commit into
mainfrom
fix/holdings-guard-gaps
Oct 26, 2026
Merged

daggerok merged 1 commit into
mainfrom
fix/holdings-guard-gaps

Conversation

@daggerok

Copy link
Copy Markdown
Owner

What

  • Q4: parseTopHoldingsMarkdown turns a weight that is no number into an empty cell instead of "0", so holdingsGuard's numeric check can reject a broken product-page list
  • Q5: when no fresh holdings source applies, the updater re-reads the published sheet as before, but first runs the guard over it on its own (the fund's HOLDINGS_GUARD_RELAX, no row-count check). A sheet that fails is junk: it is not republished, the fund gets totalRows: 0 with the default source not available from current public SEC filing, the stale page file is removed, and the run prints [ holdings ] <T>: published holdings dropped (...). A later N-PORT filing or a real Name + weight list on the product page fills it again
  • Data: the WSLS and WTAL cleanup produced by the updater itself (TICKERS=WSLS,WTAL): funds/{WSLS,WTAL}/holdings/001.json deleted, holdings and source.holdingsSource in their meta.json reset, index rows holdings: 0, counts 39,334 -> 39,243 holdings rows. Nothing else in the feed changed

Why

open-items etfs Q4 and Q5, owner decisions 2026-10-25. WSLS and WTAL (launched 2026-10-08, series S000109280 and S000109282, no N-PORT yet) still published the allocation summary the old parser read as holdings (weights add up to 581.43 and 599.68); WT-1 (#82) stopped new junk but kept republishing the old sheet

Evidence that only these two are affected: running the guard over every published sheet (96 funds) rejects exactly WSLS and WTAL; BTCW (1 row) and WSPC (top 10, relaxed sum) pass. A valid published list is still kept when the page turns into an allocation summary (existing test unchanged)

Checks

  • bun test: 53 pass, 0 fail, exit 0; with the old update-data.ts 2 fail (the empty-weight parsing case and the junk-sheet pipeline case)
  • bun build --target=bun scripts/update-data.ts --outfile=/dev/null and bun build --target=bun src/main.tsx --outfile=/dev/null: exit 0
  • TICKERS=WSLS,WTAL REQUEST_SLEEP=0 bun scripts/update-data.ts: 2 updated, 0 failed with the two dropped lines (committed); a second run over WSPC,BTCW,WSLS,WTAL: WSLS and WTAL unchanged, WSPC and BTCW pass the guard, 0 failed (their refreshed data discarded)
  • .claude/tools/etfs/tc/check.sh: 64 lines before and after, same set (pre-existing [ide] errors), none added
  • git diff --check: clean

Not changed here: parseNport still writes "0" for a missing pctVal/valUSD; that belongs to the shared N-PORT reader work (ETF-H2)

- product-page top holdings: a weight that is no number stays empty, never
  "0", so the holdings guard's numeric check can fire (open-items etfs Q4)
- a published sheet that fails the guard on its own is not republished:
  WSLS and WTAL lose their allocation tables (weight sums 581 and 600) and
  the product-page source label until a valid source exists (Q5)
@daggerok
daggerok merged commit 53e4ca3 into main Oct 26, 2026
1 check passed
@daggerok
daggerok deleted the fix/holdings-guard-gaps branch October 26, 2026 03:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant