async def test_update_portfolio_data_with_fees(
        future_trader_simulator_with_default_linear):
    config, exchange_manager_inst, trader_inst, default_contract = future_trader_simulator_with_default_linear
    portfolio_manager = exchange_manager_inst.exchange_personal_data.portfolio_manager
    default_contract.set_current_leverage(decimal.Decimal(10))

    # Test sell order
    market_sell = SellMarketOrder(trader_inst)
    sell_order_price = decimal.Decimal(10)
    market_sell.update(order_type=enums.TraderOrderType.SELL_MARKET,
                       symbol=DEFAULT_FUTURE_SYMBOL,
                       current_price=sell_order_price,
                       quantity=decimal.Decimal(25),
                       price=sell_order_price)

    if not os.getenv('CYTHON_IGNORE'):
        with mock.patch.object(market_sell, "get_total_fees",
                               mock.Mock(return_value=5)):
            portfolio_manager.portfolio.update_portfolio_available(
                market_sell, True)
            assert portfolio_manager.portfolio.get_currency_portfolio(
                "USDT").available == decimal.Decimal('975.0')
            assert portfolio_manager.portfolio.get_currency_portfolio(
                "USDT").total == decimal.Decimal('1000')

            # fill order with fees
            await fill_market_order(market_sell)
            await _update_position_mark_price(exchange_manager_inst,
                                              sell_order_price,
                                              DEFAULT_FUTURE_SYMBOL)
            assert portfolio_manager.portfolio.get_currency_portfolio(
                "USDT").available == decimal.Decimal('970.0')
            assert portfolio_manager.portfolio.get_currency_portfolio(
                "USDT").total == decimal.Decimal('995')
async def test_update_portfolio_data_from_order_with_huge_loss_on_filled_orders_linear_contract(
        future_trader_simulator_with_default_linear):
    config, exchange_manager_inst, trader_inst, default_contract = future_trader_simulator_with_default_linear
    portfolio_manager = exchange_manager_inst.exchange_personal_data.portfolio_manager
    default_contract.set_current_leverage(decimal.Decimal(2))

    # Test sell order
    market_sell = SellMarketOrder(trader_inst)
    sell_order_price = decimal.Decimal(10)
    market_sell.update(order_type=enums.TraderOrderType.SELL_MARKET,
                       symbol=DEFAULT_FUTURE_SYMBOL,
                       current_price=sell_order_price,
                       quantity=decimal.Decimal(25),
                       price=sell_order_price)

    # Test buy order
    market_buy = BuyMarketOrder(trader_inst)
    buy_order_price = decimal.Decimal(13)
    market_buy.update(order_type=enums.TraderOrderType.BUY_MARKET,
                      symbol=DEFAULT_FUTURE_SYMBOL,
                      current_price=buy_order_price,
                      quantity=decimal.Decimal(10),
                      price=buy_order_price)

    portfolio_manager.portfolio.update_portfolio_available(market_sell, True)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal('875.0')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal('1000')

    # Open short position
    await fill_market_order(market_sell)
    await _update_position_mark_price(exchange_manager_inst, sell_order_price,
                                      DEFAULT_FUTURE_SYMBOL)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal('874.9')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal('999.9')

    portfolio_manager.portfolio.update_portfolio_available(market_buy, True)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal('874.9')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal('999.9')

    # Close short position with loss
    await fill_market_order(market_buy)
    await _update_position_mark_price(exchange_manager_inst, buy_order_price,
                                      DEFAULT_FUTURE_SYMBOL)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal('902.4')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal('902.4')
Exemplo n.º 3
0
async def test_get_order_position(future_trader_simulator_with_default_linear):
    config, exchange_manager, trader, default_contract = future_trader_simulator_with_default_linear
    positions_manager = exchange_manager.exchange_personal_data.positions_manager
    symbol_contract = default_contract
    trader.exchange_manager.exchange.set_pair_future_contract(
        DEFAULT_FUTURE_SYMBOL, default_contract)

    p1 = positions_manager.get_symbol_position(symbol=DEFAULT_FUTURE_SYMBOL,
                                               side=enums.PositionSide.BOTH)
    market_sell = SellMarketOrder(trader)
    market_sell.update(order_type=enums.TraderOrderType.SELL_MARKET,
                       symbol=DEFAULT_FUTURE_SYMBOL,
                       position_side=enums.PositionSide.SHORT)
    p1bis = positions_manager.get_order_position(market_sell,
                                                 contract=symbol_contract)
    assert p1 is p1bis
