import json, math, collections, statistics as S
from eng2 import *
TS = {k: run(k) for k in KEYS}
RET = {k: {SERIES[k][0][i]: SERIES[k][1][i + 1] / SERIES[k][1][i] - 1 for i in range(len(SERIES[k][1]) - 1)} for k in KEYS}
days = sorted({d for k in KEYS for d in SERIES[k][0]})
# per-day position status for each basket: weight (1, .5 after HOT) and trade record
POS = {k: {} for k in KEYS}; INFO = {k: {} for k in KEYS}
for k in KEYS:
    ds, L = SERIES[k]; idx = {d: i for i, d in enumerate(ds)}
    for t in TS[k]:
        i0, i1 = idx[t['entry']], idx[t['exit']]; cur = 1.0
        for j in range(i0, i1):
            if j > i0 and cur == 1.0 and STAGES[k][j][0] == 'HOT': cur = 0.5
            POS[k][ds[j]] = cur; INFO[k][ds[j]] = t
def score(t, how):
    if how == 'r30': return t['f_r30'] or 0
    if how == 'r7': return t['f_r7'] or 0
    if how == 'vol': return t['f_vol'] or 0
    if how == 'rsi': return t['f_rsi'] or 0
    if how == 'combo': return (t['f_r7'] or 0) + 0.5 * (t['f_vol'] or 0)
    if how == 'meme_r7': return (t['f_r7'] or 0) + 0.2 * t['f_meme']
    return 0
def sim(K=3, how='r30', swap=False, start='2023-01-01'):
    eq = 0; pk = 0; mdd = 0; prev = {}; held = {}; yr = collections.defaultdict(float); ex = []
    for d in days:
        if d < start: continue
        held = {k: v for k, v in held.items() if POS[k].get(d, 0) > 0}
        new = [k for k in KEYS if POS[k].get(d, 0) > 0 and INFO[k][d]['entry'] == d and k not in held]
        new.sort(key=lambda k: -score(INFO[k][d], how))
        for k in new:
            if len(held) < K: held[k] = 1
            elif swap:
                ext = [h for h in held if POS[h].get(d, 0) == 0.5]   # extended (half taken)
                if ext:
                    out = min(ext, key=lambda h: score(INFO[h][d], how)); del held[out]; held[k] = 1
        wt = {k: POS[k][d] / K for k in held if d in RET[k]}
        turn = sum(abs(wt.get(k, 0) - prev.get(k, 0)) for k in set(wt) | set(prev))
        r = sum(x * RET[k][d] for k, x in wt.items()) - turn * 0.005; prev = wt
        lr = math.log(1 + r); eq += lr; yr[d[:4]] += lr; pk = max(pk, eq); mdd = min(mdd, eq - pk); ex.append(sum(wt.values()))
    return dict(total=round((math.exp(eq) - 1) * 100), worst=round((math.exp(mdd) - 1) * 100), money_in=round(S.mean(ex) * 100),
                by_year={y: round((math.exp(v) - 1) * 100) for y, v in sorted(yr.items())})
R = {}
for i, nm, kw in [(100, "BUY days only, 3 slots, rank 30d move (v4)", dict(how='r30')),
                  (101, "rank by 7 day move", dict(how='r7')), (102, "rank by rising volume", dict(how='vol')),
                  (103, "rank by RSI", dict(how='rsi')), (104, "rank by 7d move + volume", dict(how='combo')),
                  (105, "rank 7d move, swap out an extended basket for a fresh BUY", dict(how='r7', swap=True)),
                  (106, "rank 30d, swap extended for fresh BUY", dict(how='r30', swap=True)),
                  (107, "rank 7d move, 2 slots", dict(how='r7', K=2)), (108, "rank 7d move, 4 slots", dict(how='r7', K=4)),
                  (109, "rank 7d move + swap, 2 slots", dict(how='r7', K=2, swap=True)),
                  (110, "same as 105 but only from 2025", dict(how='r7', swap=True, start='2025-01-01')),
                  (111, "same as 100 but only from 2025", dict(how='r30', start='2025-01-01'))]:
    r = sim(**kw); R[i] = dict(name=nm, **r); print(i, nm, r, flush=True)
json.dump(R, open('res_i.json', 'w'))
