{
 "np2_check": null,
 "seconds_per_sim": null,
 "paired": {
  "n": 0,
  "mean_diff": null,
  "se": null,
  "worst": null
 },
 "measurements": {
  "calibration_np2_minus5bps_vs_np2_2260000_2261999": null,
  "calibration_np2_minus5bps_vs_np2_2262000_2263999": null,
  "agree_within_2se": null,
  "sims_per_hour": null
 },
 "code": "#!/usr/bin/env python3\n\"\"\"Paired comparison of two AMM strategies (amm-challenge @6b6921f).\nusage: python pair.py A.sol B.sol SEED_START COUNT [--chunk N] [--workers W]\nPer seed s: rng=default_rng(seed=s); size, rate, sigma drawn as in\nMatchRunner._build_configs; cfg.seed=s. Each strategy runs vs the 30bps\nvanilla normalizer on identical configs; diff = edge(A)-edge(B) per seed.\"\"\"\nimport argparse, json, math, sys, time\nfrom pathlib import Path\nimport numpy as np\nimport amm_sim_rs\nfrom amm_competition.evm.baseline import load_vanilla_strategy\nfrom amm_competition.evm.compiler import SolidityCompiler\nfrom amm_competition.evm.validator import SolidityValidator\nfrom amm_competition.competition.config import (\n    BASELINE_SETTINGS as S, BASELINE_VARIANCE as V, resolve_n_workers)\n\n\ndef compile_sol(path):\n    src = Path(path).read_text()\n    v = SolidityValidator().validate(src)\n    if not v.valid:\n        sys.exit(f\"{path}: validation failed: {v.errors}\")\n    c = SolidityCompiler().compile(src)\n    if not c.success:\n        sys.exit(f\"{path}: compile failed: {c.errors}\")\n    return list(c.bytecode)\n\n\ndef cfg_for(s):\n    rng = np.random.default_rng(seed=s)\n    size = rng.uniform(V.retail_mean_size_min, V.retail_mean_size_max) if V.vary_retail_mean_size else S.retail_mean_size\n    rate = rng.uniform(V.retail_arrival_rate_min, V.retail_arrival_rate_max) if V.vary_retail_arrival_rate else S.retail_arrival_rate\n    sig = rng.uniform(V.gbm_sigma_min, V.gbm_sigma_max) if V.vary_gbm_sigma else S.gbm_sigma\n    return amm_sim_rs.SimulationConfig(\n        n_steps=S.n_steps, initial_price=S.initial_price, initial_x=S.initial_x,\n        initial_y=S.initial_y, gbm_mu=S.gbm_mu, gbm_sigma=sig, gbm_dt=S.gbm_dt,\n        retail_arrival_rate=rate, retail_mean_size=size,\n        retail_size_sigma=S.retail_size_sigma, retail_buy_prob=S.retail_buy_prob,\n        seed=s)\n\n\ndef edges(bc, norm, cfgs, w):\n    r = amm_sim_rs.run_batch(bc, norm, cfgs, w)\n    return [x.edges.get(\"submission\", 0.0) for x in r.results]\n\n\ndef main():\n    ap = argparse.ArgumentParser()\n    ap.add_argument(\"a\"); ap.add_argument(\"b\")\n    ap.add_argument(\"start\", type=int); ap.add_argument(\"count\", type=int)\n    ap.add_argument(\"--chunk\", type=int, default=500)\n    ap.add_argument(\"--workers\", type=int, default=None)\n    ap.add_argument(\"--json\", action=\"store_true\")\n    a = ap.parse_args()\n    w = a.workers or resolve_n_workers()\n    A, B = compile_sol(a.a), compile_sol(a.b)\n    norm = list(load_vanilla_strategy()._bytecode)\n    ea, eb, sims, t0 = [], [], 0, time.time()\n    seeds = list(range(a.start, a.start + a.count))\n    for i in range(0, len(seeds), a.chunk):\n        cf = [cfg_for(s) for s in seeds[i:i + a.chunk]]\n        ea += edges(A, norm, cf, w); eb += edges(B, norm, cf, w)\n        sims += 2 * len(cf)\n    dt = time.time() - t0\n    d = np.array(ea) - np.array(eb); n = len(d)\n    se = float(d.std(ddof=1) / math.sqrt(n)) if n > 1 else float(\"nan\")\n    k = np.argsort(d)[:5]\n    out = {\"n\": n, \"mean_diff\": float(d.mean()), \"se\": se,\n           \"worst\": [[seeds[j], float(d[j])] for j in k],\n           \"mean_a\": float(np.mean(ea)), \"mean_b\": float(np.mean(eb)),\n           \"workers\": w, \"wall_s\": dt, \"seconds_per_sim\": dt / sims,\n           \"sims_per_hour\": 3600 * sims / dt}\n    if a.json:\n        print(json.dumps(out))\n    else:\n        for key, v in out.items():\n            print(f\"{key}: {v}\")\n\n\nif __name__ == \"__main__\":\n    main()\n",
 "code_name": "pair.py",
 "blocked": {
  "step": "setup: git clone github.com/benedictbrady/amm-challenge (and every later network fetch: uv, rustup, pypi)",
  "error": "shell network egress fails: git clone -> 'fatal: unable to access https://github.com/benedictbrady/amm-challenge/: Proxy CONNECT aborted'; curl to github.com, pypi.org, static.rust-lang.org, api.imd.fun -> 'curl: (56) Proxy CONNECT aborted'. Retried; same result. Host also lacks numpy, uv and cargo, so the simulator cannot be built offline."
 },
 "notes": "Nothing was simulated: np2_check, timing and both calibrations were not run, and NP2 was not assembled or hashed. pair.py was written from the simulator source at 6b6921f, read with a web-fetch tool (match.py _build_configs, cli.py run, config.py). Each strategy is run vs load_vanilla_strategy() (30bps normalizer) through amm_sim_rs.run_batch(A, norm, cfgs, workers) and scored by edges['submission'], as amm-match run does. Configs follow _build_configs: rng=np.random.default_rng(seed=s); uniform size [19,21], rate [0.6,1.0], sigma [0.000882,0.001008] in that order; seed=s; other fields from BASELINE_SETTINGS. Output: n, mean_diff (A-B), se=std(ddof=1)/sqrt(n), 5 worst seeds, both means, seconds_per_sim (wall time / total sims at the given worker count) and sims_per_hour. The only check was a control-flow smoke test against stub amm_sim_rs/numpy modules. Run it from the checkout root after setup.sh: . scratch/env.sh && python pair.py A.sol B.sol 2260000 2000. First check that pair.py on CH reproduces 525.525882178 on seeds 0..999 (mean_a)."
}