diff --git a/ExchangeInterfaces/BinanceExchange.py b/ExchangeInterfaces/BinanceExchange.py index 9cee588..415f5c3 100644 --- a/ExchangeInterfaces/BinanceExchange.py +++ b/ExchangeInterfaces/BinanceExchange.py @@ -17,6 +17,12 @@ def __init__(self, apiKey, apiSecret, pairs, name): super().__init__(apiKey, apiSecret, pairs, name) self.connection = Client(self.api['key'], self.api['secret']) + + symbol_info_arr = self.connection.get_exchange_info() + dict_symbols_info = {item['symbol']: item for item in symbol_info_arr["symbols"]} + actual_symbols_info = {symbol: dict_symbols_info[symbol] for symbol in self.pairs} + self.symbols_info = actual_symbols_info + self.update_balance() self.socket = BinanceSocketManager(self.connection) self.socket.start_user_socket(self.on_balance_update) @@ -24,7 +30,7 @@ def __init__(self, apiKey, apiSecret, pairs, name): self.is_last_order_event_completed = True self.step_sizes = {} self.balance_updated = True - symbol_info_arr = self.connection.get_exchange_info() + for symbol_info in symbol_info_arr['symbols']: if symbol_info['symbol'] in self.pairs: self.step_sizes[symbol_info['symbol']] = \ @@ -37,9 +43,19 @@ def update_balance(self): account_information = self.connection.get_account() self.set_balance(account_information['balances']) + def get_trading_symbols(self): + symbols = set() + if not self.symbols_info: + raise RuntimeError("Cant get exchange info") + for key, value in self.symbols_info.items(): + symbols.add(value["quoteAsset"]) + symbols.add(value["baseAsset"]) + return symbols + def set_balance(self, balances): symbols = self.get_trading_symbols() - actual_balance = list(filter(lambda elem: str(elem['asset']) in symbols, balances)) + dict_balances = {item['asset']: item for item in balances} + actual_balance = {symbol: dict_balances[symbol] for symbol in symbols} self.balance = actual_balance def on_balance_update(self, upd_balance_ev): @@ -49,13 +65,7 @@ def on_balance_update(self, upd_balance_ev): balance.append({'asset': ev['a'], 'free': ev['f'], 'locked': ev['l']}) - # self.set_balance(balance) - i = 0 - while i < len(self.balance): - for act_bal in balance: - if self.balance[i]['asset'] == act_bal['asset']: - self.balance[i] = act_bal - i += 1 + self.balance.update({item['asset']: item for item in balance}) def get_open_orders(self): orders = self.connection.get_open_orders() @@ -154,8 +164,8 @@ def create_order(self, order): :param order: """ quantity = self.calc_quantity_from_part(order.symbol, order.quantityPart, order.price, order.side) - self.logger.info('Slave ' + self.name + ' ' + str(self._get_balance_market_by_symbol(order.symbol)) + ' ' - + str(self._get_balance_coin_by_symbol(order.symbol)) + + self.logger.info('Slave ' + self.name + ' ' + str(self._get_quote_balance(order.symbol)) + ' ' + + str(self._get_base_balance(order.symbol)) + ', Create Order:' + ' amount: ' + str(quantity) + ', price: ' + str(order.price)) try: if order.type == 'STOP_LOSS_LIMIT' or order.type == "TAKE_PROFIT_LIMIT": @@ -182,21 +192,21 @@ def create_order(self, order): except Exception as e: self.logger.error(str(e)) - def _get_balance_market_by_symbol(self, symbol): - return list(filter(lambda el: el['asset'] == symbol[3:], self.get_balance()))[0] + def _get_quote_balance(self, symbol): + return self.balance[self.symbols_info[symbol]['quoteAsset']] - def _get_balance_coin_by_symbol(self, symbol): - return list(filter(lambda el: el['asset'] == symbol[:3], self.get_balance()))[0] + def _get_base_balance(self, symbol): + return self.balance[self.symbols_info[symbol]['baseAsset']] def get_part(self, symbol: str, quantity: float, price: float, side: str): # get part of the total balance of this coin # if order[side] == sell: need obtain coin balance if side == 'BUY': - get_context_balance = self._get_balance_market_by_symbol + get_context_balance = self._get_quote_balance market_value = float(quantity) * float(price) else: - get_context_balance = self._get_balance_coin_by_symbol + get_context_balance = self._get_base_balance market_value = float(quantity) balance = float(get_context_balance(symbol)['free']) @@ -217,10 +227,10 @@ def calc_quantity_from_part(self, symbol, quantityPart, price, side): # if order[side] == sell: need obtain coin balance if side == 'BUY': - get_context_balance = self._get_balance_market_by_symbol + get_context_balance = self._get_quote_balance buy_koef = float(price) else: - get_context_balance = self._get_balance_coin_by_symbol + get_context_balance = self._get_base_balance buy_koef = 1 cur_bal = float(get_context_balance(symbol)['free']) diff --git a/ExchangeInterfaces/BitmexExchange.py b/ExchangeInterfaces/BitmexExchange.py index da8e8d5..a513a21 100644 --- a/ExchangeInterfaces/BitmexExchange.py +++ b/ExchangeInterfaces/BitmexExchange.py @@ -13,6 +13,7 @@ class BitmexExchange(Exchange): exchange_name = "Bitmex" isMargin = True ENDPOINT = "https://www.bitmex.com/api/v1" + TEST = False def __init__(self, apiKey, apiSecret, pairs, name): @@ -20,18 +21,18 @@ def __init__(self, apiKey, apiSecret, pairs, name): self.pairs = list(map(lambda pair: self.translate(pair) if pair != self.translate(pair) else self.logger.debug(f"Can't translate word {pair} in {self.exchange_name}"), self.pairs)) self.pairs = list(filter(None, self.pairs)) - self.connection = bitmex.bitmex(api_key=apiKey, api_secret=apiSecret) + self.connection = bitmex.bitmex(api_key=apiKey, api_secret=apiSecret, test=self.TEST) self.socket = {} # self.firts_copy_flag = True self.balance_updated = False - - self.socket['XBTUSD'] = BitMEXWebsocket(endpoint=self.ENDPOINT, symbol='XBTUSD', - api_key=self.api['key'], - api_secret=self.api['secret'], on_balance_update=self.on_balance_update) for pair in self.pairs: if pair == 'XBTUSD': - continue - self.socket[pair] = BitMEXWebsocket(endpoint=self.ENDPOINT, symbol=pair, + self.socket['XBTUSD'] = BitMEXWebsocket(endpoint=self.ENDPOINT, symbol='XBTUSD', + api_key=self.api['key'], + api_secret=self.api['secret'], + on_balance_update=self.on_balance_update) + else: + self.socket[pair] = BitMEXWebsocket(endpoint=self.ENDPOINT, symbol=pair, api_key=self.api['key'], api_secret=self.api['secret'] ) @@ -56,11 +57,14 @@ def stop(self): def on_balance_update(self, event): if 'availableMargin' in event: - self.balance = event['availableMargin'] + self.balance = event['availableMargin'] / (10**8) * (self.socket['XBTUSD'].get_instrument()['midPrice']\ + if "XBTUSD" in self.socket else self.connection.Instrument.Instrument_get(symbol='XBTUSD', count=1, reverse=True).result()[0][0]['midPrice']) + self.balance_updated = True def update_balance(self): - self.balance = self.socket[self.pairs[0]].funds()['availableMargin'] + self.balance = self.socket['XBTUSD'].funds()['availableMargin'] / 10**8 *\ + self.socket['XBTUSD'].get_instrument()['midPrice'] def get_open_orders(self): open_orders = [] @@ -72,22 +76,25 @@ def get_open_orders(self): general_orders.append(self._self_order_to_global(o)) return general_orders - def get_part(self, symbol, quantity, price): - btc = float(quantity) / float(price) - btc_satoshi = btc * (10 ** 8) + def get_part(self, symbol, quantity: float, price: float): + # btc = float(quantity) / float(price) + # btc_satoshi = btc * (10 ** 8) + + usd_order_value = quantity balance = self.get_balance() - if self.balance_updated: - part = float(btc_satoshi) / float(balance + (float(price) * float(quantity))) - else: - part = float(btc_satoshi) / float(balance) + # if self.balance_updated: + # part = usd_order_value / float(balance + usd_order_value) + # else: + # part = usd_order_value / balance + part = usd_order_value / balance part = part * 0.99 # decrease part for 1% for avoid rounding errors in calculation return part def calc_quantity_from_part(self, symbol, quantityPart, price, **kwargs): - btc_satoshi = float(quantityPart) * float(self.get_balance()) - btc = btc_satoshi / (10 ** 8) - amount_usd = float(btc) * float(price) + amount_usd = float(quantityPart) * float(self.get_balance()) + # btc = btc_satoshi / (10 ** 8) + # amount_usd = float(btc) * float(price) return amount_usd def process_event(self, event): diff --git a/ExchangeInterfaces/BitmexTest.py b/ExchangeInterfaces/BitmexTest.py index d7273f4..46b8364 100644 --- a/ExchangeInterfaces/BitmexTest.py +++ b/ExchangeInterfaces/BitmexTest.py @@ -3,3 +3,4 @@ class BitmexTest(BitmexExchange): ENDPOINT = "https://testnet.bitmex.com/api/v1" + TEST = True diff --git a/ExchangeInterfaces/Exchange.py b/ExchangeInterfaces/Exchange.py index 324c51c..e1ff1a9 100644 --- a/ExchangeInterfaces/Exchange.py +++ b/ExchangeInterfaces/Exchange.py @@ -17,16 +17,10 @@ def __init__(self, apiKey, apiSecret, pairs, name): self.ids = [] # store here order which was created by program self.logger = logging.getLogger('cct') - def get_balance(self): + def get_balance(self) -> float: return self.balance - def get_trading_symbols(self): - symbols = set() - for pair in self.pairs: - pair = str(pair) - symbols.add(pair[:3]) - symbols.add(pair[3:]) - return symbols + @abstractmethod def stop(self):