import asyncio
import json
import aiohttp
import websockets
from collections import defaultdict

# ===========================
# CONFIGURACIÓN
# ===========================
VOLATILITY_THRESHOLD = 0.2  # % para considerar alta volatilidad
BREAKOUT_THRESHOLD = 0.1    # % sobre la media para marcar compra/venta
HISTORY_LENGTH = 60         # Número de ticks guardados

# ===========================
# GLOBALS
# ===========================
usdc_pairs = []
price_history = defaultdict(list)
latest_data = {}

# ===========================
# Obtener lista de pares USDC
# ===========================
async def fetch_usdc_pairs():
    url = "https://api.binance.com/api/v3/exchangeInfo"
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            data = await resp.json()
            symbols = [
                s["symbol"].lower()
                for s in data["symbols"]
                if s["quoteAsset"] == "USDC" and s["status"] == "TRADING"
            ]
            return symbols

# ===========================
# Escuchar WebSocket
# ===========================
async def listen_all():
    stream_url = (
        "wss://stream.binance.com:9443/stream?streams=" +
        "/".join(f"{s}@bookTicker" for s in usdc_pairs)
    )
    async with websockets.connect(stream_url) as ws:
        async for msg in ws:
            data = json.loads(msg)["data"]
            symbol = data["s"].lower()
            bid = float(data["b"])
            ask = float(data["a"])
            last = (bid + ask) / 2
            latest_data[symbol] = last

            # Guardar histórico
            ph = price_history[symbol]
            ph.append(last)
            if len(ph) > HISTORY_LENGTH:
                ph.pop(0)

# ===========================
# Monitor de volatilidad y señales
# ===========================
async def monitor_signals():
    while True:
        ranking = []
        signals = []

        for symbol in usdc_pairs:
            hist = price_history.get(symbol, [])
            if len(hist) < 5:
                continue

            curr = latest_data[symbol]
            max_p = max(hist)
            min_p = min(hist)
            avg_p = sum(hist) / len(hist)
            volatility = (max_p - min_p) / min_p * 100

            # Ranking de volatilidad
            ranking.append((symbol, volatility))

            # Señales de breakout
            breakout = (curr - avg_p) / avg_p * 100
            if volatility > VOLATILITY_THRESHOLD:
                if breakout > BREAKOUT_THRESHOLD:
                    signals.append(f"🟢 BUY SIGNAL {symbol.upper()} Volatility: {volatility:.2f}% Breakout: +{breakout:.2f}%")
                elif breakout < -BREAKOUT_THRESHOLD:
                    signals.append(f"🔴 SELL SIGNAL {symbol.upper()} Volatility: {volatility:.2f}% Breakout: {breakout:.2f}%")

        # Ordenar por volatilidad
        ranking.sort(key=lambda x: x[1], reverse=True)

        print("=" * 80)
        print("🔝 Top Volatility Pairs:")
        for s, v in ranking[:5]:
            print(f"{s.upper()}: {v:.2f}%")
        if signals:
            print("-" * 80)
            for s in signals:
                print(s)
        print("=" * 80)

        await asyncio.sleep(5)

# ===========================
# MAIN
# ===========================
async def main():
    global usdc_pairs
    usdc_pairs = await fetch_usdc_pairs()
    print(f"✅ USDC pairs loaded: {', '.join(usdc_pairs).upper()}")

    tasks = [
        listen_all(),
        monitor_signals(),
    ]
    await asyncio.gather(*tasks)

if __name__ == "__main__":
    asyncio.run(main())
