1"""Phase 3 gate — computational performance and stylized facts at N = 100, 1,000, 10,000 traders (no API)."""2from __future__ import annotations34import json5import sys6import time7from pathlib import Path89sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))10from market_agents.experiments.config import RunConfig # noqa: E40211from market_agents.experiments.runner import run_config # noqa: E40212from market_agents.metrics.outcomes import run_outcomes # noqa: E4021314ROOT = Path(__file__).resolve().parents[1]15rows = []16for n, seeds in ((100, [1, 2, 3]), (1000, [1, 2, 3]), (10000, [1])):17 for s in seeds:18 act = {k: v * 100.0 / n for k, v in RunConfig().population.activity.items()} # constant order flow per tick19 cfg = RunConfig.from_yaml(ROOT / "configs/baseline.yaml", **{"name": f"scale_{n}", "seed": s, "population.n_traders": n,20 "population.activity": act})21 t0 = time.perf_counter()22 res = run_config(cfg)23 oc = run_outcomes(res)24 oc["wall_s"] = time.perf_counter() - t025 oc["n_orders"] = int(res.agents["n_orders"].sum())26 rows.append(oc)27 print(f"N={n} seed={s}: {oc['wall_s']:.1f}s, {oc['n_trades']} trades, {oc['n_orders']} orders, mad={oc['mad_pct']:.2f}% "28 f"acf1={oc['acf_r_1']:.2f} kurt={oc['kurtosis']:.1f} spread={oc['spread_bp']:.1f}bp", flush=True)29out = ROOT / "results/calibration"30out.mkdir(parents=True, exist_ok=True)31with open(out / "scale_benchmark.json", "w") as f:32 json.dump(rows, f, indent=1, default=float)33