コード例 #1
0
async def test_order_book_ticker_update(order_book_manager):
    b_price = random_price()
    a_price = random_price()
    b_quantity = random_quantity()
    a_quantity = random_quantity()
    order_book_manager.order_book_ticker_update(a_quantity, a_price,
                                                b_quantity, b_price)
    assert order_book_manager.ask_quantity == a_quantity
    assert order_book_manager.ask_price == a_price
    assert order_book_manager.bid_quantity == b_quantity
    assert order_book_manager.bid_price == b_price
コード例 #2
0
async def test_take_profit_sell_order_trigger(take_profit_sell_order):
    order_price = random_price(min_value=2)
    take_profit_sell_order.update(
        price=order_price,
        quantity=random_quantity(max_value=DEFAULT_SYMBOL_QUANTITY / 10),
        symbol=DEFAULT_ORDER_SYMBOL,
        order_type=TraderOrderType.TAKE_PROFIT,
    )
    take_profit_sell_order.exchange_manager.is_backtesting = True  # force update_order_status
    await take_profit_sell_order.initialize()
    take_profit_sell_order.exchange_manager.exchange_personal_data.orders_manager.upsert_order_instance(
        take_profit_sell_order)
    price_events_manager = take_profit_sell_order.exchange_manager.exchange_symbols_data.get_exchange_symbol_data(
        DEFAULT_ORDER_SYMBOL).price_events_manager
    price_events_manager.handle_recent_trades([
        random_recent_trade(price=random_price(max_value=order_price - 1),
                            timestamp=take_profit_sell_order.timestamp)
    ])
    await wait_asyncio_next_cycle()
    assert not take_profit_sell_order.is_filled()
    price_events_manager.handle_recent_trades([
        random_recent_trade(price=order_price,
                            timestamp=take_profit_sell_order.timestamp - 1)
    ])
    await wait_asyncio_next_cycle()
    assert not take_profit_sell_order.is_filled()
    price_events_manager.handle_recent_trades([
        random_recent_trade(price=order_price,
                            timestamp=take_profit_sell_order.timestamp)
    ])

    # wait for 2 cycles as secondary orders are created
    await wait_asyncio_next_cycle()
    await wait_asyncio_next_cycle()
    assert take_profit_sell_order.is_filled()
コード例 #3
0
async def test_buy_limit_order_trigger(buy_limit_order):
    order_price = random_price()
    buy_limit_order.update(
        price=order_price,
        quantity=random_quantity(max_value=DEFAULT_MARKET_QUANTITY /
                                 order_price),
        symbol=DEFAULT_ORDER_SYMBOL,
        order_type=TraderOrderType.BUY_LIMIT,
    )
    buy_limit_order.exchange_manager.is_backtesting = True  # force update_order_status
    await buy_limit_order.initialize()
    buy_limit_order.exchange_manager.exchange_personal_data.orders_manager.upsert_order_instance(
        buy_limit_order)
    price_events_manager = buy_limit_order.exchange_manager.exchange_symbols_data.get_exchange_symbol_data(
        DEFAULT_ORDER_SYMBOL).price_events_manager
    price_events_manager.handle_recent_trades([
        random_recent_trade(price=random_price(min_value=order_price + 1),
                            timestamp=buy_limit_order.timestamp)
    ])
    await wait_asyncio_next_cycle()
    assert not buy_limit_order.is_filled()
    price_events_manager.handle_recent_trades([
        random_recent_trade(price=order_price,
                            timestamp=buy_limit_order.timestamp - 1)
    ])
    await wait_asyncio_next_cycle()
    assert not buy_limit_order.is_filled()
    price_events_manager.handle_recent_trades([
        random_recent_trade(price=order_price,
                            timestamp=buy_limit_order.timestamp)
    ])

    await wait_asyncio_next_cycle()
    assert buy_limit_order.is_filled()
