Esempio n. 1
0
 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())
Esempio n. 2
0
 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))
Esempio n. 5
0
 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())
Esempio n. 6
0
 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
Esempio n. 7
0
    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()
Esempio n. 8
0
 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
Esempio n. 10
0
 def status(
         self,  # type: HummingbotApplication
 ):
     safe_ensure_future(self.status_check_all(), loop=self.ev_loop)
Esempio n. 11
0
 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())
Esempio n. 12
0
    def create(cls):
        configuration_data_source = cls()
        safe_ensure_future(configuration_data_source._configure())

        return configuration_data_source
Esempio n. 13
0
    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)
Esempio n. 14
0
 async def start(self):
     self._emit_trade_event_task = safe_ensure_future(
         self._emit_trade_event_loop())
Esempio n. 15
0
    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)
Esempio n. 16
0
 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()
Esempio n. 18
0
 def exit_(event):
     hb.app.log("\n[Double CTRL + C] keyboard exit")
     safe_ensure_future(hb.exit_loop())
Esempio n. 19
0
 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
Esempio n. 20
0
 def balance(self):
     safe_ensure_future(self.show_balances())
Esempio n. 21
0
 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)
Esempio n. 23
0
 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())
Esempio n. 24
0
 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())
Esempio n. 25
0
 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)
Esempio n. 29
0
    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)
Esempio n. 30
0
 async def start_loop(self):
     self.stop()
     self._check_profitability_task = safe_ensure_future(
         self.check_profitability_loop())
     self._started = True