"""
Conditional convergence: do LARGE Kalshi-vs-Pinnacle gaps close by kickoff, and
who moves -- Kalshi toward Pinnacle (catch-up) or Pinnacle toward Kalshi?
Bucket each fixture/side by its EARLIEST-PRE signed gap (pin_fair - kalshi_mid),
then compare to its LATEST-PRE snapshot. Signed gap > 0 = Kalshi underpricing
that side (the direction we bet).
"""
import csv, glob, sys
from collections import defaultdict
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
files = sorted(glob.glob(r'E:\soccer\live_data\*.csv'))

def fval(r, k):
    try: return float(r.get(k, ''))
    except (TypeError, ValueError): return None

series = defaultdict(list)
for fp in files:
    with open(fp, newline='', encoding='utf-8', errors='replace') as f:
        for r in csv.DictReader(f):
            if r.get('status') != 'PRE':
                continue
            el = fval(r, 'elapsed')
            if el is None or el >= 0:
                continue
            for side in ('home', 'away'):
                pf = fval(r, f'pin_fair_{side}')
                km = fval(r, f'kalshi_{side}_mid')
                if pf and km and 0 < pf < 1 and 0 < km < 1:
                    series[(r['game_date'], r['home'], r['away'], side)].append((-el, pf, km))
for v in series.values():
    v.sort()  # ascending mins-to-ko: v[0]=closest, v[-1]=furthest

# bucket by earliest signed gap in cents
bands = [(-99,-3),(-3,-1),(-1,1),(1,3),(3,5),(5,99)]
blab  = ['<-3','-3..-1','-1..1','1..3','3..5','>5']
agg = {b: {'n':0,'g0':0.0,'g1':0.0,'kal_to_pin':0,'pin_to_kal':0,'kalmove':0.0,'pinmove':0.0,'closed':0} for b in bands}

for v in series.values():
    if len(v) < 2: continue
    m0,pf0,km0 = v[-1]   # furthest from ko (early)
    m1,pf1,km1 = v[0]    # closest to ko (late)
    if m0 - m1 < 60: continue   # need >=1h of tracking span
    g0 = (pf0-km0)*100           # early signed gap, cents
    g1 = (pf1-km1)*100           # late signed gap
    for b in bands:
        if b[0] <= g0 < b[1]:
            a=agg[b]; a['n']+=1
            a['g0']+=g0; a['g1']+=g1
            a['kalmove'] += (km1-km0)*100
            a['pinmove'] += (pf1-pf0)*100
            if abs(km1-pf0) < abs(km0-pf0): a['kal_to_pin']+=1
            if abs(pf1-km0) < abs(pf0-km0): a['pin_to_kal']+=1
            if abs(g1) < abs(g0): a['closed']+=1
            break

print("Bucketed by EARLY signed gap (pin_fair - kalshi_mid). Tracking earliest->latest PRE.")
print("(+gap = Kalshi underpricing that side = the side we'd back)\n")
print(f"{'band':>8}{'N':>6}{'earlyGap':>9}{'lateGap':>9}{'closed%':>9}"
      f"{'KalMove':>9}{'PinMove':>9}{'K->P%':>7}{'P->K%':>7}")
print('-'*73)
for b,lab in zip(bands,blab):
    a=agg[b]
    if not a['n']: continue
    n=a['n']
    print(f"{lab:>8}{n:>6}{a['g0']/n:>+8.2f}c{a['g1']/n:>+8.2f}c{100*a['closed']/n:>8.0f}%"
          f"{a['kalmove']/n:>+8.2f}c{a['pinmove']/n:>+8.2f}c{100*a['kal_to_pin']/n:>6.0f}%{100*a['pin_to_kal']/n:>6.0f}%")