コード例 #4
0
async def test_update_and_reset_mini_ticker(ticker_manager):
    vol = random_quantity()
    open_p = random_price()
    ticker_manager.mini_ticker_update({
        ExchangeConstantsMiniTickerColumns.HIGH_PRICE.value:
        random_price(),
        ExchangeConstantsMiniTickerColumns.LOW_PRICE.value:
        random_price(),
        ExchangeConstantsMiniTickerColumns.OPEN_PRICE.value:
        open_p,
        ExchangeConstantsMiniTickerColumns.CLOSE_PRICE.value:
        random_price(),
        ExchangeConstantsMiniTickerColumns.VOLUME.value:
        vol,
        ExchangeConstantsMiniTickerColumns.TIMESTAMP.value:
        random_timestamp()
    })
    assert ticker_manager.mini_ticker[
        ExchangeConstantsMiniTickerColumns.VOLUME.value] == vol
    assert ticker_manager.mini_ticker[
        ExchangeConstantsMiniTickerColumns.OPEN_PRICE.value] == open_p
    if not os.getenv('CYTHON_IGNORE'):
        ticker_manager.reset_mini_ticker()
        assert ticker_manager.mini_ticker == {
            ExchangeConstantsMiniTickerColumns.HIGH_PRICE.value: nan,
            ExchangeConstantsMiniTickerColumns.LOW_PRICE.value: nan,
            ExchangeConstantsMiniTickerColumns.OPEN_PRICE.value: nan,
            ExchangeConstantsMiniTickerColumns.CLOSE_PRICE.value: nan,
            ExchangeConstantsMiniTickerColumns.VOLUME.value: nan,
            ExchangeConstantsMiniTickerColumns.TIMESTAMP.value: 0
        }
コード例 #5
0
async def test_stop_loss_buy_order_trigger(stop_loss_buy_order):
    order_price = random_price()
    stop_loss_buy_order.update(
        price=order_price,
        quantity=random_quantity(max_value=DEFAULT_SYMBOL_QUANTITY),
        symbol=DEFAULT_ORDER_SYMBOL,
        order_type=TraderOrderType.STOP_LOSS,
    )
    stop_loss_buy_order.exchange_manager.is_backtesting = True  # force update_order_status
    await stop_loss_buy_order.initialize()
    stop_loss_buy_order.exchange_manager.exchange_personal_data.orders_manager.upsert_order_instance(
        stop_loss_buy_order)
    price_events_manager = stop_loss_buy_order.exchange_manager.exchange_symbols_data.get_exchange_symbol_data(
        DEFAULT_ORDER_SYMBOL).price_events_manager
    # stop loss buy order triggers when price is above or equal to its trigger price
    price_events_manager.handle_recent_trades([
        random_recent_trade(price=random_price(max_value=order_price - 1),
                            timestamp=stop_loss_buy_order.timestamp)
    ])
    await wait_asyncio_next_cycle()
    assert not stop_loss_buy_order.is_filled()
    price_events_manager.handle_recent_trades([
        random_recent_trade(price=order_price,
                            timestamp=stop_loss_buy_order.timestamp - 1)
    ])
    await wait_asyncio_next_cycle()
    assert not stop_loss_buy_order.is_filled()
    price_events_manager.handle_recent_trades([
        random_recent_trade(price=order_price,
                            timestamp=stop_loss_buy_order.timestamp)
    ])

    await wait_asyncio_next_cycle()
    assert stop_loss_buy_order.is_filled()
コード例 #6
0
async def test_create_position_instance_from_raw(trader_simulator):
    config, exchange_manager_inst, trader_inst = trader_simulator

    raw_position = {
        enums.ExchangeConstantsPositionColumns.SYMBOL.value:
        "BTC/USDT",
        enums.ExchangeConstantsPositionColumns.STATUS.value:
        enums.PositionStatus.ADL.value
    }
    position = personal_data.create_position_instance_from_raw(
        trader_inst, raw_position)
    position_leverage = random_int(max_value=200)
    position_quantity = random_quantity(max_value=1000)
    cross_position_open = personal_data.create_position_instance_from_raw(
        trader_inst, {
            enums.ExchangeConstantsPositionColumns.SYMBOL.value:
            "BTC/USDT",
            enums.ExchangeConstantsPositionColumns.LEVERAGE.value:
            position_leverage,
            enums.ExchangeConstantsPositionColumns.QUANTITY.value:
            position_quantity,
            enums.ExchangeConstantsPositionColumns.MARGIN_TYPE.value:
            enums.TraderPositionType.CROSS.value
        })
    assert position.symbol == "BTC/USDT"
    assert position.market == "USDT"
    assert position.currency == "BTC"
    assert position.status == enums.PositionStatus.ADL
    assert isinstance(position, personal_data.IsolatedPosition)

    assert cross_position_open.status == enums.PositionStatus.OPEN
    assert cross_position_open.leverage == position_leverage
    assert cross_position_open.quantity == position_quantity
    assert isinstance(cross_position_open, personal_data.CrossPosition)
