79 lines
3.3 KiB
Python
79 lines
3.3 KiB
Python
import os
|
|
from typing import Any
|
|
from binance.client import Client # type: ignore
|
|
from app.base.markets import ProductInfo, MarketWrapper, Price
|
|
|
|
|
|
def extract_product(currency: str, ticker_data: dict[str, Any]) -> ProductInfo:
|
|
product = ProductInfo()
|
|
product.id = ticker_data.get('symbol', '')
|
|
product.symbol = ticker_data.get('symbol', '').replace(currency, '')
|
|
product.price = float(ticker_data.get('price', 0))
|
|
product.volume_24h = float(ticker_data.get('volume', 0))
|
|
product.currency = currency
|
|
return product
|
|
|
|
def extract_price(kline_data: list[Any]) -> Price:
|
|
timestamp = kline_data[0]
|
|
|
|
price = Price()
|
|
price.open = float(kline_data[1])
|
|
price.high = float(kline_data[2])
|
|
price.low = float(kline_data[3])
|
|
price.close = float(kline_data[4])
|
|
price.volume = float(kline_data[5])
|
|
price.set_timestamp(timestamp_ms=timestamp)
|
|
return price
|
|
|
|
class BinanceWrapper(MarketWrapper):
|
|
"""
|
|
Wrapper per le API autenticate di Binance.\n
|
|
Implementa l'interfaccia BaseWrapper per fornire accesso unificato
|
|
ai dati di mercato di Binance tramite le API REST con autenticazione.\n
|
|
https://binance-docs.github.io/apidocs/spot/en/
|
|
"""
|
|
|
|
def __init__(self, currency: str = "USD"):
|
|
"""
|
|
Inizializza il wrapper di Binance con le credenziali API e la valuta di riferimento.
|
|
Se viene fornita una valuta fiat come "USD", questa viene automaticamente convertita in una stablecoin Tether ("USDT") per compatibilità con Binance,
|
|
poiché Binance non supporta direttamente le valute fiat per il trading di criptovalute.
|
|
Tutti i prezzi e volumi restituiti saranno quindi denominati nella stablecoin (ad esempio, "USDT") e non nella valuta fiat originale.
|
|
Args:
|
|
currency (str): Valuta in cui restituire i prezzi. Se "USD" viene fornito, verrà utilizzato "USDT". Default è "USD".
|
|
"""
|
|
api_key = os.getenv("BINANCE_API_KEY")
|
|
api_secret = os.getenv("BINANCE_API_SECRET")
|
|
|
|
self.currency = f"{currency}T"
|
|
self.client = Client(api_key=api_key, api_secret=api_secret)
|
|
|
|
def __format_symbol(self, asset_id: str) -> str:
|
|
"""
|
|
Formatta l'asset_id nel formato richiesto da Binance.
|
|
"""
|
|
return asset_id.replace('-', '') if '-' in asset_id else f"{asset_id}{self.currency}"
|
|
|
|
def get_product(self, asset_id: str) -> ProductInfo:
|
|
symbol = self.__format_symbol(asset_id)
|
|
|
|
ticker: dict[str, Any] = self.client.get_symbol_ticker(symbol=symbol) # type: ignore
|
|
ticker_24h: dict[str, Any] = self.client.get_ticker(symbol=symbol) # type: ignore
|
|
ticker['volume'] = ticker_24h.get('volume', 0)
|
|
|
|
return extract_product(self.currency, ticker)
|
|
|
|
def get_products(self, asset_ids: list[str]) -> list[ProductInfo]:
|
|
return [ self.get_product(asset_id) for asset_id in asset_ids ]
|
|
|
|
def get_historical_prices(self, asset_id: str, limit: int = 100) -> list[Price]:
|
|
symbol = self.__format_symbol(asset_id)
|
|
|
|
# Ottiene candele orarie degli ultimi 30 giorni
|
|
klines: list[list[Any]] = self.client.get_historical_klines( # type: ignore
|
|
symbol=symbol,
|
|
interval=Client.KLINE_INTERVAL_1HOUR,
|
|
limit=limit,
|
|
)
|
|
return [extract_price(kline) for kline in klines]
|