"""
pick_report.py -- [2026-09-27] How well an entry-rules run recognized the
day's winners (held to 15:55, so a pick = win if the stock was higher at
the close than at the pick).
  * picks, winning / losing picks per day
  * coverage: of each day's winners (closed above the 9:30 open) and big
    winners (closed 5%+ above the open), how many were picked, and how
    many of those picks still made money
  * indicator values at the pick: winning picks vs losing picks
Usage: python3 sim/analysis/pick_report.py data/simulations/<run>.json [...]
"""
import json
import statistics as st
import sys
from collections import defaultdict

DW = {(r["date"], r["symbol"]): r for r in json.load(open(
    "/var/www/screener/trade/reports/open_window/daily_winners.json"))}
IND = ["vas", "bar_rvol", "smooth_accel", "imbalance", "spread_pct", "price_vs_vwap_pct",
       "dist_to_hod_pct", "own_change_5bar_pct", "rs_min", "vol_slope_5", "minutes_after_open", "up_from_open_pct"]


def flat(t, day):
    i = t["plan"]["indicators"]
    rs = [x for x in (i.get("rel_strength_pct") or {}).values() if x is not None]
    vr = i.get("volume_rising") or {}
    from datetime import datetime
    et = datetime.fromisoformat(t["entry_time"])
    o = DW.get((day, t["symbol"]), {}).get("open")
    return {**{k: i.get(k) for k in IND}, "rs_min": min(rs) if rs else None, "vol_slope_5": vr.get("slope_norm"),
            "minutes_after_open": (et.hour * 60 + et.minute) - (13 * 60 + 30),
            "up_from_open_pct": (t["entry_price"] / o - 1) * 100 if o else None,
            "trend_3bar": i.get("trend_3bar")}


def report(path):
    res = json.load(open(path))
    print(f"\n=================== {res['name']} ===================")
    tot = defaultdict(float)
    rows = []
    print(f"{'day':6} {'picks':>5} {'win':>4} {'lose':>4} {'P/L':>9} | {'winners picked':>15} {'big winners picked':>19} {'big picked & won':>17}")
    for day in sorted(res["days"]):
        tr = res["days"][day]["trades"]
        w = [t for t in tr if t["pl_dollars"] > 0]
        dayw = [s for (d, s), r in DW.items() if d == day and r["open_close_pct"] > 0]
        dayb = [s for (d, s), r in DW.items() if d == day and r["open_close_pct"] >= 5]
        picked = {t["symbol"]: t for t in tr}
        wp = [s for s in dayw if s in picked]
        bp = [s for s in dayb if s in picked]
        bpw = [s for s in bp if picked[s]["pl_dollars"] > 0]
        for k, v in (("picks", len(tr)), ("win", len(w)), ("lose", len(tr) - len(w)), ("pl", sum(t["pl_dollars"] for t in tr)),
                     ("dayw", len(dayw)), ("wp", len(wp)), ("dayb", len(dayb)), ("bp", len(bp)), ("bpw", len(bpw))):
            tot[k] += v
        print(f"{day[5:]:6} {len(tr):5} {len(w):4} {len(tr)-len(w):4} {sum(t['pl_dollars'] for t in tr):+9.0f} | "
              f"{len(wp):>7}/{len(dayw):<7} {len(bp):>9}/{len(dayb):<9} {len(bpw):>8}/{len(bp):<8}")
        for t in tr:
            rows.append((t["pl_dollars"] > 0, flat(t, day), day, t))
    print(f"{'TOTAL':6} {tot['picks']:5.0f} {tot['win']:4.0f} {tot['lose']:4.0f} {tot['pl']:+9.0f} | "
          f"{tot['wp']:>7.0f}/{tot['dayw']:<7.0f} {tot['bp']:>9.0f}/{tot['dayb']:<9.0f} {tot['bpw']:>8.0f}/{tot['bp']:<8.0f}")
    print("\nIndicator medians at the pick:   winning picks | losing picks")
    for k in IND:
        a = [f[k] for ok, f, *_ in rows if ok and f.get(k) is not None]
        b = [f[k] for ok, f, *_ in rows if not ok and f.get(k) is not None]
        if a and b:
            print(f"   {k:22} {st.median(a):10.3f} | {st.median(b):10.3f}")
    return rows


if __name__ == "__main__":
    for p in sys.argv[1:]:
        report(p)
