def pre_rebalance(exchange: Exchange, weights: Dict[str, Decimal], base: str = 'USDT'): resources = exchange.get_resources() currencies = (exchange.through_trade_currencies() | set(list(resources.keys())) | set(list(weights.keys()))) all_possible_products = [ '_'.join([i, j]) for i in currencies for j in currencies ] orderbooks = exchange.get_orderbooks(all_possible_products) # getting all ordebrooks and filtering out orderbooks, # that use other currencies products = set(orderbook.product for orderbook in orderbooks) price_estimates = get_price_estimates_from_orderbooks(orderbooks, base) initial_weights = get_weights_from_resources(resources, price_estimates) portfolio_value = get_portfolio_value_from_resources( resources, price_estimates) orderbooks = {orderbook.product: orderbook for orderbook in orderbooks} spread_fees = { product: spread_to_fee(orderbook) for product, orderbook in orderbooks.items() } return (products, resources, orderbooks, price_estimates, portfolio_value, initial_weights, spread_fees)
def limit_order_rebalance_with_orders(update_function, exchange: Exchange, resources: Dict[str, Decimal], products: List[str], orders: List[Order], max_retries: int, time_delta: int, base: str): number_of_trials = {order.product: 0 for order in orders} rets = [] while len(orders) and (all(number_of_trials[order.product] <= max_retries for order in orders)): orderbooks = exchange.get_orderbooks(products) orderbooks = {ob.product: ob for ob in orderbooks} currencies_from = set() currencies_to = set() for order in orders: currency_commodity, currency_base = order.product.split('_') if order._action == OrderAction.SELL: currencies_from.add(currency_commodity) currencies_to.add(currency_base) else: currencies_to.add(currency_commodity) currencies_from.add(currency_base) currencies_free = currencies_from - currencies_to order_responses = [] orders_to_remove = [] for order in orders: currency_commodity, currency_base = order.product.split('_') orderbook = orderbooks[order.product] order._price = orderbook.get_mid_market_price() if order._action == OrderAction.SELL: if (currency_commodity not in currencies_free and resources[currency_commodity] < order._quantity): # if selling commodity, which we don't have yet continue else: if (currency_base not in currencies_free and resources[currency_base] < order._quantity * order._price): # if buying commodity, for which we don't have base yet continue order_response = exchange.place_limit_order(order) if order_response is None: number_of_trials[order.product] = max_retries orders_to_remove.append(order) elif not isinstance(order_response, Exception): order_response.update({'order': order}) order_responses.append(order_response) else: number_of_trials[order.product] += 1 for order in orders_to_remove: number_of_trials[order.product] = max_retries orders.remove(order) update_function( limit_order_rebalance_retry_after_time_estimate( number_of_trials, max_retries, time_delta)) time.sleep(time_delta) for order_response in order_responses: exchange.cancel_limit_order(order_response) resp = exchange.get_order(order_response) rets.append(resp) order = order_response['order'] if (Decimal(resp['orig_quantity']) - Decimal(resp['executed_quantity'])) > Decimal('1e-3'): order._quantity = Decimal(resp['orig_quantity']) - Decimal( resp['executed_quantity']) number_of_trials[order.product] += 1 else: number_of_trials[order.product] = max_retries orders.remove(order) return rets