P0-B (registry is the single source of truth for scoring): - FACTORS now carries center/span normalization spec; unused hand-written per-theme surprise blocks in dashboard.py replaced by one registry-driven compute_theme_surprises() (themes.py). - THEMES['banks'] adds bank_npl weight so NPL is genuinely blended. - factor_value/normalize hardened against NaN/inf (finite guards). - Board re-ranks (TRUE/GULF up, TOP->3) per registry weights; 3 new tests incl. 'changing a registry weight changes output'. P3 (point-in-time backtest): - run_backtest is now a real multi-rebalance engine (reallocates every window, reconciles holdings, marks to market) instead of allocate-once+break. - Added leakage_guard (False unless a PIT score_fn is supplied), planned vs actual rebalances, and momentum_at() true 12-1 (skips last month, PIT). P4 (factor-weight learning): - weight_learning.py: cross-sectional Spearman IC, forward-return builder, IC aggregation + t-stat, and apply_weight_update (new = clip(old*(1+shrink*IC))). - GET /api/v1/learning/momentum endpoint. Live result: momentum IC=0.012 t=0.132 over 22 periods -> momentum has no reliable predictive power here. Macro/demographic factors blocked (no historical factor vintages yet). Two independent review gates passed (deleg_fe6f45cd, deleg_718218f8): empty security/logic arrays; their non-blocking suggestions applied (finite guards, dedupe leakage_guard resolution). 226 tests pass; Vite build passes.
3.3 KiB
3.3 KiB