Ejemplo n.º 1
0
    def add_dusts_to_quantity_if_necessary(quantity, price, symbol_market,
                                           current_symbol_holding):
        remaining_portfolio_amount = float("{1:.{0}f}".format(
            CURRENCY_DEFAULT_MAX_PRICE_DIGITS,
            current_symbol_holding - quantity))
        remaining_max_total_order_price = remaining_portfolio_amount * price

        symbol_market_limits = symbol_market[Ecmsc.LIMITS.value]

        limit_amount = symbol_market_limits[Ecmsc.LIMITS_AMOUNT.value]
        limit_cost = symbol_market_limits[Ecmsc.LIMITS_COST.value]

        if not (AbstractTradingModeCreator._is_valid(
                limit_amount, Ecmsc.LIMITS_AMOUNT_MIN.value)
                and AbstractTradingModeCreator._is_valid(
                    limit_cost, Ecmsc.LIMITS_COST_MIN.value)):
            fixed_market_status = ExchangeMarketStatusFixer(
                symbol_market, price).get_market_status()
            limit_amount = fixed_market_status[Ecmsc.LIMITS.value][
                Ecmsc.LIMITS_AMOUNT.value]
            limit_cost = fixed_market_status[Ecmsc.LIMITS.value][
                Ecmsc.LIMITS_COST.value]

        min_quantity = get_value_or_default(limit_amount,
                                            Ecmsc.LIMITS_AMOUNT_MIN.value,
                                            math.nan)
        min_cost = get_value_or_default(limit_cost,
                                        Ecmsc.LIMITS_COST_MIN.value, math.nan)

        if remaining_max_total_order_price < min_cost or remaining_portfolio_amount < min_quantity:
            return current_symbol_holding
        else:
            return quantity
 def get_market_status(self, symbol, price_example=None, with_fixer=True):
     try:
         if with_fixer:
             return ExchangeMarketStatusFixer(self.client.find_market(symbol), price_example).get_market_status()
         else:
             return self.client.find_market(symbol)
     except Exception as e:
         self.logger.error(f"Fail to get market status of {symbol}: {e}")
         return {}
Ejemplo n.º 3
0
 def _is_valid(element, key):
     return key in element and ExchangeMarketStatusFixer.is_ms_valid(
         element[key])
Ejemplo n.º 4
0
    def check_and_adapt_order_details_if_necessary(quantity,
                                                   price,
                                                   symbol_market,
                                                   fixed_symbol_data=False):
        symbol_market_limits = symbol_market[Ecmsc.LIMITS.value]

        limit_amount = symbol_market_limits[Ecmsc.LIMITS_AMOUNT.value]
        limit_cost = symbol_market_limits[Ecmsc.LIMITS_COST.value]
        limit_price = symbol_market_limits[Ecmsc.LIMITS_PRICE.value]

        # case 1: try with data directly from exchange
        if AbstractTradingModeCreator._is_valid(limit_amount,
                                                Ecmsc.LIMITS_AMOUNT_MIN.value):
            min_quantity = get_value_or_default(limit_amount,
                                                Ecmsc.LIMITS_AMOUNT_MIN.value,
                                                math.nan)
            max_quantity = None
            # not all symbol data have a max quantity
            if AbstractTradingModeCreator._is_valid(
                    limit_amount, Ecmsc.LIMITS_AMOUNT_MAX.value):
                max_quantity = get_value_or_default(
                    limit_amount, Ecmsc.LIMITS_AMOUNT_MAX.value, math.nan)

            # adapt digits if necessary
            valid_quantity = AbstractTradingModeCreator._adapt_quantity(
                symbol_market, quantity)
            valid_price = AbstractTradingModeCreator.adapt_price(
                symbol_market, price)

            total_order_price = valid_quantity * valid_price

            if valid_quantity < min_quantity:
                # invalid order
                return []

            # case 1.1: use only quantity and cost
            if AbstractTradingModeCreator._is_valid(
                    limit_cost, Ecmsc.LIMITS_COST_MIN.value):
                min_cost = get_value_or_default(limit_cost,
                                                Ecmsc.LIMITS_COST_MIN.value,
                                                math.nan)
                max_cost = None
                # not all symbol data have a max cost
                if AbstractTradingModeCreator._is_valid(
                        limit_cost, Ecmsc.LIMITS_COST_MAX.value):
                    max_cost = get_value_or_default(
                        limit_cost, Ecmsc.LIMITS_COST_MAX.value, math.nan)

                # check total_order_price not < min_cost
                if not AbstractTradingModeCreator._check_cost(
                        total_order_price, min_cost):
                    return []

                # check total_order_price not > max_cost and valid_quantity not > max_quantity
                elif (max_cost is not None and total_order_price > max_cost) or \
                        (max_quantity is not None and valid_quantity > max_quantity):
                    # split quantity into smaller orders
                    return AbstractTradingModeCreator._split_orders(
                        total_order_price, max_cost, valid_quantity,
                        max_quantity, price, quantity, symbol_market)

                else:
                    # valid order that can be handled wy the exchange
                    return [(valid_quantity, valid_price)]

            # case 1.2: use only quantity and price
            elif AbstractTradingModeCreator._is_valid(
                    limit_price, Ecmsc.LIMITS_PRICE_MIN.value):
                min_price = get_value_or_default(limit_price,
                                                 Ecmsc.LIMITS_PRICE_MIN.value,
                                                 math.nan)
                max_price = None
                # not all symbol data have a max price
                if AbstractTradingModeCreator._is_valid(
                        limit_price, Ecmsc.LIMITS_PRICE_MAX.value):
                    max_price = get_value_or_default(
                        limit_price, Ecmsc.LIMITS_PRICE_MAX.value, math.nan)

                if (max_price is not None and
                    (max_price <= valid_price)) or valid_price <= min_price:
                    # invalid order
                    return []

                # check total_order_price not > max_cost and valid_quantity not > max_quantity
                elif max_quantity is not None and valid_quantity > max_quantity:
                    # split quantity into smaller orders
                    return AbstractTradingModeCreator \
                        ._adapt_order_quantity_because_quantity(valid_quantity, max_quantity,
                                                                quantity, price, symbol_market)
                else:
                    # valid order that can be handled wy the exchange
                    return [(valid_quantity, valid_price)]

        if not fixed_symbol_data:
            # case 2: try fixing data from exchanges
            fixed_data = ExchangeMarketStatusFixer(symbol_market,
                                                   price).get_market_status()
            return AbstractTradingModeCreator.check_and_adapt_order_details_if_necessary(
                quantity, price, fixed_data, fixed_symbol_data=True)
        else:
            # impossible to check if order is valid: refuse it
            return []