# -*- coding: utf-8 -*-
"""
Multi-Asset Correlation & Hedging Engine
- 1-week 1H bars correlation matrix (30 macro assets)
- Data: OKX(crypto) + Binance(PAXG) + Yahoo Finance(rest)
"""
import math, time, json, os, sys
from datetime import datetime

_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, _ROOT)
from config import MACRO_ASSETS
from exchange.http import http_get

ASSETS = MACRO_ASSETS
BAR = '1H'
LIMIT = 168


def fetch_price_history(asset_key, bar=BAR, limit=LIMIT):
    """获取价格历史（收盘价），支持多数据源"""
    cfg = ASSETS.get(asset_key)
    if not cfg: return []
    sym, src = cfg["symbol"], cfg["source"]
    try:
        if src == "okx":
            r = http_get('https://www.okx.com/api/v5/market/candles',
                         params={'instId': sym, 'bar': bar, 'limit': str(limit)}, timeout=12)
            candles = r.json().get('data', [])
            return [float(c[4]) for c in reversed(candles)]
        elif src == "binance":
            interval = {"1H":"1h","4H":"4h","1D":"1d"}.get(bar,"1h")
            r = http_get('https://api.binance.com/api/v3/klines',
                         params={'symbol': sym, 'interval': interval, 'limit': limit}, timeout=12)
            return [float(c[4]) for c in r.json()]
        elif src == "yahoo":
            import yfinance as yf
            interval = {"1H":"1h","4H":"1h","1D":"1d"}.get(bar,"1h")
            t = yf.Ticker(sym)
            df = t.history(period="7d", interval=interval)
            return df['Close'].dropna().tolist() if not df.empty else []
    except Exception:
        return []


def calc_returns(prices):
    """对数收益率"""
    if len(prices) < 2:
        return []
    return [math.log(prices[i]/prices[i-1]) for i in range(1, len(prices))]


def correlation(x, y):
    """Pearson 相关系数"""
    n = min(len(x), len(y))
    if n < 5: return 0.0
    rx, ry = x[-n:], y[-n:]
    mx, my = sum(rx)/n, sum(ry)/n
    num = sum((a-mx)*(b-my) for a,b in zip(rx,ry))
    da = math.sqrt(sum((a-mx)**2 for a in rx))
    db = math.sqrt(sum((b-my)**2 for b in ry))
    return round(num/(da*db), 4) if da>1e-10 and db>1e-10 else 0.0


def analyze():
    symbols = list(ASSETS.keys())
    prices = {}
    returns = {}

    for sym in symbols:
        p = fetch_price_history(sym)  # uses asset key now
        if p:
            prices[sym] = p
            returns[sym] = calc_returns(p)

    valid_syms = [s for s in symbols if s in returns]
    if not valid_syms:
        return {'error': 'no price data'}

    # Correlation matrix
    matrix = {}
    for si in valid_syms:
        matrix[si] = {}
        for sj in valid_syms:
            matrix[si][sj] = correlation(returns[si], returns[sj])

    # Volatilities (annualized from 1H bars)
    vols = {}
    for sym in valid_syms:
        r = returns[sym]
        if r:
            avg = sum(r)/len(r)
            var = sum((x-avg)**2 for x in r)/len(r)
            vols[sym] = round(math.sqrt(var)*math.sqrt(365*24)*100, 2)

    # Current prices
    current = {}
    for sym in valid_syms:
        if sym in prices and prices[sym]:
            current[sym] = round(prices[sym][-1], 2)

    # Hedge suggestions vs BTC
    hedge = []
    btc_corr = matrix.get('BTC', {})
    for sym in valid_syms:
        if sym == 'BTC': continue
        corr_val = btc_corr.get(sym, 0)
        if corr_val < -0.1:    quality = 'Excellent'
        elif corr_val < 0.2:   quality = 'Good'
        elif corr_val < 0.5:   quality = 'Moderate'
        else:                  quality = 'Poor'
        hedge.append({
            'symbol': sym, 'label': ASSETS[sym]['label'],
            'corr': round(corr_val, 3), 'quality': quality,
            'vol': vols.get(sym, 0),
        })
    hedge.sort(key=lambda x: x['corr'])

    # Simple allocation: inverse-correlation weighting
    total_w = 0
    for h in hedge:
        w = max(0, 1 - h['corr'])
        h['weight'] = w
        total_w += w
    if total_w > 0:
        for h in hedge:
            h['weight'] = round(h['weight']/total_w*100, 1)

    return {
        'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
        'bar': BAR, 'limit': LIMIT,
        'symbols': valid_syms,
        'labels': {s: ASSETS[s]['label'] for s in valid_syms},
        'prices': current,
        'correlation_matrix': matrix,
        'volatilities': vols,
        'hedge_suggestions': hedge,
    }


if __name__ == '__main__':
    print(json.dumps(analyze(), indent=1, ensure_ascii=False))