async def test_update_portfolio_reduce_size_with_market_sell_long_linear_contract(
        future_trader_simulator_with_default_linear):
    config, exchange_manager_inst, trader_inst, default_contract = future_trader_simulator_with_default_linear
    portfolio_manager = exchange_manager_inst.exchange_personal_data.portfolio_manager
    default_contract.set_current_leverage(decimal.Decimal(10))

    position_inst = LinearPosition(trader_inst, default_contract)
    await position_inst.initialize()
    await position_inst.update(update_size=decimal.Decimal(10),
                               mark_price=decimal.Decimal(101))
    position_inst.update_from_raw({
        enums.ExchangeConstantsPositionColumns.SYMBOL.value:
        DEFAULT_FUTURE_SYMBOL
    })
    exchange_manager_inst.exchange_personal_data.positions_manager.upsert_position_instance(
        position_inst)

    # Test sell order
    market_sell = SellMarketOrder(trader_inst)
    market_sell.update(order_type=enums.TraderOrderType.SELL_MARKET,
                       symbol=DEFAULT_FUTURE_SYMBOL,
                       current_price=decimal.Decimal(101),
                       quantity=decimal.Decimal(25),
                       price=decimal.Decimal(101))

    # test sell order creation
    portfolio_manager.portfolio.update_portfolio_available(market_sell, True)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal(str(1000))
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal(str(1000))
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").available == decimal.Decimal(str(10))
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").total == decimal.Decimal(str(10))

    # fill order
    await fill_market_order(market_sell)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal("998.99")
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal(str("998.99"))
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").available == decimal.Decimal(str(10))
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").total == decimal.Decimal(str(10))
async def test_update_portfolio_available_from_order_with_leverage(
        backtesting_trader):
    config, exchange_manager, trader = backtesting_trader
    portfolio_manager = exchange_manager.exchange_personal_data.portfolio_manager

    # set future contract
    btcusd_future_contract = FutureContract("BTC/USDT")
    btcusd_future_contract.current_leverage = 2
    btcusd_future_contract.contract_type = FutureContractType.PERPETUAL
    exchange_manager.exchange.set_pair_future_contract("BTC/USDT",
                                                       btcusd_future_contract)

    # Test buy order
    market_buy = BuyMarketOrder(trader)
    market_buy.update(order_type=TraderOrderType.BUY_MARKET,
                      symbol="BTC/USDT",
                      current_price=555,
                      quantity=10,
                      price=555)

    # test buy order creation
    portfolio_manager.portfolio.update_portfolio_available(market_buy, True)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC", PORTFOLIO_AVAILABLE) == 10
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT", PORTFOLIO_AVAILABLE) == 995
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC", PORTFOLIO_TOTAL) == 10
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT", PORTFOLIO_TOTAL) == 1000

    # Test sell order
    market_sell = SellMarketOrder(trader)
    market_sell.update(order_type=TraderOrderType.SELL_MARKET,
                       symbol="BTC/USDT",
                       current_price=555,
                       quantity=3,
                       price=555)

    # test sell order creation
    portfolio_manager.portfolio.update_portfolio_available(market_sell, True)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC", PORTFOLIO_AVAILABLE) == 10
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT", PORTFOLIO_AVAILABLE) == 993.5
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC", PORTFOLIO_TOTAL) == 10
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT", PORTFOLIO_TOTAL) == 1000

    # Test limit order to restore initial portfolio with a is_new=False and a quantity of 10 + 3
    market_buy = BuyMarketOrder(trader)
    market_buy.update(order_type=TraderOrderType.BUY_MARKET,
                      symbol="BTC/USDT",
                      current_price=555,
                      quantity=13,
                      price=555)

    # test buy order creation
    portfolio_manager.portfolio.update_portfolio_available(market_buy, False)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC", PORTFOLIO_AVAILABLE) == 10
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT", PORTFOLIO_AVAILABLE) == 1000
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC", PORTFOLIO_TOTAL) == 10
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT", PORTFOLIO_TOTAL) == 1000
async def test_update_portfolio_from_liquidated_position_with_orders_on_short_position_linear_contract(
        future_trader_simulator_with_default_linear):
    config, exchange_manager_inst, trader_inst, default_contract = future_trader_simulator_with_default_linear
    portfolio_manager = exchange_manager_inst.exchange_personal_data.portfolio_manager
    default_contract.set_current_leverage(decimal.Decimal(50))
    trader_inst.exchange_manager.exchange.set_pair_future_contract(
        DEFAULT_FUTURE_SYMBOL, default_contract)

    position_inst = LinearPosition(trader_inst, default_contract)
    await position_inst.initialize()
    position_inst.update_from_raw({
        enums.ExchangeConstantsPositionColumns.SYMBOL.value:
        DEFAULT_FUTURE_SYMBOL
    })
    await position_inst.update(update_size=decimal.Decimal(-100),
                               mark_price=decimal.Decimal(99))
    exchange_manager_inst.exchange_personal_data.positions_manager.upsert_position_instance(
        position_inst)

    # Test sell order
    market_sell = SellMarketOrder(trader_inst)
    market_sell.update(order_type=enums.TraderOrderType.SELL_MARKET,
                       symbol=DEFAULT_FUTURE_SYMBOL,
                       current_price=decimal.Decimal(99),
                       quantity=decimal.Decimal(5),
                       price=decimal.Decimal(99))

    # test sell order creation
    portfolio_manager.portfolio.update_portfolio_available(market_sell, True)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal('990.1')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal('1000')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").available == decimal.Decimal('10')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").total == decimal.Decimal('10')

    await fill_market_order(market_sell)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal('989.902')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal('999.802')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").available == decimal.Decimal('10')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").total == decimal.Decimal('10')

    # Test buy order
    market_buy = BuyMarketOrder(trader_inst)
    market_buy.update(order_type=enums.TraderOrderType.BUY_MARKET,
                      symbol=DEFAULT_FUTURE_SYMBOL,
                      current_price=decimal.Decimal(90),
                      quantity=decimal.Decimal(10),
                      price=decimal.Decimal(90))

    portfolio_manager.portfolio.update_portfolio_available(market_buy, True)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal('989.902')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal('999.802')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").available == decimal.Decimal('10')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").total == decimal.Decimal('10')

    await fill_market_order(market_buy)  # reducing position with positive PNL
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal('999.802')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal('1089.802')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").available == decimal.Decimal('10')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").total == decimal.Decimal('10')

    portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").wallet_balance = decimal.Decimal('10')
    portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").wallet_balance = decimal.Decimal('1000')
    await position_inst.update(mark_price=position_inst.liquidation_price)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal('808.2010')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal('808.2010')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").available == decimal.Decimal('10')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").total == decimal.Decimal('10')
