feat(adversarial): flat_too_long_threshold parametrico (CLI ablation)
Estende AdversarialAgent con flat_too_long_threshold (default 0.95) configurabile, simmetrico a fees_eat_alpha_threshold. Propagato a RunConfig.flat_too_long_threshold e flag CLI --flat-too-long-threshold. Motivazione: pop30-combo ha registrato 75 finding flat_too_long HIGH (secondo killer dopo fees_eat_alpha 87). Rilassare la soglia 0.95→0.98 ammette strategie più passive ma marginalmente attive — analogo all'ablation fees già verificata (+23% stabile). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -63,9 +63,11 @@ class AdversarialAgent:
|
||||
self,
|
||||
fees_bp: float = 5.0,
|
||||
fees_eat_alpha_threshold: float = 0.5,
|
||||
flat_too_long_threshold: float = 0.95,
|
||||
) -> None:
|
||||
self._engine = BacktestEngine(fees_bp=fees_bp)
|
||||
self._fees_eat_alpha_threshold = fees_eat_alpha_threshold
|
||||
self._flat_too_long_threshold = flat_too_long_threshold
|
||||
|
||||
def review(self, strategy: Strategy, ohlcv: pd.DataFrame) -> AdversarialReport:
|
||||
signal_fn = compile_strategy(strategy)
|
||||
@@ -133,12 +135,15 @@ class AdversarialAgent:
|
||||
n_active = int(((signals == Side.LONG) | (signals == Side.SHORT)).sum())
|
||||
n_flat_or_nan = n_bars - n_active
|
||||
flat_ratio = n_flat_or_nan / n_bars if n_bars > 0 else 1.0
|
||||
if flat_ratio > 0.95:
|
||||
if flat_ratio > self._flat_too_long_threshold:
|
||||
report.findings.append(
|
||||
Finding(
|
||||
name="flat_too_long",
|
||||
severity=Severity.HIGH,
|
||||
detail=f"Signal flat for {flat_ratio * 100:.1f}% of bars (>95% threshold)",
|
||||
detail=(
|
||||
f"Signal flat for {flat_ratio * 100:.1f}% of bars "
|
||||
f"(>{self._flat_too_long_threshold * 100:.0f}% threshold)"
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user