diff --git a/scripts/run_phase1.py b/scripts/run_phase1.py index 6e399d8..17c1d48 100644 --- a/scripts/run_phase1.py +++ b/scripts/run_phase1.py @@ -43,6 +43,12 @@ def parse_args() -> argparse.Namespace: default=0.5, help="Adversarial gate: kill se fees/gross_pnl > soglia (default 0.5, ablation 0.7)", ) + p.add_argument( + "--flat-too-long-threshold", + type=float, + default=0.95, + help="Adversarial gate: kill se signal flat > soglia delle bar (default 0.95, ablation 0.98)", + ) return p.parse_args() @@ -98,6 +104,7 @@ def main() -> None: db_path=settings.db_path, prompt_mutation_weight=args.prompt_mutation_weight, fees_eat_alpha_threshold=args.fees_eat_alpha_threshold, + flat_too_long_threshold=args.flat_too_long_threshold, ) run_id = run_phase1(cfg, ohlcv=ohlcv, llm=llm) diff --git a/src/multi_swarm/agents/adversarial.py b/src/multi_swarm/agents/adversarial.py index 0237585..a585b99 100644 --- a/src/multi_swarm/agents/adversarial.py +++ b/src/multi_swarm/agents/adversarial.py @@ -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)" + ), ) ) diff --git a/src/multi_swarm/orchestrator/run.py b/src/multi_swarm/orchestrator/run.py index c6afca2..66ee388 100644 --- a/src/multi_swarm/orchestrator/run.py +++ b/src/multi_swarm/orchestrator/run.py @@ -51,6 +51,7 @@ class RunConfig: db_path: Path = field(default_factory=lambda: Path("./runs.db")) prompt_mutation_weight: float = 0.0 # Phase 2.5: opt-in LLM mutator fees_eat_alpha_threshold: float = 0.5 # adversarial gate, allenta verso 0.7-0.8 + flat_too_long_threshold: float = 0.95 # adversarial gate, allenta verso 0.98-0.99 def run_phase1( @@ -82,6 +83,7 @@ def run_phase1( adversarial_agent = AdversarialAgent( fees_bp=cfg.fees_bp, fees_eat_alpha_threshold=cfg.fees_eat_alpha_threshold, + flat_too_long_threshold=cfg.flat_too_long_threshold, ) cost_tracker = CostTracker()