"""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 + 48 * 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)))
print("\n(2) EXIT BY KIT (band $250k-$1M)")
for kk in ("A", "B"):
    for ex in ("4h", "trail3_48h", "trail5_48h", "hold48"):
        Rk = [r for r in book(ex, "4h") if r[2] == kk]
        print("  kit %s %-11s H1 %s | H2 %s" % (kk, ex, S(Rk, D1), S(Rk, D2)))
for ex in ("4h", "tp5_4h", "trail3_48h"):
    Rk = [r for r in book("4h", ex) if r[2] not in ("A", "B")]
    print("  non-kit %-11s H1 %s | H2 %s" % (ex, S(Rk, D1), S(Rk, D2)))
print("\n(3) COMBINED BOOKS")
CANDS = []
for kitex in ("4h", "trail3_48h", "trail5_48h"):
    for nonex in ("4h", "tp5_4h"):
        for skip in (False, True):
            for wideB in (False, True):
                R = book(kitex, nonex, skip, wideB)
                v1 = [x for p, x, k in R if day(p["t"]) in D1]
                CANDS.append((sum(x - 1 for x in v1) * 100 / len(D1), kitex, nonex, skip, wideB))
                print("  kit=%-10s non=%-6s skip_nonkit=%d wideB=%d | H1 %s | H2 %s" % (kitex, nonex, skip, wideB, S(R, D1), S(R, D2)))
CANDS.sort(key=lambda c: -c[0]); best = CANDS[0]
print("\nH1 PICK by $/day:", best[1:], "H1 $%.0f/day" % best[0])
R = book(*best[1:]); B0 = book("4h", "4h")
print("  pick H2:", S(R, D2)); print("  base H2:", S(B0, D2))
random.seed(7)
for name, RR in (("pick", R), ("base", B0)):
    byd = collections.defaultdict(lambda: [0.0, 0])
    for p, x, k in RR:
        if day(p["t"]) in D2: byd[day(p["t"])][0] += x - 1; byd[day(p["t"])][1] += 1
    dd = sorted(byd); res = []
    for _ in range(1000):
        smp = [random.choice(dd) for _ in dd]; c = sum(byd[d][1] for d in smp); res.append(1 + sum(byd[d][0] for d in smp) / c)
    res.sort(); print("  %s H2 bootstrap under 1.0x %.1f%% 5th %.2fx" % (name, sum(r < 1 for r in res) / 10, res[50]))