コード例 #7
0
async def test_refresh_simulated_trader_portfolio_from_order(backtesting_trader):
    config, exchange_manager, trader = backtesting_trader
    portfolio_manager = exchange_manager.exchange_personal_data.portfolio_manager

    if os.getenv('CYTHON_IGNORE'):
        return
    order = BuyLimitOrder(trader)
    await order.initialize()
    with patch.object(portfolio_manager.portfolio, 'update_portfolio_available',
                      new=Mock()) as update_portfolio_available_mock:
        update_portfolio_available_mock.assert_not_called()
        portfolio_manager._refresh_simulated_trader_portfolio_from_order(order)
        update_portfolio_available_mock.assert_called_once()

    price = random_price()
    order.update(
        price=random_price(),
        quantity=random_quantity(max_value=DEFAULT_MARKET_QUANTITY / price),
        symbol="BTC/USDT"
    )
    await order.on_fill(force_fill=True)
    assert order.is_filled()

    with patch.object(portfolio_manager.portfolio, 'update_portfolio_from_filled_order',
                      new=Mock()) as update_portfolio_from_filled_order_mock:
        update_portfolio_from_filled_order_mock.assert_not_called()
        portfolio_manager._refresh_simulated_trader_portfolio_from_order(order)
        update_portfolio_from_filled_order_mock.assert_called_once()
コード例 #8
0
async def test_stop_loss_limit_order_trigger(stop_loss_limit_order):
    order_price = random_price()
    stop_loss_limit_order.update(
        price=order_price,
        quantity=random_quantity(),
        symbol=DEFAULT_SYMBOL_ORDER,
        order_type=TraderOrderType.STOP_LOSS_LIMIT,
    )
    stop_loss_limit_order.exchange_manager.is_backtesting = True  # force update_order_status
    await stop_loss_limit_order.initialize()
    stop_loss_limit_order.exchange_manager.exchange_personal_data.orders_manager.upsert_order_instance(
        stop_loss_limit_order)
    price_events_manager = stop_loss_limit_order.exchange_manager.exchange_symbols_data.get_exchange_symbol_data(
        DEFAULT_SYMBOL_ORDER).price_events_manager
    price_events_manager.handle_recent_trades([
        random_recent_trade(price=random_price(min_value=order_price + 1),
                            timestamp=stop_loss_limit_order.timestamp)
    ])
    await wait_asyncio_next_cycle()
    assert not stop_loss_limit_order.is_filled()
    price_events_manager.handle_recent_trades([
        random_recent_trade(price=order_price,
                            timestamp=stop_loss_limit_order.timestamp - 1)
    ])
    await wait_asyncio_next_cycle()
    assert not stop_loss_limit_order.is_filled()
    price_events_manager.handle_recent_trades([
        random_recent_trade(price=order_price,
                            timestamp=stop_loss_limit_order.timestamp)
    ])

    # wait for 2 cycles as secondary orders are created
    await wait_asyncio_next_cycle()
    await wait_asyncio_next_cycle()
    assert stop_loss_limit_order.is_filled()
コード例 #9
0
async def test_buy_market_order_trigger(buy_market_order):
    order_price = random_price()
    buy_market_order.update(
        price=order_price,
        quantity=random_quantity(),
        symbol=DEFAULT_SYMBOL_ORDER,
        order_type=TraderOrderType.BUY_MARKET,
    )
    buy_market_order.exchange_manager.is_backtesting = True  # force update_order_status
    await buy_market_order.initialize()
    assert buy_market_order.is_filled()
コード例 #10
0
def get_test_order(order_side, order_id, order_price=None, order_size=None):
    return {
        ECOBIC.SIDE.value:
        order_side,
        ECOBIC.SIZE.value:
        order_size if order_size is not None else random_quantity(),
        ECOBIC.PRICE.value:
        order_price if order_price is not None else random_price(),
        ECOBIC.ORDER_ID.value:
        order_id
    }
