def test_request(self):
        impl = WebsocketRequestImpl("")
        symbols = list()
        symbols.append("btcusdt")

        def callback(event):
            pass

        request = impl.subscribe_candlestick_event(symbols, CandlestickInterval.MIN1, callback)
        mock_connection = MockWebsocketConnection(request)
        request.subscription_handler(mock_connection)
        subscription = mock_connection.pop_output_message()
        self.assertTrue(subscription.find("market.btcusdt.kline.1min") != -1)
    def test_result(self):
        impl = WebsocketRequestImpl("")
        symbols = list()
        symbols.append("btcusdt")

        def callback(event):
            pass

        request = impl.subscribe_candlestick_event(symbols, CandlestickInterval.MIN1, callback)
        candlestick_event = request.json_parser(parse_json_from_string(data))
        self.assertEqual("btcusdt", candlestick_event.symbol)
        self.assertEqual( convert_cst_in_millisecond_to_utc(1550469651403), candlestick_event.timestamp)
        self.assertEqual(CandlestickInterval.MIN1, candlestick_event.interval)
        self.assertEqual(3719.88, candlestick_event.data.open)
        self.assertEqual(3719.91, candlestick_event.data.close)
        self.assertEqual(3719.45, candlestick_event.data.low)
        self.assertEqual(3719.99, candlestick_event.data.high)
        self.assertEqual(5.470327974838371482, candlestick_event.data.amount)
        self.assertEqual(20349.2034519999999944659, candlestick_event.data.volume)
        self.assertEqual(73, candlestick_event.data.count)
