Objective
If users expect financing-cost-adjusted leverage, add an optional borrow-rate drag model to levered_path_returns and re-derive catalog leverage with an explicit cost column, with an explicit borrow-rate source selection.
Approach
Selected FRED DGS3MO (daily %, 1981-09-01, 1d lag) with TB3MS (monthly %, 1934-01-01, 10d lag) backfill as the public, redistributable borrow-rate proxy via backtest/macro.month_end_yield combine_first and backtest/datastore.read_macro (offline, no DB mutation, no credential). Implemented financing_borrow_rate_by_month() (returns {YYYY-MM: decimal annual}) and apply_financing_drag() ((L-1)*annual/12 with optional spread_bps) in research/levered_path_returns.py; extended compose_substitute_path_returns and path_returns_for_strategy with optional financing/borrow_by_month params (default None preserves identity and existing feasibility windows). Extended research/reports/catalog_leverage.py level_entry_from_path/strategy_leverage_entry/build_catalog_leverage/write_catalog_leverage to compute financing {source, method, annual_drag_bps, mean_borrow_annual, n_months_with_rate, missing_months} and metrics_net (CAGR/Sharpe/Sortino/MaxDD net) per L>1 when financing supplied, keeping gross metrics unchanged and schema catalog-leverage/v1 backward compatible. Regenerated docs/site-data/catalog-leverage.json with financing={'spread_bps':0.0} using live borrow map (1111 months). Updated docs/site-data/README.md payload contract for the financing field.
Files changed
- research/levered_path_returns.py — added BORROW_RATE_SOURCE_ID/METHOD/SERIES_IDS, financing_borrow_rate_by_month, apply_financing_drag, optional financing params to compose and path functions
- research/reports/catalog_leverage.py — added financing import, extended level/strategy/build/write to emit financing/metrics_net per level and top-level financing summary
- docs/site-data/catalog-leverage.json — regenerated with cost disclosure (384KB, top-level financing, per-level annual_drag_bps and metrics_net; e.g., haa-balanced 1.5× gross 12.83% vs net 11.89% drag 84bps)
- docs/site-data/README.md — documented catalog-leverage financing field and FRED source
- research/results/qm-kigo.md — this note
Validation
- python3 -m pytest -q tests/test_levered_path_returns.py tests/test_catalog_leverage.py — 12 passed (default None identity preserved)
- python3 -c financing_borrow_rate_by_month() — 1111 months 1934-01..2026-07, haa-balanced 1.5× mean_borrow 1.688% drag 84bps
- python3 -m research.artifacts check --mode full --offline — shared artifacts deterministic and current
- python3 research/scripts/check_static_reports.py docs — local bundle OK: 1213 files; 178 canary routes
- Verified weighted_meta 2 pre-existing failures (sortino window 56 vs 49) remain via git stash pop, unrelated to this change
Results
Borrow-rate source selected as FRED:DGS3MO+TB3MS (time-varying month-end yield, (L-1)*annual/12 drag). Levered monthly returns optionally net of financing via compose/path financing param; catalog leverage regenerated with explicit cost column (top-level financing disclosure and per-level financing + metrics_net) while preserving gross LETF price-embedded metrics. LETF ER remains embedded in price; explicit margin drag disclosed separately per qm-arn.9. No private data in public docs artifacts; report/read paths remain read-only.