#!/usr/bin/env python3
"""Build calibration.md from one or more calibrate.py logs (the per-year lines), so that arms run
in separate processes, or a run stopped early, can still be summarised. Standard library only.

Usage: python3 summarise_log.py <log> [<log> ...]
"""
import os
import re
import statistics
import sys
from datetime import datetime, timezone

HERE = os.path.dirname(os.path.abspath(__file__))
LINE = re.compile(r"^(null|edge) year\s+\d+: trades\s+(\d+) rule\s+([-+\d.]+) ctrl_se\s+([\d.]+) excess\s+([-+\d.]+) same=(True|False)")


def load(paths):
    arms = {"null": [], "edge": []}
    for p in paths:
        for line in open(p):
            m = LINE.match(line)
            if m:
                arms[m.group(1)].append({"trades": int(m.group(2)), "rule_mean": float(m.group(3)),
                                         "control_se": float(m.group(4)), "excess": float(m.group(5)),
                                         "same_sign": m.group(6) == "True"})
    return arms


def summarise(rows):
    ex = [r["excess"] for r in rows]
    n = len(rows)
    return {
        "years": n,
        "trades_mean": statistics.fmean(r["trades"] for r in rows),
        "excess_mean": statistics.fmean(ex),
        "excess_sd": statistics.pstdev(ex),
        "cert2": sum(e >= 2 for e in ex) / n,
        "cert2same": sum(e >= 2 and r["same_sign"] for e, r in zip(ex, rows)) / n,
        "cert1_5": sum(e >= 1.5 for e in ex) / n,
        "cert1_5same": sum(e >= 1.5 and r["same_sign"] for e, r in zip(ex, rows)) / n,
    }


def main():
    arms = load(sys.argv[1:])
    lines = [f"# Calibration of the London-breakout test — summarised {datetime.now(timezone.utc):%Y-%m-%d %H:%M} UTC", "",
             "This is a test record, not advice.", "",
             "Built by `summarise_log.py` from the per-year lines of `calibrate.py` runs (logs: "
             + ", ".join(f"`{os.path.basename(p)}`" for p in sys.argv[1:]) + "). "
             "Null arm: every 1-minute mid return of every real 2026 day multiplied by an independent random sign, "
             "spreads and wick sizes kept. Edge arm: the same, plus a drift in the breakout direction after the day's first breakout "
             "(see the run's own header for the size). Full pipeline unchanged: rule, random-entry control, halves.", "",
             "| arm | years | mean trades | excess mean | excess s.d. | ≥2 s.e. | ≥2 s.e. and halves agree | ≥1.5 s.e. | ≥1.5 and agree |",
             "|---|---|---|---|---|---|---|---|---|"]
    for name, key in (("null (sign-flipped returns)", "null"), ("edge injected", "edge")):
        rows = arms[key]
        if not rows:
            lines.append(f"| {name} | 0 | | | | | | | |")
            continue
        s = summarise(rows)
        lines.append(f"| {name} | {s['years']} | {s['trades_mean']:.0f} | {s['excess_mean']:+.2f} | {s['excess_sd']:.2f} | "
                     f"{s['cert2']:.1%} | {s['cert2same']:.1%} | {s['cert1_5']:.1%} | {s['cert1_5same']:.1%} |")
    lines += ["", "Under a calibrated statistic the null column reads s.d. ≈ 1.00 and ≥2 s.e. ≈ 2.3%.", ""]
    if arms["null"]:
        lines += ["Excess statistic per null year (sorted):", "",
                  "    " + " ".join(f"{e:+.2f}" for e in sorted(r["excess"] for r in arms["null"])), ""]
    if arms["edge"]:
        lines += ["Excess statistic per edge year (sorted):", "",
                  "    " + " ".join(f"{e:+.2f}" for e in sorted(r["excess"] for r in arms["edge"])), ""]
    text = "\n".join(lines) + "\n"
    with open(os.path.join(HERE, "calibration.md"), "w") as f:
        f.write(text)
    print(text)


if __name__ == "__main__":
    main()
