import asyncio import json import websockets import requests class BinancePerpStream: def __init__(self, quote_filters, chunk_size=50): self.base_url = "wss://fstream.binance.com/stream" self.quote_filters = quote_filters self.chunk_size = chunk_size self.symbol_chunks = self.get_symbol_chunks() def get_symbol_chunks(self): try: url = "https://fapi.binance.com/fapi/v1/exchangeInfo" data = requests.get(url).json() symbols = [s["symbol"] for s in data["symbols"] if s["quoteAsset"] in self.quote_filters] print("[BINANCE] Starting stream with", len(symbols), "symbols") return [symbols[i:i+self.chunk_size] for i in range(0, len(symbols), self.chunk_size)] except Exception as e: print("[BINANCE REST ERROR]", e) return [] def normalize_symbol(self, symbol): return symbol.replace("USDT", "/USDT") def parse_tick(self, msg): data = msg.get("data") if not data: return None symbol = data["s"] return { "exchange": "binance", "symbol": self.normalize_symbol(symbol), "bid": float(data["b"]), "ask": float(data["a"]), "bid_size": float(data["B"]), "ask_size": float(data["A"]) } async def stream_chunk(self, symbols): streams = "/".join([f"{s.lower()}@bookTicker" for s in symbols]) url = f"{self.base_url}?streams={streams}" async with websockets.connect(url) as ws: async for msg in ws: try: data = json.loads(msg) tick = self.parse_tick(data) if tick: yield tick except Exception as e: print("[BINANCE PAR