Source code for dccd.histo_dl.binance

#!/usr/bin/env python3
# coding: utf-8
# @Author: ArthurBernard
# @Email: arthur.bernard.92@gmail.com
# @Date: 2019-02-13 18:26:20
# @Last modified by: ArthurBernard
# @Last modified time: 2019-09-03 22:04:22

""" Objects to download historical data from Binance exchange.

.. currentmodule:: dccd.histo_dl.binance

.. autoclass:: FromBinance
   :members: import_data, save, get_data, import_trades, save_trades, import_orderbook, save_orderbook
   :show-inheritance:

"""

from __future__ import annotations

# Import built-in packages
import logging
from typing import Any

# Import third-party packages
from dccd.histo_dl.exchange import ImportDataCryptoCurrencies

# Import local packages
from dccd.tools.date_time import binance_interval

__all__ = ['FromBinance']

_logger = logging.getLogger(__name__)


[docs] class FromBinance(ImportDataCryptoCurrencies): """ Class to import crypto-currencies data from the Binance exchange. Parameters ---------- path : str Root directory for data files. crypto : str Crypto-currency symbol, e.g. ``'BTC'``. span : int or str Candle interval in seconds (minimum 60) or a label such as ``'hourly'`` or ``'1h'``. fiat : str, optional Quote currency. Default is ``'USD'``, which is silently coerced to ``'USDT'`` (Binance does not support fiat; only USDT is accepted as a USD-equivalent). ``'EUR'`` is likewise coerced to ``'USDT'`` with a warning. form : str, optional Legacy parameter — ignored. Storage is always Parquet via :class:`~dccd.storage.DataStore`. tz : str, optional Timezone for date parsing: ``'local'`` (default), ``'UTC'``, or any IANA timezone name (e.g. ``'Europe/Paris'``). See Also -------- FromKraken, FromCoinbase, FromBybit, FromOKX Notes ----- See Binance API documentation [1]_ for more details on parameters. References ---------- .. [1] https://github.com/binance-exchange/binance-official-api-docs Attributes ---------- pair : str Pair symbol, `crypto + fiat`. start, end : int Timestamp to starting and ending download data. span : int Number of seconds between observations. full_path : str Directory managed by :class:`~dccd.storage.DataStore` — ``{path}/binance/ohlc/{pair}/{span}/``. Methods ------- import_data save get_data import_trades save_trades import_orderbook save_orderbook """
[docs] @staticmethod def format_pair(crypto: str, fiat: str) -> str: """ Return the Binance pair symbol for *crypto* and *fiat*. Parameters ---------- crypto, fiat : str Asset symbols (e.g. ``'BTC'``, ``'USDT'``). Returns ------- str Concatenated pair (e.g. ``'BTCUSDT'``). """ if crypto == 'XBT': crypto = 'BTC' return crypto + fiat
def __init__(self, path, crypto, span, fiat='USD', form='xlsx', tz='local'): if fiat in ['EUR', 'USD']: _logger.warning( "Binance don't allow fiat currencies. " "The equivalent of US dollar is Tether USD as USDT." ) self.fiat = fiat = 'USDT' ImportDataCryptoCurrencies.__init__( self, path, crypto, span, 'Binance', fiat, form, tz=tz ) self.pair = self.format_pair(crypto, fiat) def _import_data(self, start: int | str = 'last', end: int | str = 'now') -> list[dict[str, Any]]: self.start, self.end = self._set_time(start, end) param = { 'symbol': self.pair, 'startTime': self.start * 1000, 'endTime': self.end * 1000, 'interval': binance_interval(self.span), 'limit': 1000, } r = self._fetch('https://api.binance.com/api/v3/klines', param) text = r.json() data = [{ 'date': float(e[0] / 1000), 'open': float(e[1]), 'high': float(e[2]), 'low': float(e[3]), 'close': float(e[4]), 'volume': float(e[5]), 'quoteVolume': float(e[7]) } for e in text] return data def _import_trades(self, start: int, end: int) -> list[dict[str, Any]]: param = { 'symbol': self.pair, 'startTime': start * 1000, 'endTime': end * 1000, 'limit': 1000, } r = self._fetch('https://api.binance.com/api/v3/aggTrades', param) return [{ 'tid': int(e['a']), 'timestamp': float(e['T']) / 1000, 'price': float(e['p']), 'amount': float(e['q']), 'type': 'sell' if e['m'] else 'buy', } for e in r.json()] def _import_orderbook(self, depth: int = 50) -> list[dict[str, Any]]: r = self._fetch( 'https://api.binance.com/api/v3/depth', {'symbol': self.pair, 'limit': depth}, ) book = r.json() result = [] for bid in book['bids']: result.append({'side': 'bid', 'price': bid[0], 'amount': float(bid[1]), 'count': None}) for ask in book['asks']: result.append({'side': 'ask', 'price': ask[0], 'amount': float(ask[1]), 'count': None}) return result
[docs] def import_data(self, start: int | str = 'last', end: int | str = 'now') -> ImportDataCryptoCurrencies: """ Download data from Binance for specific time interval. Parameters ---------- start : int or str Timestamp of the first observation of you want as int or date format 'yyyy-mm-dd hh:mm:ss' as string. end : int or str Timestamp of the last observation of you want as int or date format 'yyyy-mm-dd hh:mm:ss' as string. Returns ------- data : pl.DataFrame Data sorted and cleaned in a data frame. """ data = self._import_data(start=start, end=end) return self._sort_data(data)