コード例 #11
0
async def test_sell_market_order_trigger(sell_market_order):
    order_price = random_price()
    sell_market_order.update(
        price=order_price,
        quantity=random_quantity(max_value=DEFAULT_SYMBOL_QUANTITY),
        symbol=DEFAULT_ORDER_SYMBOL,
        order_type=TraderOrderType.SELL_MARKET,
    )
    sell_market_order.exchange_manager.is_backtesting = True  # force update_order_status
    await sell_market_order.initialize()
    assert sell_market_order.is_filled()
コード例 #12
0
async def test_random_quantity_handle_balance_update(backtesting_trader):
    config, exchange_manager, trader = backtesting_trader
    portfolio_manager = exchange_manager.exchange_personal_data.portfolio_manager
    portfolio_profitability = portfolio_manager.portfolio_profitability
    portfolio_value_holder = portfolio_manager.portfolio_value_holder
    original_symbol_quantity = decimal.Decimal(str(10))

    # set the original values
    portfolio_manager.handle_balance_updated()
    assert portfolio_profitability.profitability == 0
    assert portfolio_profitability.profitability_percent == 0
    assert portfolio_profitability.profitability_diff == 0
    assert portfolio_value_holder.portfolio_origin_value == original_symbol_quantity
    assert portfolio_value_holder.portfolio_current_value == original_symbol_quantity

    new_btc_available = random_quantity(
        max_value=15)  # shouldn't impact profitability
    new_btc_total = decimal_random_quantity(min_value=new_btc_available,
                                            max_value=15)
    new_prof_percent = decimal.Decimal(
        str((100 * new_btc_total / original_symbol_quantity) - 100))
    portfolio_manager.portfolio.update_portfolio_from_balance(
        {
            'BTC': {
                'available': decimal.Decimal(str(new_btc_available)),
                'total': new_btc_total
            }
        }, exchange_manager)
    portfolio_manager.handle_balance_updated()
    assert portfolio_profitability.profitability == new_btc_total - original_symbol_quantity
    assert portfolio_profitability.profitability_percent == new_prof_percent
    assert portfolio_profitability.profitability_diff == new_prof_percent - 0
    assert portfolio_value_holder.portfolio_origin_value == original_symbol_quantity
    assert portfolio_value_holder.portfolio_current_value == new_btc_total

    new_btc_total_2 = decimal_random_quantity(min_value=new_btc_available,
                                              max_value=12)
    new_prof_percent_2 = decimal.Decimal(
        str((100 * new_btc_total_2 / original_symbol_quantity) - 100))
    portfolio_manager.portfolio.update_portfolio_from_balance(
        {'BTC': {
            'total': new_btc_total_2
        }}, exchange_manager)
    portfolio_manager.handle_balance_updated()
    assert portfolio_profitability.profitability == new_btc_total_2 - original_symbol_quantity
    assert portfolio_profitability.profitability_percent == new_prof_percent_2
    assert portfolio_profitability.profitability_diff == new_prof_percent_2 - new_prof_percent
    assert portfolio_value_holder.portfolio_origin_value == original_symbol_quantity
    assert portfolio_value_holder.portfolio_current_value == new_btc_total_2
コード例 #13
0
async def initialize_trailing_stop(
        order) -> Tuple[TrailingStopOrder, float, PriceEventsManager]:
    order_price = random_price()
    order.update(
        price=order_price,
        quantity=random_quantity(),
        symbol=DEFAULT_SYMBOL_ORDER,
        order_type=TradeOrderType.TRAILING_STOP,
    )
    order.exchange_manager.is_backtesting = True  # force update_order_status
    await order.initialize()
    price_events_manager = order.exchange_manager.exchange_symbols_data.get_exchange_symbol_data(
        DEFAULT_SYMBOL_ORDER).price_events_manager
    order.exchange_manager.exchange_personal_data.orders_manager.upsert_order_instance(
        order)
    return order, order_price, price_events_manager
