Skip to content

fix(holdings): accept only a name and weight table as product-page top holdings - #82

Merged
daggerok merged 1 commit into
mainfrom
fix/top-holdings-allocation-table
Oct 25, 2026
Merged

daggerok merged 1 commit into
mainfrom
fix/top-holdings-allocation-table

Conversation

@daggerok

Copy link
Copy Markdown
Owner

What changed

  • parseTopHoldingsMarkdown (product-page top holdings fallback) reads only the ### Holdings section up to the next heading of level 1-3, and only a table whose header is Name plus a weight column (Weight (%)). Any other table (the long/short funds' Group | Long | Short | Group Weight allocation summary) gives no rows
  • A parsed list whose weights add up to more than 105 gives no rows (a top-N list covers at most the whole fund) unless the ticker is in TOP_HOLDINGS_LEVERAGED, which stays empty: WSLS and WTAL publish no holdings list at all, so nothing needs the override
  • No rows -> the next source or the published sheet applies exactly as before; the reason is logged in verbose mode. The holdings guard from fix(holdings): reject broken fresh holdings with the shared holdings guard #81 still checks fresh holdings at the write step; this parser check does not duplicate its code

Why

WSLS (Efficient Long/Short U.S. Smallcap) and WTAL (Global Alpha) published their allocation table as holdings: 34 and 57 rows like "Group" 0, "Cash&Collateral" 100, "Equities" 100.72, sectors, "Equity Futures" 90, summing to 581.43 and 599.68. The old parser matched ### Holdings Summary, skipped only a Name header row and took the second column (Long) of any table

Evidence

  • Product pages fetched read-only through r.jina.ai on 2026-10-24: WSLS and WTAL show only ### Holdings Summary with | Group | Long | Short | Group Weight | (Equities long 100.72% short -88.06%, Equity Futures 90%); WSPC shows ### Holdings / | Name | Weight (%) | top 10 plus Remaining Portfolio, then ### Sector Breakdown (also Name/Weight, must not be read)
  • SEC EDGAR: series S000109280 (WSLS) and S000109282 (WTAL) have no NPORT-P filing yet (both funds started 10/8/2026), so no real holdings exist to check a leveraged override against
  • New parser on those pages: WSLS 0 rows and WTAL 0 rows (rejected: no Name and weight table), WSPC 10 rows summing 46.46, as of 2026-10-22, sector table not included

After this PR

WSLS and WTAL keep their published allocation rows: the parser gives nothing, so the updater re-uses the published sheet (not checked by the guard, which only checks fresh holdings) and refreshes everything else. They change only when an N-PORT filing appears or the published sheet is removed (owner decision, not done here)

Checks run

  • bun test: 53 pass, 0 fail (rc 0); same with the config values exported as env: 53 pass (rc 0)
  • New parsing test (WSPC-like list stopping at the next heading, WSLS-like allocation summary, a list summing 191.4, no holdings section) and pipeline test (a published Name/Weight list, then an allocation summary: holdings stay as published, returns refresh, exit code 0). With the origin/main parser both tests fail (checked once)
  • bun build --target=bun scripts/update-data.ts --outfile=/dev/null: rc 0; git diff --check: clean
  • tc/check.sh: esnext 0, ide 67 error lines (same as origin/main)

…p holdings

The product-page fallback parsed the Holdings Summary allocation table of the long/short funds (Group, Long, Short, Group Weight) as holdings. Only a Name plus weight table inside the Holdings section counts now, the section ends at the next heading, and a list whose weights add up to more than 105 is rejected unless the fund is in TOP_HOLDINGS_LEVERAGED (empty).
@daggerok
daggerok merged commit 5902e6b into main Oct 25, 2026
1 check passed
@daggerok
daggerok deleted the fix/top-holdings-allocation-table branch October 25, 2026 03:53
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