#!/usr/bin/env python3
import json, os, math, statistics as stats

ROOT = os.path.expanduser("~/kleiner")
DATA = os.path.join(ROOT, "data")
HIST = os.path.join(DATA, "history")
OUT  = os.path.join(DATA, "indicators.json")

def load_hist(path):
    if not os.path.exists(path): return []
    with open(path, "r", encoding="utf-8") as f:
        arr = json.load(f)
    # erwartet: [{t:'YYYY-MM-DD', o,h,l,c,v}, …] aufsteigend
    return [r for r in arr if all(k in r for k in ("o","h","l","c","v"))]

def ema(values, n):
    if not values: return None
    k = 2/(n+1)
    e = values[0]
    for v in values[1:]:
        e = v*k + e*(1-k)
    return e

def atr14(rows):
    # Wilder ATR(14)
    if len(rows) < 2: return None
    trs = []
    prev_c = rows[0]["c"]
    for r in rows[1:]:
        hl = r["h"] - r["l"]
        hc = abs(r["h"] - prev_c)
        lc = abs(r["l"] - prev_c)
        tr = max(hl, hc, lc)
        trs.append(tr)
        prev_c = r["c"]
    if len(trs) < 14: 
        return stats.fmean(trs) if trs else None
    # Initial-ATR
    atr = sum(trs[:14]) / 14.0
    for tr in trs[14:]:
        atr = (atr*13 + tr) / 14.0
    return atr

def rvol20(rows):
    if len(rows) < 21: return None
    vol_last = rows[-1]["v"]
    avg20 = stats.fmean([r["v"] for r in rows[-21:-1]])
    return (vol_last/avg20) if avg20 else None

def classify_trend(close, ema200, band=0.005):
    if ema200 is None or close is None: return "—"
    if close > ema200*(1+band): return "Aufwärts"
    if close < ema200*(1-band): return "Abwärts"
    return "Seitwärts"

def score_simple(trend, atrp, rvol):
    # Grober Score 60–95 als Platzhalter
    s = 65
    if trend == "Aufwärts": s += 10
    if trend == "Abwärts": s += 5   # neutraler Bonus, echte Logik später getrennt für Long/Short
    if rvol is not None:
        s += max(-5, min(15, (rvol-1.0)*10))  # 1.0 -> 0; 2.5 -> +15; 0.5 -> -5
    if atrp is not None:
        # sweet spot 2–8 %
        if 2 <= atrp <= 8: s += 8
        elif atrp < 1.2: s -= 6
        elif atrp > 10: s -= 4
    return int(max(50, min(99, round(s))))

def process_symbol(sym):
    rows = load_hist(os.path.join(HIST, f"{sym}.json"))
    if not rows: 
        return {"symbol": sym, "ready": False}
    closes = [r["c"] for r in rows]
    ema200 = ema(closes[-min(len(closes), 300):], 200)
    ema220 = ema(closes[-min(len(closes), 320):], 220)
    atr = atr14(rows[-120:])  # genug Historie
    close = rows[-1]["c"]
    atrp = (atr/close*100.0) if (atr and close) else None
    rv = rvol20(rows)
    trend = classify_trend(close, ema200)
    score = score_simple(trend, atrp, rv)

    return {
        "symbol": sym,
        "ready": True if len(rows) >= 220 else False,
        "close": round(close, 4),
        "ema200": round(ema200, 4) if ema200 else None,
        "ema220": round(ema220, 4) if ema220 else None,
        "atr14": round(atr, 4) if atr else None,
        "atrp": round(atrp, 2) if atrp is not None else None,
        "rvol20": round(rv, 2) if rv is not None else None,
        "trend": trend,
        "score": score
    }

def main():
    # Universum = alle Dateien in /history
    syms = [f[:-5] for f in os.listdir(HIST) if f.endswith(".json")]
    out = [process_symbol(s) for s in sorted(syms)]
    tmp = OUT + ".tmp"
    with open(tmp, "w", encoding="utf-8") as f:
        json.dump(out, f, ensure_ascii=False, separators=(",",":"))
    os.replace(tmp, OUT)
    print("indicators ok:", len(out))

if __name__ == "__main__":
    main()
