diff --git a/xchange/clients/base.py b/xchange/clients/base.py index 979febf..6df1c3d 100644 --- a/xchange/clients/base.py +++ b/xchange/clients/base.py @@ -1,4 +1,5 @@ import requests +from decimal import Decimal try: from urllib.parse import urlencode except ImportError: @@ -98,6 +99,9 @@ def _process_response(self, response, model_class=None, transformation=None): data = model_class(data) return data + def _empty_account_balance(self, symbol): + return {'symbol': symbol, 'amount': Decimal('0')} + # public endpoints def get_ticker(self, symbol_pair): diff --git a/xchange/clients/bitfinex.py b/xchange/clients/bitfinex.py index 8d471f2..461238b 100644 --- a/xchange/clients/bitfinex.py +++ b/xchange/clients/bitfinex.py @@ -21,6 +21,10 @@ class BitfinexClient(BaseExchangeClient): currencies.BTC_USD: 'btcusd', currencies.ETH_USD: 'ethusd', currencies.LTC_USD: 'ltcusd', + currencies.BCH_USD: 'bchusd', + currencies.XRP_USD: 'xrpusd', + currencies.EOS_USD: 'eosusd', + currencies.BTG_USD: 'btgusd', } def _sign_payload(self, payload): @@ -85,7 +89,7 @@ def get_account_balance(self, symbol=None): for symbol_balance in data: if symbol_balance.symbol == symbol: return symbol_balance - raise self.ERROR_CLASS('Symbol "{}" was not found in the account balance'.format(symbol)) + return self._empty_account_balance(symbol) def get_open_orders(self, symbol_pair): is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS) diff --git a/xchange/clients/kraken.py b/xchange/clients/kraken.py index 9545a77..1970523 100644 --- a/xchange/clients/kraken.py +++ b/xchange/clients/kraken.py @@ -25,6 +25,10 @@ class KrakenClient(BaseExchangeClient): currencies.BTC_USD: 'XBTUSD', currencies.ETH_USD: 'ETHUSD', currencies.LTC_USD: 'LTCUSD', + + currencies.BCH_USD: 'BCHUSD', + currencies.XRP_USD: 'XRPUSD', + currencies.EOS_USD: 'EOSUSD', } def _sign_payload(self, urlpath, payload): @@ -199,12 +203,13 @@ def get_account_balance(self, symbol=None): data = self._post(path, headers=headers, body=payload, transformation=self._transform_account_balance, model_class=KrakenAccountBalance) + if symbol is None: return data for symbol_balance in data: if symbol_balance.symbol == symbol: return symbol_balance - raise self.ERROR_CLASS('Symbol "{}" was not found in the account balance'.format(symbol)) + return self._empty_account_balance(symbol) def get_open_orders(self, symbol_pair): is_restricted_to_values(symbol_pair, currencies.SYMBOL_PAIRS) diff --git a/xchange/clients/okex.py b/xchange/clients/okex.py index 305db74..9084863 100644 --- a/xchange/clients/okex.py +++ b/xchange/clients/okex.py @@ -20,6 +20,10 @@ class OkexClient(BaseExchangeClient): currencies.BTC_USD: 'btc_usd', currencies.ETH_USD: 'eth_usd', currencies.LTC_USD: 'ltc_usd', + currencies.BCH_USD: 'bch_usd', + currencies.XRP_USD: 'xrp_usd', + currencies.EOS_USD: 'eos_usd', + currencies.BTG_USD: 'btg_usd', } ORDER_STATUS = { 'unfilled': 1, @@ -35,6 +39,10 @@ class OkexClient(BaseExchangeClient): 'btc_usd': 100, 'eth_usd': 10, 'ltc_usd': 10, + 'bch_usd': 10, + 'xrp_usd': 10, + 'eos_usd': 10, + 'btg_usd': 10, } def _sign_params(self, params): @@ -44,22 +52,7 @@ def _sign_params(self, params): data = sign + 'secret_key=' + self.api_secret return hashlib.md5(data.encode("utf8")).hexdigest().upper() - # FIXME: Try to find a better way of caching ticker responses - # without duplicating properties for each symbol_pair - @cached_property_with_ttl(ttl=60) # cache invalidates after 1 minute - def btc_usd_ticker(self): - return self.get_ticker(currencies.BTC_USD) - - @cached_property_with_ttl(ttl=60) - def eth_usd_ticker(self): - return self.get_ticker(currencies.ETH_USD) - - @cached_property_with_ttl(ttl=60) - def ltc_usd_ticker(self): - return self.get_ticker(currencies.LTC_USD) - # transformation functions - def _transform_account_balance(self, json_response): """ Original JSON response: @@ -360,3 +353,11 @@ def close_all_positions(self, symbol_pair): self.open_order( action, pos.amount, pos.symbol_pair, pos.price, exchanges.MARKET, amount_in_contracts=True, closing=True) + + +# OkexClient.btc_usd_ticker = cached_property_with_ttl(ttl=60)(lambda self: self.get_ticker(currencies.BTC_USD)) +for symbol_pair in OkexClient.SYMBOLS_MAPPING: + attr_name = '{}_ticker'.format(symbol_pair) + fun = lambda self: self.get_ticker(symbol_pair) + fun.__name__ = attr_name + setattr(OkexClient, attr_name, cached_property_with_ttl(ttl=60)(fun)) diff --git a/xchange/constants/currencies.py b/xchange/constants/currencies.py index eb73402..5f9441c 100644 --- a/xchange/constants/currencies.py +++ b/xchange/constants/currencies.py @@ -26,7 +26,7 @@ SYMBOL_VARIANTS = { USD: ('zusd', ), BTC: ('xxbt', ), - BCH: ('bcc', 'bcc'), + BCH: ('bcc', ), BTG: (), ETH: ('xeth', ), ETC: (), @@ -40,14 +40,26 @@ BTC_USD = '{}_{}'.format(BTC, USD) ETH_USD = '{}_{}'.format(ETH, USD) LTC_USD = '{}_{}'.format(LTC, USD) +BCH_USD = '{}_{}'.format(BCH, USD) +XRP_USD = '{}_{}'.format(XRP, USD) +EOS_USD = '{}_{}'.format(EOS, USD) +BTG_USD = '{}_{}'.format(BTG, USD) SYMBOL_PAIRS = [ BTC_USD, ETH_USD, - LTC_USD + LTC_USD, + BCH_USD, + XRP_USD, + EOS_USD, + BTG_USD, ] SYMBOL_PAIR_VARIANTS = { BTC_USD: ('btcusd', 'xbtusd', 'xxbtzusd', 'btc0929', 'btc1229', ), ETH_USD: ('ethusd', 'eth0511', 'eth0518', 'eth0629', 'xethzusd', ), LTC_USD: ('ltcusd', 'ltc0511', 'ltc0518', 'ltc0629'), + BCH_USD: ('bchusd', 'bccusd'), + XRP_USD: ('xrpusd', ), + EOS_USD: ('eosusd', ), + BTG_USD: ('btgusd', ), }