add cross-sectional signal evaluation (factor rank-IC) to the backtest
The per-setup hit-rate report can't tell whether a signal predicts returns — only how a target/stop structure built on one performs. This adds a cross-sectional factor-IC pass: each week the universe is ranked by a price-only signal and graded by its rank correlation (Spearman IC) and top-minus-bottom- quintile spread against the forward 30-day return. Candidate signals (point-in-time from price; sentiment/fundamentals have no history in the replay): 12-1/6-1/3-1 month momentum, 1-month reversal, price-vs-200d SMA, proximity to the 52-week high (George/Hwang), and 126-day realized volatility (low-vol anomaly). Reuses the existing per-ticker replay loop (no new data, no second DB pass); results land in the cached backtest_report as `signal_eval` and render as a "Signal edge" table in BacktestPanel beside the calibration curve. 330 backend tests pass (10 new in test_signal_eval); frontend build clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -224,6 +224,16 @@ export interface BacktestSweepRow extends BacktestBucket {
|
||||
min_expected_value: number;
|
||||
}
|
||||
|
||||
export interface BacktestSignalEvalRow {
|
||||
signal: string;
|
||||
weeks: number;
|
||||
avg_cross_section: number | null;
|
||||
mean_ic: number;
|
||||
ic_t_stat: number | null;
|
||||
ic_positive_pct: number;
|
||||
mean_quintile_spread: number | null;
|
||||
}
|
||||
|
||||
export interface BacktestReport {
|
||||
generated_at: string;
|
||||
tickers: number;
|
||||
@@ -236,6 +246,8 @@ export interface BacktestReport {
|
||||
min_expected_value: number;
|
||||
sweep: BacktestSweepRow[];
|
||||
calibration: BacktestCalibrationRow[];
|
||||
signal_eval?: BacktestSignalEvalRow[];
|
||||
signal_eval_note?: string;
|
||||
note: string;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user