Exemple #1
0
    def getBalances(self):
        bf = BtfxWss(key=self.key, secret=self.secret)
        bf.start()

        while not bf.conn.connected.is_set():
            time.sleep(1)

        bf.authenticate()
        time.sleep(1)

        resp = bf.wallets
        timeout = time.time() + 10
        while resp.qsize == 0 or time.time() <= timeout:
            time.sleep(1)

        bf.stop()

        l = list()
        while resp.qsize() > 0:
            l.append(resp.get())

        logging.debug(l)
        #logging.info(l[0][0][1])

        balance = dict()
        if len(l) == 0:
            return balance

        for entry in l[0][0][1]:
            #[['funding', 'IOT', 0.00471435, 0, None], ['exchange', 'ETH', 0, 0, None], ['exchange', 'IOT', 408.54209381, 0, None], ['exchange', 'BTC', 0, 0, None]]
            cur = entry[1]
            value = entry[2]

            if cur not in balance:
                balance[cur] = 0.0
            balance[cur] += value

        return balance
Exemple #2
0
class Trader(_Account):
    """
    Class interface for trading on the Bitfinex Exchange
    :param key: str: Bitfinex api-key
    :param secret:  str: Bitfinex api-secret
    """
    _sleep_time = 0.01
    _min_order_value = 35.
    _max_order_history = 100
    _trade_types = {'market', 'limit'}
    _sources = ('Orders', 'Order New', 'Order Update', 'Order Cancel',
                'Wallets')

    def __init__(self, key, secret):
        super(Trader, self).__init__()
        self.symbols = []
        self.symbols_gen = get_symbols_as_updated()
        self.wss = BtfxWss(key=key, secret=secret, log_level='CRITICAL')
        self._disconnect_event = Event()
        self._receiver = None

    def cancel(self, _id):
        """
        Cancel an order
        :param _id: int: order id
        :return: None
        """
        self.wss.cancel_order(multi=False, id=_id)

    def cancel_all(self, older_than=0):
        """
        Cancel all orders older than a certain time
        :param older_than: int/float:
            age of order that should be cancelled (in seconds)
        :return: None
        """
        now = time.time()
        for _id, order in self._orders.copy().items():
            if now - order['timestamp'] > older_than:
                self.cancel(_id)

    def connect(self):
        """Open a connection to a Bitfinex websocket"""
        self.wss.start()
        while not self.wss.conn.connected.is_set():
            time.sleep(1e-4)
        self.wss.authenticate()
        # This thread will wait for 99.999% of its life
        subscriber_thread = Thread(target=self._subscribe)
        subscriber_thread.setDaemon(True)
        subscriber_thread.start()
        # This thread should be working and is therefore joined
        self._receiver = Thread(target=self._receive)
        self._receiver.start()

    def close(self):
        """Close the connection to the Bitfinex websocket"""
        self._disconnect_event.set()
        for symbol in self.symbols:
            self.wss.unsubscribe_from_ticker(symbol)
        self.wss.stop()
        self._receiver.join()

    def order(self,
              symbol,
              price,
              *,
              dollar_amount=None,
              ratio=None,
              value_ratio=None,
              trade_type='limit',
              pad_price=None,
              return_id=True):
        """
        Make an exchange order
        :param symbol: str:
            ticker symbol to order (e.g. 'BTCUSD', 'ETHUSD'...)

        :param price: float:
            Price at which to submit order
            You can also pass "market" as an argument for price
            to order at current market value
            e.g. Trader.order('BTCUSD', 'market', dollar_amount=5)

        :param dollar_amount: float:
            Dollar equivalent value of trade amount (negative for selling)
            e.g. ordering 10 BTCUSD at $5 per coin
                -> Trader.order('BTCUSD', 5, dollar_amount=50)

        :param ratio: float:
            Ratio of available balance for requested symbol (negative for sell)
            e.g. With $1000 USD in wallet, ordering 100 BTCUSD at $5 per coin
                -> Trader.order('BTCUSD', 5, ratio=0.5)

        :param value_ratio: float:
            Ratio of Trader.value (negative for selling)
            e.g. With $500 in USD and $500 in BTCUSD (at $5) in wallet,
                 ordering 100 BTCUSD at $5 per coin
                -> Trader.order('BTCUSD', 5, value_ratio=0.5)

        :param trade_type: str: (optional)
            Bitfinex api trade type - one of {'market', 'limit'}
            see https://www.bitfinex.com/features for details

        :param pad_price: float: (optional)
            Ratio based price padding - used to undercut or overshoot price
            If buying then pad_price * price is added to submitted price
            If selling then pad_price * price is subtracted from price

        :param return_id: bool: (optional)
            If true, Trader.order blocks until order_id is returned
            from Bitfinex, otherwise returns immediately

        :return: int:
            If return_id is True, then order id is returned, otherwise None

        :raises: AssertionError:
            If values passed are non-consistent
        """

        assert dollar_amount or ratio or value_ratio, \
            'Must provide either `dollar_amount`, `ratio` or `value_ratio`'
        assert sum(bool(i) for i in [dollar_amount, ratio, value_ratio]) == 1,\
            'Must provide only 1 of `dollar_amount`, `ratio` or `value_ratio`'
        assert trade_type.lower() in self._trade_types, \
            'Unknown trade type, try one of these: %s' % str(self._trade_types)

        symbol_lower = symbol.lower().replace('usd', '')
        symbol = symbol.upper().split('USD')[0] + 'USD'
        buying = (dollar_amount or ratio or value_ratio) > 0

        if price == 'market' or trade_type == 'market':
            trade_type = 'market'
            price = self._prices[symbol]

        if pad_price:
            delta = price * pad_price
            price += max(delta, 0.01) if buying else min(-delta, -0.01)
        assert price >= 0.01, 'Price cannot be less than $0.01'

        if buying:
            max_amount = self.available_balances['usd'] / price
        else:
            max_amount = self.available_balances[symbol_lower]

        if dollar_amount:
            amount = dollar_amount / price
        elif ratio:
            amount = max_amount * ratio
        else:
            amount = min(max(-max_amount, self.value * value_ratio / price),
                         max_amount)
        amount, max_amount = round(amount, 8), round(max_amount, 8)

        assertion_msg = 'Trade value (${:.2f}) is %s available trade value ' \
                        '($%.2f)'.format(abs(amount * price))
        assert abs(amount) >= self._min_order_value / price, \
            assertion_msg % ('below minimum', self._min_order_value)
        assert abs(amount) <= max_amount, \
            assertion_msg % ('above maximum', max_amount * price)

        current_order_ids = set(self._orders.keys())
        if len(self._executed_orders) == 0:
            last_executed_id = None
        else:
            last_executed_id = self._executed_orders[-1][0]

        self.wss.new_order(
            cid=int(time.time()),
            type="EXCHANGE %s" % trade_type.upper(),
            symbol="t%s" % symbol,
            amount="%.8f" % amount,
            price="%.2f" % price,
        )

        while return_id:
            for _id in self._orders.copy().keys():
                # new order arrives in _orders
                if _id not in current_order_ids:
                    return _id
            else:
                # new order is executed immediately
                if len(self._executed_orders) > 0 \
                 and self._executed_orders[-1][0] != last_executed_id:
                    return self._executed_orders[-1][0]
                time.sleep(self._sleep_time)

    def subscribe(self, symbol):
        """
        Subscribe to a symbol for price watching
        :param symbol: str: symbol to subscribe to (e.g. 'BTCUSD', 'ETHUSD'...)
        """
        self.symbols.append(symbol)
        self.wss.subscribe_to_ticker(symbol)

    def wait_execution(self, _id, seconds=1e9):
        """
        Waits for an order to execute
        :param _id: int: id of order to wait for
        :param seconds: int/float: time to wait before raising error
        :return: dict: order in json format
        :raises: TimeoutError (if order is not executed in given time)
        """
        start_time = time.time()
        while time.time() - start_time < seconds:
            try:
                ids, trades = tuple(zip(*self._executed_orders))
                return trades[ids.index(_id)]
            except ValueError:
                time.sleep(self._sleep_time)
        raise TimeoutError('Waiting for execution of order '
                           '%d timed out after %d seconds' % (_id, seconds))

    def _receive(self):
        while not self._disconnect_event.is_set():
            for source in self._sources:
                with suppress(Empty):
                    q = self.wss.queue_processor.account[source]
                    cmd, data = q.get_nowait()[0]
                    self._update(cmd, data)

            for symbol in self.symbols:
                with suppress(Empty):
                    q = self.wss.queue_processor.tickers[('ticker', symbol)]
                    data = q.get_nowait()[0]
                    self._update('t' + symbol, data)

    def _subscribe(self):
        for symbol in self.symbols_gen:
            self.subscribe(symbol)
            current_dict[key] = definition
            break
    return current_dict


