Exemple #1
0
    async def test_close_filled_sell_limit_order_one_in_two(self):
        _, exchange_manager, trader_inst = await self.init_default()
        portfolio_manager = exchange_manager.exchange_personal_data.portfolio_manager
        initial_portfolio = copy.copy(portfolio_manager.portfolio)
        orders_manager = exchange_manager.exchange_personal_data.orders_manager
        trades_manager = exchange_manager.exchange_personal_data.trades_manager

        # Test buy order
        limit_buy = create_order_instance(trader=trader_inst,
                                          order_type=TraderOrderType.BUY_LIMIT,
                                          symbol="BQX/BTC",
                                          current_price=decimal.Decimal("4"),
                                          quantity=decimal.Decimal("2"),
                                          price=decimal.Decimal("4"))

        await trader_inst.create_order(limit_buy, portfolio_manager.portfolio)

        # Test second buy order
        second_limit_buy = create_order_instance(trader=trader_inst,
                                                 order_type=TraderOrderType.BUY_LIMIT,
                                                 symbol="VEN/BTC",
                                                 current_price=decimal.Decimal("1"),
                                                 quantity=decimal.Decimal("1.5"),
                                                 price=decimal.Decimal("1"))

        await trader_inst.create_order(second_limit_buy, portfolio_manager.portfolio)

        assert not trades_manager.trades

        with pytest.raises(KeyError):
            assert portfolio_manager.portfolio.portfolio["BQX"].available == 0
        assert portfolio_manager.portfolio.portfolio["BTC"].available == 0.5

        # Fill only 1st one
        limit_buy.filled_price = 4
        limit_buy.status = OrderStatus.FILLED
        with patch.object(ccxt.async_support.binance, "calculate_fee", Mock(return_value=FEES_MOCK)) \
                as calculate_fee_mock:
            await limit_buy.on_fill(force_fill=True)
            # ensure call ccxt calculate_fee for order fees
            calculate_fee_mock.assert_called_once()

        # added filled orders as filled trades
        assert len(trades_manager.trades) == 1
        assert all(trade.status is OrderStatus.FILLED for trade in trades_manager.trades.values())

        assert limit_buy not in orders_manager.get_open_orders()
        assert second_limit_buy in orders_manager.get_open_orders()

        assert initial_portfolio != portfolio_manager.portfolio
        # (mocked) fees are taken into account
        assert portfolio_manager.portfolio.portfolio["BQX"].available == decimal.Decimal(str(2 - 0.1))
        assert portfolio_manager.portfolio.portfolio["BTC"].available == decimal.Decimal("0.5")
        assert portfolio_manager.portfolio.portfolio["BTC"].total == decimal.Decimal("2")

        await self.stop(exchange_manager)