Example #3
0
class SubscriptionClient(object):
    def __init__(self, **kwargs):
        """
        Create the subscription client to subscribe the update from server.

        :param kwargs: The option of subscription connection.
            api_key: The public key applied from Huobi.
            secret_key: The private key applied from Huobi.
            uri: Set the URI for subscription.
            is_auto_connect: When the connection lost is happening on the subscription line, specify whether the client
                            reconnect to server automatically. The connection lost means:
                                Caused by network problem
                                The connection close triggered by server (happened every 24 hours)
                            No any message can be received from server within a specified time, see receive_limit_ms
            receive_limit_ms: Set the receive limit in millisecond. If no message is received within this limit time,
                            the connection will be disconnected.
            connection_delay_failure: If auto reconnect is enabled, specify the delay time before reconnect.
        """
        api_key = None
        secret_key = None
        if "api_key" in kwargs:
            api_key = kwargs["api_key"]
        if "secret_key" in kwargs:
            secret_key = kwargs["secret_key"]
        self.__api_key = api_key
        self.__secret_key = secret_key
        self.websocket_request_impl = WebsocketRequestImpl(self.__api_key)
        self.connections = list()
        self.uri = WebSocketDefine.Uri
        is_auto_connect = True
        receive_limit_ms = 60000
        connection_delay_failure = 15
        if "uri" in kwargs:
            self.uri = kwargs["uri"]
        if "is_auto_connect" in kwargs:
            is_auto_connect = kwargs["is_auto_connect"]
        if "receive_limit_ms" in kwargs:
            receive_limit_ms = kwargs["receive_limit_ms"]
        if "connection_delay_failure" in kwargs:
            connection_delay_failure = kwargs["connection_delay_failure"]
        self.__watch_dog = WebSocketWatchDog(is_auto_connect, receive_limit_ms,
                                             connection_delay_failure)

        try:
            host = urllib.parse.urlparse(self.uri).hostname
            impl = RestApiRequestImpl(api_key, secret_key, "https://" + host)
            account_info_map.update_user_info(api_key, impl)
        except Exception:
            pass

    def __create_connection(self, request):
        connection = WebsocketConnection(self.__api_key, self.__secret_key,
                                         self.uri, self.__watch_dog, request)
        self.connections.append(connection)
        connection.connect()

    def subscribe_candlestick_event(self,
                                    symbols: 'str',
                                    interval: 'CandlestickInterval',
                                    callback,
                                    error_handler=None):
        """
        Subscribe candlestick/kline event. If the candlestick/kline is updated, server will send the data to client and onReceive in callback will be called.

        :param symbols: The symbols, like "btcusdt". Use comma to separate multi symbols, like "btcusdt,ethusdt".
        :param interval: The candlestick/kline interval, MIN1, MIN5, DAY1 etc.
        :param callback: The implementation is required. onReceive will be called if receive server's update.
            example: def callback(candlestick_event: 'CandlestickEvent'):
                        pass
        :param error_handler: The error handler will be called if subscription failed or error happen between client and Huobi server
            example: def error_handler(exception: 'HuobiApiException')
                        pass
        :return: No return
        """
        symbol_list = symbols.split(",")
        request = self.websocket_request_impl.subscribe_candlestick_event(
            symbol_list, interval, callback, error_handler)
        self.__create_connection(request)

    def subscribe_price_depth_event(self,
                                    symbols: 'str',
                                    depth_step: 'str',
                                    callback,
                                    error_handler=None):
        """
        Subscribe price depth event. If the price depth is updated, server will send the data to client and onReceive in callback will be called.

        :param symbols: The symbols, like "btcusdt". Use comma to separate multi symbols, like "btcusdt,ethusdt".
        :param depth_step: The depth precision, string from step0 to step5.
        :param callback: The implementation is required. onReceive will be called if receive server's update.
            example: def callback(price_depth_event: 'PriceDepthEvent'):
                        pass
        :param error_handler: The error handler will be called if subscription failed or error happen between client and Huobi server
            example: def error_handler(exception: 'HuobiApiException')
                        pass

        :return:  No return
        """
        symbol_list = symbols.split(",")
        request = self.websocket_request_impl.subscribe_price_depth_event(
            symbol_list, depth_step, callback, error_handler)
        self.__create_connection(request)

    def subscribe_price_depth_bbo_event(self,
                                        symbols: 'str',
                                        callback,
                                        error_handler=None):
        """
        Subscribe price depth event. If the price depth is updated, server will send the data to client and onReceive in callback will be called.

        :param symbols: The symbols, like "btcusdt". Use comma to separate multi symbols, like "btcusdt,ethusdt".
        :param callback: The implementation is required. onReceive will be called if receive server's update.
            example: def callback(price_depth_event: 'PriceDepthEvent'):
                        pass
        :param error_handler: The error handler will be called if subscription failed or error happen between client and Huobi server
            example: def error_handler(exception: 'HuobiApiException')
                        pass

        :return:  No return
        """
        symbol_list = symbols.split(",")
        request = self.websocket_request_impl.subscribe_price_depth_bbo_event(
            symbol_list, callback, error_handler)
        self.__create_connection(request)

    def subscribe_order_update_event(self,
                                     symbols: 'str',
                                     callback,
                                     error_handler=None):
        """
        Subscribe order changing event. If a order is created, canceled etc, server will send the data to client and onReceive in callback will be called.

        :param symbols: The symbols, like "btcusdt". Use comma to separate multi symbols, like "btcusdt,ethusdt".
        :param callback: The implementation is required. onReceive will be called if receive server's update.
            example: def callback(order_update_event: 'OrderUpdateEvent'):
                        pass
        :param error_handler: The error handler will be called if subscription failed or error happen between client and Huobi server
            example: def error_handler(exception: 'HuobiApiException')
                        pass
        :return:  No return
        """
        symbol_list = symbols.split(",")
        request = self.websocket_request_impl.subscribe_order_update(
            symbol_list, callback, error_handler)
        self.__create_connection(request)

    def subscribe_order_update_new_event(self,
                                         symbols: 'str',
                                         callback,
                                         error_handler=None):
        """
        Subscribe order changing event. If a order is created, canceled etc, server will send the data to client and onReceive in callback will be called.

        :param symbols: The symbols, like "btcusdt". Use comma to separate multi symbols, like "btcusdt,ethusdt".
        :param callback: The implementation is required. onReceive will be called if receive server's update.
            example: def callback(order_update_event: 'OrderUpdateEvent'):
                        pass
        :param error_handler: The error handler will be called if subscription failed or error happen between client and Huobi server
            example: def error_handler(exception: 'HuobiApiException')
                        pass
        :return:  No return
        """
        symbol_list = symbols.split(",")
        request = self.websocket_request_impl.subscribe_order_update_new(
            symbol_list, callback, error_handler)
        self.__create_connection(request)

    def subscribe_trade_event(self,
                              symbols: 'str',
                              callback,
                              error_handler=None):
        """
        Subscribe price depth event. If the price depth is updated, server will send the data to client and onReceive in callback will be called.

        :param symbols: The symbols, like "btcusdt". Use comma to separate multi symbols, like "btcusdt,ethusdt".
        :param callback: The implementation is required. onReceive will be called if receive server's update.
            example: def callback(trade_event: 'TradeEvent'):
                        pass
        :param error_handler: The error handler will be called if subscription failed or error happen between client and Huobi server
            example: def error_handler(exception: 'HuobiApiException')
                        pass
        :return:  No return
        """
        symbol_list = symbols.split(",")
        request = self.websocket_request_impl.subscribe_trade_event(
            symbol_list, callback, error_handler)
        self.__create_connection(request)

    def subscribe_24h_trade_statistics_event(self,
                                             symbols: 'str',
                                             callback,
                                             error_handler=None):
        """
        Subscribe 24 hours trade statistics event. If statistics is generated, server will send the data to client and onReceive in callback will be called.

        :param symbols: The symbols, like "btcusdt". Use comma to separate multi symbols, like "btcusdt,ethusdt".
        :param callback: The implementation is required. onReceive will be called if receive server's update.
            example: def callback(trade_statistics_event: 'TradeStatisticsEvent'):
                        pass
        :param error_handler: The error handler will be called if subscription failed or error happen between client and Huobi server
            example: def error_handler(exception: 'HuobiApiException')
                        pass
        :return:  No return
        """
        symbol_list = symbols.split(",")
        request = self.websocket_request_impl.subscribe_24h_trade_statistics_event(
            symbol_list, callback, error_handler)
        self.__create_connection(request)

    def subscribe_account_event(self,
                                mode: 'BalanceMode',
                                callback,
                                error_handler=None):
        """
        Subscribe account changing event. If the balance is updated, server will send the data to client and onReceive in callback will be called.

        :param mode: when mode is AVAILABLE, balance refers to available balance; when mode is TOTAL, balance refers to TOTAL balance for trade sub account (available+frozen).
        :param callback: The implementation is required. onReceive will be called if receive server's update.
            example: def callback(account_event: 'AccountEvent'):
                        pass
        :param error_handler: The error handler will be called if subscription failed or error happen between client and Huobi server
            example: def error_handler(exception: 'HuobiApiException')
                        pass
        :return:  No return
        """
        request = self.websocket_request_impl.subscribe_account_event(
            mode, callback, error_handler)
        self.__create_connection(request)

    def request_account_balance_event(self,
                                      callback,
                                      client_req_id=None,
                                      auto_close=True,
                                      error_handler=None):
        """
        Subscribe account changing event. If the balance is updated, server will send the data to client and onReceive in callback will be called.

        :param client_req_id: client request ID
        :param auto_close : close websocket connection after get data
        :param callback: The implementation is required. onReceive will be called if receive server's update.
            example: def callback(account_event: 'AccountEvent'):
                        pass
        :param error_handler: The error handler will be called if subscription failed or error happen between client and Huobi server
            example: def error_handler(exception: 'HuobiApiException')
                        pass
        :return:  No return
        """
        request = self.websocket_request_impl.request_account_balance_event(
            callback, client_req_id, auto_close, error_handler)
        self.__create_connection(request)

    def request_candlestick_event(self,
                                  symbols: 'str',
                                  interval: 'CandlestickInterval',
                                  callback,
                                  from_ts_second=None,
                                  end_ts_second=None,
                                  auto_close=True,
                                  error_handler=None):
        """
        Subscribe candlestick/kline event. If the candlestick/kline is updated, server will send the data to client and onReceive in callback will be called.

        :param symbols: The symbols, like "btcusdt". Use comma to separate multi symbols, like "btcusdt,ethusdt".
        :param interval: The candlestick/kline interval, MIN1, MIN5, DAY1 etc.
        :param callback: The implementation is required. onReceive will be called if receive server's update.
            example: def callback(candlestick_event: 'CandlestickEvent'):
                        pass
        :param from_ts_second : data from timestamp [it's second]
        :param end_ts_second : data util timestamp [it's second]
        :param auto_close : close websocket connection after get data
        :param error_handler: The error handler will be called if subscription failed or error happen between client and Huobi server
            example: def error_handler(exception: 'HuobiApiException')
                        pass
        :return: No return
        """
        symbol_list = symbols.split(",")
        request = self.websocket_request_impl.request_candlestick_event(
            symbol_list, interval, callback, from_ts_second, end_ts_second,
            auto_close, error_handler)
        self.__create_connection(request)

    def request_price_depth_event(self,
                                  symbols: 'str',
                                  depth_step: 'str',
                                  callback,
                                  auto_close=True,
                                  error_handler=None):
        """
        Subscribe price depth event. If the price depth is updated, server will send the data to client and onReceive in callback will be called.

        :param symbols: The symbols, like "btcusdt". Use comma to separate multi symbols, like "btcusdt,ethusdt".
        :param depth_step: The depth precision, string from step0 to step5.
        :param callback: The implementation is required. onReceive will be called if receive server's update.
            example: def callback(price_depth_event: 'PriceDepthEvent'):
                        pass
        :param auto_close : close websocket connection after get data
        :param error_handler: The error handler will be called if subscription failed or error happen between client and Huobi server
            example: def error_handler(exception: 'HuobiApiException')
                        pass

        :return:  No return
        """
        symbol_list = symbols.split(",")
        request = self.websocket_request_impl.request_price_depth_event(
            symbol_list, depth_step, callback, auto_close, error_handler)
        self.__create_connection(request)

    def request_trade_event(self,
                            symbols: 'str',
                            callback,
                            auto_close=True,
                            error_handler=None):
        """
        Subscribe price depth event. If the price depth is updated, server will send the data to client and onReceive in callback will be called.

        :param symbols: The symbols, like "btcusdt". Use comma to separate multi symbols, like "btcusdt,ethusdt".
        :param callback: The implementation is required. onReceive will be called if receive server's update.
            example: def callback(trade_event: 'TradeEvent'):
                        pass
        :param auto_close : close websocket connection after get data
        :param error_handler: The error handler will be called if subscription failed or error happen between client and Huobi server
            example: def error_handler(exception: 'HuobiApiException')
                        pass
        :return:  No return
        """
        symbol_list = symbols.split(",")
        request = self.websocket_request_impl.request_trade_event(
            symbol_list, callback, auto_close, error_handler)
        self.__create_connection(request)

    def request_24h_trade_statistics_event(self,
                                           symbols: 'str',
                                           callback,
                                           auto_close=True,
                                           error_handler=None):
        """
        Subscribe 24 hours trade statistics event. If statistics is generated, server will send the data to client and onReceive in callback will be called.

        :param symbols: The symbols, like "btcusdt". Use comma to separate multi symbols, like "btcusdt,ethusdt".
        :param callback: The implementation is required. onReceive will be called if receive server's update.
            example: def callback(trade_statistics_event: 'TradeStatisticsEvent'):
                        pass
        :param auto_close : close websocket connection after get data
        :param error_handler: The error handler will be called if subscription failed or error happen between client and Huobi server
            example: def error_handler(exception: 'HuobiApiException')
                        pass
        :return:  No return
        """
        symbol_list = symbols.split(",")
        request = self.websocket_request_impl.request_24h_trade_statistics_event(
            symbol_list, callback, auto_close, error_handler)
        self.__create_connection(request)

    def request_order_list_event(self,
                                 symbol: 'str',
                                 account_id: int,
                                 callback,
                                 order_states=None,
                                 client_req_id=True,
                                 auto_close=True,
                                 error_handler=None):
        """
        Subscribe candlestick/kline event. If the candlestick/kline is updated, server will send the data to client and onReceive in callback will be called.

        :param symbol: The symbol, like "btcusdt".
        :param order_states: order status, can be one state or many state sepearted by comma, such as "submitted,partial-filled,partial-canceled,filled,canceled,created"
        :param callback: The implementation is required. onReceive will be called if receive server's update.
            example: def callback(candlestick_event: 'CandlestickEvent'):
                        pass
        :param client_req_id: client request ID
        :param auto_close : close websocket connection after get data
        :param error_handler: The error handler will be called if subscription failed or error happen between client and Huobi server
            example: def error_handler(exception: 'HuobiApiException')
                        pass
        :return: No return
        """
        request = self.websocket_request_impl.request_order_list_event(
            symbol, account_id, callback, order_states, client_req_id,
            auto_close, error_handler)
        self.__create_connection(request)

    def request_order_detail_event(self,
                                   order_id: 'str',
                                   callback,
                                   client_req_id=None,
                                   auto_close=True,
                                   error_handler=None):
        """
        Subscribe candlestick/kline event. If the candlestick/kline is updated, server will send the data to client and onReceive in callback will be called.

        :param symbols: The symbols, like "btcusdt". Use comma to separate multi symbols, like "btcusdt,ethusdt".
        :param interval: The candlestick/kline interval, MIN1, MIN5, DAY1 etc.
        :param callback: The implementation is required. onReceive will be called if receive server's update.
            example: def callback(candlestick_event: 'CandlestickEvent'):
                        pass
        :param client_req_id: client request ID
        :param auto_close : close websocket connection after get data
        :param error_handler: The error handler will be called if subscription failed or error happen between client and Huobi server
            example: def error_handler(exception: 'HuobiApiException')
                        pass
        :return: No return
        """
        request = self.websocket_request_impl.request_order_detail_event(
            order_id, callback, client_req_id, auto_close, error_handler)
        self.__create_connection(request)

    def unsubscribe_all(self):
        for conn in self.connections:
            conn.close()
        self.connections.clear()