Beispiel #1
0
 def dump_balance_log(self):
     print_(['margin dumping balance'])
     with open(make_get_filepath(self.balance_log_filepath), 'a') as f:
         self.balance['timestamp'] = self.cc.milliseconds()
         line = json.dumps(self.balance) + '\n'
         f.write(line)
     self.time_keepers['dump_balance_log'] = time()
Beispiel #2
0
 def update_open_orders(self, symbol: str):
     '''
     may be called threaded
     '''
     print_(['margin updating open orders', symbol])
     if symbol == 'all':
         symbols = set()
         self.my_asks = {s: [] for s in self.symbols}
         self.my_bids = {s: [] for s in self.symbols}
         for oo in sorted(self.fetch_margin_open_orders(),
                          key=lambda x: (x['symbol'], x['price'])):
             symbols.add(oo['symbol'])
             if oo['side'] == 'buy':
                 if oo['symbol'] not in self.my_bids:
                     self.my_bids[oo['symbol']] = []
                 self.my_bids[oo['symbol']].append(oo)
             else:
                 if oo['symbol'] not in self.my_asks:
                     self.my_asks[oo['symbol']] = []
                 self.my_asks[oo['symbol']].append(oo)
     else:
         symbols = [symbol]
         open_orders = self.fetch_margin_open_orders(symbol)
         self.my_bids[symbol], self.my_asks[symbol] = [], []
         for oo in sorted(open_orders, key=lambda x: x['price']):
             if oo['side'] == 'buy':
                 self.my_bids[symbol].append(oo)
             else:
                 self.my_asks[symbol].append(oo)
     now = time()
     for symbol in symbols:
         self.time_keepers['update_open_orders'][symbol] = now
Beispiel #3
0
 def on_update(self, symbol: str, update: dict):
     try:
         if symbol not in self.symbols_set:
             return
         if update['bids'][-1]['price'] < self.cm.previous_updates[symbol][
                 'bids'][-1]['price']:
             # highest bid became lower. was my bid taken
             if self.my_bids[symbol]:
                 if update['bids'][-1]['price'] <= self.my_bids[symbol][-1][
                         'price']:
                     # maybe or yes
                     print_(['margin bid taken', symbol])
                     self.previous_ts_bid_taken[symbol] = time()
                     self.time_keepers['update_balance'] = 0
         if update['asks'][0]['price'] > self.cm.previous_updates[symbol][
                 'asks'][0]['price']:
             # lowest ask became higher. was my ask taken
             if self.my_asks[symbol]:
                 if update['asks'][0]['price'] >= self.my_asks[symbol][0][
                         'price']:
                     # maybe or yes
                     print_(['margin ask taken', symbol])
                     self.previous_ts_ask_taken[symbol] = time()
                     self.time_keepers['update_balance'] = 0
         if all([
                 self.time_keepers[key][symbol] > 10
                 for key in ['update_open_orders', 'update_my_trades']
         ]):
             self.try_wrapper(self.update_ideal_orders, (symbol, ))
             self.try_wrapper(self.execute_to_exchange, (symbol, ))
         self.last_stream_tick_ts = time()
     except (Exception) as e:
         print('\n\nERROR in on_update', e)
Beispiel #4
0
 def update_loan_history(self, coin: str, side: str):
     assert side in ['borrow', 'repay']
     if coin == self.quot:
         return
     elif coin == 'BNB':
         getattr(self, f'{side}_history')[coin] = []
         return
     print_([f'margin update {side} history', coin])
     if coin not in getattr(self, f'{side}_history'):
         self.init_loan_history(coin, side)
     else:
         old_loans = getattr(self, f'{side}_history')[coin]
         fetched = new_loans = getattr(self, f'fetch_{side}_history')(coin)
         prev_fetch = []
         most_recent_id = old_loans[-1]['id'] if old_loans else 0
         current = 2
         while fetched and fetched != prev_fetch and fetched[0][
                 'id'] > most_recent_id:
             prev_fetch = fetched
             fetched = getattr(self, f'fetch_{side}_history')(coin, current)
             new_loans = fetched + new_loans
             current += 1
         condition = lambda x: x['id'] > most_recent_id
         cache_filepath = f'cache/binance/{self.user}/{side}_history/{coin}/'
         written_loans = self.write_cache(cache_filepath, new_loans,
                                          condition)
         getattr(self, f'{side}_history')[coin] += written_loans
     self.time_keepers[f'update_{side}_history'][coin] = time()
