async def test_handle_price(price_events_manager):
    random_price_1 = decimal_random_price()
    random_timestamp_1 = random_timestamp(min_value=2, max_value=1000)
    price_event_1 = price_events_manager.add_event(
        decimal.Decimal(str(random_price_1)), random_timestamp_1, True)
    with patch.object(price_event_1, 'set', new=Mock()) as price_event_1_set:
        price_events_manager.handle_price(trading_constants.ZERO,
                                          random_timestamp())
        with pytest.raises(AssertionError):
            price_event_1_set.assert_called_once()
        price_events_manager.handle_price(price=decimal_random_price(
            max_value=random_price_1 - trading_constants.ONE),
                                          timestamp=random_timestamp())
        with pytest.raises(AssertionError):
            price_event_1_set.assert_called_once()
        price_events_manager.handle_price(price=decimal_random_price(
            max_value=random_price_1 - trading_constants.ONE),
                                          timestamp=random_timestamp())
        price_events_manager.handle_price(
            price=decimal_random_price(min_value=random_price_1),
            timestamp=random_timestamp_1 - 1)
        with pytest.raises(AssertionError):
            price_event_1_set.assert_called_once()
        price_events_manager.handle_price(
            price=decimal_random_price(min_value=random_price_1),
            timestamp=random_timestamp_1 + 1)
        price_event_1_set.assert_called_once()
async def test_handle_recent_trades(price_events_manager):
    random_price_1 = random_price(min_value=2)
    random_timestamp_1 = random_timestamp(min_value=2, max_value=1000)
    price_event_1 = price_events_manager.add_event(random_price_1,
                                                   random_timestamp_1, True)
    with patch.object(price_event_1, 'set', new=Mock()) as price_event_1_set:
        price_events_manager.handle_recent_trades([])
        with pytest.raises(AssertionError):
            price_event_1_set.assert_called_once()
        price_events_manager.handle_recent_trades([
            random_recent_trade(
                price=random_price(max_value=random_price_1 - 1),
                timestamp=random_timestamp(max_value=random_timestamp_1 - 1)),
            random_recent_trade(
                price=random_price(max_value=random_price_1 - 1),
                timestamp=random_timestamp(max_value=random_timestamp_1 - 1)),
            random_recent_trade(
                price=random_price(max_value=random_price_1 - 1),
                timestamp=random_timestamp(max_value=random_timestamp_1 - 1))
        ])
        with pytest.raises(AssertionError):
            price_event_1_set.assert_called_once()
        price_events_manager.handle_recent_trades([
            random_recent_trade(price=random_price(max_value=random_price_1 -
                                                   1)),
            random_recent_trade(price=random_price_1,
                                timestamp=random_timestamp_1),
            random_recent_trade(price=random_price(max_value=random_price_1 -
                                                   1)),
            random_recent_trade(price=random_price(max_value=random_price_1 -
                                                   1))
        ])
        price_event_1_set.assert_called_once()
async def test_add_event(price_events_manager):
    price_events_manager.add_event(decimal_random_price(), random_timestamp(),
                                   True)
    price_events_manager.add_event(decimal_random_price(), random_timestamp(),
                                   False)
    if not os.getenv('CYTHON_IGNORE'):
        assert price_events_manager.events
        assert len(price_events_manager.events) == 2
async def test_reset_funding(funding_manager):
    funding_manager.next_update = random_timestamp()
    funding_manager.last_updated = random_timestamp()
    funding_manager.funding_rate = random_funding_rate()
    funding_manager.predicted_funding_rate = random_funding_rate()
    funding_manager.reset_funding()
    assert funding_manager.next_update == 0
    assert funding_manager.last_updated == 0
    assert funding_manager.funding_rate == constants.ZERO
    assert funding_manager.predicted_funding_rate == constants.ZERO
async def test_funding_update(funding_manager):
    last_updated = random_timestamp()
    next_updated = random_timestamp(last_updated)
    funding_rate = random_funding_rate()
    predicted_funding_rate = random_funding_rate()
    funding_manager.funding_update(funding_rate, predicted_funding_rate,
                                   next_updated, last_updated)
    assert funding_manager.next_update == next_updated
    assert funding_manager.last_updated == last_updated
    assert funding_manager.funding_rate == funding_rate
    assert funding_manager.predicted_funding_rate == predicted_funding_rate
async def test_remove_event(price_events_manager):
    event_1 = price_events_manager.add_event(decimal_random_price(),
                                             random_timestamp(), True)
    event_2 = price_events_manager.add_event(decimal_random_price(),
                                             random_timestamp(), False)
    if not os.getenv('CYTHON_IGNORE'):
        assert price_events_manager.events
        price_events_manager.remove_event(event_1)
        assert event_1 not in price_events_manager.events
        assert len(price_events_manager.events) == 1
        price_events_manager.remove_event(Event())
        assert len(price_events_manager.events) == 1
        price_events_manager.remove_event(event_2)
        assert event_2 not in price_events_manager.events
        assert len(price_events_manager.events) == 0
