""" run_game — carica le 100 strategie proposte dagli agenti ciechi (file in data/games/specs/agent_*.json), lancia il torneo (epoche + cull) e stampa la classifica finale, poi RIVELA cosa erano X e Y. Se mancano agenti (file assenti o malformati) riempie con spec casuali, cosi' il gioco gira sempre a 100 concorrenti. """ from __future__ import annotations import json import os import random from pathlib import Path from scripts.games import engine from scripts.games import arena from scripts.games.arena import random_spec, run_tournament, leaderboard, _normalize SPECS_DIR = Path(os.environ.get("GAME_SPECS_DIR", "data/games/specs")) OUT_NAME = os.environ.get("GAME_OUT", "tournament_result.json") N = 100 def load_specs(): rng = random.Random(123) specs, briefs, sources = [], [], [] for i in range(N): f = SPECS_DIR / f"agent_{i}.json" spec = None if f.exists(): try: raw = json.loads(f.read_text()) fam = raw.get("family") params = dict(raw.get("params", {})) if "direction" in raw and "direction" not in params: params["direction"] = raw["direction"] spec = {"family": fam, "series": raw.get("series", "A"), "tf": raw.get("tf", "1h"), "params": params} # X->A, Y->B mapping (gli agenti vedono X/Y) s = spec["series"] spec["series"] = {"X": "A", "Y": "B", "AB": "AB", "A": "A", "B": "B"}.get(s, "A") spec = _normalize(spec) briefs.append(str(raw.get("hypothesis", ""))[:300]) sources.append("agent") except Exception as e: spec = None if spec is None: spec = random_spec(rng) briefs.append("(spec mancante -> sostituto casuale)") sources.append("random") specs.append(spec) n_agent = sources.count("agent") print(f"caricati {n_agent}/{N} spec da agenti reali, " f"{N - n_agent} sostituiti casuali") return specs, briefs def main(): slip = float(os.environ.get("GAME_SLIP", "0.0")) engine.set_slippage(slip) if os.environ.get("GAME_NO_LIVE") == "1": arena.set_no_live(True) print("VINCOLO: solo strategie NON in live (no pairs, no zscore/breakout-reversion)") if slip > 0: print(f"SLIPPAGE attivo: {slip*100:.3f}%/lato " f"(single-leg {2*slip*100:.2f}% RT extra, pairs {4*slip*100:.2f}% extra)") specs, briefs = load_specs() payload = run_tournament(specs, briefs=briefs, seed=2026, epochs=90, cull_every=10, cull_n=10, out_name=OUT_NAME) leaderboard(payload, top=10) rev = payload["reveal"] print(f"\n>>> RIVELAZIONE: Serie X = {rev['A']}, Serie Y = {rev['B']} " f"(timeframe base {rev['tf']}). Gli agenti non lo sapevano. <<<") # vincitore w = payload["results"][0] sp = w["spec"] print(f"\nVINCITORE: agente #{w['agent']} su {w['tf']} | {sp['family']} " f"{sp['series']} {sp['params'].get('direction','')}") print(f" ipotesi dell'agente: {w['brief']}") print(f" TEST(OOS): PnL {w['test']['pnl_pct']:.0f}% | win " f"{w['test']['win_rate']*100:.0f}% | {w['test']['tpm']:.1f} trade/mese " f"| Sharpe {w['test']['sharpe']:.1f}") if __name__ == "__main__": main()