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_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
    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 self._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=float(order_price),
                        quantity=float(order_quantity),
                        price=float(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 self._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=float(order_quantity),
                        price=float(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=float(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 self._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=float(order_quantity),
                        price=float(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 self._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=float(order_price),
                        quantity=float(order_quantity),
                        price=float(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 []
Beispiel #4
0
async def test_get_additional_dusts_to_quantity_if_necessary():
    symbol_market = {
        Ecmsc.LIMITS.value: {
            Ecmsc.LIMITS_AMOUNT.value: {
                Ecmsc.LIMITS_AMOUNT_MIN.value: 0.5
            },
            Ecmsc.LIMITS_COST.value: {
                Ecmsc.LIMITS_COST_MIN.value: 1
            }
        }
    }

    current_symbol_holding = 5
    quantity = 3
    price = 1
    assert personal_data.add_dusts_to_quantity_if_necessary(
        quantity, price, symbol_market, current_symbol_holding) == quantity + 0

    current_symbol_holding = 5
    quantity = 4
    price = 1
    assert personal_data.add_dusts_to_quantity_if_necessary(
        quantity, price, symbol_market, current_symbol_holding) == quantity + 1

    current_symbol_holding = 5
    quantity = 4.5
    price = 1
    assert personal_data.add_dusts_to_quantity_if_necessary(
        quantity, price, symbol_market,
        current_symbol_holding) == quantity + 0.5

    symbol_market = {
        Ecmsc.LIMITS.value: {
            Ecmsc.LIMITS_AMOUNT.value: {
                Ecmsc.LIMITS_AMOUNT_MIN.value: 0.005
            },
            Ecmsc.LIMITS_COST.value: {
                Ecmsc.LIMITS_COST_MIN.value: 0.00005
            }
        }
    }

    current_symbol_holding = 0.99000000001
    quantity = 0.9
    price = 0.5
    assert personal_data.add_dusts_to_quantity_if_necessary(
        quantity, price, symbol_market, current_symbol_holding) == quantity + 0

    current_symbol_holding = 0.99000000001
    quantity = 0.0215245845
    price = 0.5
    assert personal_data.add_dusts_to_quantity_if_necessary(
        quantity, price, symbol_market, current_symbol_holding) == quantity + 0

    current_symbol_holding = 0.99999999
    quantity = 0.99999
    price = 0.5
    assert personal_data.add_dusts_to_quantity_if_necessary(
        quantity, price, symbol_market, current_symbol_holding) == 0.99999999

    current_symbol_holding = 0.88
    quantity = 0.7055680057024826
    price = 0.0002
    assert personal_data.add_dusts_to_quantity_if_necessary(
        quantity, price, symbol_market, current_symbol_holding) == 0.88

    # price = 0 => no dust
    assert personal_data.add_dusts_to_quantity_if_necessary(
        quantity, 0, symbol_market, current_symbol_holding) == quantity