def get_last_universal_transfer_time(self, transfer_type: str) -> int: """ return the latest time when a universal transfer was made If None, return the millistamp corresponding to 2017/01/01 :param transfer_type: enum of the transfer type (ex: 'MAIN_MARGIN') :type transfer_type: str :return: millistamp :rtype: int """ table = tables.UNIVERSAL_TRANSFER_TABLE conditions_list = [(table.trfType, SQLConditionEnum.equal, transfer_type)] selection = f"MAX({table.trfTime})" result = self.get_conditions_rows(table, selection=selection, conditions_list=conditions_list) default = datetime_to_millistamp(datetime.datetime(2017, 1, 1, tzinfo=datetime.timezone.utc)) try: result = result[0][0] except IndexError: return default if result is None: return default return result
def get_last_lending_interest_time(self, lending_type: Optional[str] = None) -> int: """ return the latest time when an interest was received. If None, return the millistamp corresponding to 2017/01/01 :param lending_type: type of lending :type lending_type: str :return: millistamp :rtype: int """ conditions_list = [] table = tables.LENDING_INTEREST_TABLE if lending_type is not None: conditions_list.append((table.lendingType, SQLConditionEnum.equal, lending_type)) selection = f"MAX({table.interestTime})" result = self.get_conditions_rows(table, selection=selection, conditions_list=conditions_list) default = datetime_to_millistamp(datetime.datetime(2017, 1, 1, tzinfo=datetime.timezone.utc)) try: result = result[0][0] except IndexError: return default if result is None: return default return result
def update_spot_dusts(self): """ update the dust database. As there is no way to get the dust by id or timeframe, the table is cleared for each update sources: https://python-binance.readthedocs.io/en/latest/binance.html#binance.client.Client.get_dust_log https://binance-docs.github.io/apidocs/spot/en/#dustlog-user_data :return: None :rtype: None """ self.db.drop_table(tables.SPOT_DUST_TABLE) result = self._call_binance_client('get_dust_log') dusts = result['results'] pbar = tqdm(total=dusts['total']) pbar.set_description("fetching spot dusts") for d in dusts['rows']: for sub_dust in d['logs']: date_time = dateparser.parse(sub_dust['operateTime'] + 'Z') self.db.add_spot_dust(tran_id=sub_dust['tranId'], time=datetime_to_millistamp(date_time), asset=sub_dust['fromAsset'], asset_amount=sub_dust['amount'], bnb_amount=sub_dust['transferedAmount'], bnb_fee=sub_dust['serviceChargeAmount'], auto_commit=False) pbar.update() self.db.commit() pbar.close()
def get_last_loan_time(self, asset: str, margin_type: str) -> int: """ return the latest time when an loan was made on a defined asset If None, return the millistamp corresponding to 2017/01/01 :param asset: name of the asset loaned :type asset: str :param margin_type: either 'cross' or 'isolated' :type margin_type: :return: millistamp :rtype: int """ if margin_type == 'cross': table = tables.CROSS_MARGIN_LOAN_TABLE elif margin_type == 'isolated': raise NotImplementedError else: raise ValueError(f"margin type should be 'cross' or 'isolated' but {margin_type} was received") conditions_list = [(table.asset, SQLConditionEnum.equal, asset)] selection = f"MAX({table.loanTime})" result = self.get_conditions_rows(table, selection=selection, conditions_list=conditions_list) default = datetime_to_millistamp(datetime.datetime(2017, 1, 1, tzinfo=datetime.timezone.utc)) try: result = result[0][0] except IndexError: return default if result is None: return default return result
def update_spot_dividends(self, day_jump: float = 90, limit: int = 500): """ update the dividends database (earnings distributed by Binance) sources: https://python-binance.readthedocs.io/en/latest/binance.html#binance.client.Client.get_asset_dividend_history https://binance-docs.github.io/apidocs/spot/en/#asset-dividend-record-user_data :param day_jump: length of the time window in days, max is 90 :type day_jump: float :param limit: max number of dividends to retrieve per call, max is 500 :type limit: int :return: None :rtype: None """ limit = min(500, limit) delta_jump = min(day_jump, 90) * 24 * 3600 * 1000 start_time = self.db.get_last_spot_dividend_time() + 1 now_millistamp = datetime_to_millistamp( datetime.datetime.now(tz=datetime.timezone.utc)) pbar = tqdm(total=math.ceil((now_millistamp - start_time) / delta_jump)) pbar.set_description("fetching spot dividends") while start_time < now_millistamp: # the stable working version of client.get_asset_dividend_history is not released yet, # for now it has a post error, so this protected member is used in the meantime params = { 'startTime': start_time, 'endTime': start_time + delta_jump, 'limit': limit } client_params = { 'method': 'get', 'path': 'asset/assetDividend', 'signed': True, 'data': params } result = self._call_binance_client('_request_margin_api', client_params) dividends = result['rows'] for div in dividends: self.db.add_dividend(div_id=int(div['tranId']), div_time=int(div['divTime']), asset=div['asset'], amount=float(div['amount']), auto_commit=False) pbar.update() if len(dividends) < limit: start_time += delta_jump + 1 # endTime is included in the previous return, so we have to add 1 else: # limit was reached before the end of the time windows start_time = int(dividends[0]['divTime']) + 1 if len(dividends): self.db.commit() pbar.close()
def update_spot_withdraws(self, day_jump: float = 90): """ This fetch the crypto withdraws made on the spot account from the last withdraw time in the database to now. It is done with multiple call, each having a time window of day_jump days. The withdraws are then saved in the database. Only successful withdraws are fetched. sources: https://python-binance.readthedocs.io/en/latest/binance.html#binance.client.Client.get_withdraw_history https://binance-docs.github.io/apidocs/spot/en/#withdraw-history-user_data :param day_jump: length of the time window for each call (max 90) :type day_jump: float :return: None :rtype: None """ delta_jump = min(day_jump, 90) * 24 * 3600 * 1000 start_time = self.db.get_last_spot_withdraw_time() + 1 now_millistamp = datetime_to_millistamp( datetime.datetime.now(tz=datetime.timezone.utc)) pbar = tqdm(total=math.ceil((now_millistamp - start_time) / delta_jump)) pbar.set_description("fetching spot withdraws") while start_time < now_millistamp: client_params = { 'startTime': start_time, 'endTime': start_time + delta_jump, 'status': 6 } result = self._call_binance_client('get_withdraw_history', client_params) withdraws = result['withdrawList'] for withdraw in withdraws: self.db.add_withdraw(withdraw_id=withdraw['id'], tx_id=withdraw['txId'], apply_time=int(withdraw['applyTime']), asset=withdraw['asset'], amount=float(withdraw['amount']), fee=float(withdraw['transactionFee']), auto_commit=False) pbar.update() start_time += delta_jump + 1 # endTime is included in the previous return, so we have to add 1 if len(withdraws): self.db.commit() pbar.close()
def update_spot_deposits(self, day_jump: float = 90): """ This fetch the crypto deposit made on the spot account from the last deposit time in the database to now. It is done with multiple call, each having a time window of day_jump days. The deposits are then saved in the database. Only successful deposits are fetched. sources: https://python-binance.readthedocs.io/en/latest/binance.html#binance.client.Client.get_deposit_history https://binance-docs.github.io/apidocs/spot/en/#deposit-history-user_data :param day_jump: length of the time window for each call (max 90) :type day_jump: float :return: None :rtype: None """ delta_jump = min(day_jump, 90) * 24 * 3600 * 1000 start_time = self.db.get_last_spot_deposit_time() + 1 now_millistamp = datetime_to_millistamp( datetime.datetime.now(tz=datetime.timezone.utc)) pbar = tqdm(total=math.ceil((now_millistamp - start_time) / delta_jump)) pbar.set_description("fetching spot deposits") while start_time < now_millistamp: client_params = { 'startTime': start_time, 'endTime': start_time + delta_jump, 'status': 1 } result = self._call_binance_client('get_deposit_history', client_params) deposits = result['depositList'] for deposit in deposits: self.db.add_deposit(tx_id=deposit['txId'], asset=deposit['asset'], insert_time=int(deposit['insertTime']), amount=float(deposit['amount']), auto_commit=False) pbar.update() start_time += delta_jump if len(deposits): self.db.commit() pbar.close()
def get_last_spot_withdraw_time(self) -> int: """ fetch the latest time a withdraw has been made on the spot account. If None is found, return the millistamp corresponding to 2017/1/1 :return: """ table = tables.SPOT_WITHDRAW_TABLE selection = f"MAX({table.applyTime})" result = self.get_conditions_rows(table, selection=selection) default = datetime_to_millistamp(datetime.datetime(2017, 1, 1, tzinfo=datetime.timezone.utc)) try: result = result[0][0] except IndexError: return default if result is None: return default return result
def get_last_spot_dividend_time(self) -> int: """ fetch the latest time a dividend has been distributed on the spot account. If None is found, return the millistamp corresponding to 2017/1/1 :return: """ table = tables.SPOT_DIVIDEND_TABLE selection = f"MAX({table.divTime})" result = self.get_conditions_rows(table, selection=selection) default = datetime_to_millistamp(datetime.datetime(2017, 1, 1, tzinfo=datetime.timezone.utc)) try: result = result[0][0] except IndexError: return default if result is None: return default return result
def get_last_spot_deposit_time(self) -> int: """ fetch the latest time a deposit has been made on the spot account. If None is found, return the millistamp corresponding to 2017/1/1 :return: last deposit millistamp :rtype: int """ table = tables.SPOT_DEPOSIT_TABLE selection = f"MAX({table.insertTime})" result = self.get_conditions_rows(table, selection=selection) default = datetime_to_millistamp(datetime.datetime(2017, 1, 1, tzinfo=datetime.timezone.utc)) try: result = result[0][0] except IndexError: return default if result is None: return default return result
def get_last_margin_interest_time(self, margin_type: str, asset: Optional[str] = None): """ return the latest time when a margin interest was accured on a defined asset or on all assets If None, return the millistamp corresponding to 2017/01/01 :param asset: name of the asset charged as interest :type asset: Optional[str] :param margin_type: either 'cross' or 'isolated' :type margin_type: :return: millistamp :rtype: int """ if margin_type == 'cross': table = tables.CROSS_MARGIN_INTEREST_TABLE elif margin_type == 'isolated': raise NotImplementedError else: raise ValueError(f"margin type should be 'cross' or 'isolated' but {margin_type} was received") conditions_list = [] if asset is not None: conditions_list = [(table.asset, SQLConditionEnum.equal, asset)] selection = f"MAX({table.interestTime})" result = self.get_conditions_rows(table, selection=selection, conditions_list=conditions_list) default = datetime_to_millistamp(datetime.datetime(2017, 1, 1, tzinfo=datetime.timezone.utc)) try: result = result[0][0] except IndexError: return default if result is None: return default return result