"""Flat vs Kelly sizing on the exact 286-bet xlow (rerouted-to-Kalshi) stream.

Reuses kalshi_only_execution's loader/rule verbatim; only the staking differs.
p_win = pin_fair (same as live _kelly_stake), price = Kalshi ask, fee mirrors
the research convention (0.07 * (1-px) per unit staked).
"""
import sys, math
sys.path.insert(0, r"E:\soccer\research")
import kalshi_only_execution as K

# patch xlow to also record pin_fair of the picked side
_orig_xlow = K.xlow
def xlow_pf(fx):
    for r in fx['pre']:
        ph, pd_, pa = K._f(r.get('pin_home')), K._f(r.get('pin_draw')), K._f(r.get('pin_away'))
        if None in (ph, pd_, pa) or not (ph > 1 and pd_ > 1 and pa > 1): continue
        pf = K.fair_mult((ph, pd_, pa)); cands = []
        for side, si in (('home', 0), ('away', 2)):
            km = K._f(r.get(f'kalshi_{side}_mid')); ka = K._f(r.get(f'kalshi_{side}_ask'))
            pm = K._f(r.get(f'poly_{side}_price'))
            if km is None or pm is None or not (0 < km < 1 and 0 < pm < 1): continue
            if km <= pm: book, mid, px, other = 'kalshi', km, (ka if ka and 0 < ka < 1 else km), pm
            else:        book, mid, px, other = 'poly', pm, pm + K.half_spread(pm), km
            clv = (pf[si] - mid) / pf[si]; oclv = (pf[si] - other) / pf[si]
            if not (mid < other and K.LO <= clv < K.HI): continue
            if K.LO <= oclv < K.HI: continue
            won = (fx['ftr'] == 'H' and side == 'home') or (fx['ftr'] == 'A' and side == 'away')
            kalshi_ask_here = ka if ka and 0 < ka < 1 else km
            cands.append(dict(clv=clv, px=px, book=book, won=won, gd=fx['gd'],
                              kalshi_ask=kalshi_ask_here, pf=pf[si]))
        if cands: return max(cands, key=lambda d: d['clv'])
    return None

F = K.load()
bets = [b for b in (xlow_pf(f) for f in F) if b]
bets.sort(key=lambda b: b['gd'])
poly_orig = [b for b in bets if b['book'] == 'poly']
stream = sorted([b for b in bets if b['book'] == 'kalshi'] +
                [dict(b, px=b['kalshi_ask']) for b in poly_orig], key=lambda b: b['gd'])
print(f"stream n={len(stream)}")

def run(stream, stake_fn, start=1000.0, label=""):
    bank, peak, maxdd, skipped = start, start, 0.0, 0
    for b in stream:
        px = b['px']
        s = stake_fn(bank, b)
        if s <= 0: skipped += 1; continue
        if b['won']:
            gross = s * (1 - px) / px
            fee = 0.07 * (1 - px) * s / 1.0  # research fee convention per unit staked
            bank += gross - fee
        else:
            bank -= s
        peak = max(peak, bank); maxdd = max(maxdd, (peak - bank) / peak)
    print(f"{label:44s} end=${bank:9.2f}  net={bank-start:+8.2f}  maxDD={maxdd*100:5.1f}%  skipped={skipped}")
    return bank

def kelly_f(b):
    px, p = b['px'], b['pf']
    o = (1 - px) / px
    return (p * o - (1 - p)) / o

# schemes
run(stream, lambda bank, b: 10.0, label="FLAT $10/bet (1% of start)")
run(stream, lambda bank, b: 20.0, label="FLAT $20/bet (2% of start)")
run(stream, lambda bank, b: max(min(bank*0.25, bank*0.25*kelly_f(b)), 1.0) if kelly_f(b) > 0 else 0,
    label="0.25-KELLY compounding (live paper scheme)")
run(stream, lambda bank, b: max(min(5.0, 1000*0.25*kelly_f(b)), 1.0) if kelly_f(b) > 0 else 0,
    label="0.25-KELLY fixed $1k notional, $5 cap (auto)")
run(stream, lambda bank, b: bank*0.01, label="FLAT-FRACTION 1% of current bank")

# per-bet ROI identical check: avg kelly stake size
ks = [1000*0.25*kelly_f(b) for b in stream if kelly_f(b) > 0]
neg = sum(1 for b in stream if kelly_f(b) <= 0)
print(f"\nkelly f<=0 on {neg}/{len(stream)} bets (skipped by Kelly, taken by flat)")
print(f"uncapped 0.25-kelly stake off $1k: median ${sorted(ks)[len(ks)//2]:.2f}, mean ${sum(ks)/len(ks):.2f}")