secStr = btfAccount()

loginName = str(secStr['APIK'])
passName = str(secStr['APIS'])

wss = BtfxWss(key=loginName, secret=passName)
wss.start()

while not wss.conn.connected.is_set():
    time.sleep(1)
wss.authenticate()  #Success
##############################################################################
# Subscribe to some channels
wss.subscribe_to_ticker('BTCUSD')
wss.subscribe_to_order_book('BTCUSD')
wss.subscribe_to_trades('BTCUSD')

time.sleep(5)
#Accessing data stored in BtfxWss:
ticker_q = wss.tickers('BTCUSD')
while not ticker_q.empty():
    print(ticker_q.get()[0][0][0])
    break

##################################################################################
Exemple #4
0
class RateMonitor(object):
    def __init__(self, symbols):
        self.DEBUG = True
        self._rest_client = bitfinex_v1_rest.FullApi()
        self._wss = None
        self._symbols = symbols
        self._funding = {}
        self._credits = {}
        self._offers = {}
        self._wss = BtfxWss(key=config.BFX_API_KEY,
                            secret=config.BFX_API_SECRET)
        self._wss.start()

    def reset(self):
        self._funding = {}
        self._credits = {}
        self._offers = {}

    def connect(self):
        log("Server connected")
        self._wss.authenticate()
        for symbol in self._symbols:
            self._wss.subscribe_to_trades(symbol)
            self._funding['latest_ts'] = 0
            self._funding['latest_rate'] = 0.0

    def run(self):
        while True:
            self.check_system()
            self.check_account_info()
            self.check_trades()
            time.sleep(0.5)

    def check_system(self):
        try:
            server_q = self._wss.opened
            while not server_q.empty():
                server_q.get()
                self.reset()
                self.connect()
        except KeyError:
            # KeyError means Btfxwss doesn't get related information yet.
            # It's fine to pass and check in the next time.
            pass

    def check_account_info(self):
        try:
            wallets_q = self._wss.wallets
            while not wallets_q.empty():
                self.received_wallets(wallets_q.get())

            wallet_update_q = self._wss.wallet_update
            while not wallet_update_q.empty():
                self.received_wallet_update(wallet_update_q.get())

            credits_q = self._wss.credits
            while not credits_q.empty():
                self.received_credits(credits_q.get())

            offer_new_q = self._wss.offer_new
            while not offer_new_q.empty():
                self.received_offer_new(offer_new_q.get())

            offer_cancel_q = self._wss.offer_cancel
            while not offer_cancel_q.empty():
                self.received_offer_cancel(offer_cancel_q.get())

            credit_close_q = self._wss.credit_close
            while not credit_close_q.empty():
                self.received_credit_close(credit_close_q.get())

            credit_update_q = self._wss.credit_update
            while not credit_update_q.empty():
                self.received_credit_update(credit_update_q.get())

            q = self._wss.offer_update
            while not q.empty():
                print(q.get())
        except KeyError:
            # KeyError means Btfxwss doesn't get related information yet.
            # It's fine to pass and check in the next time.
            pass

    def check_trades(self):
        for symbol in self._symbols:
            try:
                trades_q = self._wss.trades(symbol)
                while not trades_q.empty():
                    self.received_trades(symbol, trades_q.get())
            except KeyError:
                # KeyError means Btfxwss doesn't get related information yet.
                # It's fine to pass and check in the next time.
                pass

    def received_wallets(self, message):
        # pylint: disable=W0612
        data, ts = message
        for wallet in data[1]:
            self.process_wallet(wallet)

    def received_wallet_update(self, message):
        # pylint: disable=W0612
        data, ts = message
        self.process_wallet(data[1])

    def received_credits(self, message):
        # pylint: disable=W0612
        data, ts = message
        self._funding['lent'] = 0
        for credit in data[1]:
            self._funding['lent'] += self.process_credit(credit)
        log("Funding usd lent: %f" % self._funding['lent'])

    def received_offer_new(self, message):
        # pylint: disable=W0612
        data, ts = message
        self.process_offer(data[1])

    def received_offer_cancel(self, message):
        # pylint: disable=W0612
        data, ts = message
        self.process_offer(data[1])

    def received_credit_close(self, message):
        # pylint: disable=W0612
        data, ts = message
        self.process_credit(data[1])

    def received_credit_update(self, message):
        # pylint: disable=W0612
        data, ts = message
        self.process_credit(data[1])

    def received_trades(self, symbol, message):
        # pylint: disable=W0612
        data, ts = message
        if isinstance(data[0], list):
            for transaction in data[0]:
                self.process_public_trade(symbol, transaction)
        elif data[0] == 'fte':
            self.process_public_trade(symbol, data[1])
            self.lend_strategy()

    def process_wallet(self, data):
        if self.DEBUG:
            print(data)
        wallet = bitfinex_v2_rest.Wallet(data)
        if wallet.wallet_type == 'funding' and wallet.currency == 'USD':
            self._funding['total'] = wallet.balance
            log("Funding usd: %f" % self._funding['total'])

    def process_credit(self, data):
        if self.DEBUG:
            print(data)
        credit = bitfinex_v2_rest.Credit(data)
        if credit.symbol == 'fUSD':
            if credit.status == 'ACTIVE':
                self._credits[credit.id] = credit.amount
                return credit.amount
            elif credit.status.startswith('CLOSED'):
                del self._credits[credit.id]
                self._funding['lent'] -= credit.amount
                log('Close a credit, amount: %f' % credit.amount)
                self.lend_strategy()
        return 0

    def process_offer(self, data):
        if self.DEBUG:
            print(data)
        offer = bitfinex_v2_rest.FundingOffer(data)
        if offer.symbol == 'fUSD':
            if offer.status == 'ACTIVE':
                if offer.id not in self._offers:
                    self._offers[offer.id] = offer.amount_orig
                    self._funding['lent'] += offer.amount_orig
                    log('Create an offer, amount: %f' % offer.amount_orig)
            elif offer.status == 'CANCEL':
                self._funding['lent'] -= offer.amount
                log('Cancel an offer, amount: %f' % offer.amount)
                del self._offers[offer.id]
            elif offer.status.startswith('EXECUTED'):
                if offer.id not in self._offers:
                    self._funding['lent'] += offer.amount_orig
                    log('Create an offer, amount: %f' % offer.amount_orig)
                else:
                    del self._offers[offer.id]

    def process_public_trade(self, symbol, data):
        trade = bitfinex_v2_rest.Trade(data)
        log("%s: Timestamp: %s, Rate: %f, Period: %d, Amount: %f" %
            (symbol, time.strftime("%H:%M:%S", time.localtime(trade.time)),
             trade.rate * 100, trade.period, abs(trade.amount)))

        if trade.time > self._funding['latest_ts']:
            self._funding['latest_ts'] = trade.time
            self._funding['latest_rate'] = trade.rate

    def lend_strategy(self):
        if 'total' in self._funding and 'lent' in self._funding:
            available = self._funding['total'] - self._funding['lent']
        else:
            return
        if 'available' not in self._funding or (available !=
                                                self._funding['available']):
            log('total: %f, lent: %f, available: %f' %
                (self._funding['total'], self._funding['lent'], available))
            self._funding['available'] = available

        # Re-write the strategy by yourself
        if available > 50:
            # rate 0 means FRR
            self.new_offer('USD', available - Decimal(0.000001), 0, 2)

    def new_offer(self, currency, amount, rate, period):
        """Create an new offer
        :param rate: Rate per day
        """
        try:
            result = self._rest_client.new_offer(currency, amount, rate,
                                                 period)
        except BitfinexClientError as e:
            log(e.value)
            raise

        log('Create an new %s offer with amount: %f, rate: %f, ' %
            (currency, amount, rate) + 'period: %d' % period)
        self._offers[result['offer_id']] = amount
        self._funding['lent'] += amount
        return result['offer_id']

    def cancel_offer(self, offer_id):
        """Cancel an offer"""
        try:
            self._rest_client.cancel_offer(offer_id)
        except BitfinexClientError as e:
            log(e.value)
            raise
        log('Cancel an offer with id: %d' % offer_id)
