From 846c68d2f5e8a5e666cbd1c1c10b626b1454299e Mon Sep 17 00:00:00 2001 From: AdrianoDev Date: Sat, 9 May 2026 20:37:38 +0200 Subject: [PATCH] feat(scripts): Phase 1 runner CLI entry point Aggiunge scripts/run_phase1.py come entry point CLI per eseguire un run end-to-end di Phase 1 con parametri configurabili via argparse (popolazione, generazioni, simbolo, finestra temporale, fees, seed). Aggiunge marker py.typed al package multi_swarm per esporre i tipi a consumatori esterni (scripts/) sotto mypy --strict. Co-Authored-By: Claude Opus 4.7 (1M context) --- scripts/__init__.py | 0 scripts/run_phase1.py | 74 ++++++++++++++++++++++++++++++++++++++++ src/multi_swarm/py.typed | 0 3 files changed, 74 insertions(+) create mode 100644 scripts/__init__.py create mode 100644 scripts/run_phase1.py create mode 100644 src/multi_swarm/py.typed diff --git a/scripts/__init__.py b/scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scripts/run_phase1.py b/scripts/run_phase1.py new file mode 100644 index 0000000..2e65c8b --- /dev/null +++ b/scripts/run_phase1.py @@ -0,0 +1,74 @@ +from __future__ import annotations + +import argparse +from datetime import datetime + +from multi_swarm.config import load_settings +from multi_swarm.data.ohlcv_loader import OHLCVLoader, OHLCVRequest +from multi_swarm.genome.hypothesis import ModelTier +from multi_swarm.llm.client import LLMClient +from multi_swarm.orchestrator.run import RunConfig, run_phase1 + + +def parse_args() -> argparse.Namespace: + p = argparse.ArgumentParser(description="Multi-Swarm Phase 1 runner") + p.add_argument("--name", default="phase1-spike-001") + p.add_argument("--population-size", type=int, default=20) + p.add_argument("--n-generations", type=int, default=10) + p.add_argument("--elite-k", type=int, default=2) + p.add_argument("--tournament-k", type=int, default=3) + p.add_argument("--p-crossover", type=float, default=0.5) + p.add_argument("--seed", type=int, default=42) + p.add_argument("--symbol", default="BTC/USDT") + p.add_argument("--timeframe", default="1h") + p.add_argument("--start", default="2024-01-01T00:00:00+00:00") + p.add_argument("--end", default="2026-01-01T00:00:00+00:00") + p.add_argument("--fees-bp", type=float, default=5.0) + p.add_argument("--n-trials-dsr", type=int, default=50) + return p.parse_args() + + +def main() -> None: + args = parse_args() + settings = load_settings() + + loader = OHLCVLoader(cache_dir=settings.series_dir) + req = OHLCVRequest( + symbol=args.symbol, + timeframe=args.timeframe, + start=datetime.fromisoformat(args.start), + end=datetime.fromisoformat(args.end), + ) + ohlcv = loader.load(req) + print(f"OHLCV loaded: {len(ohlcv)} bars from {ohlcv.index[0]} to {ohlcv.index[-1]}") + + llm = LLMClient( + openrouter_api_key=settings.openrouter_api_key.get_secret_value(), + anthropic_api_key=( + settings.anthropic_api_key.get_secret_value() + if settings.anthropic_api_key else None + ), + ) + + cfg = RunConfig( + run_name=args.name, + population_size=args.population_size, + n_generations=args.n_generations, + elite_k=args.elite_k, + tournament_k=args.tournament_k, + p_crossover=args.p_crossover, + seed=args.seed, + model_tier=ModelTier.C, + symbol=args.symbol, + timeframe=args.timeframe, + fees_bp=args.fees_bp, + n_trials_dsr=args.n_trials_dsr, + db_path=settings.db_path, + ) + + run_id = run_phase1(cfg, ohlcv=ohlcv, llm=llm) + print(f"Run completed: {run_id}") + + +if __name__ == "__main__": + main() diff --git a/src/multi_swarm/py.typed b/src/multi_swarm/py.typed new file mode 100644 index 0000000..e69de29