async def test_sell_limit_order_trigger(sell_limit_order): order_price = random_price(min_value=1) sell_limit_order.update( price=order_price, quantity=random_quantity(), symbol=DEFAULT_SYMBOL_ORDER, order_type=TraderOrderType.SELL_LIMIT, ) sell_limit_order.exchange_manager.is_backtesting = True # force update_order_status await sell_limit_order.initialize() sell_limit_order.exchange_manager.exchange_personal_data.orders_manager.upsert_order_instance( sell_limit_order) price_events_manager = sell_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(max_value=order_price - 1), timestamp=sell_limit_order.timestamp) ]) await wait_asyncio_next_cycle() assert not sell_limit_order.is_filled() price_events_manager.handle_recent_trades([ random_recent_trade(price=order_price, timestamp=sell_limit_order.timestamp - 1) ]) await wait_asyncio_next_cycle() assert not sell_limit_order.is_filled() price_events_manager.handle_recent_trades([ random_recent_trade(price=order_price, timestamp=sell_limit_order.timestamp) ]) await wait_asyncio_next_cycle() assert sell_limit_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_stop_loss_buy_order_trigger(stop_loss_buy_order): order_price = random_price() stop_loss_buy_order.update( price=order_price, quantity=random_quantity(), symbol=DEFAULT_SYMBOL_ORDER, 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_SYMBOL_ORDER).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_take_profit_buy_order_trigger(take_profit_buy_order): order_price = random_price() take_profit_buy_order.update( price=order_price, quantity=random_quantity(), symbol=DEFAULT_SYMBOL_ORDER, order_type=TraderOrderType.TAKE_PROFIT, ) take_profit_buy_order.exchange_manager.is_backtesting = True # force update_order_status await take_profit_buy_order.initialize() take_profit_buy_order.exchange_manager.exchange_personal_data.orders_manager.upsert_order_instance( take_profit_buy_order ) price_events_manager = take_profit_buy_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=take_profit_buy_order.timestamp)]) await wait_asyncio_next_cycle() assert not take_profit_buy_order.is_filled() price_events_manager.handle_recent_trades( [random_recent_trade(price=order_price, timestamp=take_profit_buy_order.timestamp - 1)]) await wait_asyncio_next_cycle() assert not take_profit_buy_order.is_filled() price_events_manager.handle_recent_trades([random_recent_trade(price=order_price, timestamp=take_profit_buy_order.timestamp)]) # wait for 2 cycles as secondary orders are created await wait_asyncio_next_cycle() await wait_asyncio_next_cycle() assert take_profit_buy_order.is_filled()
async def test_set_all_recent_trades(recent_trades_manager): # if setting no new trades recent_trades_manager.set_all_recent_trades([]) assert not recent_trades_manager.recent_trades recent_trades_manager.set_all_recent_trades(None) assert not recent_trades_manager.recent_trades # test removing all previous values recent_trades_manager.recent_trades.append(1) assert 1 in recent_trades_manager.recent_trades trades = random_recent_trades() recent_trades_manager.set_all_recent_trades(trades) assert trades[-1] in recent_trades_manager.recent_trades assert 1 not in recent_trades_manager.recent_trades # test set values recent_trade_1 = random_recent_trade() recent_trade_2 = random_recent_trade() recent_trade_3 = random_recent_trade() trades = [recent_trade_3, recent_trade_2, recent_trade_1] recent_trades_manager.set_all_recent_trades(trades) assert recent_trade_1 in recent_trades_manager.recent_trades assert recent_trade_2 in recent_trades_manager.recent_trades assert recent_trades_manager.recent_trades[-1] == recent_trade_1 assert recent_trades_manager.recent_trades[-2] == recent_trade_2 assert recent_trades_manager.recent_trades[-3] == recent_trade_3
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_new_trades(recent_trades_manager): # if adding no new trades recent_trades_manager.add_new_trades([]) assert not recent_trades_manager.recent_trades recent_trades_manager.add_new_trades(None) assert not recent_trades_manager.recent_trades # test set values recent_trade_1 = random_recent_trade() recent_trade_2 = random_recent_trade() recent_trade_3 = random_recent_trade() recent_trade_4 = random_recent_trade() recent_trade_5 = random_recent_trade() trades = [recent_trade_1, recent_trade_2] recent_trades_manager.add_new_trades(trades) assert recent_trade_1 in recent_trades_manager.recent_trades assert recent_trade_2 in recent_trades_manager.recent_trades assert recent_trades_manager.recent_trades[0] == recent_trade_1 assert recent_trades_manager.recent_trades[1] == recent_trade_2 with pytest.raises(IndexError): recent_trades_manager.recent_trades[2] # test add duplicate trades = [recent_trade_2, recent_trade_3, recent_trade_4] recent_trades_manager.add_new_trades(trades) assert recent_trades_manager.recent_trades[0] == recent_trade_1 assert recent_trades_manager.recent_trades[1] == recent_trade_2 assert recent_trades_manager.recent_trades[2] == recent_trade_3 assert recent_trades_manager.recent_trades[3] == recent_trade_4 with pytest.raises(IndexError): recent_trades_manager.recent_trades[4] trades = [recent_trade_2, recent_trade_5] recent_trades_manager.add_new_trades(trades) assert recent_trades_manager.recent_trades[0] == recent_trade_1 assert recent_trades_manager.recent_trades[1] == recent_trade_2 assert recent_trades_manager.recent_trades[2] == recent_trade_3 assert recent_trades_manager.recent_trades[3] == recent_trade_4 assert recent_trades_manager.recent_trades[4] == recent_trade_5
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()
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_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() buy_market_order.exchange_manager.exchange_personal_data.orders_manager.upsert_order_instance( buy_market_order ) price_events_manager = buy_market_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(), timestamp=buy_market_order.timestamp)]) await wait_asyncio_next_cycle() assert buy_market_order.is_filled()