Beispiel #5
0
 def print_update(self, update: dict):
     print_([
         'margin',
         {
             k: update[k]
             for k in [
                 'coin', 'symbol', 'side', 'type', 'status', 'price',
                 'amount', 'tranId'
             ] if k in update
         }
     ])
Beispiel #6
0
 def repay(self, coin: str, amount: float):
     amount = round(amount, 8)
     if amount <= 0.0:
         return
     print_([f'repaying {amount} {coin}'])
     repaid = self.cc.sapi_post_margin_repay(params={
         'asset': coin,
         'amount': amount
     })
     repaid['coin'] = coin
     repaid['amount'] = amount
     repaid['side'] = 'repay'
     repaid['timestamp'] = self.cc.milliseconds()
     return repaid
Beispiel #7
0
 def borrow(self, coin: str, amount: float):
     amount = round(amount, 8)
     if amount <= 0.0:
         return
     print_([f'borrowing {amount} {coin}'])
     borrowed = self.cc.sapi_post_margin_loan(params={
         'asset': coin,
         'amount': amount
     })
     borrowed['coin'] = coin
     borrowed['amount'] = amount
     borrowed['side'] = 'borrow'
     borrowed['timestamp'] = self.cc.milliseconds()
     return borrowed
Beispiel #8
0
    def update_my_trades(self, symbol: str):
        print_(['margin updating my trades', symbol])
        if symbol not in self.my_trades:
            self.init_my_trades(symbol)
        else:
            limit = 100
            new_my_trades = fetched_my_trades = self.fetch_margin_my_trades(
                symbol,
                limit=limit,
                from_id=self.my_trades[symbol][-1]['id'] +
                1 if self.my_trades[symbol] else 0)
            prev_fetch = []
            while fetched_my_trades != prev_fetch and len(
                    fetched_my_trades) == limit:
                limit = 1000
                prev_fetch = fetched_my_trades
                fetched_my_trades = self.fetch_margin_my_trades(
                    symbol,
                    limit=limit,
                    from_id=fetched_my_trades[-1]['id'] + 1)
                new_my_trades += fetched_my_trades
            if new_my_trades:
                no_dash = symbol.replace('/', '_')
                cache_filepath = f'cache/binance/{self.user}/my_trades/{no_dash}/'
                condition = lambda x: x['id'] > self.my_trades[symbol][-1]['id'
                                                                           ]
                written_my_trades = self.write_cache(cache_filepath,
                                                     new_my_trades, condition)
                self.my_trades[symbol], self.my_trades_analyses[symbol] = \
                    analyze_my_trades(self.my_trades[symbol] + written_my_trades)

            age_limit_millis = self.cc.milliseconds(
            ) - self.hyperparams['max_memory_span_millis']
            my_trades = [
                e for e in self.my_trades[symbol]
                if e['timestamp'] > age_limit_millis
            ]
            self.my_trades[symbol] = my_trades
            self.time_keepers['update_my_trades'][symbol] = time()
