def tickers(self, assets): """ Retrieve current tick data for the given assets Parameters ---------- assets: list[TradingPair] Returns ------- list[dict[str, float] """ tickers = dict() try: for asset in assets: symbol = self.get_symbol(asset) # TODO: use fetch_tickers() for efficiency # I tried using fetch_tickers() but noticed some # inconsistencies, see issue: # https://github.com/ccxt/ccxt/issues/870 ticker = self.api.fetch_ticker(symbol=symbol) if not ticker: log.warn('ticker not found for {} {}'.format( self.name, symbol )) continue ticker['last_traded'] = from_ms_timestamp(ticker['timestamp']) if 'last_price' not in ticker: # TODO: any more exceptions? ticker['last_price'] = ticker['last'] if 'baseVolume' in ticker and ticker['baseVolume'] is not None: # Using the volume represented in the base currency ticker['volume'] = ticker['baseVolume'] elif 'info' in ticker and 'bidQty' in ticker['info'] \ and 'askQty' in ticker['info']: ticker['volume'] = float(ticker['info']['bidQty']) + \ float(ticker['info']['askQty']) else: ticker['volume'] = 0 tickers[asset] = ticker except ExchangeNotAvailable as e: log.warn( 'unable to fetch ticker: {} {}'.format( self.name, asset.symbol ) ) raise ExchangeRequestError(error=e) return tickers
def get_orderbook(self, asset, order_type='all', limit=None): ccxt_symbol = self.get_symbol(asset) params = dict() if limit is not None: params['depth'] = limit order_book = self.api.fetch_order_book(ccxt_symbol, params) order_types = ['bids', 'asks'] if order_type == 'all' else [order_type] result = dict(last_traded=from_ms_timestamp(order_book['timestamp'])) for index, order_type in enumerate(order_types): if limit is not None and index > limit - 1: break result[order_type] = [] for entry in order_book[order_type]: result[order_type].append(dict( rate=float(entry[0]), quantity=float(entry[1]) )) return result
def _create_order(self, order_status): """ Create a Catalyst order object from a CCXT order dictionary Parameters ---------- order_status: dict[str, Object] The order dict from the CCXT api. Returns ------- Order The Catalyst order object """ order_id = order_status['id'] symbol = self.get_symbol(order_status['symbol'], source='ccxt') asset = self.get_asset(symbol) s = order_status['status'] amount = order_status['amount'] filled = order_status['filled'] if s == 'canceled' or (s == 'closed' and filled == 0): status = ORDER_STATUS.CANCELLED elif s == 'closed' and filled > 0: if filled < amount: log.warn( 'order {id} is executed but only partially filled:' ' {filled} {symbol} out of {amount}'.format( id=order_status['status'], filled=order_status['filled'], symbol=asset.symbol, amount=order_status['amount'], ) ) else: log.info( 'order {id} executed in full: {filled} {symbol}'.format( id=order_id, filled=filled, symbol=asset.symbol, ) ) status = ORDER_STATUS.FILLED elif s == 'open': status = ORDER_STATUS.OPEN elif filled > 0: log.info( 'order {id} partially filled: {filled} {symbol} out of ' '{amount}, waiting for complete execution'.format( id=order_id, filled=filled, symbol=asset.symbol, amount=amount, ) ) status = ORDER_STATUS.OPEN else: log.warn( 'invalid state {} for order {}'.format( s, order_id ) ) status = ORDER_STATUS.OPEN if order_status['side'] == 'sell': amount = -amount filled = -filled price = order_status['price'] order_type = order_status['type'] limit_price = price if order_type == 'limit' else None executed_price = order_status['cost'] / order_status['amount'] commission = order_status['fee'] date = from_ms_timestamp(order_status['timestamp']) order = Order( dt=date, asset=asset, amount=amount, stop=None, limit=limit_price, filled=filled, id=order_id, commission=commission ) order.status = status return order, executed_price