Spaces:
Running
Running
Sync from GitHub (tests passed)
Browse files
screener/feature_screener/orchestrator.py
CHANGED
|
@@ -467,7 +467,7 @@ class FeatureScreener:
|
|
| 467 |
return {"selected": [], "limits_applied": {}}
|
| 468 |
|
| 469 |
# Selection rules version (increment when limits/logic changes)
|
| 470 |
-
SELECTION_RULES_VERSION = "3.
|
| 471 |
|
| 472 |
# Global cap - hard limit on total selected
|
| 473 |
MAX_SELECTED_TOTAL = 20
|
|
@@ -476,7 +476,8 @@ class FeatureScreener:
|
|
| 476 |
oos_quality_gates = {
|
| 477 |
"min_oos_n_obs": 52, # ~1 year of weekly data
|
| 478 |
"min_oos_abs_pearson": 0.30, # abs() to include negative correlations
|
| 479 |
-
"max_oos_rolling_std": 0.25
|
|
|
|
| 480 |
}
|
| 481 |
|
| 482 |
# Category limits - WHITELIST approach (default=0)
|
|
@@ -512,6 +513,7 @@ class FeatureScreener:
|
|
| 512 |
"oos_n_obs_too_low": 0,
|
| 513 |
"oos_abs_pearson_too_low": 0,
|
| 514 |
"oos_rolling_std_too_high": 0,
|
|
|
|
| 515 |
"oos_metrics_missing": 0,
|
| 516 |
"category_not_whitelisted": 0,
|
| 517 |
"category_limit_reached": 0,
|
|
@@ -541,6 +543,13 @@ class FeatureScreener:
|
|
| 541 |
excluded_reasons["oos_rolling_std_too_high"] += 1
|
| 542 |
continue
|
| 543 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 544 |
quality_passed.append(candidate)
|
| 545 |
|
| 546 |
# Step 2: Apply category limits (whitelist) + global cap
|
|
|
|
| 467 |
return {"selected": [], "limits_applied": {}}
|
| 468 |
|
| 469 |
# Selection rules version (increment when limits/logic changes)
|
| 470 |
+
SELECTION_RULES_VERSION = "3.1.0" # v3.1: + target redundancy filter
|
| 471 |
|
| 472 |
# Global cap - hard limit on total selected
|
| 473 |
MAX_SELECTED_TOTAL = 20
|
|
|
|
| 476 |
oos_quality_gates = {
|
| 477 |
"min_oos_n_obs": 52, # ~1 year of weekly data
|
| 478 |
"min_oos_abs_pearson": 0.30, # abs() to include negative correlations
|
| 479 |
+
"max_oos_rolling_std": 0.25, # stability requirement
|
| 480 |
+
"max_target_corr": 0.95 # exclude target copies (only at lag=0)
|
| 481 |
}
|
| 482 |
|
| 483 |
# Category limits - WHITELIST approach (default=0)
|
|
|
|
| 513 |
"oos_n_obs_too_low": 0,
|
| 514 |
"oos_abs_pearson_too_low": 0,
|
| 515 |
"oos_rolling_std_too_high": 0,
|
| 516 |
+
"oos_target_redundant": 0, # high corr + lag=0 = target copy
|
| 517 |
"oos_metrics_missing": 0,
|
| 518 |
"category_not_whitelisted": 0,
|
| 519 |
"category_limit_reached": 0,
|
|
|
|
| 543 |
excluded_reasons["oos_rolling_std_too_high"] += 1
|
| 544 |
continue
|
| 545 |
|
| 546 |
+
# Gate 4: Target redundancy filter (only for contemporaneous, lag=0)
|
| 547 |
+
# High correlation AT LAG=0 means "target copy", not "leading signal"
|
| 548 |
+
frozen_lag = oos.frozen_lag if oos.frozen_lag is not None else candidate.is_metrics.best_lead_lag
|
| 549 |
+
if frozen_lag == 0 and abs(oos.pearson) > oos_quality_gates["max_target_corr"]:
|
| 550 |
+
excluded_reasons["oos_target_redundant"] += 1
|
| 551 |
+
continue
|
| 552 |
+
|
| 553 |
quality_passed.append(candidate)
|
| 554 |
|
| 555 |
# Step 2: Apply category limits (whitelist) + global cap
|