async def _create_initial_arbitrage_order(self, arbitrage_container):
        current_symbol_holding, current_market_holding, market_quantity, price, symbol_market = \
            await trading_personal_data.get_pre_order_data(self.exchange_manager,
                                                           symbol=self.trading_mode.symbol,
                                                           timeout=trading_constants.ORDER_DATA_FETCHING_TIMEOUT)

        created_orders = []
        order_type = trading_enums.TraderOrderType.BUY_LIMIT if arbitrage_container.state is trading_enums.EvaluatorStates.LONG \
            else trading_enums.TraderOrderType.SELL_LIMIT
        quantity = self._get_quantity_from_holdings(current_symbol_holding,
                                                    market_quantity,
                                                    arbitrage_container.state)
        if order_type is trading_enums.TraderOrderType.SELL_LIMIT:
            quantity = trading_personal_data.add_dusts_to_quantity_if_necessary(
                quantity, price, symbol_market, current_symbol_holding)
        for order_quantity, order_price in trading_personal_data.check_and_adapt_order_details_if_necessary(
                quantity, arbitrage_container.own_exchange_price,
                symbol_market):
            current_order = trading_personal_data.create_order_instance(
                trader=self.exchange_manager.trader,
                order_type=order_type,
                symbol=self.trading_mode.symbol,
                current_price=arbitrage_container.own_exchange_price,
                quantity=order_quantity,
                price=order_price)
            created_order = await self.exchange_manager.trader.create_order(
                current_order)
            created_orders.append(created_order)
            arbitrage_container.initial_limit_order_id = created_order.order_id
            self.open_arbitrages.append(arbitrage_container)
            # only create one order per arbitrage
            return created_orders
    async def create_buy_order(self, symbol, timeout, volume_weight, price_weight):
        current_order = None
        try:
            current_symbol_holding, current_market_holding, market_quantity, price, symbol_market = \
                await trading_personal_data.get_pre_order_data(self.exchange_manager, symbol=symbol, timeout=timeout)

            base, _ = symbol_util.split_symbol(symbol)
            created_orders = []
            quantity = await self._get_buy_quantity_from_weight(volume_weight, market_quantity, base)
            limit_price = trading_personal_data.adapt_price(symbol_market, self.get_limit_price(price))
            for order_quantity, order_price in trading_personal_data.check_and_adapt_order_details_if_necessary(
                    quantity,
                    limit_price,
                    symbol_market):
                current_order = trading_personal_data.create_order_instance(trader=self.exchange_manager.trader,
                                                                            order_type=trading_enums.TraderOrderType.BUY_LIMIT,
                                                                            symbol=symbol,
                                                                            current_price=price,
                                                                            quantity=order_quantity,
                                                                            price=order_price)
                created_order = await self.exchange_manager.trader.create_order(current_order)
                created_orders.append(created_order)
                self._register_buy_order(created_order.order_id, price_weight)
            if created_orders:
                return created_orders
            raise trading_errors.MissingMinimalExchangeTradeVolume()

        except (trading_errors.MissingFunds, trading_errors.MissingMinimalExchangeTradeVolume):
            raise
        except Exception as e:
            self.logger.error(f"Failed to create order : {e}. Order: "
                              f"{current_order.get_string_info() if current_order else None}")
            self.logger.exception(e, False)
            return []
    def _generate_sell_orders(self, sell_orders_count, quantity, sell_weight,
                              sell_base, symbol_market):
        volume_with_price = []
        sell_max = sell_base * self.PRICE_WEIGH_TO_PRICE_PERCENT[sell_weight]
        adapted_sell_orders_count, increment = \
            self._check_limits(sell_base, sell_max, quantity, sell_orders_count, symbol_market)
        if adapted_sell_orders_count:
            order_volume = quantity / adapted_sell_orders_count

            for i in range(adapted_sell_orders_count):
                order_price = sell_base + (increment * (i + 1))
                for adapted_quantity, adapted_price in trading_personal_data.check_and_adapt_order_details_if_necessary(
                        order_volume, order_price, symbol_market):
                    volume_with_price.append((adapted_quantity, adapted_price))
        return volume_with_price
    async def _create_secondary_arbitrage_order(self, arbitrage_container,
                                                quantity):
        created_orders = []
        current_symbol_holding, current_market_holding, market_quantity, price, symbol_market = \
            await trading_personal_data.get_pre_order_data(self.exchange_manager,
                                                           symbol=self.trading_mode.symbol,
                                                           timeout=trading_constants.ORDER_DATA_FETCHING_TIMEOUT)
        now_selling = arbitrage_container.state is trading_enums.EvaluatorStates.LONG
        if now_selling:
            quantity = trading_personal_data.add_dusts_to_quantity_if_necessary(
                quantity, price, symbol_market, current_symbol_holding)
        for order_quantity, order_price in trading_personal_data.check_and_adapt_order_details_if_necessary(
                quantity, arbitrage_container.target_price, symbol_market):
            current_order = trading_personal_data.create_order_instance(
                trader=self.exchange_manager.trader,
                order_type=trading_enums.TraderOrderType.SELL_LIMIT
                if now_selling else trading_enums.TraderOrderType.BUY_LIMIT,
                symbol=self.trading_mode.symbol,
                current_price=arbitrage_container.own_exchange_price,
                quantity=order_quantity,
                price=order_price)
            created_order = await self.exchange_manager.trader.create_order(
                current_order)
            created_orders.append(created_order)
            arbitrage_container.secondary_limit_order_id = created_order.order_id

            stop_price = self._get_stop_loss_price(
                symbol_market, arbitrage_container.own_exchange_price,
                now_selling)
            current_order = trading_personal_data.create_order_instance(
                trader=self.exchange_manager.trader,
                order_type=trading_enums.TraderOrderType.STOP_LOSS,
                symbol=self.trading_mode.symbol,
                current_price=arbitrage_container.own_exchange_price,
                quantity=order_quantity,
                price=stop_price,
                linked_to=created_order,
                side=trading_enums.TradeOrderSide.SELL
                if now_selling else trading_enums.TradeOrderSide.BUY)
            await self.exchange_manager.trader.create_order(current_order)
            arbitrage_container.secondary_stop_order_id = current_order.order_id
            return created_orders
