Files
PythagorasGoal/scripts/games/run_game.py
T
Adriano Dal Pastro 8d69a0cef5 feat(games): sessioni 2-3 Blind Traders (opzioni/session/grid) + gate PORT06 e tooling reset
- Gioco GRID TRADERS (sessione 3, regola STRATEGIA_GRIGLIA.md): grid_engine
  (backtest causale fee-aware della griglia geometrica), grid_brief (digest
  anonimo per dimensionare la griglia), grid_arena (torneo 100 agenti);
  diario docs/diary/2026-06-10-grid-traders-game3.md
- Gioco OPZIONI: options_engine (BS + skew fittato + DVOL storica),
  options_arena, opt_calibrate (superficie premi REALE da cerbero-bite)
- Gioco SESSION: session_engine/session_arena (pattern orari intraday)
- arena: vincolo GAME_NO_LIVE=1 (vieta pairs e fade zscore/breakout/momentum
  gia' live, coercizione a trend/ma_cross) + normalize del candidato PRIMA
  della valutazione nel hill-climb
- Gate: grid_game_gate (griglia ETH vincitrice vs PORT06, mark-to-market),
  pairs30m_gate (ETH/BTC 30m ridondante col 15m gia' deployato?)
- reset_flatten: flatten one-shot del conto testnet per il reset portafoglio
- .gitignore: data/portfolio_paper_stats/ (stato runtime sleeve paper-only)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 09:49:17 +00:00

89 lines
3.4 KiB
Python

"""
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()