async def test_handle_new_book(order_book_manager):
    """
    Handle ccxt request
    {
    'bids': [
        [ price, amount ], // [ float, float ]
        [ price, amount ],
        ...
    ],
    'asks': [
        [ price, amount ],
        [ price, amount ],
        ...
    ],
    'timestamp': 1499280391811, // Unix Timestamp in milliseconds (seconds * 1000)
    'datetime': '2017-07-05T18:47:14.692Z', // ISO8601 datetime string with milliseconds
    'nonce': 1499280391811, // an increasing unique identifier of the orderbook snapshot
    }
    """
    ts = random_timestamp()
    asks = random_order_book_side(count=100)
    bids = random_order_book_side(count=100)
    order_book_manager.handle_new_book({
        ECOBIC.ASKS.value: asks,
        ECOBIC.BIDS.value: bids,
        ECOBIC.TIMESTAMP.value: ts
    })
    assert order_book_manager.timestamp == ts
    assert order_book_manager.get_ask()
    assert order_book_manager.get_bid()
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
        }
async def test_handle_new_books(order_book_manager):
    ts = random_timestamp()
    asks = random_order_book_side(count=100)
    bids = random_order_book_side(count=100)
    order_book_manager.handle_new_books(asks, bids, timestamp=ts)
    assert order_book_manager.order_book_initialized
    assert order_book_manager.timestamp == ts
    assert order_book_manager.get_ask()
    assert order_book_manager.get_bid()
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
        }
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
async def test_handle_recent_trades_multiple_events(price_events_manager):
    random_price_1 = decimal_random_price(min_value=decimal.Decimal(2))
    random_price_2 = decimal_random_price(min_value=random_price_1)
    random_timestamp_1 = random_timestamp(min_value=2, max_value=1000)
    random_timestamp_2 = random_timestamp(min_value=random_timestamp_1 + 2,
                                          max_value=5000)
    price_event_1 = price_events_manager.add_event(random_price_1,
                                                   random_timestamp_1, True)
    price_event_2 = price_events_manager.add_event(random_price_2,
                                                   random_timestamp_2, True)
    with patch.object(price_event_1, 'set', new=Mock()) as price_event_1_set, \
            patch.object(price_event_2, 'set', new=Mock()) as price_event_2_set:
        price_events_manager.handle_recent_trades([
            decimal_random_recent_trade(price=decimal_random_price(
                max_value=random_price_1 - trading_constants.ONE)),
            decimal_random_recent_trade(price=decimal_random_price(
                max_value=random_price_1 - trading_constants.ONE)),
            decimal_random_recent_trade(price=decimal_random_price(
                max_value=random_price_1 - trading_constants.ONE))
        ])
        with pytest.raises(AssertionError):
            price_event_1_set.assert_called_once()
        with pytest.raises(AssertionError):
            price_event_2_set.assert_called_once()
        price_events_manager.handle_recent_trades([
            decimal_random_recent_trade(
                price=decimal_random_price(max_value=random_price_1 -
                                           trading_constants.ONE),
                timestamp=random_timestamp(max_value=random_timestamp_1 - 1)),
            decimal_random_recent_trade(
                price=random_price_2 - trading_constants.ONE,
                timestamp=random_timestamp(min_value=random_timestamp_1,
                                           max_value=random_timestamp_2))
        ])
        price_event_1_set.assert_called_once()
        with pytest.raises(AssertionError):
            price_event_2_set.assert_called_once()
        price_events_manager.handle_recent_trades([
            decimal_random_recent_trade(price=decimal_random_price(
                max_value=random_price_1 - trading_constants.ONE)),
            decimal_random_recent_trade(price=random_price_2,
                                        timestamp=random_timestamp_2)
        ])
        price_event_2_set.assert_called_once()

    price_event_1 = price_events_manager.add_event(random_price_1,
                                                   random_timestamp_1, True)
    price_event_2 = price_events_manager.add_event(random_price_2,
                                                   random_timestamp_2, True)
    with patch.object(price_event_1, 'set', new=Mock()) as price_event_1_set, \
            patch.object(price_event_2, 'set', new=Mock()) as price_event_2_set:
        price_events_manager.handle_recent_trades([
            decimal_random_recent_trade(
                price=decimal_random_price(max_value=random_price_1 -
                                           trading_constants.ONE),
                timestamp=random_timestamp(max_value=random_timestamp_1 - 1)),
            decimal_random_recent_trade(
                price=random_price_2 + decimal.Decimal(10),
                timestamp=random_timestamp(min_value=random_timestamp_2 + 1))
        ])
        price_event_1_set.assert_called_once()
        price_event_2_set.assert_called_once()

    price_event_1 = price_events_manager.add_event(random_price_1,
                                                   random_timestamp_1, True)
    price_event_2 = price_events_manager.add_event(random_price_2,
                                                   random_timestamp_2, True)
    with patch.object(price_event_1, 'set', new=Mock()) as price_event_1_set, \
            patch.object(price_event_2, 'set', new=Mock()) as price_event_2_set:
        price_events_manager.handle_recent_trades([
            decimal_random_recent_trade(
                price=decimal_random_price(min_value=random_price_1,
                                           max_value=random_price_2 -
                                           trading_constants.ONE),
                timestamp=random_timestamp(min_value=random_timestamp_1 - 1)),
            decimal_random_recent_trade(
                price=random_price_2,
                timestamp=random_timestamp(max_value=random_timestamp_2 - 1))
        ])
        price_event_1_set.assert_called_once()
        with pytest.raises(AssertionError):
            price_event_2_set.assert_called_once()