- fundlab/narrative.py: data-driven English prose per fund (performance,
drivers tiered by fit, explicit 'what we do NOT know', bottom line)
- fundlab/reportdata.py: static build -> reports/report_data.json
- app.py Fund Lab Summary: at-a-glance table + per-fund expanders
(narrative, equity curve, period table with fund-ref gap, drivers,
reference mix, tax, cluster peers)
- fundlab/report.py: narrative in the HTML report; forward-selected
reference (weak-fit funds anchor to cash); SLEEVE_DESC exposure
explanations
- BUG: mix_series() never applied the betas (reference curves were raw
sleeve sums; JLPSX 'reference' +407% vs fund +123%) - fixed and all
reference curves/tables regenerated
- reports/fund_report.html + report_data.json regenerated
fundlab/report.py -> reports/fund_report.html (20 MB, plotly inlined,
opens offline). Per fund: max-history equity curve (fund vs fitted
reference vs IVV); performance table (full/5y/1y, the 5 market
episodes, calendar years) with the fund-minus-reference period-alpha
column; drivers (reference-model R²/alpha/t + 34-sleeve signature +
curated decomposition verdict and N-PORT cross-check notes); the
reference mix explained sleeve-by-sleeve (what each exposure actually
is, plus net-cash/net-levered read); tax character + taxable/IRA
placement; and a peer table of the 4 best funds in the same k=30
return-driver cluster with computed advantages/disadvantages.
Weak-fit (R²<0.5) funds anchor their tables to CASH rather than the
statistically-thin forward-selected mix (which can be an offsetting
VIX/duration spec combination whose path is meaningless); the loadings
are still shown with a 'weak fit' caveat.