Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Issue #36. Add BinanceExchange.symbols_info #37

Merged
merged 2 commits into from
Nov 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 29 additions & 19 deletions ExchangeInterfaces/BinanceExchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,20 @@ 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)
self.socket.start()
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']] = \
Expand All @@ -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):
Expand All @@ -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()
Expand Down Expand Up @@ -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":
Expand All @@ -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'])
Expand All @@ -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'])
Expand Down
45 changes: 26 additions & 19 deletions ExchangeInterfaces/BitmexExchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,26 @@ class BitmexExchange(Exchange):
exchange_name = "Bitmex"
isMargin = True
ENDPOINT = "https://www.bitmex.com/api/v1"
TEST = False

def __init__(self, apiKey, apiSecret, pairs, name):

super().__init__(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']
)
Expand All @@ -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 = []
Expand All @@ -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):
Expand Down
1 change: 1 addition & 0 deletions ExchangeInterfaces/BitmexTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@

class BitmexTest(BitmexExchange):
ENDPOINT = "https://testnet.bitmex.com/api/v1"
TEST = True
10 changes: 2 additions & 8 deletions ExchangeInterfaces/Exchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down