"""v3kitsim.py (A1.21): mc5 split and exits by launch kit. $100, real depth, dust guard, stop 0.5x, pull = 0.
Kit exits: no 4 h stop, 50% trail armed at 3x or 5x, max hold 48 h. Non-kit: 4 h, or sell all at 5x.
Set = trades whose first swap is 48 h+ before chain head (so every exit can finish). Pick on H1, test once on H2."""
import json, collections, statistics as st, datetime, random
exec(open("/root/fwa1/v3exit.py").read().split("extdone = ")[0])
src = open("/root/fwa1/v3exit.py").read(); exec(src[src.index("def run("):src.index("H = 3600")])
KIT = json.load(open("/root/fwa1/v3/kit.json"))
H = 3600; NEED48 = int((300 + 4 * H + 600) / SPB)
full = [p for p in pools if meta[p["pool"]][4] + NEED48 <= head and p["pool"] in KIT]
for p in full: CACHE[p["pool"]] = path12(p)
SC.clear()
SIG = []
for p in full:
    pth = CACHE[p["pool"]][0]; i = state(pth, 300)
    if i is None or pth[i][4] < 0.1 or not any(x[2] for x in pth[:i + 1]): continue      # dust guard
    s = series_t(p, 100, 300)
    if s and 1.5e5 <= s[4] < 2e6: SIG.append((p, s, KIT[p["pool"]]["kit"]))
print("pools with 48 h data", len(full), "signals in $150k-$2M", len(SIG), collections.Counter(k for p, s, k in SIG), flush=True)
def inband(s, k, wideB): return (1.5e5 <= s[4] < 2e6) if (wideB and k == "B") else (2.5e5 <= s[4] < 1e6)
EX = {"4h": dict(tstop=300 + 4 * H), "tp5_4h": dict(tstop=300 + 4 * H), "trail3_48h": dict(tstop=300 + 48 * H, trail=0.5, arm=3.0),
      "trail5_48h": dict(tstop=300 + 48 * H, trail=0.5, arm=5.0), "hold48": dict(tstop=300 + 48 * H)}
def x_of(s, ex):
    if ex == "tp5_4h":
        T, M, pull, m0, mc = s
        import numpy as np
        ok = T <= 300 + 4 * H; Tn, Mn = T[ok], M[ok]
        for k in range(len(Mn)):
            if pull is not None and pull <= Tn[k]: return 0.0
            if Mn[k] <= 0.5:
                j = max(k, int(np.searchsorted(T, Tn[k] + 3, "right")) - 1); return float(M[j])
            if Mn[k] >= 5:
                j = max(k, int(np.searchsorted(T, Tn[k] + 3, "right")) - 1); return float(M[j])
        if pull is not None and pull <= 300 + 4 * H: return 0.0
        return float(Mn[-1]) if len(Mn) else m0
    return run(s, **EX[ex])
def book(kitex, nonex, skip_nonkit=False, wideB=False):
    R = []
    for p, s, k in SIG:
        if not inband(s, k, wideB): continue
        iskit = k in ("A", "B")
        if skip_nonkit and not iskit: continue
        R.append((p, x_of(s, kitex if iskit else nonex), k))
    return R
alld = sorted({day(p["t"]) for p, s, k in SIG}); D1 = [d for d in alld if d < day(CUT)]; D2 = [d for d in alld if d >= day(CUT)]
def worst3(R, days):
    pn = collections.defaultdict(float)
    for p, x, k in R: pn[day(p["t"])] += (x - 1) * 100
    dl = sorted(datetime.date(2026, int(d[:2]), int(d[3:])) for d in days)
    cal = [dl[0] + datetime.timedelta(j) for j in range((dl[-1] - dl[0]).days + 1)]
    v = [pn.get(c.strftime("%m-%d"), 0.0) for c in cal]
    return min(sum(v[i:i + 3]) for i in range(max(1, len(v) - 2)))
def S(R, days, lab=""):
    v = [x for p, x, k in R if day(p["t"]) in days]
    if not v: return "n0"
    return "n%d (%.1f/day) mean %.2fx med %.2fx $%.0f/day worst3 $%.0f" % (len(v), len(v) / len(days), st.mean(v), st.median(v), sum(x - 1 for x in v) * 100 / len(days), worst3([r for r in R if day(r[0]["t"]) in days], days))
print("days H1 %d (%s..%s) H2 %d (%s..%s)" % (len(D1), D1[0], D1[-1], len(D2), D2[0], D2[-1]))
print("\n(1) SPLIT BY KIT, base exit (stop 0.5x, 4 h), band $250k-$1M")
base = book("4h", "4h")
for kk in ("A", "B", "PM", "other"):
    Rk = [r for r in base if r[2] == kk]
    print("  %-6s H1 %s | H2 %s" % (kk, S(Rk, D1), S(Rk, D2)))
print("  ALL    H1 %s | H2 %s" % (S(base, D1), S(base, D2)))