Exemple #2
0
    async def test_close_filled_sell_limit_order_one_in_two(self):
        _, exchange_manager, trader_inst = await self.init_default()
        portfolio_manager = exchange_manager.exchange_personal_data.portfolio_manager
        initial_portfolio = copy.deepcopy(portfolio_manager.portfolio.portfolio)
        orders_manager = exchange_manager.exchange_personal_data.orders_manager
        trades_manager = exchange_manager.exchange_personal_data.trades_manager

        # Test buy order
        limit_buy = create_order_instance(trader=trader_inst,
                                          order_type=TraderOrderType.BUY_LIMIT,
                                          symbol="BQX/BTC",
                                          current_price=4,
                                          quantity=2,
                                          price=4)

        await trader_inst.create_order(limit_buy, portfolio_manager.portfolio)

        # Test second buy order
        second_limit_buy = create_order_instance(trader=trader_inst,
                                                 order_type=TraderOrderType.BUY_LIMIT,
                                                 symbol="VEN/BTC",
                                                 current_price=1,
                                                 quantity=1.5,
                                                 price=1)

        await trader_inst.create_order(second_limit_buy, portfolio_manager.portfolio)

        assert not trades_manager.trades

        with pytest.raises(KeyError):
            assert portfolio_manager.portfolio.portfolio["BQX"][commons_constants.PORTFOLIO_AVAILABLE] == 0
        assert portfolio_manager.portfolio.portfolio["BTC"][commons_constants.PORTFOLIO_AVAILABLE] == 0.5

        # Fill only 1st one
        limit_buy.filled_price = 4
        limit_buy.status = OrderStatus.FILLED
        await limit_buy.on_fill(force_fill=True)

        # added filled orders as filled trades
        assert len(trades_manager.trades) == 1
        assert all(trade.status is OrderStatus.FILLED for trade in trades_manager.trades.values())

        assert limit_buy not in orders_manager.get_open_orders()
        assert second_limit_buy in orders_manager.get_open_orders()

        assert initial_portfolio != portfolio_manager.portfolio
        assert portfolio_manager.portfolio.portfolio["BQX"][commons_constants.PORTFOLIO_AVAILABLE] == 2
        assert portfolio_manager.portfolio.portfolio["BTC"][commons_constants.PORTFOLIO_AVAILABLE] == 0.5
        assert portfolio_manager.portfolio.portfolio["BTC"][commons_constants.PORTFOLIO_TOTAL] == 2

        await self.stop(exchange_manager)
Exemple #3
0
    async def test_close_filled_stop_buy_order(self):
        _, exchange_manager, trader_inst = await self.init_default()
        portfolio_manager = exchange_manager.exchange_personal_data.portfolio_manager
        initial_portfolio = copy.deepcopy(portfolio_manager.portfolio.portfolio)
        orders_manager = exchange_manager.exchange_personal_data.orders_manager
        trades_manager = exchange_manager.exchange_personal_data.trades_manager

        # Test buy order
        stop_order = create_order_instance(trader=trader_inst,
                                           order_type=TraderOrderType.BUY_LIMIT,
                                           symbol="BQX/BTC",
                                           current_price=decimal.Decimal("4"),
                                           quantity=decimal.Decimal("2"),
                                           price=decimal.Decimal("4"),
                                           side=TradeOrderSide.BUY)

        await trader_inst.create_order(stop_order, portfolio_manager.portfolio)

        assert not trades_manager.trades

        await stop_order.on_fill(force_fill=True)

        assert stop_order not in orders_manager.get_open_orders()

        assert not initial_portfolio == portfolio_manager.portfolio.portfolio

        # added filled orders as filled trades
        assert len(trades_manager.trades) == 1
        assert all(trade.status is stop_order.status for trade in trades_manager.trades.values())

        await self.stop(exchange_manager)
 async def _sell_everything(self, symbol, inverted, timeout=None):
     created_orders = []
     order_type = octobot_trading.enums.TraderOrderType.BUY_MARKET \
         if inverted else octobot_trading.enums.TraderOrderType.SELL_MARKET
     async with self.exchange_manager.exchange_personal_data.portfolio_manager.portfolio.lock:
         current_symbol_holding, current_market_quantity, _, price, symbol_market = \
             await order_util.get_pre_order_data(self.exchange_manager, symbol, timeout=timeout)
         if inverted:
             if price > 0:
                 quantity = current_market_quantity / price
             else:
                 quantity = 0
         else:
             quantity = current_symbol_holding
         for order_quantity, order_price in decimal_order_adapter.decimal_check_and_adapt_order_details_if_necessary(
                 quantity, price, symbol_market):
             current_order = order_factory.create_order_instance(
                 trader=self,
                 order_type=order_type,
                 symbol=symbol,
                 current_price=order_price,
                 quantity=order_quantity,
                 price=order_price)
             created_orders.append(await self.create_order(
                 current_order, self.exchange_manager.
                 exchange_personal_data.portfolio_manager.portfolio))
     return created_orders
 async def create_artificial_order(self, order_type, symbol, current_price,
                                   quantity, price, linked_portfolio):
     """
     Creates an OctoBot managed order (managed orders example: stop loss that is not published on the exchange and
     that is maintained internally).
     """
     await self.create_order(
         order_factory.create_order_instance(
             trader=self,
             order_type=order_type,
             symbol=symbol,
             current_price=current_price,
             quantity=quantity,
             price=price,
             linked_portfolio=linked_portfolio))
