f/fundlab
Greg Pomerantz 8a9ca25750 Tax-location plan: taxable account vs IRA per fund
fundlab/taxplan.py categorizes the 16-fund shortlist, the 22 N-PORT
cross-checked candidates, and all 250 screened candidates by the
expected CHARACTER of their distributions, given the user's premise
that the current LTCG rate < the post-retirement ordinary rate:

  qualified div + LTCG      -> TAXABLE  (score >= 0.60)
  tax-exempt (munis)        -> TAXABLE
  ordinary / STCG / REIT    -> IRA      (score <= 0.35)
  in between                -> MIXED (pull the 1099-DIV)
  cash                      -> FLEXIBLE

score = estimated share of distributions that are tax-favorable,
from three tiers of ground truth: N-PORT keyword buckets (16), SEC
assetCat/issuerCat buckets (22), sleeve loadings (250), with a
sleeve fallback when the keyword parser left >50% of a book
unclassified, and a manual override for the Leuthold wrappers
(91.7% Leuthold Core ETF, no return history yet).

Key findings:
- shortlist: TAXABLE = ATESX, JLPSX, LAMHX, LCORX, LCRIX (equity);
  IRA = ATRFX, COSIX, CVSIX, PMORX, SVARX, EAGMX/EGRSX;
  MIXED = MBXIX, QSPNX, PMAIX/PMFKX (same fund, two classes)
- cross-checked: 4 munis -> TAXABLE; HMEZX + MERVX are the merger-
  arb trap - equity-looking books whose distributions are mostly
  SHORT-TERM gains -> IRA
- candidates: 109 munis TAXABLE, 127 IRA, 6 equity TAXABLE, 7 MIXED

App: Fund Lab "Tax location" expander. Output:
fundlab/taxplan_results.json. Tests: test_taxplan() (9 checks).
97/32 suites green.
2026-08-27 14:08:15 -04:00
..
nport_cache N-PORT cross-check: verify top candidates' actual holdings 2026-08-27 12:43:17 -04:00
pool Fund Lab: returns-based strategy decomposition for the 16 shortlist funds 2026-08-26 11:59:59 -04:00
__init__.py fundlab: EDGAR investment-objective fetcher + curated fallback 2026-08-25 18:15:48 -04:00
cluster_kmeans.json Factor screen (v2, 35 drivers) + return-driver clusters 2026-08-27 08:35:42 -04:00
cluster_tree.json Factor screen (v2, 35 drivers) + return-driver clusters 2026-08-27 08:35:42 -04:00
cluster.py Factor screen (v2, 35 drivers) + return-driver clusters 2026-08-27 08:35:42 -04:00
dbmine.py Find candidate funds NOT in the DB: exhaustive EDGAR 497-universe pass 2026-08-26 15:22:52 -04:00
decompose_results.json Fund Lab: returns-based strategy decomposition for the 16 shortlist funds 2026-08-26 11:59:59 -04:00
decompose.py Alpha search: mine + screen the local DB for idiosyncratic alpha complements 2026-08-26 13:34:34 -04:00
drawdown_results.json Drawdown-resilience screen: who was positive when equities crashed 2026-08-27 13:29:01 -04:00
drawdown.py Drawdown-resilience screen: who was positive when equities crashed 2026-08-27 13:29:01 -04:00
edgar_universe.py Find candidate funds NOT in the DB: exhaustive EDGAR 497-universe pass 2026-08-26 15:22:52 -04:00
edgar.py fundlab: extract strategy sections from EDGAR docs; --strategy CLI mode 2026-08-25 23:06:13 -04:00
factor_results.json Factor screen (v2, 35 drivers) + return-driver clusters 2026-08-27 08:35:42 -04:00
factors.log Factor screen (v2, 35 drivers) + return-driver clusters 2026-08-27 08:35:42 -04:00
factors.py Factor screen (v2, 35 drivers) + return-driver clusters 2026-08-27 08:35:42 -04:00
fundinfo.py fundlab: extract strategy sections from EDGAR docs; --strategy CLI mode 2026-08-25 23:06:13 -04:00
funds_curated.json fundlab: EDGAR investment-objective fetcher + curated fallback 2026-08-25 18:15:48 -04:00
harvest.py Alpha search: mine + screen the local DB for idiosyncratic alpha complements 2026-08-26 13:34:34 -04:00
nport_manifest.json N-PORT cross-check: verify top candidates' actual holdings 2026-08-27 12:43:17 -04:00
nport.py N-PORT cross-check: verify top candidates' actual holdings 2026-08-27 12:43:17 -04:00
overnight.log Overnight comprehensive screen COMPLETE: 2,384 funds, 250 candidates, RESEARCH.md results + next iterations 2026-08-27 06:56:33 -04:00
overnight.py Watchdog: pidfile liveness (pgrep -f was fooled by shells quoting the pattern); per-batch download fault isolation 2026-08-26 22:09:20 -04:00
pool.py fundlab: EDGAR investment-objective fetcher + curated fallback 2026-08-25 18:15:48 -04:00
RESEARCH.md Tax-location plan: taxable account vs IRA per fund 2026-08-27 14:08:15 -04:00
resolved_tickers.json Alpha search: mine + screen the local DB for idiosyncratic alpha complements 2026-08-26 13:34:34 -04:00
search_all.json Overnight comprehensive screen COMPLETE: 2,384 funds, 250 candidates, RESEARCH.md results + next iterations 2026-08-27 06:56:33 -04:00
search_external.json Find candidate funds NOT in the DB: exhaustive EDGAR 497-universe pass 2026-08-26 15:22:52 -04:00
search_harvest.json Alpha search: mine + screen the local DB for idiosyncratic alpha complements 2026-08-26 13:34:34 -04:00
search_mined.json Alpha search: mine + screen the local DB for idiosyncratic alpha complements 2026-08-26 13:34:34 -04:00
search_results.json Alpha search: mine + screen the local DB for idiosyncratic alpha complements 2026-08-26 13:34:34 -04:00
search.py Alpha search: mine + screen the local DB for idiosyncratic alpha complements 2026-08-26 13:34:34 -04:00
searchlist.py Alpha search: mine + screen the local DB for idiosyncratic alpha complements 2026-08-26 13:34:34 -04:00
taxplan_results.json Tax-location plan: taxable account vs IRA per fund 2026-08-27 14:08:15 -04:00
taxplan.py Tax-location plan: taxable account vs IRA per fund 2026-08-27 14:08:15 -04:00
tickers.py Alpha search: mine + screen the local DB for idiosyncratic alpha complements 2026-08-26 13:34:34 -04:00
watchdog.log Overnight comprehensive screen COMPLETE: 2,384 funds, 250 candidates, RESEARCH.md results + next iterations 2026-08-27 06:56:33 -04:00
watchdog.sh Watchdog: pidfile liveness (pgrep -f was fooled by shells quoting the pattern); per-batch download fault isolation 2026-08-26 22:09:20 -04:00
xcheck_report.json N-PORT cross-check: verify top candidates' actual holdings 2026-08-27 12:43:17 -04:00
xcheck.py N-PORT cross-check: verify top candidates' actual holdings 2026-08-27 12:43:17 -04:00