コード例 #14
0
async def initialize_trailing_stop(
    order,
    side=TradeOrderSide.SELL
) -> Tuple[TrailingStopOrder, float, PriceEventsManager]:
    order_price = random_price()
    order_max_quantity = DEFAULT_SYMBOL_QUANTITY \
        if side is TradeOrderSide.SELL else DEFAULT_MARKET_QUANTITY / order_price
    order.update(
        price=order_price,
        # divide quantity by 2 to prevent trailing price movement to impact usable quantity
        quantity=random_quantity(max_value=order_max_quantity / 2),
        symbol=DEFAULT_ORDER_SYMBOL,
        order_type=TradeOrderType.TRAILING_STOP,
    )
    order.side = side
    order.exchange_manager.is_backtesting = True  # force update_order_status
    await order.initialize()
    price_events_manager = order.exchange_manager.exchange_symbols_data.get_exchange_symbol_data(
        DEFAULT_ORDER_SYMBOL).price_events_manager
    order.exchange_manager.exchange_personal_data.orders_manager.upsert_order_instance(
        order)
    return order, order_price, price_events_manager
コード例 #15
0
async def test_limit_and_stop_loss(stop_loss_sell_order, sell_limit_order):
    # fill both orders: limit first
    limit_order_price = random_price()
    quantity = random_quantity()
    sell_limit_order.update(
        price=limit_order_price,
        quantity=quantity,
        symbol=DEFAULT_SYMBOL_ORDER,
        order_type=TraderOrderType.SELL_LIMIT,
    )
    stop_order_price = random_price(max_value=limit_order_price - 1)
    stop_loss_sell_order.update(price=stop_order_price,
                                quantity=quantity,
                                symbol=DEFAULT_SYMBOL_ORDER,
                                order_type=TraderOrderType.STOP_LOSS,
                                linked_to=sell_limit_order)
    stop_loss_sell_order.linked_orders.append(sell_limit_order)
    sell_limit_order.linked_orders.append(stop_loss_sell_order)
    stop_loss_sell_order.exchange_manager.is_backtesting = True  # force update_order_status
    # initialize limit order first
    await sell_limit_order.initialize()
    await stop_loss_sell_order.initialize()
    price_events_manager = stop_loss_sell_order.exchange_manager.exchange_symbols_data.get_exchange_symbol_data(
        DEFAULT_SYMBOL_ORDER).price_events_manager
    # stop loss sell order triggers when price is bellow or equal to its trigger price
    # sell limit order triggers when price is above or equal to its trigger price
    # here trigger both: limit is triggered first (initialized first): sell stop loss order should be
    # cancelled and not filled even though its price has been hit
    price_events_manager.handle_recent_trades([
        random_recent_trade(price=random_price(max_value=stop_order_price - 1),
                            timestamp=sell_limit_order.timestamp),
        random_recent_trade(price=random_price(min_value=limit_order_price +
                                               1),
                            timestamp=stop_loss_sell_order.timestamp)
    ])
    await wait_asyncio_next_cycle()
    assert stop_loss_sell_order.is_cancelled()
    assert sell_limit_order.is_filled()
コード例 #16
0
async def test_update_and_reset_ticker(ticker_manager):
    price = random_price()
    tm = random_timestamp()
    vlm = random_quantity()
    ticker_manager.ticker_update({
        ExchangeConstantsTickersColumns.ASK.value:
        price,
        ExchangeConstantsTickersColumns.ASK_VOLUME.value:
        vlm,
        ExchangeConstantsTickersColumns.TIMESTAMP.value:
        tm
    })
    assert ticker_manager.ticker[
        ExchangeConstantsTickersColumns.ASK.value] == price
    assert ticker_manager.ticker[
        ExchangeConstantsTickersColumns.ASK_VOLUME.value] == vlm
    assert ticker_manager.ticker[
        ExchangeConstantsTickersColumns.TIMESTAMP.value] == tm
    if not os.getenv('CYTHON_IGNORE'):
        ticker_manager.reset_ticker()
        assert ticker_manager.ticker == {
            ExchangeConstantsTickersColumns.ASK.value: nan,
            ExchangeConstantsTickersColumns.ASK_VOLUME.value: nan,
            ExchangeConstantsTickersColumns.BID.value: nan,
            ExchangeConstantsTickersColumns.BID_VOLUME.value: nan,
            ExchangeConstantsTickersColumns.OPEN.value: nan,
            ExchangeConstantsTickersColumns.LOW.value: nan,
            ExchangeConstantsTickersColumns.HIGH.value: nan,
            ExchangeConstantsTickersColumns.CLOSE.value: nan,
            ExchangeConstantsTickersColumns.LAST.value: nan,
            ExchangeConstantsTickersColumns.AVERAGE.value: nan,
            ExchangeConstantsTickersColumns.SYMBOL.value: nan,
            ExchangeConstantsTickersColumns.QUOTE_VOLUME.value: nan,
            ExchangeConstantsTickersColumns.TIMESTAMP.value: 0,
            ExchangeConstantsTickersColumns.VWAP.value: nan
        }
