"""chain-2 trading rule, shared by the live engine and the backtest.
BUY: first bar of CONFIRMED UP (90 bar low in the last 60 bars, above a rising 20 bar trend, close above the
prior BRK bar high) while the BTC risk switch is on. SELL at the first of: close below the 20 bar trend,
-STOP from entry, the basket turns HOT, or MAXH bars. One trade at a time per basket. COST is round trip."""
import math, statistics as S
from stages import stage_series, ema
BRK, STOP, MAXH, COST = 10, 0.12, 14, 0.01

def risk_series(days, btc, n=100, band=0.01):
    """BTC above its n day average by band = on, below by band = off, in between keeps the last state."""
    out = {}; prev = False; ds = [d for d in days if d in btc]
    for i, d in enumerate(ds):
        if i < n - 1: continue
        ma = sum(btc[x] for x in ds[i - n + 1:i + 1]) / n; v = btc[d]
        prev = True if v > ma * (1 + band) else (False if v < ma * (1 - band) else prev)
        out[d] = prev
    return out

def trades(keys, L, risk, brk=BRK, stop=STOP, maxh=MAXH, delay=0, cost=COST, tp=True, trend=True):
    """keys: bar labels (day strings or unix ts), L: levels, risk: dict label->bool (missing = off)."""
    st = stage_series(L, BRK=brk); e = ema([math.log(x) for x in L], 20); out = []; i = 0; prev = None
    while i < len(L):
        s = st[i][0]
        if s == "CONFIRMED UP" and prev != "CONFIRMED UP" and risk.get(keys[i]):
            j0 = i + delay
            if j0 >= len(L): break
            ent = L[j0]; ex = None; why = "day %d" % maxh
            for j in range(j0 + 1, min(j0 + maxh + 1, len(L))):
                r = L[j] / ent - 1
                if r <= -stop: ex = j; why = "stop"; break
                if trend and math.log(L[j]) < e[j]: ex = j; why = "trend"; break
                if tp and st[j][0] == "HOT": ex = j; why = "hot"; break
            status = "closed"
            if ex is None:
                if j0 + maxh > len(L) - 1: ex = len(L) - 1; status = "open"; why = ""
                else: ex = j0 + maxh
            out.append(dict(sig=keys[i], entry=keys[j0], entry_lvl=ent, exit=keys[ex] if status == "closed" else None,
                            last=keys[ex], exit_lvl=L[ex], ret=L[ex] / ent - 1 - (cost if status == "closed" else cost / 2),
                            why=why, bars=ex - j0, status=status, stop_lvl=ent * (1 - stop)))
            prev = st[ex][0]; i = ex + 1 if status == "closed" else len(L); continue
        prev = s; i += 1
    return out

def stats(ts):
    xs = [t["ret"] for t in ts if t.get("status", "closed") == "closed"]
    if not xs: return dict(n=0)
    w = [x for x in xs if x > 0]; l = [x for x in xs if x <= 0]
    return dict(n=len(xs), mean=round(S.mean(xs) * 100, 1), med=round(S.median(xs) * 100, 1), win=round(len(w) / len(xs) * 100),
                avgw=round(S.mean(w) * 100, 1) if w else None, avgl=round(S.mean(l) * 100, 1) if l else None,
                pf=round(sum(w) / -sum(l), 2) if l and sum(l) < 0 else None)