def worker_function(quit_flag, launch_flag, globalz):
    counter = 0
    established = False
    wss = None
    qq = None
    first = True
    order = False
    OCHLVlast = 0
    OCHLVcur = 0

    while not quit_flag.value:

        if launch_flag.value == 5:

            if established == False:
                wss = BtfxWss(key=API_KEY, secret=API_SECRET)
                wss.start()

                while not wss.conn.connected.is_set():
                    time.sleep(1)
                    established = True
                    wss.authenticate()
                # Subscribe to some channels
                wss.subscribe_to_ticker('BTCUSD')
                wss.subscribe_to_candles('BTCUSD', '15m')
                wss.subscribe_to_candles('BTCUSD', '1m')
                wss.subscribe_to_order_book('BTCUSD')

            # Do something else
            t = time.time()
            while time.time() - t < 2:
                pass

            # Accessing data stored in BtfxWss:
            ticker_q = wss.candles(
                'BTCUSD', '1m')  # returns a Queue object for the pair.
            wallet = wss.wallets

            while not ticker_q.empty():
                qq = np.asarray(ticker_q.get())
                #globalz[0] = int(np.asarray(qq)[1])
                if type(qq[0][0][0]) == list:
                    first = True
                if first:
                    globalz[0] = int(((qq)[0][0][0][0]) / 1000)
                    #globalz[1] =
                    logging.debug(((qq)[0][0][0][0]) / 1000)
                    #loggin.debug()
                    #logging.debug(type((qq)[0][0][0][0]))
                    #logging.debug(type((qq)[0][0][0]))
                    #logging.debug(type((qq)[0][0]))
                    #logging.debug(type((qq)[0]))
                    #logging.debug(type((qq)))

                    with open('my.ts', 'w') as file:

                        for i in range(len(qq[0][0])):
                            stri = (str(qq[0][0][i]))
                            file.write((stri))
                            file.write("\n")

                    first = False
                else:
                    globalz[30] = int(((qq)[1]))
                    globalz[0] = int(((qq)[0][0][0]) / 1000)
                    globalz[5] = int(((qq)[0][0][5]) * 1000)
                    globalz[6] = int(((qq)[0][0][5]) * 1000)

                    #globalz[0] =

                    for i in range(1, 5):
                        globalz[i] = int((np.asarray(qq)[0][0][i]))

                    #logging.debug(counter)
                    logging.debug((np.asarray(qq)[0][0]))
                    #logging.debug((np.asarray(qq)[0][0][1]))

            if wallet.empty() == False:
                logging.debug(wallet.get())

            #ticker_q = wss.candles('BTCUSD')  # returns a Queue object for the pair.

            counter += 1
            logging.debug("Tick # %s" % counter)

            #var.set()
            #time.sleep(0.01)

        elif launch_flag.value == -1:
            if established == True:
                logging.info("Stopping kekush at # %s" % counter)
                time.sleep(0.01)

                wss.unsubscribe_from_ticker('BTCUSD')
                wss.unsubscribe_from_candles('BTCUSD')
                wss.unsubscribe_from_order_book('BTCUSD')

                # Shutting down the client:
                wss.stop()
                wss = None
                counter = 0
                established = False
                first = True

        elif launch_flag.value == 6:
            if order == False:
                logging.info("Ordering some shit at # %s" % counter)

                order = {
                    "cid": 373617,  #change to the API_Key Number
                    "type": "LIMIT",
                    "symbol": "tEOSUSD",
                    "amount": "2",
                    "price": "14",
                    "hidden": 0,
                    "postonly": 1
                }

                wss.new_order(**order)

                launch_flag.value = 7
                order = True

                time.sleep(3)
                logging.info(wss.orders.get())