Beispiel #5
0
    async def create_new_orders(self, symbol, final_note, state, **kwargs):
        current_order = None
        try:
            base, market = symbol_util.split_symbol(symbol)
            if market != self.exchange_manager.exchange_personal_data.portfolio_manager.reference_market:
                self.logger.warning(f"Ignored DCA order creation on {symbol} : it's not a reference market pair.")
                return []

            current_symbol_holding, current_market_holding, market_quantity, price, symbol_market = \
                await trading_personal_data.get_pre_order_data(self.exchange_manager, symbol=symbol,
                                                               timeout=trading_constants.ORDER_DATA_FETCHING_TIMEOUT)

            created_orders = []
            quantity = self.order_quantity_of_ref_market / price
            limit_price = trading_personal_data.adapt_price(symbol_market, price * (1 - self.ORDER_PRICE_DISTANCE))
            for order_quantity, order_price in trading_personal_data.check_and_adapt_order_details_if_necessary(
                    quantity,
                    limit_price,
                    symbol_market):
                current_order = trading_personal_data.create_order_instance(trader=self.exchange_manager.trader,
                                                                            order_type=trading_enums.TraderOrderType.BUY_LIMIT,
                                                                            symbol=symbol,
                                                                            current_price=price,
                                                                            quantity=order_quantity,
                                                                            price=order_price)
                created_order = await self.exchange_manager.trader.create_order(current_order)
                created_orders.append(created_order)
            if created_orders:
                return created_orders
            raise trading_errors.MissingMinimalExchangeTradeVolume()

        except (trading_errors.MissingFunds, trading_errors.MissingMinimalExchangeTradeVolume):
            raise
        except Exception as e:
            self.logger.error(f"Failed to create order : {e}. Order: "
                              f"{current_order if current_order else None}")
            self.logger.exception(e, False)
            return []