コード例 #17
0
async def test_kline_update(kline_manager):
    rc_1 = random_kline()
    kline_manager.kline_update(rc_1)
    assert kline_manager.kline[PriceIndexes.IND_PRICE_CLOSE.value] == rc_1[
        PriceIndexes.IND_PRICE_CLOSE.value]

    # trigger a new candle
    rc_2 = [0] * len(PriceIndexes)
    rc_2[PriceIndexes.IND_PRICE_CLOSE.value] = 0
    rc_2[PriceIndexes.IND_PRICE_OPEN.value] = 0
    rc_2[PriceIndexes.IND_PRICE_HIGH.value] = 0
    rc_2[PriceIndexes.IND_PRICE_LOW.value] = 0
    rc_2[PriceIndexes.IND_PRICE_VOL.value] = 0
    rc_2[PriceIndexes.IND_PRICE_TIME.value] = random_timestamp()
    kline_manager.kline_update(rc_2)
    assert kline_manager.kline != rc_1

    # don't trigger a new candle
    first_kline = [0] * len(PriceIndexes)
    first_kline[PriceIndexes.IND_PRICE_CLOSE.value] = 0
    first_kline[PriceIndexes.IND_PRICE_OPEN.value] = 0
    first_kline[PriceIndexes.IND_PRICE_HIGH.value] = 0
    first_kline[PriceIndexes.IND_PRICE_LOW.value] = 0
    first_kline[PriceIndexes.IND_PRICE_VOL.value] = 0
    first_kline[PriceIndexes.IND_PRICE_TIME.value] = rc_2[
        PriceIndexes.IND_PRICE_TIME.value]
    assert kline_manager.kline == first_kline

    # shouldn't use new low
    rc_3 = rc_2
    rc_3[PriceIndexes.IND_PRICE_LOW.value] = random_price(1)
    kline_manager.kline_update(rc_3)
    assert kline_manager.kline == first_kline

    # should use new low
    rc_4 = rc_3
    new_high = random_price(10)
    rc_4[PriceIndexes.IND_PRICE_HIGH.value] = new_high
    kline_manager.kline_update(rc_4)
    second_kline = first_kline
    second_kline[PriceIndexes.IND_PRICE_HIGH.value] = new_high
    assert kline_manager.kline == second_kline

    # shouldn't use new low
    rc_5 = rc_4
    rc_5[PriceIndexes.IND_PRICE_HIGH.value] = new_high - 1
    kline_manager.kline_update(rc_5)
    assert kline_manager.kline == second_kline

    # should use new low
    rc_6 = rc_5
    rc_6[PriceIndexes.IND_PRICE_HIGH.value] = new_high + 1
    third_kline = second_kline
    third_kline[PriceIndexes.IND_PRICE_HIGH.value] = new_high + 1
    kline_manager.kline_update(rc_6)
    assert kline_manager.kline == third_kline

    # should use new vol
    rc_7 = rc_6
    new_vol = random_quantity()
    rc_7[PriceIndexes.IND_PRICE_VOL.value] = new_vol
    kline_4 = third_kline
    kline_4[PriceIndexes.IND_PRICE_VOL.value] = new_vol
    kline_manager.kline_update(rc_7)
    assert kline_manager.kline == kline_4

    # should use new close
    rc_8 = rc_7
    new_price = random_price()
    rc_8[PriceIndexes.IND_PRICE_CLOSE.value] = new_price
    kline_5 = kline_4
    kline_5[PriceIndexes.IND_PRICE_CLOSE.value] = new_price
    kline_manager.kline_update(rc_8)
    assert kline_manager.kline == kline_5

    # shouldn't use new open
    rc_9 = rc_8
    new_open = random_price()
    rc_9[PriceIndexes.IND_PRICE_OPEN.value] = new_open
    kline_manager.kline_update(rc_9)
    assert kline_manager.kline == kline_5
