"""Index construction checks: equal weight reset daily (current) vs weekly drift (like the official Robinhood
indices) vs top 10 / top 30 members. Same rule (#35 filters except breadth, which needs the full set)."""
import json, glob, os, datetime as dt, math, statistics as S, collections, sys
sys.path.insert(0, '/home/claude/chains')
from baskets_def import CMC_BASKETS, EXCLUDE, MEME, AI, DEFI
from stages import stage_series
import eng
files = sorted(glob.glob('/home/claude/chains/snapB/*.json')); days = [os.path.basename(f)[:10] for f in files]
snap = {d: json.load(open(f)) for d, f in zip(days, files)}
px = {d: {c[0]: c[6] for c in s if c[6]} for d, s in snap.items()}
has = lambda t, s: bool(set(t) & s)
B = {b[0]: (b[1], b[3]) for b in CMC_BASKETS}
B['eth_memes'] = ("Ethereum", lambda t: has(t, MEME)); B['bnb_memes'] = ("BNB Smart Chain (BEP20)", lambda t: has(t, MEME))
def build(key, topn=15, drift=False):
    plat, rule = B[key]; ex = EXCLUDE.get(key, set()); line = []; lvl = 1.0; mem = None; started = False; w = {}
    for i in range(len(days) - 1):
        d, n = days[i], days[i + 1]
        if mem is None or dt.date.fromisoformat(d).weekday() == 0:
            xs = [c for c in snap[d] if c[3] == plat and not c[9] and c[1] not in ex and rule(c[10]) and c[8] >= 25000 and c[6] > 0 and c[7] > 0]
            xs.sort(key=lambda c: -c[7]); m = [c[0] for c in xs[:topn]]; mem = m if len(m) >= 4 else None
            if mem: w = {c: 1 / len(mem) for c in mem}
        if mem is None:
            if started: line.append((n, lvl))
            continue
        rs = {}
        for cid in mem:
            a = px[d].get(cid); z = px[n].get(cid)
            if not a: continue
            if z is None:
                if any(cid in px[days[k]] for k in range(i + 2, min(i + 5, len(days)))): continue
                rs[cid] = -0.5; continue
            rs[cid] = max(-0.9, min(2.0, z / a - 1))
        if len(rs) < 4:
            if started: line.append((n, lvl)); continue
        started = True
        if drift:
            tw = sum(w.get(c, 0) for c in rs); r = sum(w.get(c, 0) * rs[c] for c in rs) / tw if tw else 0
            for c in rs: w[c] = w.get(c, 0) * (1 + rs[c])
            s = sum(w.values()); w = {c: v / s for c, v in w.items()}
        else:
            r = sum(rs.values()) / len(rs)
        lvl *= 1 + r; line.append((n, lvl))
    return [d for d, _ in line], [x for _, x in line]
keys = ['sol_pump', 'sol_memes', 'sol_defi', 'base_memes', 'eth_memes', 'bnb_memes']
res = {}
for nm, kw in [("59 equal weight reset daily, top 15 (current)", {}), ("60 weekly drift (like Robinhood Indices), top 15", dict(drift=True)),
               ("61 top 10", dict(topn=10)), ("62 top 30", dict(topn=30))]:
    allt = []
    for k in keys:
        ds, L = build(k, **kw)
        eng.SERIES[k] = (ds, L); eng.STAGES[k] = stage_series(L)
        allt += eng.run(k, solbtc_froth=0.20)
    a = [t for t in allt if t['entry'] < eng.SPLIT]; b = [t for t in allt if t['entry'] >= eng.SPLIT]
    res[nm] = dict(all=eng.stats(allt), A=eng.stats(a), B=eng.stats(b))
    print(nm, res[nm], flush=True)
json.dump(res, open('res_f.json', 'w'))