Exemple #6
0
wss = BtfxWss()
wss.start()

while not wss.conn.connected.is_set():
    time.sleep(1)

# Subscribe to some channels
wss.subscribe_to_ticker('BTCUSD')
wss.subscribe_to_order_book('BTCUSD')

# Do something else
t = time.time()
while time.time() - t < 10:
    pass

# Accessing data stored in BtfxWss:
ticker_q = wss.tickers('BTCUSD')  # returns a Queue object for the pair.
wss.authenticate()
wss.notifications
wss.authenticate()
while not ticker_q.empty():
    print(ticker_q.get())

# Unsubscribing from channels:
wss.unsubscribe_from_ticker('BTCUSD')
wss.unsubscribe_from_order_book('BTCUSD')

# Shutting down the client:
wss.stop()
Exemple #7
0
class WebSocketApi(object):
    """ Wrapper to use BtfxWss. """
    def __init__(self, symbols=None, callbacks=None):
        """
        Args:
            symbols: A list used to subscribe tickers.
            callbacks: A list of functions to handle events:
                'reset',
                'process_wallet',
                'process_order',
                'process_tick',
                'process_notification'
        """
        required_callbacks = [
            'reset',
            'process_wallet',
            'process_order',
            'process_tick',
            'process_notification'
        ]
        if not symbols or not callbacks:
            log(LOG_ERROR, 'Require parameters symbols and callbacks')
            return
        for callback in required_callbacks:
            if callback not in callbacks:
                log(LOG_ERROR, 'Require %s callback function' % callback)
                return

        self._tick_symbols = symbols
        self._callbacks = callbacks

        self._received_order_snapshot = False
        self._received_wallet_snapshot = False
        self._wss = BtfxWss(
            key=config.BFX_API_KEY, secret=config.BFX_API_SECRET)
        self._wss.start()

    def __connect(self):
        """
        Reset data and subscribe tick data after connect to server.
        """
        log(LOG_INFO, "Server connected")
        self._received_order_snapshot = False
        self._received_wallet_snapshot = False

        self._wss.authenticate()
        for pair in self._tick_symbols:
            symbol = 't' + pair
            self._wss.subscribe_to_ticker(symbol)

    def __check_system(self):
        """ Check the connection is established or not. """
        try:
            server_q = self._wss.opened
            while not server_q.empty():
                server_q.get()
                self._callbacks['reset']()
                self.__connect()
        except KeyError:
            # KeyError means Btfxwss doesn't get related information yet.
            # It's fine to pass and check in the next time.
            pass

    def __check_account_info(self):
        """ Check account information. """
        try:
            wallets_q = self._wss.wallets
            while not wallets_q.empty():
                self.__received_wallets(wallets_q.get()[0][1])

            wallet_update_q = self._wss.wallet_update
            while not wallet_update_q.empty():
                self.__received_wallet_update(
                    wallet_update_q.get()[0][1])

            orders_q = self._wss.orders
            while not orders_q.empty():
                self.__received_orders(orders_q.get()[0][1])

            order_new_q = self._wss.order_new
            while not order_new_q.empty():
                self.__received_order(order_new_q.get()[0][1])

            order_cancel_q = self._wss.order_cancel
            while not order_cancel_q.empty():
                self.__received_order(order_cancel_q.get()[0][1])

            notification_q = self._wss.notifications
            while not notification_q.empty():
                self.__received_notification(notification_q.get()[0][1])
        except KeyError:
            # KeyError means Btfxwss doesn't get related information yet.
            # It's fine to pass and check in the next time.
            pass

    def __check_tickers(self):
        """ Check tick data. """
        for symbol in self._tick_symbols:
            try:
                trades_q = self._wss.tickers(symbol)
                while not trades_q.empty():
                    self.__received_tickers(symbol, trades_q.get()[0])
            except KeyError:
                # KeyError means Btfxwss doesn't get related information
                # yet. It's fine to pass and check in the next time.
                pass

    def __check_unused_info(self):
        """
        Websocket may have many events which are not used.
        Just pop it and ignore it. Otherwise, the queue may use too many
        memories.
        """
        def pop_queue(queue):
            """ pop unused queue """
            while not queue.empty():
                queue.get()

        try:
            queues = [
                self._wss.credits, self._wss.offer_new,
                self._wss.offer_cancel, self._wss.credit_new,
                self._wss.credit_close, self._wss.credit_update,
                self._wss.positions, self._wss.offer_update,
                self._wss.order_update, self._wss.position_update,
                self._wss.position_close, self._wss.loan_new,
                self._wss.loan_close, self._wss.loan_update,
                self._wss.unknown]

            for queue in queues:
                pop_queue(queue)
        except KeyError:
            # KeyError means Btfxwss doesn't get related information yet.
            # It's fine to pass and check in the next time.
            pass

    def __received_wallets(self, wallets):
        """
        Handle wallet snapshot.
        Args:
            wallets: balance of all currencies
        """
        for wallet in wallets:
            self._callbacks['process_wallet'](bitfinex_v2_rest.Wallet(wallet))
        self._received_wallet_snapshot = True

    def __received_wallet_update(self, wallet):
        """
        Handle wallet update.
        Args:
            wallets: balance of one currency
        """
        self._callbacks['process_wallet'](bitfinex_v2_rest.Wallet(wallet))

    def __received_orders(self, orders):
        """
        Handle order snapshot.
        Args:
            orders: current orders snapshot
        """
        for order in orders:
            self._callbacks['process_order'](bitfinex_v2_rest.Order(order))
        self._received_order_snapshot = True

    def __received_order(self, order):
        """
        Handle one order
        Args:
            order: order status
        """
        self._callbacks['process_order'](bitfinex_v2_rest.Order(order))

    def __received_tickers(self, pair, tickers):
        """
        Handle ticks
        Args:
            pair: ex BTCUSD
            tickers: tickers of the pair
        """
        if isinstance(tickers, list):
            for tick in tickers:
                self._callbacks['process_tick'](
                    bitfinex_v2_rest.TradingTicker([pair] + tick))

    def __received_notification(self, message):
        """
        Handle notification
        Args:
            message: notification from web socket
        """
        self._callbacks['process_notification'](
            bitfinex_v2_rest.Notifications(message))

    def new_order(self, pair, price, amount):
        """
        Create an new order.
        Args:
            pair: ex BTCUSD.
            price: 0 means the market order.
            amount: Positive number means buy order. Negative number means
                    sell order.
        """
        symbol = 't' + pair
        cid = int(round(time.time() * 1000))
        if price > 0:
            order = {
                'cid': cid,
                'type': "EXCHANGE LIMIT",
                'symbol': symbol,
                'amount': str(amount),
                'price': str(price),
                'hidden': 0
                }
        else:
            order = {
                'cid': cid,
                'type': "EXCHANGE MARKET",
                'symbol': symbol,
                'amount': str(amount),
                'hidden': 0
                }
        self._wss.new_order(**order)

    def cancel_order(self, order_id):
        """
        Cancel an order.
        Args:
            order_id: The id of the order.
        """
        value = {'id': order_id}
        self._wss.cancel_order(False, **value)

    def check_events(self):
        """ Check all events from web socket """
        self.__check_system()
        self.__check_account_info()
        self.__check_tickers()
        self.__check_unused_info()

    def is_received_order_snapshot(self):
        """ Return True if recevied order snapshot """
        return self._received_order_snapshot

    def is_received_wallet_snapshot(self):
        """ Return True if recevied wallet snapshot """
        return self._received_wallet_snapshot