"""
Counterfactual equity at different Kelly multipliers. Each historical paper bet
was sized at frac = min(kelly_f * 0.25, 0.25) of $1000, so kelly_f ~= stake/250.
Re-simulate the compounded path at an arbitrary KELLY_MULT, from $1000.
mult=0.25 reproduces the live path (sanity check). Emails the chart.
"""
import json, io, smtplib, sys
from pathlib import Path
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

sys.stdout.reconfigure(encoding='utf-8', errors='replace')
START, MAX_BET_PCT, BASE_MULT = 1000.0, 0.25, 0.25

bets = json.load(open(r'E:\soccer\data\bet_history.json'))
idx = {id(b): i for i, b in enumerate(bets)}
paper = [b for b in bets if b.get('kalshi_stake') and b.get('kalshi_pnl') is not None]
paper.sort(key=lambda b: (b.get('date') or '', idx[id(b)]))

def kelly_f(b):
    # prefer recorded fraction; else reconstruct from the 0.25-sized stake
    kf = b.get('kalshi_kelly_f')
    if kf:
        return kf
    return (b['kalshi_stake'] / 1000.0) / BASE_MULT

def replay(mult):
    eq = [START]; run = START
    for b in paper:
        ask = b['kalshi_ask']
        if not ask or ask <= 0:
            continue
        frac = min(kelly_f(b) * mult, MAX_BET_PCT)
        stake = round(frac * run, 2)
        if stake < 1.0:
            stake = 1.0
        if stake > run:
            stake = round(run, 2)
        bo = (1 - ask) / ask
        run += stake * bo if b.get('won') else -stake
        eq.append(run)
    return eq

paths = {0.25: replay(0.25), 0.10: replay(0.10)}
for m, eq in paths.items():
    print(f"Kelly {m:.2f}: final ${eq[-1]:,.2f}  ({(eq[-1]-START)/START*100:+.1f}%)")

fig, ax = plt.subplots(figsize=(11, 5.5))
colors = {0.25: '#d62728', 0.10: '#2077b4'}
for m in (0.25, 0.10):
    eq = paths[m]
    ax.plot(range(len(eq)), eq, color=colors[m], lw=2,
            label=f'Kelly {m:.2f}  (${eq[-1]:,.0f}, {(eq[-1]-START)/START*100:+.1f}%)')
ax.axhline(START, color='gray', ls='--', lw=1, alpha=0.6)
ax.set_xlabel('Bet number'); ax.set_ylabel('Bankroll ($)')
ax.set_title('Kalshi compounded equity — Kelly 0.25 (current) vs 0.10')
ax.legend(loc='best'); ax.grid(True, alpha=0.3)
fig.tight_layout()
buf = io.BytesIO(); fig.savefig(buf, format='png', dpi=120); plt.close(fig)
png = buf.getvalue(); Path(r'E:\soccer\_equity_kelly.png').write_bytes(png)

def _env(p):
    e = {}
    for ln in open(p):
        ln = ln.strip()
        if ln and not ln.startswith('#') and '=' in ln:
            k, v = ln.split('=', 1); e[k.strip()] = v.strip()
    return e
env = _env(r'E:\soccer\.env')
msg = MIMEMultipart('related')
msg['Subject'] = f"Equity: Kelly 0.25 ${paths[0.25][-1]:,.0f} vs 0.10 ${paths[0.10][-1]:,.0f}"
msg['From'] = env.get('EMAIL_SENDER', ''); msg['To'] = env.get('EMAIL_RECIPIENT', '')
alt = MIMEMultipart('alternative'); msg.attach(alt)
alt.attach(MIMEText(f'<html><body><h3>Kalshi compounded equity by Kelly multiplier</h3>'
                    f'<p>Kelly 0.25 (current): <b>${paths[0.25][-1]:,.2f}</b> '
                    f'({(paths[0.25][-1]-START)/START*100:+.1f}%)<br>'
                    f'Kelly 0.10: <b>${paths[0.10][-1]:,.2f}</b> '
                    f'({(paths[0.10][-1]-START)/START*100:+.1f}%)</p>'
                    f'<img src="cid:eq" style="max-width:100%"></body></html>', 'html'))
img = MIMEImage(png, _subtype='png'); img.add_header('Content-ID', '<eq>')
img.add_header('Content-Disposition', 'inline', filename='equity.png'); msg.attach(img)
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as s:
    s.login(env['EMAIL_SENDER'], env['EMAIL_APP_PASSWORD'])
    s.sendmail(env['EMAIL_SENDER'], env['EMAIL_RECIPIENT'], msg.as_string())
print("emailed.")