Exemple #6
0
    async def test_close_filled_sell_limit_order(self):
        _, exchange_manager, trader_inst = await self.init_default()
        portfolio_manager = exchange_manager.exchange_personal_data.portfolio_manager
        initial_portfolio = copy.deepcopy(
            portfolio_manager.portfolio.portfolio)
        orders_manager = exchange_manager.exchange_personal_data.orders_manager
        trades_manager = exchange_manager.exchange_personal_data.trades_manager

        # Test buy order
        limit_buy = create_order_instance(trader=trader_inst,
                                          order_type=TraderOrderType.BUY_LIMIT,
                                          symbol="BQX/BTC",
                                          current_price=0.1,
                                          quantity=10,
                                          price=0.1)

        await trader_inst.create_order(limit_buy, portfolio_manager.portfolio)

        limit_buy.filled_price = limit_buy.origin_price
        limit_buy.filled_quantity = limit_buy.origin_quantity
        limit_buy.status = OrderStatus.FILLED

        assert not trades_manager.trades

        with patch.object(ccxt.async_support.binance, "calculate_fee", Mock(return_value=FEES_MOCK)) \
                as calculate_fee_mock:
            await limit_buy.on_fill(force_fill=True)
            calculate_fee_mock.assert_called_once()

        assert limit_buy not in orders_manager.get_open_orders()

        # added filled orders as filled trades
        assert len(trades_manager.trades) == 1
        assert all(trade.status is OrderStatus.FILLED
                   for trade in trades_manager.trades.values())

        assert initial_portfolio != portfolio_manager.portfolio
        assert portfolio_manager.portfolio.portfolio["BTC"][
            commons_constants.PORTFOLIO_AVAILABLE] == 9
        assert portfolio_manager.portfolio.portfolio["BTC"][
            commons_constants.PORTFOLIO_TOTAL] == 9
        # 0.1 as fee
        assert portfolio_manager.portfolio.portfolio["BQX"][
            commons_constants.PORTFOLIO_AVAILABLE] == 9.9
        assert portfolio_manager.portfolio.portfolio["BQX"][
            commons_constants.PORTFOLIO_TOTAL] == 9.9

        await self.stop(exchange_manager)
    async def close_position(self, position, limit_price=None, timeout=1):
        """
        Creates a close position order
        :param position: the position to close
        :param limit_price: the close order limit price if None uses a market order
        :param timeout: the mark price timeout
        :return: the list of created orders
        """
        created_orders = []
        async with self.exchange_manager.exchange_personal_data.portfolio_manager.portfolio.lock:
            _, _, _, price, symbol_market = await order_util.get_pre_order_data(
                self.exchange_manager, position.symbol, timeout=timeout)
            for order_quantity, order_price in decimal_order_adapter.decimal_check_and_adapt_order_details_if_necessary(
                    position.get_quantity_to_close().copy_abs(), price,
                    symbol_market):

                if limit_price is not None:
                    order_type = enums.TraderOrderType.SELL_LIMIT \
                        if position.is_long() else enums.TraderOrderType.BUY_LIMIT
                else:
                    order_type = enums.TraderOrderType.SELL_MARKET \
                        if position.is_long() else enums.TraderOrderType.BUY_MARKET

                # TODO add reduce_only or close_position attribute
                current_order = order_factory.create_order_instance(
                    trader=self,
                    order_type=order_type,
                    symbol=position.symbol,
                    current_price=order_price,
                    quantity=order_quantity,
                    price=limit_price
                    if limit_price is not None else order_price)
                created_orders.append(await self.create_order(
                    current_order, self.exchange_manager.
                    exchange_personal_data.portfolio_manager.portfolio))
        return created_orders