#!/usr/bin/env python3
"""6669 緯穎 split-adjusted indicator computation from TWSE official data."""
import json, re
from datetime import date
import numpy as np
import pandas as pd

FILES = ['tw_6669_202604.json', 'tw_6669_202605.json', 'tw_6669_202606.json',
         'tw_6669_202607.json', 'tw_6669_202608.json', 'tw_6669_sep.json', 'tw_6669_oct.json']
SPLIT_DATE = date(2026, 9, 2)
SPLIT_FACTOR = 3.0

def parse(path):
    d = json.load(open(path, encoding='utf-8'))
    if d.get('stat') != 'OK':
        return None
    rows = []
    for r in d['data']:
        m = re.match(r'^(\d+)/(\d+)/(\d+)$', r[0].strip())
        y = int(m.group(1)) + 1911
        num = lambda x: float(str(x).replace(',', '').replace('+', '').strip())
        rows.append(dict(date=date(y, int(m.group(2)), int(m.group(3))), vol=num(r[1]),
                         open=num(r[3]), high=num(r[4]), low=num(r[5]), close=num(r[6])))
    return pd.DataFrame(rows).set_index('date').sort_index()

fr = [parse(f) for f in FILES]
h = pd.concat([f for f in fr if f is not None])
h = h[~h.index.duplicated(keep='last')].sort_index()
h = h[h['vol'] > 0]
raw = h.copy()
for col in ['open', 'high', 'low', 'close']:
    h[col] = np.where(h.index < SPLIT_DATE, h[col] / SPLIT_FACTOR, h[col])

c, v = h['close'], h['vol']
ema = lambda s, n: s.ewm(span=n, adjust=False).mean()

ma20 = c.rolling(20).mean()
ma60 = c.rolling(60).mean()
d = c.diff(); up = d.clip(lower=0); dn = -d.clip(upper=0)
rs = (up.rolling(14).mean() / dn.rolling(14).mean()).replace([np.inf, -np.inf], np.nan).fillna(50)
rsi = 100 - 100 / (1 + rs)
macd = ema(c, 12) - ema(c, 26); sig = ema(macd, 9); hist = macd - sig
low9 = h['low'].rolling(9).min(); high9 = h['high'].rolling(9).min()
low9 = h['low'].rolling(9).min(); high9 = h['high'].rolling(9).max()
rsv = ((c - low9) / (high9 - low9) * 100).fillna(50)
k_ema = rsv.ewm(com=2, adjust=False).mean(); d_ema = k_ema.ewm(com=2, adjust=False).mean()
k_sma = rsv.rolling(3).mean(); d_sma = k_sma.rolling(3).mean()

# streak of consecutive closes below MA60
below = (c < ma60).values
streak = 0
for b in reversed(below):
    if b:
        streak += 1
    else:
        break
seg = v.iloc[-streak:]
streak_dates = [str(x) for x in h.index[-streak:]]
prev3 = float(seg.iloc[:3].mean()); last3 = float(seg.tail(3).mean())
vol_chg = (last3 - prev3) / prev3 * 100

v20 = float(v.rolling(20).mean().iloc[-1])
vol_today = float(v.iloc[-1])

out = {
    "split_note": f"2026-09-02 ex-split 1:3 (7,800 -> 2,610); pre-split OHLC divided by {SPLIT_FACTOR}",
    "bars": int(len(h)), "last": str(h.index[-1]),
    "close": float(c.iloc[-1]), "prev_close": float(c.iloc[-2]),
    "chg_pct": float((c.iloc[-1] / c.iloc[-2] - 1) * 100),
    "ma20": float(ma20.iloc[-1]), "ma60": float(ma60.iloc[-1]),
    "ma20_prev": float(ma20.iloc[-2]), "ma60_prev": float(ma60.iloc[-2]),
    "rsi14": float(rsi.iloc[-1]), "rsi_prev": float(rsi.iloc[-2]),
    "macd": float(macd.iloc[-1]), "signal": float(sig.iloc[-1]),
    "hist": float(hist.iloc[-1]), "hist_prev": float(hist.iloc[-2]),
    "K_ema": float(k_ema.iloc[-1]), "D_ema": float(d_ema.iloc[-1]),
    "K_ema_prev": float(k_ema.iloc[-2]), "D_ema_prev": float(d_ema.iloc[-2]),
    "K_sma": float(k_sma.iloc[-1]), "D_sma": float(d_sma.iloc[-1]),
    "K_sma_prev": float(k_sma.iloc[-2]), "D_sma_prev": float(d_sma.iloc[-2]),
    "volume": vol_today, "vol20avg": v20, "vol_ratio": vol_today / v20,
    "low20": float(c.tail(20).min()), "high20": float(c.tail(20).max()),
    "high60": float(c.tail(60).max()),
    "streak_below_ma60": int(streak), "streak_first": streak_dates[0] if streak_dates else None,
    "streak_prev3_avg_vol": prev3, "streak_last3_avg_vol": last3,
    "streak_vol_chg_pct": vol_chg,
    "last20": [[str(i), float(cc), float(vv), float(m60v), float(rsiv), float(histv), float(ma20v)]
               for i, cc, vv, m60v, rsiv, histv, ma20v in zip(c.tail(20).index, c.tail(20), v.tail(20), ma60.tail(20), rsi.tail(20), hist.tail(20), ma20.tail(20))],
    "ma60_cross_note": {
        "last_close_above_ma60": None,
    },
    "fixed_2142_streak": None,
}

# fixed-threshold reading (skill's stated MA60 = 2,142)
fixed = 2142.0
below_fix = (c < fixed).values
st = 0
for b in reversed(below_fix):
    if b:
        st += 1
    else:
        break
segf = v.iloc[-st:]
out["fixed_2142_streak"] = int(st)
out["fixed_2142_first"] = str(h.index[-st]) if st else None
out["fixed_2142_prev3"] = float(segf.iloc[:3].mean())
out["fixed_2142_last3"] = float(segf.tail(3).mean())
out["fixed_2142_volchg"] = (float(segf.tail(3).mean()) - float(segf.iloc[:3].mean())) / float(segf.iloc[:3].mean()) * 100

print("###JSON###")
print(json.dumps(out, ensure_ascii=False, indent=1))
