def __init__(self, cache: BinanceCache, config: Config, binance_client: binance.client.Client, logger: Logger): self.cache = cache self.logger = logger self.bw_api_manager = BinanceWebSocketApiManager( output_default="UnicornFy", enable_stream_signal_buffer=True, exchange=f"binance.{config.BINANCE_TLD}" ) self.bw_api_manager.create_stream( ["arr"], ["!miniTicker"], api_key=config.BINANCE_API_KEY, api_secret=config.BINANCE_API_SECRET_KEY ) self.bw_api_manager.create_stream( ["arr"], ["!userData"], api_key=config.BINANCE_API_KEY, api_secret=config.BINANCE_API_SECRET_KEY ) if config.PRICE_TYPE == Config.PRICE_TYPE_ORDERBOOK: supported_coin_list=config.SUPPORTED_COIN_LIST bridge_coin=config.BRIDGE_SYMBOL symbols = [] for symbol in supported_coin_list: symbol=symbol.lower()+ bridge_coin.lower() symbols.append(symbol) self.bw_api_manager.create_stream( ["bookTicker"], symbols ) self.binance_client = binance_client self.pending_orders: Set[Tuple[str, int]] = set() self.pending_orders_mutex: threading.Lock = threading.Lock() self._processorThread = threading.Thread(target=self._stream_processor) self._processorThread.start()
def __init__( self, cache: BinanceCache, api_key: str, api_secret: str, binance_client: binance.client.Client, logger: Logger ): self.cache = cache self.logger = logger self.bw_api_manager = BinanceWebSocketApiManager(output_default="UnicornFy", enable_stream_signal_buffer=True) self.bw_api_manager.create_stream(["arr"], ["!miniTicker"], api_key=api_key, api_secret=api_secret) self.bw_api_manager.create_stream(["arr"], ["!userData"], api_key=api_key, api_secret=api_secret) self.binance_client = binance_client self.pending_orders: Set[Tuple[str, int]] = set() self.pending_orders_mutex: threading.Lock = threading.Lock() self._processorThread = threading.Thread(target=self._stream_processor) self._processorThread.start()
def __init__(self, cache: BinanceCache, config: Config, binance_client: binance.client.Client, logger: Logger): self.cache = cache self.logger = logger self.bw_api_manager = BinanceWebSocketApiManager( output_default="UnicornFy", enable_stream_signal_buffer=True, exchange=f"binance.{config.BINANCE_TLD}") self.bw_api_manager.create_stream( ["arr"], ["!miniTicker"], api_key=config.BINANCE_API_KEY, api_secret=config.BINANCE_API_SECRET_KEY) self.bw_api_manager.create_stream( ["arr"], ["!userData"], api_key=config.BINANCE_API_KEY, api_secret=config.BINANCE_API_SECRET_KEY) self.binance_client = binance_client self.pending_orders: Set[Tuple[str, int]] = set() self.pending_orders_mutex: threading.Lock = threading.Lock() self._processorThread = threading.Thread(target=self._stream_processor) self._processorThread.start()
class BinanceStreamManager: def __init__(self, cache: BinanceCache, config: Config, binance_client: binance.client.Client, logger: Logger): self.cache = cache self.logger = logger self.bw_api_manager = BinanceWebSocketApiManager( output_default="UnicornFy", enable_stream_signal_buffer=True, exchange=f"binance.{config.BINANCE_TLD}") self.bw_api_manager.create_stream( ["arr"], ["!miniTicker"], api_key=config.BINANCE_API_KEY, api_secret=config.BINANCE_API_SECRET_KEY) self.bw_api_manager.create_stream( ["arr"], ["!userData"], api_key=config.BINANCE_API_KEY, api_secret=config.BINANCE_API_SECRET_KEY) self.binance_client = binance_client self.pending_orders: Set[Tuple[str, int]] = set() self.pending_orders_mutex: threading.Lock = threading.Lock() self._processorThread = threading.Thread(target=self._stream_processor) self._processorThread.start() def acquire_order_guard(self): return OrderGuard(self.pending_orders, self.pending_orders_mutex) def _fetch_pending_orders(self): pending_orders: Set[Tuple[str, int]] with self.pending_orders_mutex: pending_orders = self.pending_orders.copy() for (symbol, order_id) in pending_orders: order = None while True: try: order = self.binance_client.get_order(symbol=symbol, orderId=order_id) except (BinanceRequestException, BinanceAPIException) as e: self.logger.error( f"Got exception during fetching pending order: {e}") if order is not None: break time.sleep(1) fake_report = { "symbol": order["symbol"], "side": order["side"], "order_type": order["type"], "order_id": order["orderId"], "cumulative_quote_asset_transacted_quantity": float(order["cummulativeQuoteQty"]), "current_order_status": order["status"], "order_price": float(order["price"]), "transaction_time": order["time"], } self.logger.info( f"Pending order {order_id} for symbol {symbol} fetched:\n{fake_report}", False) self.cache.orders[fake_report["order_id"]] = BinanceOrder( fake_report) def _invalidate_balances(self): with self.cache.open_balances() as balances: balances.clear() def _stream_processor(self): while True: if self.bw_api_manager.is_manager_stopping(): sys.exit() stream_signal = self.bw_api_manager.pop_stream_signal_from_stream_signal_buffer( ) stream_data = self.bw_api_manager.pop_stream_data_from_stream_buffer( ) if stream_signal is not False: signal_type = stream_signal["type"] stream_id = stream_signal["stream_id"] if signal_type == "CONNECT": stream_info = self.bw_api_manager.get_stream_info( stream_id) if "!userData" in stream_info["markets"]: self.logger.debug("Connect for userdata arrived", False) self._fetch_pending_orders() self._invalidate_balances() if stream_data is not False: self._process_stream_data(stream_data) if stream_data is False and stream_signal is False: time.sleep(0.01) def _process_stream_data(self, stream_data): event_type = stream_data["event_type"] if event_type == "executionReport": # !userData self.logger.debug(f"execution report: {stream_data}") order = BinanceOrder(stream_data) self.cache.orders[order.id] = order elif event_type == "balanceUpdate": # !userData self.logger.debug(f"Balance update: {stream_data}") with self.cache.open_balances() as balances: asset = stream_data["asset"] if asset in balances: del balances[stream_data["asset"]] elif event_type in ("outboundAccountPosition", "outboundAccountInfo"): # !userData self.logger.debug(f"{event_type}: {stream_data}") with self.cache.open_balances() as balances: for bal in stream_data["balances"]: balances[bal["asset"]] = float(bal["free"]) elif event_type == "24hrMiniTicker": for event in stream_data["data"]: self.cache.ticker_values[event["symbol"]] = float( event["close_price"]) else: self.logger.error( f"Unknown event type found: {event_type}\n{stream_data}") def close(self): self.bw_api_manager.stop_manager_with_all_streams()
class BinanceStreamManager: def __init__(self, cache: BinanceCache, api_key: str, api_secret: str, binance_client: binance.client.Client, logger: Logger): self.cache = cache self.logger = logger self.bwApiManager = BinanceWebSocketApiManager( output_default="UnicornFy", enable_stream_signal_buffer=True) self.bwApiManager.create_stream(["arr"], ["!miniTicker"], api_key=api_key, api_secret=api_secret) self.bwApiManager.create_stream(["arr"], ["!userData"], api_key=api_key, api_secret=api_secret) self.binance_client = binance_client self.pending_orders: Set[(str, int)] = set() self._processorThread = threading.Thread(target=self._stream_processor) self._processorThread.start() def add_pending_order(self, order_tag: (str, int)): self.pending_orders.add(order_tag) def remove_pending_order(self, order_tag: (str, int)): self.pending_orders.remove(order_tag) def _fetch_pending_orders(self): orders = self.pending_orders.copy() for (symbol, order_id) in orders: order = None while True: try: order = self.binance_client.get_order(symbol=symbol, orderId=order_id) except (BinanceRequestException, BinanceAPIException): pass if orders is not None: break time.sleep(1) fake_report = { "symbol": order["symbol"], "side": order["side"], "order_type": order["type"], "order_id": order["orderId"], "cumulative_quote_asset_transacted_quantity": float(order["cummulativeQuoteQty"]), "current_order_status": order["status"], "order_price": float(order["price"]), "transaction_time": order["time"], } self.logger.info( f"Pending order {order_id} for symbol {symbol} fetched:\n{fake_report}", False) self.cache.orders[fake_report["order_id"]] = BinanceOrder( fake_report) def _invalidate_balances(self): with self.cache.balances_mutex: self.cache.balances.clear() def _stream_processor(self): while True: if self.bwApiManager.is_manager_stopping(): sys.exit() stream_signal = self.bwApiManager.pop_stream_signal_from_stream_signal_buffer( ) stream_data = self.bwApiManager.pop_stream_data_from_stream_buffer( ) if stream_signal is not False: signal_type = stream_signal["type"] stream_id = stream_signal["stream_id"] if signal_type == "CONNECT": stream_info = self.bwApiManager.get_stream_info(stream_id) if "!userData" in stream_info["markets"]: self.logger.debug("Connect for userdata arrived", False) self._fetch_pending_orders() self._invalidate_balances() if stream_data is not False: self._process_stream_data(stream_data) if stream_data is False and stream_signal is False: time.sleep(0.01) def _process_stream_data(self, stream_data): event_type = stream_data["event_type"] if event_type == "executionReport": # !userData self.logger.debug(f"execution report: {stream_data}") order = BinanceOrder(stream_data) self.cache.orders[order.id] = order elif event_type == "balanceUpdate": # !userData self.logger.debug(f"Balance update: {stream_data}") with self.cache.balances_mutex: del self.cache.balances[stream_data["asset"]] elif event_type == "outboundAccountPosition": # !userData self.logger.debug(f"outboundAccountPosition: {stream_data}") with self.cache.balances_mutex: for bal in stream_data["balances"]: self.cache.balances[bal["asset"]] = float(bal["free"]) elif event_type == "24hrMiniTicker": for event in stream_data["data"]: self.cache.ticker_values[event["symbol"]] = float( event["close_price"]) else: self.logger.error( f"Unknown event type found: {event_type}\n{stream_data}") def close(self): self.bwApiManager.stop_manager_with_all_streams()