Beispiel #6
0
async def test_check_and_adapt_order_details_if_necessary():
    symbol_market = {
        Ecmsc.LIMITS.value: {
            Ecmsc.LIMITS_AMOUNT.value: {
                Ecmsc.LIMITS_AMOUNT_MIN.value: 0.5,
                Ecmsc.LIMITS_AMOUNT_MAX.value: 100,
            },
            Ecmsc.LIMITS_COST.value: {
                Ecmsc.LIMITS_COST_MIN.value: 1,
                Ecmsc.LIMITS_COST_MAX.value: 200
            },
            Ecmsc.LIMITS_PRICE.value: {
                Ecmsc.LIMITS_PRICE_MIN.value: 0.5,
                Ecmsc.LIMITS_PRICE_MAX.value: 50
            },
        },
        Ecmsc.PRECISION.value: {
            Ecmsc.PRECISION_PRICE.value: 8,
            Ecmsc.PRECISION_AMOUNT.value: 8
        }
    }

    invalid_cost_symbol_market = {
        Ecmsc.LIMITS.value: {
            Ecmsc.LIMITS_AMOUNT.value: {
                Ecmsc.LIMITS_AMOUNT_MIN.value: 0.5,
                Ecmsc.LIMITS_AMOUNT_MAX.value: 100,
            },
            Ecmsc.LIMITS_COST.value: {
                Ecmsc.LIMITS_COST_MIN.value: None,
                Ecmsc.LIMITS_COST_MAX.value: None
            },
            Ecmsc.LIMITS_PRICE.value: {
                Ecmsc.LIMITS_PRICE_MIN.value: 0.5,
                Ecmsc.LIMITS_PRICE_MAX.value: 50
            },
        },
        Ecmsc.PRECISION.value: {
            Ecmsc.PRECISION_PRICE.value: 8,
            Ecmsc.PRECISION_AMOUNT.value: 8
        }
    }

    # correct min
    quantity = 0.5
    price = 2
    assert personal_data.check_and_adapt_order_details_if_necessary(
        quantity, price, symbol_market) == [(quantity, price)]

    # correct max
    quantity = 100
    price = 2
    assert personal_data.check_and_adapt_order_details_if_necessary(
        quantity, price, symbol_market) == [(quantity, price)]

    # correct
    quantity = 10
    price = 0.6
    assert personal_data.check_and_adapt_order_details_if_necessary(
        quantity, price, symbol_market) == [(quantity, price)]

    # correct
    quantity = 3
    price = 49.9
    assert personal_data.check_and_adapt_order_details_if_necessary(
        quantity, price, symbol_market) == [(quantity, price)]

    # invalid price > but valid cost
    quantity = 1
    price = 100
    assert personal_data.check_and_adapt_order_details_if_necessary(
        quantity, price, symbol_market) == [(quantity, price)]

    # invalid price < but valid cost
    quantity = 10
    price = 0.1
    assert personal_data.check_and_adapt_order_details_if_necessary(
        quantity, price, symbol_market) == [(quantity, price)]

    # invalid price > and invalid cost from exchange => use price => invalid
    quantity = 1
    price = 100
    assert personal_data.check_and_adapt_order_details_if_necessary(
        quantity, price, invalid_cost_symbol_market) == []

    # invalid price < and invalid cost from exchange => use price => invalid
    quantity = 1
    price = 0.1
    assert personal_data.check_and_adapt_order_details_if_necessary(
        quantity, price, invalid_cost_symbol_market) == []

    # invalid cost <
    quantity = 0.5
    price = 1
    assert personal_data.check_and_adapt_order_details_if_necessary(
        quantity, price, symbol_market) == []

    # invalid cost >
    quantity = 10
    price = 49
    assert personal_data.check_and_adapt_order_details_if_necessary(
        quantity, price, symbol_market) == [(1.83673469, 49), (4.08163265, 49),
                                            (4.08163265, 49)]

    # high cost but no max cost => valid
    quantity = 10
    price = 49
    assert personal_data.check_and_adapt_order_details_if_necessary(
        quantity, price, symbol_market) == [(1.83673469, 49), (4.08163265, 49),
                                            (4.08163265, 49)]

    # invalid cost with invalid price >=
    quantity = 10
    price = 50
    assert personal_data.check_and_adapt_order_details_if_necessary(
        quantity, price, symbol_market) == [(2, 50), (4, 50), (4, 50)]

    # invalid cost with invalid price > and invalid cost from exchange => use price => invalid
    quantity = 10
    price = 51
    assert personal_data.check_and_adapt_order_details_if_necessary(
        quantity, price, invalid_cost_symbol_market) == []

    # invalid amount >
    quantity = 200
    price = 5
    assert personal_data.check_and_adapt_order_details_if_necessary(
        quantity, price, symbol_market) == [(40.0, 5), (40.0, 5), (40.0, 5),
                                            (40.0, 5), (40.0, 5)]

    # invalid amount <
    quantity = 0.4
    price = 5
    assert personal_data.check_and_adapt_order_details_if_necessary(
        quantity, price, symbol_market) == []

    symbol_market = {
        Ecmsc.LIMITS.value: {
            Ecmsc.LIMITS_AMOUNT.value: {
                Ecmsc.LIMITS_AMOUNT_MIN.value: 0.0000005,
                Ecmsc.LIMITS_AMOUNT_MAX.value: 100,
            },
            Ecmsc.LIMITS_COST.value: {
                Ecmsc.LIMITS_COST_MIN.value: 0.00000001,
                Ecmsc.LIMITS_COST_MAX.value: 10
            },
            Ecmsc.LIMITS_PRICE.value: {
                Ecmsc.LIMITS_PRICE_MIN.value: 0.000005,
                Ecmsc.LIMITS_PRICE_MAX.value: 50
            },
        },
        Ecmsc.PRECISION.value: {
            Ecmsc.PRECISION_PRICE.value: 8,
            Ecmsc.PRECISION_AMOUNT.value: 8
        }
    }

    # correct quantity
    # to test _adapt_order_quantity_because_quantity
    quantity = 5000
    price = 0.001
    expected = [(100.0, 0.001), (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                (100.0, 0.001), (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                (100.0, 0.001), (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                (100.0, 0.001), (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                (100.0, 0.001), (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                (100.0, 0.001), (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                (100.0, 0.001), (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                (100.0, 0.001), (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                (100.0, 0.001), (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                (100.0, 0.001), (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                (100.0, 0.001), (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                (100.0, 0.001), (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                (100.0, 0.001), (100.0, 0.001)]
    assert personal_data.check_and_adapt_order_details_if_necessary(
        quantity, price, symbol_market) == expected

    # price = 0 => no order
    quantity = 10
    price = 0
    assert personal_data.check_and_adapt_order_details_if_necessary(
        quantity, price, symbol_market) == []

    symbol_market_without_max = {
        Ecmsc.LIMITS.value: {
            Ecmsc.LIMITS_AMOUNT.value: {
                Ecmsc.LIMITS_AMOUNT_MIN.value: 0.0000005,
                Ecmsc.LIMITS_AMOUNT_MAX.value: None,
            },
            Ecmsc.LIMITS_COST.value: {
                Ecmsc.LIMITS_COST_MIN.value: 0.00000001,
                Ecmsc.LIMITS_COST_MAX.value: None
            },
            Ecmsc.LIMITS_PRICE.value: {
                Ecmsc.LIMITS_PRICE_MIN.value: 0.000005,
                Ecmsc.LIMITS_PRICE_MAX.value: None
            },
        },
        Ecmsc.PRECISION.value: {
            Ecmsc.PRECISION_PRICE.value: 8,
            Ecmsc.PRECISION_AMOUNT.value: 8
        }
    }

    # high cost but no max cost => no split
    quantity = 10
    price = 49
    assert personal_data.check_and_adapt_order_details_if_necessary(
        quantity, price, symbol_market_without_max) == [(10, 49)]

    # high quantity but no max quantity => no split
    quantity = 10000000
    price = 49
    assert personal_data.check_and_adapt_order_details_if_necessary(quantity, price, symbol_market_without_max) == \
           [(10000000, 49)]

    # high price but no max price => no split
    quantity = 10
    price = 4900000
    assert personal_data.check_and_adapt_order_details_if_necessary(
        quantity, price, symbol_market_without_max) == [(10, 4900000)]
Beispiel #7
0
    async def create_new_orders(self, symbol, final_note, state, **kwargs):
        current_order = None
        timeout = kwargs.pop("timeout", trading_constants.ORDER_DATA_FETCHING_TIMEOUT)
        try:
            current_symbol_holding, current_market_holding, market_quantity, price, symbol_market = \
                await trading_personal_data.get_pre_order_data(self.exchange_manager, symbol=symbol, timeout=timeout)

            quote, _ = symbol_util.split_symbol(symbol)
            created_orders = []

            if state == trading_enums.EvaluatorStates.VERY_SHORT.value and not self.DISABLE_SELL_ORDERS:
                quantity = self._get_market_quantity_from_risk(final_note, current_symbol_holding, quote, True)
                quantity = trading_personal_data.add_dusts_to_quantity_if_necessary(quantity, price, symbol_market,
                                                                                    current_symbol_holding)
                for order_quantity, order_price in trading_personal_data.check_and_adapt_order_details_if_necessary(
                        quantity, price,
                        symbol_market):
                    current_order = trading_personal_data.create_order_instance(trader=self.trader,
                                                                                order_type=trading_enums.TraderOrderType.SELL_MARKET,
                                                                                symbol=symbol,
                                                                                current_price=order_price,
                                                                                quantity=order_quantity,
                                                                                price=order_price)
                    await self.trader.create_order(current_order)
                    created_orders.append(current_order)

            elif state == trading_enums.EvaluatorStates.SHORT.value and not self.DISABLE_SELL_ORDERS:
                quantity = await self._get_sell_limit_quantity_from_risk(final_note, current_symbol_holding, quote)
                quantity = trading_personal_data.add_dusts_to_quantity_if_necessary(quantity, price, symbol_market,
                                                                                    current_symbol_holding)
                limit_price = trading_personal_data.adapt_price(symbol_market,
                                                                price * self._get_limit_price_from_risk(final_note))
                for order_quantity, order_price in trading_personal_data.check_and_adapt_order_details_if_necessary(
                        quantity,
                        limit_price,
                        symbol_market):
                    current_order = trading_personal_data.create_order_instance(trader=self.trader,
                                                                                order_type=trading_enums.TraderOrderType.SELL_LIMIT,
                                                                                symbol=symbol,
                                                                                current_price=price,
                                                                                quantity=order_quantity,
                                                                                price=order_price)
                    updated_limit = await self.trader.create_order(current_order)
                    created_orders.append(updated_limit)

                    if self.USE_STOP_ORDERS:
                        stop_price = trading_personal_data.adapt_price(symbol_market,
                                                                       price * self._get_stop_price_from_risk())
                        current_order = trading_personal_data.create_order_instance(trader=self.trader,
                                                                                    order_type=trading_enums.TraderOrderType.STOP_LOSS,
                                                                                    symbol=symbol,
                                                                                    current_price=price,
                                                                                    quantity=order_quantity,
                                                                                    price=stop_price,
                                                                                    linked_to=updated_limit)
                        await self.trader.create_order(current_order)

            elif state == trading_enums.EvaluatorStates.NEUTRAL.value:
                return []

            # TODO : stop loss
            elif state == trading_enums.EvaluatorStates.LONG.value and not self.DISABLE_BUY_ORDERS:
                quantity = self._get_buy_limit_quantity_from_risk(final_note, market_quantity, quote)
                quantity = quantity * await self._get_quantity_ratio(quote)
                limit_price = trading_personal_data.adapt_price(symbol_market,
                                                                price * self._get_limit_price_from_risk(final_note))
                for order_quantity, order_price in trading_personal_data.check_and_adapt_order_details_if_necessary(
                        quantity,
                        limit_price,
                        symbol_market):
                    current_order = trading_personal_data.create_order_instance(trader=self.trader,
                                                                                order_type=trading_enums.TraderOrderType.BUY_LIMIT,
                                                                                symbol=symbol,
                                                                                current_price=price,
                                                                                quantity=order_quantity,
                                                                                price=order_price)
                    await self.trader.create_order(current_order)
                    created_orders.append(current_order)

            elif state == trading_enums.EvaluatorStates.VERY_LONG.value and not self.DISABLE_BUY_ORDERS:
                quantity = self._get_market_quantity_from_risk(final_note, market_quantity, quote)
                quantity = quantity * await self._get_quantity_ratio(quote)
                for order_quantity, order_price in trading_personal_data.check_and_adapt_order_details_if_necessary(
                        quantity, price,
                        symbol_market):
                    current_order = trading_personal_data.create_order_instance(trader=self.trader,
                                                                                order_type=trading_enums.TraderOrderType.BUY_MARKET,
                                                                                symbol=symbol,
                                                                                current_price=order_price,
                                                                                quantity=order_quantity,
                                                                                price=order_price)
                    await self.trader.create_order(current_order)
                    created_orders.append(current_order)
            if created_orders:
                return created_orders
            raise trading_errors.MissingMinimalExchangeTradeVolume()

        except (trading_errors.MissingFunds, trading_errors.MissingMinimalExchangeTradeVolume):
            raise
        except asyncio.TimeoutError as e:
            self.logger.error(f"Impossible to create order for {symbol} on {self.exchange_manager.exchange_name}: {e} "
                              f"and is necessary to compute the order details.")
            return []
        except Exception as e:
            self.logger.exception(e, True, f"Failed to create order : {e}.")
            return []