async def start_network(self): if self._poll_weth_logs_task is not None: await self.stop_network() self._blocks_watcher.add_listener(NewBlocksWatcherEvent.NewBlocks, self._event_forwarder) self._poll_weth_logs_task = safe_ensure_future(self.poll_weth_logs_loop())
def setUpClass(cls): cls.ev_loop: asyncio.BaseEventLoop = asyncio.get_event_loop() cls.user_stream_tracker: VitexUserStreamTracker = VitexUserStreamTracker( ) cls.user_stream_tracker_task: asyncio.Task = safe_ensure_future( cls.user_stream_tracker.start())
async def start(self): self._user_stream_tracking_task = safe_ensure_future( self.data_source.listen_for_user_stream(self._user_stream)) await safe_gather(self._user_stream_tracking_task)
def start(self): if self._coro_scheduler_task is not None: self.stop() self._coro_scheduler_task = safe_ensure_future( self._coro_scheduler(self._coro_queue, self._call_interval))
def start(self): super().start() self._order_book_stream_listener_task = safe_ensure_future( self._data_source.listen_for_subscriptions()) self._order_book_funding_info_listener_task = safe_ensure_future( self._data_source.listen_for_funding_info())
def start(self): if self._set_server_time_offset_task is None: self._set_server_time_offset_task = safe_ensure_future( self.update_server_time_offset_loop()) self._started = True
async def start_network(self): if self._outgoing_transactions_task is not None: await self.stop_network() async_scheduler: AsyncCallScheduler = AsyncCallScheduler.shared_instance( ) if len(self._erc20_tokens) < len(self._erc20_token_list): # Fetch token data. fetch_symbols_tasks: List[Coroutine] = [ token.get_symbol() for token in self._erc20_token_list ] fetch_decimals_tasks: List[Coroutine] = [ token.get_decimals() for token in self._erc20_token_list ] token_symbols: List[str] = await safe_gather(*fetch_symbols_tasks) token_decimals: List[int] = await safe_gather(*fetch_decimals_tasks ) for token, symbol, decimals in zip(self._erc20_token_list, token_symbols, token_decimals): self._erc20_tokens[symbol] = token self._asset_decimals[symbol] = decimals self._weth_token = self._erc20_tokens.get("WETH") # Fetch blockchain data. self._local_nonce = await async_scheduler.call_async( lambda: self.get_remote_nonce()) # Create event watchers. self._new_blocks_watcher = NewBlocksWatcher(self._w3) self._account_balance_watcher = AccountBalanceWatcher( self._w3, self._new_blocks_watcher, self._account.address, [ erc20_token.address for erc20_token in self._erc20_tokens.values() ], [token.abi for token in self._erc20_tokens.values()]) self._erc20_events_watcher = ERC20EventsWatcher( self._w3, self._new_blocks_watcher, [token.address for token in self._erc20_tokens.values()], [token.abi for token in self._erc20_tokens.values()], [self._account.address]) self._incoming_eth_watcher = IncomingEthWatcher( self._w3, self._new_blocks_watcher, [self._account.address]) if self._weth_token is not None: self._weth_watcher = WethWatcher(self._w3, self._weth_token, self._new_blocks_watcher, [self._account.address]) self._zeroex_fill_watcher = ZeroExFillWatcher( self._w3, self._new_blocks_watcher) # Connect the event forwarders. self._new_blocks_watcher.add_listener(NewBlocksWatcherEvent.NewBlocks, self._event_forwarder) self._erc20_events_watcher.add_listener( ERC20WatcherEvent.ReceivedToken, self._received_asset_event_forwarder) self._erc20_events_watcher.add_listener( ERC20WatcherEvent.ApprovedToken, self._approved_token_event_forwarder) self._incoming_eth_watcher.add_listener( IncomingEthWatcherEvent.ReceivedEther, self._received_asset_event_forwarder) self._zeroex_fill_watcher.add_listener( ZeroExEvent.Fill, self._zeroex_fill_event_forwarder) if self._weth_watcher is not None: self._weth_watcher.add_listener(WalletEvent.WrappedEth, self._wrapped_eth_event_forwarder) self._weth_watcher.add_listener( WalletEvent.UnwrappedEth, self._unwrapped_eth_event_forwarder) # Start the transaction processing tasks. self._outgoing_transactions_task = safe_ensure_future( self.outgoing_eth_transactions_loop()) self._check_transaction_receipts_task = safe_ensure_future( self.check_transaction_receipts_loop()) # Start the event watchers. await self._new_blocks_watcher.start_network() await self._account_balance_watcher.start_network() await self._erc20_events_watcher.start_network() await self._incoming_eth_watcher.start_network() if self._weth_watcher is not None: await self._weth_watcher.start_network()
def start(self, clock: Clock, timestamp: float): if self._market_info_1.market.name in ETH_WALLET_CONNECTORS or \ self._market_info_2.market.name in ETH_WALLET_CONNECTORS: self._quote_eth_rate_fetch_loop_task = safe_ensure_future( self.quote_in_eth_rate_fetch_loop())
def start(self): if self.started: self.stop() self._check_network_task = safe_ensure_future(self._check_network_loop()) self._network_status = NetworkStatus.NOT_CONNECTED
def status( self, # type: HummingbotApplication ): safe_ensure_future(self.status_check_all(), loop=self.ev_loop)
def start(self, clock: Clock, timestamp: float): if self._market_info_1.market.name in AllConnectorSettings.get_eth_wallet_connector_names() or \ self._market_info_2.market.name in AllConnectorSettings.get_eth_wallet_connector_names(): self._quote_eth_rate_fetch_loop_task = safe_ensure_future( self.quote_in_eth_rate_fetch_loop())
def create(cls): configuration_data_source = cls() safe_ensure_future(configuration_data_source._configure()) return configuration_data_source
async def start_market_making( self, # type: HummingbotApplication strategy_name: str, restore: Optional[bool] = False): start_strategy: Callable = get_strategy_starter_file(strategy_name) if strategy_name in settings.STRATEGIES: start_strategy(self) else: raise NotImplementedError try: config_path: str = self.strategy_file_name self.start_time = time.time() * 1e3 # Time in milliseconds self.clock = Clock(ClockMode.REALTIME) if self.wallet is not None: self.clock.add_iterator(self.wallet) for market in self.markets.values(): if market is not None: self.clock.add_iterator(market) self.markets_recorder.restore_market_states( config_path, market) if len(market.limit_orders) > 0: if restore is False: self._notify( f"Cancelling dangling limit orders on {market.name}..." ) await market.cancel_all(5.0) else: self._notify( f"Restored {len(market.limit_orders)} limit orders on {market.name}..." ) if self.strategy: self.clock.add_iterator(self.strategy) if global_config_map["script_enabled"].value: script_file = global_config_map["script_file_path"].value folder = dirname(script_file) if folder == "": script_file = join(settings.SCRIPTS_PATH, script_file) if self.strategy_name != "pure_market_making": self._notify( "Error: script feature is only available for pure_market_making strategy (for now)." ) else: self._script_iterator = ScriptIterator( script_file, list(self.markets.values()), self.strategy, 0.1) self.clock.add_iterator(self._script_iterator) self._notify(f"Script ({script_file}) started.") self.strategy_task: asyncio.Task = safe_ensure_future( self._run_clock(), loop=self.ev_loop) self._notify(f"\n'{strategy_name}' strategy started.\n" f"Run `status` command to query the progress.") self.logger().info("start command initiated.") if self.strategy_name == "uniswap_v3_lp": # this would be removed in subsequent iterations self._notify( "Warning: Ensure that the trading pair is in the right order .i.e. {BASE}-{QUOTE}." ) if self._trading_required: self.kill_switch = KillSwitch(self) await self.wait_till_ready(self.kill_switch.start) except Exception as e: self.logger().error(str(e), exc_info=True)
async def start(self): self._emit_trade_event_task = safe_ensure_future( self._emit_trade_event_loop())
def _process_order_message(self, order_msg: Dict[str, Any]): """ Updates in-flight order and triggers cancellation or failure event if needed. :param order_msg: The order response from either REST or web socket API (they are of the same format) Example Orders: REST request { "id" : "977f82aa-23dc-4c8b-982c-2ee7d2002882", "clientOrderId" : null, "symbol" : "BTC/USD", "orderType" : "LIMIT", "orderSide" : "BUY", "quantity" : 0.1, "price" : 54570, "payFeesWithZoomToken" : false, "orderStatus" : "PARTIALLY_FILLED", "timestamp" : "2021-03-24T04:07:26.260253Z", "executions" : [ { "id" : "38761582-2b37-4e27-a561-434981d21a96", "executionType" : "PARTIAL_FILL", "orderStatus" : "PARTIALLY_FILLED", "lastPrice" : 54570, "averagePrice" : 54570, "lastQuantity" : 0.01, "leavesQuantity" : 0.09, "cumulativeQuantity" : 0.01, "rejectReason" : null, "timestamp" : "2021-03-24T04:07:44.503222Z" } ] } WS request { 'orderId': '962a2a54-fbcf-4d89-8f37-a8854020a823', 'symbol': 'BTC/USD', 'orderType': 'LIMIT', 'orderSide': 'BUY', 'price': 5000, 'quantity': 0.001, 'executionType': 'CANCEL', 'orderStatus': 'CANCELLED', 'lastQuantity': 0, 'leavesQuantity': 0, 'cumulativeQuantity': 0, 'transactTime': '2021-03-23T19:06:51.155520Z' ... Optional fields 'id': '4eb3f26c-91bd-4bd2-bacb-15b2f432c452', "orderType": "LIMIT", "lastPrice": 56518.7, "averagePrice": 56518.7, } """ # Looks like CoinZoom might support clientOrderId eventually so leaving this here for now. # if order_msg.get('clientOrderId') is not None: # client_order_id = order_msg["clientOrderId"] # if client_order_id not in self._in_flight_orders: # return # tracked_order = self._in_flight_orders[client_order_id] # else: if "orderId" not in order_msg: exchange_order_id = str(order_msg["id"]) else: exchange_order_id = str(order_msg["orderId"]) tracked_orders = list(self._in_flight_orders.values()) track_order = [ o for o in tracked_orders if exchange_order_id == o.exchange_order_id ] if not track_order: return tracked_order = track_order[0] # Estimate fee order_msg["trade_fee"] = self.estimate_fee_pct( tracked_order.order_type is OrderType.LIMIT_MAKER) updated = tracked_order.update_with_order_update(order_msg) # Call Update balances on every message to catch order create, fill and cancel. safe_ensure_future(self._update_balances()) if updated: safe_ensure_future( self._trigger_order_fill(tracked_order, order_msg)) elif tracked_order.is_cancelled: self.logger().info( f"Successfully cancelled order {tracked_order.client_order_id}." ) self.stop_tracking_order(tracked_order.client_order_id) self.trigger_event( MarketEvent.OrderCancelled, OrderCancelledEvent(self.current_timestamp, tracked_order.client_order_id)) tracked_order.cancelled_event.set() elif tracked_order.is_failure: self.logger().info( f"The order {tracked_order.client_order_id} has failed according to order status API. " ) self.trigger_event( MarketEvent.OrderFailure, MarketOrderFailureEvent(self.current_timestamp, tracked_order.client_order_id, tracked_order.order_type)) self.stop_tracking_order(tracked_order.client_order_id)
async def start_network(self): await self.stop_network() self._fetch_price_task = safe_ensure_future(self.fetch_price_loop())
async def run_parallel_async(self, *tasks): future: asyncio.Future = safe_ensure_future(safe_gather(*tasks)) while not future.done(): await asyncio.sleep(1.0) return future.result()
def exit_(event): hb.app.log("\n[Double CTRL + C] keyboard exit") safe_ensure_future(hb.exit_loop())
def stop(self): if self._check_network_task is not None: self._check_network_task.cancel() self._check_network_task = None safe_ensure_future(self.stop_network()) self._network_status = NetworkStatus.STOPPED
def balance(self): safe_ensure_future(self.show_balances())
def _did_receive_new_blocks(self, new_blocks: List[AttributeDict]): self._last_timestamp_received_blocks = time.time() safe_ensure_future(self._update_gas_price())
def generate_certs( self, # type: HummingbotApplication ): safe_ensure_future(self._generate_certs(), loop=self.ev_loop)
async def start_network(self): if self._trading_required: self._status_polling_task = safe_ensure_future(self._status_polling_loop()) self._auto_approve_task = safe_ensure_future(self.auto_approve()) self._funding_info_polling_task = safe_ensure_future(self._funding_info_polling_loop())
def start(self): self.stop() self.get_open_order_stats_task = safe_ensure_future( self.get_open_order_stats()) self.get_event_task = safe_ensure_future(self.get_event()) self.log_report_task = safe_ensure_future(self.log_report())
async def start_network(self): if self._trading_required: self._status_polling_task = safe_ensure_future(self._status_polling_loop())
def start(self): super().start() self._order_book_event_listener_task = safe_ensure_future( self._data_source.listen_for_subscriptions()) self._order_book_instruments_info_listener_task = safe_ensure_future( self._data_source.listen_for_instruments_info())
def setUpClass(cls): cls.ev_loop: asyncio.BaseEventLoop = asyncio.get_event_loop() cls.order_book_tracker: BittrexOrderBookTracker = BittrexOrderBookTracker( OrderBookTrackerDataSourceType.EXCHANGE_API, symbols=cls.trading_pairs) cls.order_book_tracker_task: asyncio.Task = safe_ensure_future(cls.order_book_tracker.start()) cls.ev_loop.run_until_complete(cls.wait_til_tracker_ready())
def status(self, # type: HummingbotApplication live: bool = False): safe_ensure_future(self.status_check_all(live=live), loop=self.ev_loop)
def test_ask_limit_order_trade_match(self): """ Test ask limit order fill and balance simulation, and market events emission """ trading_pair = TradingPair("ETH-USDT", "ETH", "USDT") base_quantity = 2.0 starting_base_balance = 200 starting_quote_balance = 2000 self.market.set_balance(trading_pair.base_asset, starting_base_balance) self.market.set_balance(trading_pair.quote_asset, starting_quote_balance) best_ask_price = self.market.order_books[ trading_pair.trading_pair].get_price(False) client_order_id = self.market.sell(trading_pair.trading_pair, base_quantity, OrderType.LIMIT, best_ask_price) matched_limit_orders = TestUtils.get_match_limit_orders( self.market.limit_orders, { "client_order_id": client_order_id, "trading_pair": trading_pair.trading_pair, "is_buy": False, "base_currency": trading_pair.base_asset, "quote_currency": trading_pair.quote_asset, "price": best_ask_price, "quantity": base_quantity }) # Market should track limit orders self.assertEqual(1, len(matched_limit_orders)) # Market should on hold balance for the created order self.assertAlmostEqual( float(self.market.on_hold_balances[trading_pair.base_asset]), base_quantity) # Market should reflect on hold balance in available balance self.assertAlmostEqual( self.market.get_available_balance(trading_pair.base_asset), starting_base_balance - base_quantity) matched_order_create_events = TestUtils.get_match_events( self.market_logger.event_log, SellOrderCreatedEvent, { "type": OrderType.LIMIT, "amount": base_quantity, "price": best_ask_price, "order_id": client_order_id }) # Market should emit BuyOrderCreatedEvent self.assertEqual(1, len(matched_order_create_events)) async def delay_trigger_event2(): await asyncio.sleep(1) trade_event = OrderBookTradeEvent( trading_pair=trading_pair.trading_pair, timestamp=time.time(), type=TradeType.BUY, price=best_ask_price - 1, amount=base_quantity) self.market.order_books[trading_pair.trading_pair].apply_trade( trade_event) safe_ensure_future(delay_trigger_event2()) self.run_parallel(self.market_logger.wait_for(SellOrderCompletedEvent)) placed_ask_orders: List[LimitOrder] = [ o for o in self.market.limit_orders if not o.is_buy ] # Market should delete limit order when it is filled self.assertEqual(0, len(placed_ask_orders)) matched_order_complete_events = TestUtils.get_match_events( self.market_logger.event_log, SellOrderCompletedEvent, { "order_type": OrderType.LIMIT, "quote_asset_amount": base_quantity * base_quantity, "order_id": client_order_id }) # Market should emit BuyOrderCompletedEvent self.assertEqual(1, len(matched_order_complete_events)) matched_order_fill_events = TestUtils.get_match_events( self.market_logger.event_log, OrderFilledEvent, { "order_type": OrderType.LIMIT, "trade_type": TradeType.SELL, "trading_pair": trading_pair.trading_pair, "order_id": client_order_id }) # Market should emit OrderFilledEvent self.assertEqual(1, len(matched_order_fill_events)) # Market should have no more on hold balance self.assertAlmostEqual( float(self.market.on_hold_balances[trading_pair.base_asset]), 0) # Market should update balance for the filled order self.assertAlmostEqual( self.market.get_available_balance(trading_pair.base_asset), starting_base_balance - base_quantity)
async def start_loop(self): self.stop() self._check_profitability_task = safe_ensure_future( self.check_profitability_loop()) self._started = True