コード例 #18
0
async def test_get_current_crypto_currencies_values(backtesting_trader):
    config, exchange_manager, trader = backtesting_trader
    portfolio_manager = exchange_manager.exchange_personal_data.portfolio_manager
    portfolio_value_holder = portfolio_manager.portfolio_value_holder

    assert portfolio_value_holder.get_current_crypto_currencies_values() == {
        'BTC': 1,
        'USDT': 0
    }
    update_portfolio_balance(
        {
            'BTC': {
                'available': random_quantity(),
                'total': random_quantity()
            },
            'ETH': {
                'available': random_quantity(),
                'total': random_quantity()
            },
            'XRP': {
                'available': random_quantity(),
                'total': random_quantity()
            },
            'NANO': {
                'available': random_quantity(),
                'total': random_quantity()
            },
            'XLM': {
                'available': random_quantity(),
                'total': random_quantity()
            },
            'USDT': {
                'available': random_quantity(),
                'total': random_quantity()
            }
        }, exchange_manager)
    await portfolio_manager.handle_balance_updated()

    assert portfolio_value_holder.get_current_crypto_currencies_values() == {
        'BTC': 1,
        'ETH': 0,
        'XRP': 0,
        'NANO': 0,
        'XLM': 0,
        'USDT': 0
    }

    exchange_manager.client_symbols.append("XLM/BTC")
    exchange_manager.client_symbols.append("XRP/BTC")
    if not os.getenv('CYTHON_IGNORE'):
        portfolio_value_holder.missing_currency_data_in_exchange.remove("XRP")
        await portfolio_manager.handle_mark_price_update("XRP/BTC", 0.005)
        exchange_manager.client_symbols.append("NANO/BTC")
        portfolio_value_holder.missing_currency_data_in_exchange.remove("NANO")
        await portfolio_manager.handle_mark_price_update("NANO/BTC", 0.05)
        exchange_manager.client_symbols.append("BTC/USDT")

        assert portfolio_value_holder.get_current_crypto_currencies_values(
        ) == {
            'BTC': 1,
            'ETH': 0,
            'XRP': 0.005,
            'NANO': 0.05,
            'XLM': 0,
            'USDT': 0
        }
        xlm_btc_price = random_price(max_value=0.05)
        portfolio_value_holder.missing_currency_data_in_exchange.remove("XLM")
        await portfolio_manager.handle_mark_price_update(
            "XLM/BTC", xlm_btc_price)
        assert portfolio_value_holder.get_current_crypto_currencies_values(
        ) == {
            'BTC': 1,
            'ETH': 0,
            'XRP': 0.005,
            'NANO': 0.05,
            'XLM': xlm_btc_price,
            'USDT': 0
        }
        usdt_btc_price = random_price(max_value=0.01)
        portfolio_value_holder.missing_currency_data_in_exchange.remove("USDT")
        await portfolio_manager.handle_mark_price_update(
            "BTC/USDT", usdt_btc_price)
        assert portfolio_value_holder.get_current_crypto_currencies_values(
        ) == {
            'BTC': 1,
            'ETH': 0,
            'XRP': 0.005,
            'NANO': 0.05,
            'XLM': xlm_btc_price,
            'USDT': 1 / usdt_btc_price
        }
        eth_btc_price = random_price(max_value=1)
        exchange_manager.client_symbols.append("ETH/BTC")
        portfolio_value_holder.missing_currency_data_in_exchange.remove("ETH")
        await portfolio_manager.handle_mark_price_update(
            "ETH/BTC", eth_btc_price)
        assert portfolio_value_holder.get_current_crypto_currencies_values(
        ) == {
            'BTC': 1,
            'ETH': eth_btc_price,
            'XRP': 0.005,
            'NANO': 0.05,
            'XLM': xlm_btc_price,
            'USDT': 1 / usdt_btc_price
        }