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()
async def test_handle_price(price_events_manager): random_price_1 = random_price() 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_price(0, random_timestamp()) with pytest.raises(AssertionError): price_event_1_set.assert_called_once() price_events_manager.handle_price( price=random_price(max_value=random_price_1 - 1), timestamp=random_timestamp()) with pytest.raises(AssertionError): price_event_1_set.assert_called_once() price_events_manager.handle_price( price=random_price(max_value=random_price_1 - 1), timestamp=random_timestamp()) price_events_manager.handle_price( price=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=random_price(min_value=random_price_1), timestamp=random_timestamp_1 + 1) price_event_1_set.assert_called_once()
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()
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()
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()
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_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()
async def test_reset(order_book_manager): order_book_manager.bids = random_price_list(10) order_book_manager.bid_price = random_price() order_book_manager.bid_quantity = random_price() order_book_manager.reset_order_book() assert order_book_manager.bids == [] assert order_book_manager.bid_quantity == 0 assert order_book_manager.bid_price == 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
async def test_remove_event(price_events_manager): event_1 = price_events_manager.add_event(random_price(), random_timestamp(), True) event_2 = price_events_manager.add_event(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_trailing_stop_with_new_price_inversed(trailing_stop_order): trailing_stop_order, order_price, price_events_manager = await initialize_trailing_stop( trailing_stop_order, side=TradeOrderSide.BUY) await trailing_stop_order.set_trailing_percent(5) new_trailing_price = random_price(min_value=order_price * 0.99, max_value=order_price * 1.01) # set mark price set_mark_price(trailing_stop_order, new_trailing_price) # move trailing price price_events_manager.handle_recent_trades([ random_recent_trade(price=new_trailing_price, timestamp=trailing_stop_order.timestamp) ]) await wait_asyncio_next_cycle() assert not trailing_stop_order.is_filled() # test fill stop loss with new order price reference price_events_manager.handle_recent_trades([ random_recent_trade(price=get_price_percent( new_trailing_price, trailing_stop_order.trailing_percent, selling_side=False), timestamp=trailing_stop_order.timestamp) ]) await wait_asyncio_next_cycle() assert trailing_stop_order.is_filled()
async def test_trailing_stop_with_new_price(trailing_stop_order): trailing_stop_order, order_price, price_events_manager = await initialize_trailing_stop( trailing_stop_order) await trailing_stop_order.set_trailing_percent(2) new_trailing_price = random_price(min_value=order_price + 1) # set mark price set_mark_price(trailing_stop_order, new_trailing_price) # move trailing price price_events_manager.handle_recent_trades([ random_recent_trade(price=new_trailing_price, timestamp=trailing_stop_order.timestamp) ]) await wait_asyncio_next_cycle() assert not trailing_stop_order.is_filled() # test fill stop loss with new order price reference price_events_manager.handle_recent_trades([ random_recent_trade(price=get_price_percent( new_trailing_price, trailing_stop_order.trailing_percent), timestamp=trailing_stop_order.timestamp) ]) await wait_asyncio_next_cycle() assert trailing_stop_order.is_filled()
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()
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 }
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()
async def test_limit_and_stop_loss(stop_loss_sell_order, sell_limit_order): # fill both orders: limit first limit_order_price = decimal_random_price() quantity = decimal_random_quantity(max_value=DEFAULT_SYMBOL_QUANTITY) sell_limit_order.update( price=limit_order_price, quantity=quantity, symbol=DEFAULT_ORDER_SYMBOL, order_type=TraderOrderType.SELL_LIMIT, ) stop_order_price = decimal_random_price(max_value=limit_order_price - 1) stop_loss_sell_order.update(price=stop_order_price, quantity=quantity, symbol=DEFAULT_ORDER_SYMBOL, 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_ORDER_SYMBOL).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=float(stop_order_price - 1)), timestamp=sell_limit_order.timestamp), random_recent_trade( price=random_price(min_value=float(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()
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
async def test_get_mark_price(prices_manager): # without a set price with pytest.raises(asyncio.TimeoutError): await prices_manager.get_mark_price(0.01) assert not prices_manager.valid_price_received_event.is_set() # set price prices_manager.set_mark_price(10, MarkPriceSources.EXCHANGE_MARK_PRICE.value) assert await prices_manager.get_mark_price(0.01) == 10 assert prices_manager.valid_price_received_event.is_set() # expired price if not os.getenv('CYTHON_IGNORE'): prices_manager.exchange_manager.backtesting.time_manager.current_timestamp = 66666666 with pytest.raises(asyncio.TimeoutError): await prices_manager.get_mark_price(0.01) assert not prices_manager.valid_price_received_event.is_set() # reset price with this time prices_manager.set_mark_price(10, MarkPriceSources.EXCHANGE_MARK_PRICE.value) assert await prices_manager.get_mark_price(0.01) == 10 assert prices_manager.valid_price_received_event.is_set() # current time move within allowed range if not os.getenv('CYTHON_IGNORE'): prices_manager.exchange_manager.backtesting.time_manager.current_timestamp = 1 assert await prices_manager.get_mark_price(0.01) == 10 assert prices_manager.valid_price_received_event.is_set() # new value prices_manager.set_mark_price(42.0000172, MarkPriceSources.EXCHANGE_MARK_PRICE.value) assert await prices_manager.get_mark_price(0.01) == 42.0000172 assert prices_manager.valid_price_received_event.is_set() # random value random_mark_price = random_price() prices_manager.set_mark_price(random_mark_price, MarkPriceSources.EXCHANGE_MARK_PRICE.value) assert await prices_manager.get_mark_price(0.01) == random_mark_price assert prices_manager.valid_price_received_event.is_set()
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
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_trailing_stop_trigger(trailing_stop_order): trailing_stop_order, order_price, price_events_manager = await initialize_trailing_stop( trailing_stop_order) await trailing_stop_order.set_trailing_percent(10) max_trailing_hit_price = get_price_percent( order_price, trailing_stop_order.trailing_percent) # set mark price set_mark_price(trailing_stop_order, order_price) price_events_manager.handle_recent_trades([ random_recent_trade(price=random_price( min_value=max_trailing_hit_price, max_value=order_price - 1), timestamp=trailing_stop_order.timestamp) ]) await wait_asyncio_next_cycle() assert not trailing_stop_order.is_filled() price_events_manager.handle_recent_trades([ random_recent_trade(price=order_price, timestamp=trailing_stop_order.timestamp - 1) ]) await wait_asyncio_next_cycle() assert not trailing_stop_order.is_filled() price_events_manager.handle_recent_trades([ random_recent_trade(price=order_price, timestamp=trailing_stop_order.timestamp) ]) await wait_asyncio_next_cycle() assert not trailing_stop_order.is_filled() price_events_manager.handle_recent_trades([ random_recent_trade(price=max_trailing_hit_price, timestamp=trailing_stop_order.timestamp) ]) await wait_asyncio_next_cycle() assert trailing_stop_order.is_filled()
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 }
async def test_handle_recent_trades_multiple_events(price_events_manager): random_price_1 = random_price(min_value=2) random_price_2 = 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([ random_recent_trade(price=random_price(max_value=random_price_1 - 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)) ]) 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([ 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_2 - 1, 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([ random_recent_trade(price=random_price(max_value=random_price_1 - 1)), 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([ 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_2 + 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([ random_recent_trade( price=random_price(min_value=random_price_1, max_value=random_price_2 - 1), timestamp=random_timestamp(min_value=random_timestamp_1 - 1)), 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()
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_add_event(price_events_manager): price_events_manager.add_event(random_price(), random_timestamp(), True) price_events_manager.add_event(random_price(), random_timestamp(), False) if not os.getenv('CYTHON_IGNORE'): assert price_events_manager.events assert len(price_events_manager.events) == 2