Files
Binance_Altcoin_Monitor/backend/app/binance.py
T
2026-05-22 13:06:42 +08:00

89 lines
2.8 KiB
Python

import asyncio
import logging
from typing import Any
import httpx
from .config import settings
from .http_client import httpx_client_kwargs
logger = logging.getLogger(__name__)
class BinanceFuturesClient:
def __init__(self) -> None:
self.base = settings.binance_fapi_base.rstrip("/")
self._symbols_cache: list[str] | None = None
async def _get(self, path: str, params: dict | None = None) -> Any:
url = f"{self.base}{path}"
async with httpx.AsyncClient(
timeout=30.0, **httpx_client_kwargs("binance")
) as client:
resp = await client.get(url, params=params or {})
resp.raise_for_status()
return resp.json()
async def get_usdt_perpetual_symbols(self) -> list[str]:
if self._symbols_cache:
return self._symbols_cache
info = await self._get("/fapi/v1/exchangeInfo")
symbols = []
for s in info.get("symbols", []):
if (
s.get("contractType") == "PERPETUAL"
and s.get("quoteAsset") == "USDT"
and s.get("status") == "TRADING"
):
symbols.append(s["symbol"])
self._symbols_cache = sorted(symbols)
logger.info("Loaded %d USDT perpetual symbols", len(self._symbols_cache))
return self._symbols_cache
def clear_symbol_cache(self) -> None:
self._symbols_cache = None
async def get_klines(
self,
symbol: str,
start_ms: int,
end_ms: int,
interval: str = "1h",
) -> list[list]:
all_klines: list[list] = []
cursor = start_ms
while cursor < end_ms:
batch = await self._get(
"/fapi/v1/klines",
{
"symbol": symbol,
"interval": interval,
"startTime": cursor,
"endTime": end_ms,
"limit": 1500,
},
)
if not batch:
break
all_klines.extend(batch)
last_open = int(batch[-1][0])
next_cursor = last_open + 3600_000
if next_cursor <= cursor:
break
cursor = next_cursor
if len(batch) < 1500:
break
return all_klines
async def get_price(self, symbol: str) -> float:
data = await self._get("/fapi/v1/ticker/price", {"symbol": symbol})
return float(data["price"])
async def get_prices_batch(self, symbols: list[str]) -> dict[str, float]:
tickers = await self._get("/fapi/v1/ticker/price")
sym_set = set(symbols)
return {t["symbol"]: float(t["price"]) for t in tickers if t["symbol"] in sym_set}
binance_client = BinanceFuturesClient()