import requests import json from collections import defaultdict from concurrent.futures import ThreadPoolExecutor, as_completed # === GET SYMBOLS FROM EXCHANGES === def get_binance_symbols(): url = "https://fapi.binance.com/fapi/v1/exchangeInfo" data = requests.get(url).json() return [s["symbol"].replace("USDT", "/USDT") for s in data["symbols"] if s["quoteAsset"] == "USDT"] def get_bybit_symbols(): url = "https://api.bybit.com/v5/market/instruments-info" params = {"category": "linear"} r = requests.get(url, params=params) data = r.json() return [ s["symbol"].replace("USDT", "/USDT") for s in data.get("result", {}).get("list", []) if "USDT" in s["symbol"] ] def get_okx_symbols(): url = "https://www.okx.com/api/v5/public/instruments" params = {"instType": "SWAP"} data = requests.get(url, params=params).json() return [s["instId"].replace("-USDT-SWAP", "/USDT") for s in data.get("data", []) if s["instId"].endswith("USDT-SWAP")] # === LOAD SYMBOLS === bybit_symbols = get_bybit_symbols() binance_symbols = get_binance_symbols() okx_symbols = get_okx_symbols() symbols = sorted(list(set(bybit_symbols + binance_symbols + okx_symbols))) # === FUNDING FUNCTIONS === def normalize_symbol(symbol): return symbol.replace("/", "") def get_binance_funding(symbol): try: url = "https://fapi.binance.com/fapi/v1/premiumIndex" params = {"symbol": normalize_symbol(symbol)} data = requests.get(url, params=params, timeout=3).json() return "binance", symbol, float(data.get("lastFundingRate", 0)) except Exception as e: print(f"[Binance] {symbol} funding error: {e}") return "binance", symbol, 0.0 def get_bybit_funding(symbol): try: url = "https://api.bybit.com/v5/market/tickers" params = {"category": "linear"} data = requests.get(url, params=params, timeout=3).json() for item in data.get("result", {}).get("list", []): if item.get("symbol") == normalize_symbol(symbol): return "bybit", symbol, float(item.get("fundingRate", 0)) except Exception as e: print(f"[Bybit] {symbol} funding error: {e}") return "bybit", symbol, 0.0 def get_okx_funding(symbol): try: inst_id = symbol.replace("/", "-") + "-SWAP" url = "https://www.okx.com/api/v5/public/funding-rate" params = {"instId": inst_id} data = requests.get(url, params=params, timeout=3).json() return "okx", symbol, float(data.get("data", [{}])[0].get("fundingRate", 0)) except Exception as e: print(f"[OKX] {symbol} funding error: {e}") return "okx", symbol, 0.0 def get_hyperliquid_funding(symbol): try: symbol_usd = symbol.replace("USDT", "USD").replace("/", "") url = "https://api.hyperliquid.xyz/info" headers = {"Content-Type": "application/json"} payload = {"type": "metaAndAssetCtxs"} response = requests.post(url, headers=headers, json=payload) data = response.json() assets = data[0]["universe"] asset_data = data[1] for i in range(len(assets)): name = assets[i].get("name", "").upper() if name == symbol_usd.replace("USD", "").upper(): return "hyperliquid", symbol, float(asset_data[i].get("funding", 0)) except Exception as e: print(f"[Hyperliquid Funding Error] {symbol}: {e}") return "hyperliquid", symbol, 0.0 funding_funcs = [ get_binance_funding, get_bybit_funding, get_okx_funding, get_hyperliquid_funding # ✅ incluir aqui ] funding_data = defaultdict(dict) with ThreadPoolExecutor(max_workers=20) as executor: tasks = [executor.submit(func, symbol) for symbol in symbols for func in funding_funcs] for future in as_completed(tasks): exchange, symbol, rate = future.result() funding_data[symbol][exchange] = rate # Save to file with open("funding_cache.json", "w") as f: json.dump(funding_data, f, indent=2) print("[✓] funding_cache.json atualizado com sucesso")