Commit Graph

3 Commits

Author SHA1 Message Date
7b27920a77 fundlab: extract strategy sections from EDGAR docs; --strategy CLI mode
- extract_strategy(): finds the 'Principal Investment Strategies' /
  'main investment strategies' section, scores candidates (strategy prose
  +3, Q&A heading +2, TOC -5, risk subheading -5, stop-heading -2),
  truncates at the next section heading; falls back to the prose after
  the objective sentence when no heading exists
- fundinfo --strategy [--refresh]: populates the strategy field of
  funds.json from each fund's EDGAR document
- funds.json now carries objective + strategy for 20 funds (the 9
  curated index funds have no strategy: their objective is the strategy)
2026-08-25 23:06:13 -04:00
5c6d95a8b4 fundlab: actively-managed fund support (16/16 tickers)
- ticker -> CIK scoped FTS (ciks filter) over the fund's own registrant,
  word queries shed Yahoo abbreviations shortest-first
- fuzzy cover gate (SequenceMatcher, sliding window for wrapped names)
  + abbreviation table (Mgd/Glbl/Macr/Abs/Ret/Advtg/...) applied to both
  sides of the match
- family-section matching inside multi-fund filings; similarity tiers:
  gate (0.85) returns immediately, floor (0.70) is a CIK-scoped fallback
  ranked against sibling funds' documents (best sim, then newest)
- objective phrasings: 'seeks to ...', 'seeks investment results ...',
  'The Fund's investment objective is ...', '(the Fund) investment
  objective is ...' (boilerplate 'is not fundamental' rejected); TOC
  headings skipped by trying all heads
- sec_get retries on mid-stream connection drops
2026-08-25 22:10:02 -04:00
e9f8dfc462 fundlab: EDGAR investment-objective fetcher + curated fallback
- edgar.py: SEC FTS + submissions API; strict cover-gate extraction
  (name in title position or (TICKER) on the cover; underlying-reference
  names like leveraged wrappers rejected); 4-pass fetch (ticker->CIK
  filings, name search, annual reports, ticker search); keyword category
  classifier. Returns None rather than a wrong fund's objective.
- fundinfo.py CLI: curated -> cached -> EDGAR resolution into funds.json
- funds_curated.json: human-verified objectives for 13 benchmark-pool
  funds (iShares/Vanguard family-trust classes the scraper can't reach)
- tests: 26 checks incl. live EDGAR fetch of VTSAX
2026-08-25 18:15:48 -04:00