#!/usr/bin/env python3
"""更新Sniper状态到JSON，供面板读取"""
import requests, json, os, sys, time
import pandas as pd, numpy as np

STATUS_FILE = "/root/quant_pipeline/sniper_status.json"

def get_daily(limit=500):
    url = f"https://www.okx.com/api/v5/market/candles?instId=BTC-USDT-SWAP&bar=1D&limit={limit}"
    r = requests.get(url, timeout=10)
    data = r.json()["data"]
    df = pd.DataFrame(data, columns=["ts","o","h","l","c","vol","_","_","_"])
    for col in ["o","h","l","c","vol"]: df[col] = df[col].astype(float)
    df["ts"] = pd.to_datetime(df["ts"].astype(int), unit="ms")
    df = df.set_index("ts").iloc[::-1].sort_index()
    return df

def get_ticker():
    r = requests.get("https://www.okx.com/api/v5/market/ticker?instId=BTC-USDT-SWAP", timeout=10)
    return r.json()["data"][0]

try:
    ticker = get_ticker()
    current_price = float(ticker["last"])
    daily_change = float(ticker.get("change24h", 0))
    
    daily = get_daily()
    # 手动构建周线：按ISO周分组
    daily["w"] = daily.index.isocalendar().year.astype(str) + "-W" + daily.index.isocalendar().week.astype(str).str.zfill(2)
    weekly = daily.groupby("w").agg({"o": "first", "h": "max", "l": "min", "c": "last", "vol": "sum"}).reset_index(drop=True)
    C = weekly["c"].values
    n = len(C)
    
    # RSI(14)
    delta = pd.Series(C).diff()
    gain = delta.clip(lower=0).rolling(14).mean()
    loss = (-delta.clip(upper=0)).rolling(14).mean()
    rsi = (100 - 100/(1+gain/(loss+1e-9))).values
    
    sma20 = pd.Series(C).rolling(20).mean().values
    ret_8w = C / np.roll(C, 8) - 1
    ret_4w = C / np.roll(C, 4) - 1
    
    latest = n - 1
    price = C[latest]
    rsi_val = round(rsi[latest], 1) if not np.isnan(rsi[latest]) else 0
    ma20_val = round(sma20[latest], 1) if not np.isnan(sma20[latest]) else 0
    drop_8w = round(ret_8w[latest] * 100, 1) if not np.isnan(ret_8w[latest]) else 0
    drop_4w = round(ret_4w[latest] * 100, 1) if not np.isnan(ret_4w[latest]) else 0
    
    # 信号条件检查
    signal = (rsi_val > 20) and (rsi_val < 35) and (drop_8w < -10) and (price < ma20_val)
    
    # 全部转原生Python类型
    rsi_val_n = float(rsi_val)
    ma20_val_n = float(ma20_val)
    drop_8w_n = float(drop_8w)
    drop_4w_n = float(drop_4w)
    price_n = float(price)
    current_price_n = float(current_price)
    daily_change_n = float(daily_change)
    signal_bool = bool(signal)
    
    # 信号强度评分（0-100）
    signal_strength = 0
    if rsi_val_n > 20 and rsi_val_n < 35: signal_strength += 30
    if drop_8w_n < -10: signal_strength += 30
    if price_n < ma20_val_n: signal_strength += 20
    if rsi_val_n > 23 and rsi_val_n < 30: signal_strength += 20
    
    signal_strength = int(min(signal_strength, 100))
    
    # 读取已有日志
    sniper_trades = []
    log_file = "/root/quant_pipeline/sniper_log.json"
    if os.path.exists(log_file):
        with open(log_file) as f:
            sniper_trades = json.load(f)
    
    status = {
        "time": time.strftime("%Y-%m-%d %H:%M:%S"),
        "current_price": current_price_n,
        "daily_change": daily_change_n,
        "weekly_close": price_n,
        "rsi": rsi_val_n,
        "ma20": ma20_val_n,
        "drop_8w": drop_8w_n,
        "drop_4w": drop_4w_n,
        "signal": signal_bool,
        "signal_strength": signal_strength,
        "period_weeks": int(n),
        "trades": len(sniper_trades),
        "last_check": time.strftime("%Y-%m-%d %H:%M"),
    }
    
    with open(STATUS_FILE, "w") as f:
        json.dump(status, f, indent=2)
    
    print(f"✅ Sniper状态已更新: price=${current_price:.0f} RSI={rsi_val} signal={signal}")
    
except Exception as e:
    print(f"❌ 更新失败: {e}")
    # 写一个默认状态文件（如果不存在）
    if not os.path.exists(STATUS_FILE):
        with open(STATUS_FILE, "w") as f:
            json.dump({"time": time.strftime("%Y-%m-%d %H:%M:%S"), "error": str(e)}, f)