async def test_update_portfolio_data_from_order_with_cancelled_and_filled_orders_linear_contract(
        future_trader_simulator_with_default_linear):
    config, exchange_manager_inst, trader_inst, default_contract = future_trader_simulator_with_default_linear
    portfolio_manager = exchange_manager_inst.exchange_personal_data.portfolio_manager
    default_contract.set_current_leverage(decimal.Decimal(5))

    # Test sell order
    market_sell = SellMarketOrder(trader_inst)
    sell_price = decimal.Decimal(str(80))
    market_sell.update(order_type=enums.TraderOrderType.SELL_MARKET,
                       symbol=DEFAULT_FUTURE_SYMBOL,
                       current_price=sell_price,
                       quantity=decimal.Decimal(str(12)),
                       price=sell_price)

    # Test sell order
    limit_sell = SellLimitOrder(trader_inst)
    limit_sell.update(order_type=enums.TraderOrderType.SELL_LIMIT,
                      symbol=DEFAULT_FUTURE_SYMBOL,
                      current_price=decimal.Decimal(str(10)),
                      quantity=decimal.Decimal(str(46.5)),
                      price=decimal.Decimal(str(10)))

    # Test stop loss order
    stop_loss = StopLossOrder(trader_inst)
    stop_loss.update(order_type=enums.TraderOrderType.STOP_LOSS,
                     symbol=DEFAULT_FUTURE_SYMBOL,
                     current_price=decimal.Decimal(str(80)),
                     quantity=decimal.Decimal(str(46.5)),
                     price=decimal.Decimal(str(80)))

    portfolio_manager.portfolio.update_portfolio_available(stop_loss, True)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal('1000')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal('1000')

    portfolio_manager.portfolio.update_portfolio_available(limit_sell, True)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal('907.0')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal('1000')

    portfolio_manager.portfolio.update_portfolio_available(market_sell, True)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal('715.0')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal('1000')

    await fill_market_order(market_sell)
    await _update_position_mark_price(exchange_manager_inst, sell_price,
                                      DEFAULT_FUTURE_SYMBOL)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal('714.616')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal('999.616')

    # cancel other orders
    portfolio_manager.portfolio.update_portfolio_available(stop_loss, False)
    portfolio_manager.portfolio.update_portfolio_available(limit_sell, False)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").available == decimal.Decimal('10')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal('807.616')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").total == decimal.Decimal('10')
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal('999.616')
async def test_update_portfolio_data_from_order_with_market_buy_long_linear_contract(
        future_trader_simulator_with_default_linear):
    config, exchange_manager_inst, trader_inst, default_contract = future_trader_simulator_with_default_linear
    portfolio_manager = exchange_manager_inst.exchange_personal_data.portfolio_manager
    default_contract.set_current_leverage(decimal.Decimal(5))

    # Test buy order
    market_buy = BuyMarketOrder(trader_inst)
    buy_price = decimal.Decimal(str(1000))
    market_buy.update(
        order_type=enums.TraderOrderType.BUY_MARKET,
        symbol=DEFAULT_FUTURE_SYMBOL,
        current_price=buy_price,
        quantity=decimal.Decimal(3),  # real quantity = 3 / 5 = 0.6
        price=buy_price)  # real cost = 0.6 * 1000 = 600

    # test buy order creation
    portfolio_manager.portfolio.update_portfolio_available(market_buy, True)

    # create position from order
    await fill_market_order(market_buy)

    # update position mark price
    await _update_position_mark_price(exchange_manager_inst, buy_price,
                                      DEFAULT_FUTURE_SYMBOL)

    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal(str(400.0))
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal(str(1000.0))

    # Test buy order
    market_buy = BuyMarketOrder(trader_inst)
    market_buy.update(
        order_type=enums.TraderOrderType.BUY_MARKET,
        symbol=DEFAULT_FUTURE_SYMBOL,
        current_price=buy_price,
        quantity=decimal.Decimal(1),  # 0.2
        price=buy_price)  # 200

    # test buy order creation
    portfolio_manager.portfolio.update_portfolio_available(market_buy, True)
    await fill_market_order(market_buy)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal(str(200.0))
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal(str(1000.0))

    # Test reducing LONG position with a sell market order
    market_sell = SellMarketOrder(trader_inst)
    market_sell.update(
        order_type=enums.TraderOrderType.SELL_MARKET,
        symbol=DEFAULT_FUTURE_SYMBOL,
        current_price=buy_price,
        quantity=decimal.Decimal(0.5),  # 0.1
        price=buy_price)  # 100

    # Should restore available
    portfolio_manager.portfolio.update_portfolio_available(market_sell, True)
    await fill_market_order(market_sell)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").available == decimal.Decimal(10)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal(str(299.8))
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").total == decimal.Decimal(10)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal(str(999.8))

    # Test buy order 2
    market_buy = BuyMarketOrder(trader_inst)
    market_buy.update(
        order_type=enums.TraderOrderType.BUY_MARKET,
        symbol=DEFAULT_FUTURE_SYMBOL,
        current_price=buy_price,
        quantity=decimal.Decimal(0.5),  # 0.1
        price=buy_price)  # 100

    # increase position size
    portfolio_manager.portfolio.update_portfolio_available(market_buy, True)
    await fill_market_order(market_buy)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal(str(199.8))
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal(str(999.8))

    # Test reducing again LONG position with a sell market order
    market_sell = SellMarketOrder(trader_inst)
    market_sell.update(
        order_type=enums.TraderOrderType.SELL_MARKET,
        symbol=DEFAULT_FUTURE_SYMBOL,
        current_price=buy_price,
        quantity=decimal.Decimal(4),  # 0.8
        price=buy_price)  # 800

    # decrease position size
    portfolio_manager.portfolio.update_portfolio_available(market_sell, True)
    await fill_market_order(market_sell)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").available == decimal.Decimal(10)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").available == decimal.Decimal(str(998.2))
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "BTC").total == decimal.Decimal(10)
    assert portfolio_manager.portfolio.get_currency_portfolio(
        "USDT").total == decimal.Decimal(str(998.2))