示例#1
0
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