Beispiel #9
0
 def lock_execute_release(self, symbol: str, fns: [Callable],
                          args_list: [tuple], kwargs_list: [dict]):
     try:
         self.locks[symbol].acquire()
         self.time_keepers['locks'][symbol] = time()
         self.cm.add_ts_to_lists(len(fns))
         future_results = []
         for i in range(len(fns)):
             args = args_list[i] if len(args_list) > i else ()
             kwargs = kwargs_list[i] if len(kwargs_list) > i else {}
             future_result = threaded(fns[i])(*args, **kwargs)
             future_results.append(future_result)
         for future_result in future_results:
             if future_result.exception():
                 if 'Unknown order sent' in future_result.exception(
                 ).args[0]:
                     print_([
                         'ERROR', 'margin', symbol,
                         'trying to cancel non-existing order; schedule open orders update'
                     ])
                     self.time_keepers['update_open_orders'][symbol] = 0
                 elif 'Account has insufficient balance' in future_result.exception(
                 ).args[0]:
                     print_([
                         'ERROR', 'margin', symbol, fns[i].__name__, args,
                         'insufficient funds; schedule balance update'
                     ])
                     self.time_keepers['update_balance'] = 0
                 else:
                     print_([
                         'ERROR', 'margin', symbol,
                         future_result.exception(), fns, args_list
                     ])
             else:
                 self.try_wrapper(self.update_after_execution,
                                  (future_result.result(), ))
         self.locks[symbol].release()
     except (Exception) as e:
         print('\n\nERROR with lock_execute_release', e)
Beispiel #10
0
 def update_balance(self):
     '''
     may be called threaded
     '''
     print_(['margin updating balance'])
     fetched = self.cc.sapi_get_margin_account()
     new_balance = {}
     onhand_sum_quot = 0.0
     debt_sum_quot = 0.0
     borrowable_quot = self.fetch_borrowable(self.quot)
     for e in fetched['userAssets']:
         c = e['asset']
         if c not in self.all_coins_set:
             continue
         new_balance[c] = {
             'free':
             float(e['free']),
             'used':
             float(e['locked']),
             'borrowed':
             float(e['borrowed']),
             'interest':
             float(e['interest']),
             'equity':
             float(e['netAsset']),
             'free':
             float(e['free']),
             'borrowable':
             (self.cm.convert_amount(borrowable_quot, self.quot, c)
              if c in self.do_borrow else 0.0),
         }
         new_balance[c][
             'onhand'] = new_balance[c]['free'] + new_balance[c]['used']
         new_balance[c]['debt'] = new_balance[c]['interest'] + new_balance[
             c]['borrowed']
         onhand_sum_quot += self.cm.convert_amount(new_balance[c]['onhand'],
                                                   c, self.quot)
         debt_sum_quot += self.cm.convert_amount(new_balance[c]['debt'], c,
                                                 self.quot)
     for c in self.all_coins_set:
         if c not in new_balance:
             new_balance[c] = {
                 key: 0.0
                 for key in [
                     'free', 'used', 'borrowed', 'interest', 'onhand',
                     'equity', 'debt'
                 ]
             }
             new_balance[c]['borrowable'] = \
                 (self.cm.convert_amount(borrowable_quot, self.quot, c)
                  if c in self.do_borrow else 0.0)
         new_balance[c]['account_onhand'] = self.cm.convert_amount(
             onhand_sum_quot, self.quot, c)
         new_balance[c]['account_debt'] = self.cm.convert_amount(
             debt_sum_quot, self.quot, c)
         new_balance[c]['account_equity'] = \
             new_balance[c]['account_onhand'] - new_balance[c]['account_debt']
         try:
             if self.balance[c]['onhand'] != new_balance[c]['onhand']:
                 symbol = f'{c}/{self.quot}'
                 if symbol in self.symbols:
                     self.time_keepers['update_open_orders'][symbol] = 0
                     self.time_keepers['update_my_trades'][symbol] = 0
         except (KeyError):
             pass
     self.tradable_bnb = max(
         0.0, new_balance['BNB']['onhand'] - self.hyperparams['bnb_buffer'])
     self.balance = new_balance
     self.time_keepers['update_balance'] = time()