class TestOrders: def setup(self): # Fixture Setup self.trader_id = TestStubs.trader_id() self.strategy_id = TestStubs.strategy_id() self.account_id = TestStubs.account_id() self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=self.strategy_id, clock=TestClock(), ) def test_opposite_side_given_invalid_value_raises_value_error(self): # Arrange, Act, Assert with pytest.raises(ValueError): Order.opposite_side(0) # <-- invalid value def test_flatten_side_given_invalid_value_or_flat_raises_value_error(self): # Arrange, Act with pytest.raises(ValueError): Order.flatten_side(0) # <-- invalid value with pytest.raises(ValueError): Order.flatten_side(PositionSide.FLAT) @pytest.mark.parametrize( "side, expected", [ [OrderSide.BUY, OrderSide.SELL], [OrderSide.SELL, OrderSide.BUY], ], ) def test_opposite_side_returns_expected_sides(self, side, expected): # Arrange, Act result = Order.opposite_side(side) # Assert assert result == expected @pytest.mark.parametrize( "side, expected", [ [PositionSide.LONG, OrderSide.SELL], [PositionSide.SHORT, OrderSide.BUY], ], ) def test_flatten_side_returns_expected_sides(self, side, expected): # Arrange, Act result = Order.flatten_side(side) # Assert assert result == expected def test_market_order_with_quantity_zero_raises_value_error(self): # Arrange, Act, Assert with pytest.raises(ValueError): MarketOrder( self.trader_id, self.strategy_id, AUDUSD_SIM.id, ClientOrderId("O-123456"), OrderSide.BUY, Quantity.zero(), TimeInForce.DAY, UUID4(), 0, ) def test_market_order_with_invalid_tif_raises_value_error(self): # Arrange, Act, Assert with pytest.raises(ValueError): MarketOrder( self.trader_id, self.strategy_id, AUDUSD_SIM.id, ClientOrderId("O-123456"), OrderSide.BUY, Quantity.zero(), TimeInForce.GTD, # <-- invalid UUID4(), 0, ) def test_stop_market_order_with_gtd_and_expire_time_none_raises_type_error( self): # Arrange, Act, Assert with pytest.raises(TypeError): StopMarketOrder( self.trader_id, self.strategy_id, AUDUSD_SIM.id, ClientOrderId("O-123456"), OrderSide.BUY, Quantity.from_int(100000), price=Price.from_str("1.00000"), init_id=UUID4(), ts_init=0, time_in_force=TimeInForce.GTD, expire_time=None, ) def test_stop_limit_buy_order_with_gtd_and_expire_time_none_raises_type_error( self): # Arrange, Act, Assert with pytest.raises(TypeError): StopLimitOrder( self.trader_id, self.strategy_id, AUDUSD_SIM.id, ClientOrderId("O-123456"), OrderSide.BUY, Quantity.from_int(100000), price=Price.from_str("1.00001"), trigger=Price.from_str("1.00000"), init_id=UUID4(), ts_init=0, time_in_force=TimeInForce.GTD, expire_time=None, ) def test_overfill_limit_buy_order_raises_value_error(self): # Arrange, Act, Assert order = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) over_fill = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, last_qty=Quantity.from_int(110000) # <-- overfill ) # Assert with pytest.raises(ValueError): order.apply(over_fill) def test_reset_order_factory(self): # Arrange self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) # Act self.order_factory.reset() order2 = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) assert order2.client_order_id.value == "O-19700101-000000-000-001-1" def test_initialize_buy_market_order(self): # Arrange, Act order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) # Assert assert order.symbol == AUDUSD_SIM.id.symbol assert order.venue == AUDUSD_SIM.id.venue assert order.type == OrderType.MARKET assert order.status == OrderStatus.INITIALIZED assert order.event_count == 1 assert isinstance(order.last_event, OrderInitialized) assert order.is_active assert not order.is_inflight assert not order.is_working assert not order.is_completed assert order.is_buy assert order.is_aggressive assert not order.is_sell assert not order.is_contingency assert not order.is_passive assert not order.is_parent_order assert not order.is_child_order assert order.ts_last == 0 assert order.last_event.ts_init == 0 assert isinstance(order.init_event, OrderInitialized) def test_initialize_sell_market_order(self): # Arrange, Act order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.SELL, Quantity.from_int(100000), ) # Assert assert order.type == OrderType.MARKET assert order.status == OrderStatus.INITIALIZED assert order.event_count == 1 assert isinstance(order.last_event, OrderInitialized) assert len(order.events) == 1 assert order.is_active assert not order.is_inflight assert not order.is_working assert not order.is_completed assert not order.is_buy assert order.is_sell assert order.ts_last == 0 assert isinstance(order.init_event, OrderInitialized) def test_order_equality(self): # Arrange, Act order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) # Assert assert order == order def test_order_hash_str_and_repr(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), tags="ENTRY", ) # Act, Assert assert isinstance(hash(order), int) assert ( str(order) == "MarketOrder(BUY 100_000 AUD/USD.SIM MARKET GTC, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-1, venue_order_id=None, tags=ENTRY)" # noqa ) assert ( repr(order) == "MarketOrder(BUY 100_000 AUD/USD.SIM MARKET GTC, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-1, venue_order_id=None, tags=ENTRY)" # noqa ) def test_market_order_to_dict(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) # Act result = order.to_dict() # Assert assert result == { "trader_id": "TESTER-000", "strategy_id": "S-001", "instrument_id": "AUD/USD.SIM", "client_order_id": "O-19700101-000000-000-001-1", "venue_order_id": None, "position_id": None, "account_id": None, "execution_id": None, "type": "MARKET", "side": "BUY", "quantity": "100000", "time_in_force": "GTC", "reduce_only": False, "filled_qty": "0", "avg_px": None, "slippage": "0", "status": "INITIALIZED", "order_list_id": None, "parent_order_id": None, "child_order_ids": None, "contingency": "NONE", "contingency_ids": None, "tags": None, "ts_last": 0, "ts_init": 0, } def test_initialize_limit_order(self): # Arrange, Act order = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) # Assert assert order.type == OrderType.LIMIT assert order.status == OrderStatus.INITIALIZED assert order.time_in_force == TimeInForce.GTC assert order.is_passive assert order.is_active assert not order.is_aggressive assert not order.is_completed assert isinstance(order.init_event, OrderInitialized) assert ( str(order) == "LimitOrder(BUY 100_000 AUD/USD.SIM LIMIT @ 1.00000 GTC, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-1, venue_order_id=None, tags=None)" # noqa ) assert ( repr(order) == "LimitOrder(BUY 100_000 AUD/USD.SIM LIMIT @ 1.00000 GTC, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-1, venue_order_id=None, tags=None)" # noqa ) def test_limit_order_to_dict(self): # Arrange order = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), display_qty=Quantity.from_int(20000), ) # Act result = order.to_dict() # Assert assert result == { "trader_id": "TESTER-000", "strategy_id": "S-001", "instrument_id": "AUD/USD.SIM", "client_order_id": "O-19700101-000000-000-001-1", "venue_order_id": None, "position_id": None, "account_id": None, "execution_id": None, "type": "LIMIT", "side": "BUY", "quantity": "100000", "price": "1.00000", "liquidity_side": "NONE", "expire_time_ns": 0, "time_in_force": "GTC", "filled_qty": "0", "avg_px": None, "slippage": "0", "status": "INITIALIZED", "is_post_only": False, "is_reduce_only": False, "display_qty": "20000", "order_list_id": None, "parent_order_id": None, "child_order_ids": None, "contingency": "NONE", "contingency_ids": None, "tags": None, "ts_last": 0, "ts_init": 0, } def test_initialize_limit_order_with_expire_time(self): # Arrange, Act order = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), TimeInForce.GTD, expire_time=UNIX_EPOCH, ) # Assert assert order.instrument_id == AUDUSD_SIM.id assert order.type == OrderType.LIMIT assert order.price == Price.from_str("1.00000") assert order.status == OrderStatus.INITIALIZED assert order.time_in_force == TimeInForce.GTD assert order.expire_time == UNIX_EPOCH assert not order.is_completed assert isinstance(order.init_event, OrderInitialized) def test_initialize_stop_market_order(self): # Arrange, Act order = self.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) # Assert assert order.type == OrderType.STOP_MARKET assert order.status == OrderStatus.INITIALIZED assert order.time_in_force == TimeInForce.GTC assert order.is_passive assert not order.is_aggressive assert order.is_active assert not order.is_completed assert isinstance(order.init_event, OrderInitialized) assert ( str(order) == "StopMarketOrder(BUY 100_000 AUD/USD.SIM STOP_MARKET @ 1.00000 GTC, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-1, venue_order_id=None, tags=None)" # noqa ) assert ( repr(order) == "StopMarketOrder(BUY 100_000 AUD/USD.SIM STOP_MARKET @ 1.00000 GTC, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-1, venue_order_id=None, tags=None)" # noqa ) def test_stop_market_order_to_dict(self): # Arrange order = self.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) # Act result = order.to_dict() # Assert assert result == { "trader_id": "TESTER-000", "strategy_id": "S-001", "instrument_id": "AUD/USD.SIM", "client_order_id": "O-19700101-000000-000-001-1", "venue_order_id": None, "position_id": None, "account_id": None, "execution_id": None, "type": "STOP_MARKET", "side": "BUY", "quantity": "100000", "price": "1.00000", "liquidity_side": "NONE", "expire_time_ns": 0, "time_in_force": "GTC", "filled_qty": "0", "avg_px": None, "slippage": "0", "status": "INITIALIZED", "is_reduce_only": False, "order_list_id": None, "parent_order_id": None, "child_order_ids": None, "contingency": "NONE", "contingency_ids": None, "tags": None, "ts_last": 0, "ts_init": 0, } def test_initialize_stop_limit_order(self): # Arrange, Act order = self.order_factory.stop_limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), Price.from_str("1.10010"), tags="ENTRY", ) # Assert assert order.type == OrderType.STOP_LIMIT assert order.status == OrderStatus.INITIALIZED assert order.time_in_force == TimeInForce.GTC assert order.is_passive assert not order.is_aggressive assert not order.is_completed assert isinstance(order.init_event, OrderInitialized) assert ( str(order) == "StopLimitOrder(BUY 100_000 AUD/USD.SIM STOP_LIMIT @ 1.00000 GTC, trigger=1.10010, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-1)" # noqa ) assert ( repr(order) == "StopLimitOrder(BUY 100_000 AUD/USD.SIM STOP_LIMIT @ 1.00000 GTC, trigger=1.10010, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-1)" # noqa ) def test_stop_limit_order_to_dict(self): # Arrange order = self.order_factory.stop_limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), Price.from_str("1.10010"), tags="STOP_LOSS", ) # Act result = order.to_dict() # Assert assert result == { "trader_id": "TESTER-000", "strategy_id": "S-001", "instrument_id": "AUD/USD.SIM", "client_order_id": "O-19700101-000000-000-001-1", "venue_order_id": None, "position_id": None, "account_id": None, "execution_id": None, "type": "STOP_LIMIT", "side": "BUY", "quantity": "100000", "trigger": "1.10010", "price": "1.00000", "liquidity_side": "NONE", "expire_time_ns": 0, "time_in_force": "GTC", "filled_qty": "0", "avg_px": None, "slippage": "0", "status": "INITIALIZED", "is_post_only": False, "is_reduce_only": False, "display_qty": None, "order_list_id": None, "parent_order_id": None, "child_order_ids": None, "contingency": "NONE", "contingency_ids": None, "tags": "STOP_LOSS", "ts_last": 0, "ts_init": 0, } def test_order_list_equality(self): # Arrange bracket1 = self.order_factory.bracket_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), Price.from_str("1.00010"), ) bracket2 = self.order_factory.bracket_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), Price.from_str("1.00010"), ) # Act, Assert assert bracket1 == bracket1 assert bracket1 != bracket2 def test_bracket_market_order_list(self): # Arrange, Act bracket = self.order_factory.bracket_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("0.99990"), Price.from_str("1.00010"), TimeInForce.GTC, ) # Assert assert bracket.id == OrderListId("1") assert bracket.instrument_id == AUDUSD_SIM.id assert len(bracket.orders) == 3 assert bracket.orders[0].type == OrderType.MARKET assert bracket.orders[1].type == OrderType.STOP_MARKET assert bracket.orders[2].type == OrderType.LIMIT assert bracket.orders[0].instrument_id == AUDUSD_SIM.id assert bracket.orders[1].instrument_id == AUDUSD_SIM.id assert bracket.orders[2].instrument_id == AUDUSD_SIM.id assert bracket.orders[0].client_order_id == ClientOrderId( "O-19700101-000000-000-001-1") assert bracket.orders[1].client_order_id == ClientOrderId( "O-19700101-000000-000-001-2") assert bracket.orders[2].client_order_id == ClientOrderId( "O-19700101-000000-000-001-3") assert bracket.orders[0].side == OrderSide.BUY assert bracket.orders[1].side == OrderSide.SELL assert bracket.orders[2].side == OrderSide.SELL assert bracket.orders[0].quantity == Quantity.from_int(100000) assert bracket.orders[1].quantity == Quantity.from_int(100000) assert bracket.orders[2].quantity == Quantity.from_int(100000) assert bracket.orders[1].price == Price.from_str("0.99990") assert bracket.orders[2].price == Price.from_str("1.00010") assert bracket.orders[1].time_in_force == TimeInForce.GTC assert bracket.orders[2].time_in_force == TimeInForce.GTC assert bracket.orders[1].expire_time is None assert bracket.orders[2].expire_time is None assert bracket.orders[0].contingency == ContingencyType.OTO assert bracket.orders[1].contingency == ContingencyType.OCO assert bracket.orders[2].contingency == ContingencyType.OCO assert bracket.orders[0].contingency_ids == [ ClientOrderId("O-19700101-000000-000-001-2"), ClientOrderId("O-19700101-000000-000-001-3"), ] assert bracket.orders[1].contingency_ids == [ ClientOrderId("O-19700101-000000-000-001-3") ] assert bracket.orders[2].contingency_ids == [ ClientOrderId("O-19700101-000000-000-001-2") ] assert bracket.orders[0].child_order_ids == [ ClientOrderId("O-19700101-000000-000-001-2"), ClientOrderId("O-19700101-000000-000-001-3"), ] assert bracket.orders[1].parent_order_id == ClientOrderId( "O-19700101-000000-000-001-1") assert bracket.orders[2].parent_order_id == ClientOrderId( "O-19700101-000000-000-001-1") assert bracket.ts_init == 0 def test_bracket_limit_order_list(self): # Arrange, Act bracket = self.order_factory.bracket_limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), Price.from_str("0.99990"), Price.from_str("1.00010"), TimeInForce.GTC, ) # Assert assert bracket.id == OrderListId("1") assert bracket.instrument_id == AUDUSD_SIM.id assert len(bracket.orders) == 3 assert bracket.orders[0].type == OrderType.LIMIT assert bracket.orders[1].type == OrderType.STOP_MARKET assert bracket.orders[2].type == OrderType.LIMIT assert bracket.orders[0].instrument_id == AUDUSD_SIM.id assert bracket.orders[1].instrument_id == AUDUSD_SIM.id assert bracket.orders[2].instrument_id == AUDUSD_SIM.id assert bracket.orders[0].client_order_id == ClientOrderId( "O-19700101-000000-000-001-1") assert bracket.orders[1].client_order_id == ClientOrderId( "O-19700101-000000-000-001-2") assert bracket.orders[2].client_order_id == ClientOrderId( "O-19700101-000000-000-001-3") assert bracket.orders[0].side == OrderSide.BUY assert bracket.orders[1].side == OrderSide.SELL assert bracket.orders[2].side == OrderSide.SELL assert bracket.orders[0].quantity == Quantity.from_int(100000) assert bracket.orders[1].quantity == Quantity.from_int(100000) assert bracket.orders[2].quantity == Quantity.from_int(100000) assert bracket.orders[1].price == Price.from_str("0.99990") assert bracket.orders[2].price == Price.from_str("1.00010") assert bracket.orders[1].time_in_force == TimeInForce.GTC assert bracket.orders[2].time_in_force == TimeInForce.GTC assert bracket.orders[1].expire_time is None assert bracket.orders[2].expire_time is None assert bracket.orders[0].contingency == ContingencyType.OTO assert bracket.orders[1].contingency == ContingencyType.OCO assert bracket.orders[2].contingency == ContingencyType.OCO assert bracket.orders[0].contingency_ids == [ ClientOrderId("O-19700101-000000-000-001-2"), ClientOrderId("O-19700101-000000-000-001-3"), ] assert bracket.orders[1].contingency_ids == [ ClientOrderId("O-19700101-000000-000-001-3") ] assert bracket.orders[2].contingency_ids == [ ClientOrderId("O-19700101-000000-000-001-2") ] assert bracket.orders[0].child_order_ids == [ ClientOrderId("O-19700101-000000-000-001-2"), ClientOrderId("O-19700101-000000-000-001-3"), ] assert bracket.orders[1].parent_order_id == ClientOrderId( "O-19700101-000000-000-001-1") assert bracket.orders[2].parent_order_id == ClientOrderId( "O-19700101-000000-000-001-1") assert bracket.ts_init == 0 def test_order_list_str_and_repr(self): # Arrange, Act bracket = self.order_factory.bracket_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("0.99990"), Price.from_str("1.00010"), ) # Assert assert str(bracket) == ( "OrderList(id=1, instrument_id=AUD/USD.SIM, orders=[MarketOrder(BUY 100_000 AUD/USD.SIM MARKET GTC, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-1, venue_order_id=None, tags=ENTRY), StopMarketOrder(SELL 100_000 AUD/USD.SIM STOP_MARKET @ 0.99990 GTC, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-2, venue_order_id=None, tags=STOP_LOSS), LimitOrder(SELL 100_000 AUD/USD.SIM LIMIT @ 1.00010 GTC, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-3, venue_order_id=None, tags=TAKE_PROFIT)])" # noqa ) assert repr(bracket) == ( "OrderList(id=1, instrument_id=AUD/USD.SIM, orders=[MarketOrder(BUY 100_000 AUD/USD.SIM MARKET GTC, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-1, venue_order_id=None, tags=ENTRY), StopMarketOrder(SELL 100_000 AUD/USD.SIM STOP_MARKET @ 0.99990 GTC, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-2, venue_order_id=None, tags=STOP_LOSS), LimitOrder(SELL 100_000 AUD/USD.SIM LIMIT @ 1.00010 GTC, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-3, venue_order_id=None, tags=TAKE_PROFIT)])" # noqa ) def test_apply_order_denied_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) denied = OrderDenied( self.trader_id, self.strategy_id, AUDUSD_SIM.id, order.client_order_id, "SOME_REASON", UUID4(), 0, ) # Act order.apply(denied) # Assert assert order.status == OrderStatus.DENIED assert order.event_count == 2 assert order.last_event == denied assert not order.is_active assert order.is_completed def test_apply_order_submitted_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) submitted = TestStubs.event_order_submitted(order) # Act order.apply(submitted) # Assert assert order.status == OrderStatus.SUBMITTED assert order.event_count == 2 assert order.last_event == submitted assert order.is_active assert order.is_inflight assert not order.is_working assert not order.is_completed assert not order.is_pending_update assert not order.is_pending_cancel def test_apply_order_accepted_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) order.apply(TestStubs.event_order_submitted(order)) # Act order.apply(TestStubs.event_order_accepted(order)) # Assert assert order.status == OrderStatus.ACCEPTED assert order.is_active assert not order.is_inflight assert order.is_working assert not order.is_completed assert ( str(order) == "MarketOrder(BUY 100_000 AUD/USD.SIM MARKET GTC, status=ACCEPTED, client_order_id=O-19700101-000000-000-001-1, venue_order_id=1, tags=None)" # noqa ) assert ( repr(order) == "MarketOrder(BUY 100_000 AUD/USD.SIM MARKET GTC, status=ACCEPTED, client_order_id=O-19700101-000000-000-001-1, venue_order_id=1, tags=None)" # noqa ) def test_apply_order_rejected_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) order.apply(TestStubs.event_order_submitted(order)) # Act order.apply(TestStubs.event_order_rejected(order)) # Assert assert order.status == OrderStatus.REJECTED assert not order.is_active assert not order.is_inflight assert not order.is_working assert order.is_completed def test_apply_order_expired_event(self): # Arrange order = self.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("0.99990"), TimeInForce.GTD, expire_time=UNIX_EPOCH, ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) # Act order.apply(TestStubs.event_order_expired(order)) # Assert assert order.status == OrderStatus.EXPIRED assert not order.is_active assert not order.is_inflight assert not order.is_working assert order.is_completed def test_apply_order_triggered_event(self): # Arrange order = self.order_factory.stop_limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), Price.from_str("0.99990"), TimeInForce.GTD, expire_time=UNIX_EPOCH, ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) # Act order.apply(TestStubs.event_order_triggered(order)) # Assert assert order.status == OrderStatus.TRIGGERED assert order.is_active assert not order.is_inflight assert order.is_working assert not order.is_completed def test_order_status_pending_cancel(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) # Act order.apply(TestStubs.event_order_pending_cancel(order)) # Assert assert order.status == OrderStatus.PENDING_CANCEL assert order.is_active assert order.is_inflight assert order.is_working assert not order.is_completed assert not order.is_pending_update assert order.is_pending_cancel assert order.event_count == 4 def test_apply_order_canceled_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) order.apply(TestStubs.event_order_pending_cancel(order)) # Act order.apply(TestStubs.event_order_canceled(order)) # Assert assert order.status == OrderStatus.CANCELED assert not order.is_active assert not order.is_inflight assert not order.is_working assert order.is_completed assert not order.is_pending_update assert not order.is_pending_cancel assert order.event_count == 5 def test_order_status_pending_replace(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) # Act order.apply(TestStubs.event_order_pending_update(order)) # Assert assert order.status == OrderStatus.PENDING_UPDATE assert order.is_active assert order.is_inflight assert order.is_working assert not order.is_completed assert order.is_pending_update assert not order.is_pending_cancel assert order.event_count == 4 def test_apply_order_updated_event_to_stop_order(self): # Arrange order = self.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) order.apply(TestStubs.event_order_pending_update(order)) updated = OrderUpdated( order.trader_id, order.strategy_id, order.account_id, order.instrument_id, order.client_order_id, VenueOrderId("1"), Quantity.from_int(120000), Price.from_str("1.00001"), None, UUID4(), 0, 0, ) # Act order.apply(updated) # Assert assert order.status == OrderStatus.ACCEPTED assert order.venue_order_id == VenueOrderId("1") assert order.quantity == Quantity.from_int(120000) assert order.price == Price.from_str("1.00001") assert order.is_active assert not order.is_inflight assert order.is_working assert not order.is_completed assert order.event_count == 5 def test_apply_order_updated_venue_id_change(self): # Arrange order = self.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) order.apply(TestStubs.event_order_pending_update(order)) updated = OrderUpdated( order.trader_id, order.strategy_id, order.account_id, order.instrument_id, order.client_order_id, VenueOrderId("2"), Quantity.from_int(120000), Price.from_str("1.00001"), None, UUID4(), 0, 0, ) # Act order.apply(updated) # Assert assert order.venue_order_id == VenueOrderId("2") assert order.venue_order_ids == [VenueOrderId("1")] def test_apply_order_filled_event_to_order_without_accepted(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) filled = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00001"), ) # Act order.apply(filled) # Assert assert order.status == OrderStatus.FILLED assert order.filled_qty == Quantity.from_int(100000) assert order.leaves_qty == Quantity.zero() assert order.avg_px == Decimal("1.00001") assert len(order.execution_ids) == 1 assert not order.is_active assert not order.is_inflight assert not order.is_working assert order.is_completed assert order.ts_last == 0 def test_apply_order_filled_event_to_market_order(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) filled = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00001"), ) # Act order.apply(filled) # Assert assert order.status == OrderStatus.FILLED assert order.filled_qty == Quantity.from_int(100000) assert order.avg_px == Decimal("1.00001") assert len(order.execution_ids) == 1 assert not order.is_active assert not order.is_inflight assert not order.is_working assert order.is_completed assert order.ts_last == 0 def test_apply_partial_fill_events_to_market_order_results_in_partially_filled( self, ): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) fill1 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("1"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00001"), last_qty=Quantity.from_int(20000), ) fill2 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("2"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00002"), last_qty=Quantity.from_int(40000), ) # Act order.apply(fill1) order.apply(fill2) # Assert assert order.status == OrderStatus.PARTIALLY_FILLED assert order.filled_qty == Quantity.from_int(60000) assert order.leaves_qty == Quantity.from_int(40000) assert order.avg_px == Decimal("1.000014") assert len(order.execution_ids) == 2 assert order.is_active assert not order.is_inflight assert order.is_working assert not order.is_completed assert order.ts_last == 0 def test_apply_filled_events_to_market_order_results_in_filled(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) fill1 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("1"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00001"), last_qty=Quantity.from_int(20000), ) fill2 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("2"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00002"), last_qty=Quantity.from_int(40000), ) fill3 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("3"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00003"), last_qty=Quantity.from_int(40000), ) # Act order.apply(fill1) order.apply(fill2) order.apply(fill3) # Assert assert order.status == OrderStatus.FILLED assert order.filled_qty == Quantity.from_int(100000) assert order.avg_px == Decimal("1.000018571428571428571428571") assert len(order.execution_ids) == 3 assert not order.is_active assert not order.is_inflight assert not order.is_working assert order.is_completed assert order.ts_last == 0 def test_apply_order_filled_event_to_buy_limit_order(self): # Arrange order = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) filled = OrderFilled( order.trader_id, order.strategy_id, order.account_id, order.instrument_id, order.client_order_id, VenueOrderId("1"), ExecutionId("E-1"), PositionId("P-1"), order.side, order.type, order.quantity, Price.from_str("1.00001"), AUDUSD_SIM.quote_currency, Money(0, USD), LiquiditySide.MAKER, UUID4(), 0, 0, ) # Act order.apply(filled) # Assert assert order.status == OrderStatus.FILLED assert order.filled_qty == Quantity.from_int(100000) assert order.price == Price.from_str("1.00000") assert order.avg_px == Decimal("1.00001") assert order.slippage == Decimal("0.00001") assert not order.is_active assert not order.is_inflight assert not order.is_working assert order.is_completed assert order.ts_last == 0 def test_apply_order_partially_filled_event_to_buy_limit_order(self): # Arrange order = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) partially = OrderFilled( order.trader_id, order.strategy_id, order.account_id, order.instrument_id, order.client_order_id, VenueOrderId("1"), ExecutionId("E-1"), PositionId("P-1"), order.side, order.type, Quantity.from_int(50000), Price.from_str("0.999999"), AUDUSD_SIM.quote_currency, Money(0, USD), LiquiditySide.MAKER, UUID4(), 1_000_000_000, 1_000_000_000, ) # Act order.apply(partially) # Assert assert order.status == OrderStatus.PARTIALLY_FILLED assert order.filled_qty == Quantity.from_int(50000) assert order.price == Price.from_str("1.00000") assert order.avg_px == Decimal("0.999999") assert order.slippage == Decimal("-0.000001") assert order.is_active assert not order.is_inflight assert order.is_working assert not order.is_completed assert order.ts_last == 1_000_000_000, order.ts_last
class OrderTests(unittest.TestCase): def setUp(self): # Fixture Setup self.account_id = TestStubs.account_id() self.order_factory = OrderFactory( trader_id=TraderId("TESTER", "000"), strategy_id=StrategyId("S", "001"), clock=TestClock(), ) def test_opposite_side_given_invalid_value_raises_value_error(self): # Arrange # Act # Assert self.assertRaises(ValueError, Order.opposite_side, 0) def test_flatten_side_given_invalid_value_or_flat_raises_value_error(self): # Arrange # Act self.assertRaises(ValueError, Order.flatten_side, 0) self.assertRaises(ValueError, Order.flatten_side, PositionSide.FLAT) @parameterized.expand([ [OrderSide.BUY, OrderSide.SELL], [OrderSide.SELL, OrderSide.BUY], ]) def test_opposite_side_returns_expected_sides(self, side, expected): # Arrange # Act result = Order.opposite_side(side) # Assert self.assertEqual(expected, result) @parameterized.expand([ [PositionSide.LONG, OrderSide.SELL], [PositionSide.SHORT, OrderSide.BUY], ]) def test_flatten_side_returns_expected_sides(self, side, expected): # Arrange # Act result = Order.flatten_side(side) # Assert self.assertEqual(expected, result) def test_market_order_with_quantity_zero_raises_value_error(self): # Arrange # Act self.assertRaises( ValueError, MarketOrder, ClientOrderId("O-123456"), StrategyId("S", "001"), AUDUSD_SIM.id, OrderSide.BUY, Quantity(), TimeInForce.DAY, uuid4(), 0, ) def test_market_order_with_invalid_tif_raises_value_error(self): # Arrange # Act self.assertRaises( ValueError, MarketOrder, ClientOrderId("O-123456"), StrategyId("S", "001"), AUDUSD_SIM.id, OrderSide.BUY, Quantity(100), TimeInForce.GTD, uuid4(), 0, ) def test_stop_market_order_with_gtd_and_expire_time_none_raises_type_error( self): # Arrange # Act self.assertRaises( TypeError, StopMarketOrder, ClientOrderId("O-123456"), StrategyId("S", "001"), AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), price=Price("1.00000"), init_id=uuid4(), timestamp_ns=0, time_in_force=TimeInForce.GTD, expire_time=None, ) def test_stop_limit_buy_order_with_gtd_and_expire_time_none_raises_type_error( self): # Arrange # Act self.assertRaises( TypeError, StopLimitOrder, ClientOrderId("O-123456"), StrategyId("S", "001"), AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), price=Price("1.00001"), trigger=Price("1.00000"), init_id=uuid4(), timestamp_ns=0, time_in_force=TimeInForce.GTD, expire_time=None, ) def test_reset_order_factory(self): # Arrange self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) # Act self.order_factory.reset() order2 = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) self.assertEqual(ClientOrderId("O-19700101-000000-000-001-1"), order2.client_order_id) def test_limit_order_can_create_expected_decimal_price(self): # Arrange # Act order1 = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) order2 = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00001"), ) # Assert self.assertEqual(Price("1.00000"), order1.price) self.assertEqual(Price("1.00001"), order2.price) def test_initialize_buy_market_order(self): # Arrange # Act order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) # Assert self.assertEqual(AUDUSD_SIM.id.symbol, order.symbol) self.assertEqual(AUDUSD_SIM.id.venue, order.venue) self.assertEqual(OrderType.MARKET, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(1, order.event_count) self.assertTrue(isinstance(order.last_event, OrderInitialized)) self.assertFalse(order.is_working) self.assertFalse(order.is_completed) self.assertTrue(order.is_buy) self.assertFalse(order.is_sell) self.assertFalse(order.is_passive) self.assertTrue(order.is_aggressive) self.assertEqual(0, order.execution_ns) self.assertEqual(0, order.last_event.timestamp_ns) self.assertEqual(OrderInitialized, type(order.init_event)) self.assertTrue(order == order) self.assertFalse(order != order) def test_initialize_sell_market_order(self): # Arrange # Act order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.SELL, Quantity(100000), ) # Assert self.assertEqual(OrderType.MARKET, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(1, order.event_count) self.assertTrue(isinstance(order.last_event, OrderInitialized)) self.assertEqual(1, len(order.events)) self.assertFalse(order.is_working) self.assertFalse(order.is_completed) self.assertFalse(order.is_buy) self.assertTrue(order.is_sell) self.assertEqual(0, order.execution_ns) self.assertEqual(OrderInitialized, type(order.init_event)) def test_order_equality(self): # Arrange # Act order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) # Assert self.assertTrue(order == order) self.assertFalse(order != order) def test_order_str_and_repr(self): # Arrange # Act order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) # Assert self.assertEqual( "MarketOrder(BUY 100,000 AUD/USD.SIM MARKET GTC, state=INITIALIZED, " "client_order_id=O-19700101-000000-000-001-1)", str(order), ) self.assertEqual( "MarketOrder(BUY 100,000 AUD/USD.SIM MARKET GTC, state=INITIALIZED, " "client_order_id=O-19700101-000000-000-001-1)", repr(order), ) def test_initialize_limit_order(self): # Arrange # Act order = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) # Assert self.assertEqual(OrderType.LIMIT, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(TimeInForce.GTC, order.time_in_force) self.assertTrue(order.is_passive) self.assertFalse(order.is_aggressive) self.assertFalse(order.is_completed) self.assertEqual(OrderInitialized, type(order.init_event)) self.assertEqual( "LimitOrder(BUY 100,000 AUD/USD.SIM LIMIT @ 1.00000 GTC, " "state=INITIALIZED, client_order_id=O-19700101-000000-000-001-1)", str(order), ) self.assertEqual( "LimitOrder(BUY 100,000 AUD/USD.SIM LIMIT @ 1.00000 GTC, " "state=INITIALIZED, client_order_id=O-19700101-000000-000-001-1)", repr(order), ) def test_initialize_limit_order_with_expire_time(self): # Arrange # Act order = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00000"), TimeInForce.GTD, expire_time=UNIX_EPOCH, ) # Assert self.assertEqual(AUDUSD_SIM.id, order.instrument_id) self.assertEqual(OrderType.LIMIT, order.type) self.assertEqual(Price("1.00000"), order.price) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(TimeInForce.GTD, order.time_in_force) self.assertEqual(UNIX_EPOCH, order.expire_time) self.assertFalse(order.is_completed) self.assertEqual(OrderInitialized, type(order.init_event)) def test_initialize_stop_market_order(self): # Arrange # Act order = self.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) # Assert self.assertEqual(OrderType.STOP_MARKET, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(TimeInForce.GTC, order.time_in_force) self.assertTrue(order.is_passive) self.assertFalse(order.is_aggressive) self.assertFalse(order.is_completed) self.assertEqual(OrderInitialized, type(order.init_event)) self.assertEqual( "StopMarketOrder(BUY 100,000 AUD/USD.SIM STOP_MARKET @ 1.00000 GTC, " "state=INITIALIZED, client_order_id=O-19700101-000000-000-001-1)", str(order), ) self.assertEqual( "StopMarketOrder(BUY 100,000 AUD/USD.SIM STOP_MARKET @ 1.00000 GTC, " "state=INITIALIZED, client_order_id=O-19700101-000000-000-001-1)", repr(order), ) def test_initialize_stop_limit_order(self): # Arrange # Act order = self.order_factory.stop_limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00000"), Price("1.10010"), ) # Assert self.assertEqual(OrderType.STOP_LIMIT, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(TimeInForce.GTC, order.time_in_force) self.assertTrue(order.is_passive) self.assertFalse(order.is_aggressive) self.assertFalse(order.is_completed) self.assertEqual(OrderInitialized, type(order.init_event)) self.assertEqual( "StopLimitOrder(BUY 100,000 AUD/USD.SIM STOP_LIMIT @ 1.00000 GTC, " "trigger=1.10010, state=INITIALIZED, client_order_id=O-19700101-000000-000-001-1)", str(order), ) self.assertEqual( "StopLimitOrder(BUY 100,000 AUD/USD.SIM STOP_LIMIT @ 1.00000 GTC, " "trigger=1.10010, state=INITIALIZED, client_order_id=O-19700101-000000-000-001-1)", repr(order), ) def test_bracket_order_equality(self): # Arrange entry1 = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) entry2 = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) bracket_order1 = self.order_factory.bracket(entry1, Price("1.00000"), Price("1.00010")) bracket_order2 = self.order_factory.bracket(entry2, Price("1.00000"), Price("1.00010")) # Act # Assert self.assertTrue(bracket_order1 == bracket_order1) self.assertTrue(bracket_order1 != bracket_order2) def test_initialize_bracket_order(self): # Arrange entry_order = self.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("0.99995"), ) # Act bracket_order = self.order_factory.bracket( entry_order, Price("0.99990"), Price("1.00010"), TimeInForce.GTC, TimeInForce.GTC, ) # Assert self.assertEqual(AUDUSD_SIM.id, bracket_order.stop_loss.instrument_id) self.assertTrue(bracket_order.take_profit is not None) self.assertEqual(AUDUSD_SIM.id, bracket_order.take_profit.instrument_id) self.assertEqual( ClientOrderId("O-19700101-000000-000-001-1"), bracket_order.entry.client_order_id, ) self.assertEqual( ClientOrderId("O-19700101-000000-000-001-2"), bracket_order.stop_loss.client_order_id, ) self.assertEqual( ClientOrderId("O-19700101-000000-000-001-3"), bracket_order.take_profit.client_order_id, ) self.assertEqual(OrderSide.SELL, bracket_order.stop_loss.side) self.assertEqual(OrderSide.SELL, bracket_order.take_profit.side) self.assertEqual(Quantity(100000), bracket_order.stop_loss.quantity) self.assertEqual(Quantity(100000), bracket_order.take_profit.quantity) self.assertEqual(Price("0.99990"), bracket_order.stop_loss.price) self.assertEqual(Price("1.00010"), bracket_order.take_profit.price) self.assertEqual(TimeInForce.GTC, bracket_order.stop_loss.time_in_force) self.assertEqual(TimeInForce.GTC, bracket_order.take_profit.time_in_force) self.assertEqual(None, bracket_order.entry.expire_time) self.assertEqual(None, bracket_order.stop_loss.expire_time) self.assertEqual(None, bracket_order.take_profit.expire_time) self.assertEqual(BracketOrderId("BO-19700101-000000-000-001-1"), bracket_order.id) self.assertEqual(0, bracket_order.timestamp_ns) def test_bracket_order_str_and_repr(self): # Arrange # Act entry_order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) bracket_order = self.order_factory.bracket( entry_order, Price("0.99990"), Price("1.00010"), ) # Assert self.assertEqual( "BracketOrder(id=BO-19700101-000000-000-001-1, " "EntryMarketOrder(BUY 100,000 AUD/USD.SIM MARKET GTC, " "state=INITIALIZED, client_order_id=O-19700101-000000-000-001-1), " "SL=0.99990, TP=1.00010)", str(bracket_order), ) # noqa self.assertEqual( "BracketOrder(id=BO-19700101-000000-000-001-1, " "EntryMarketOrder(BUY 100,000 AUD/USD.SIM MARKET GTC, " "state=INITIALIZED, client_order_id=O-19700101-000000-000-001-1), " "SL=0.99990, TP=1.00010)", repr(bracket_order), ) # noqa def test_apply_order_invalid_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) invalid = OrderInvalid( order.client_order_id, "SOME_REASON", uuid4(), 0, ) # Act order.apply(invalid) # Assert self.assertEqual(OrderState.INVALID, order.state) self.assertEqual(2, order.event_count) self.assertEqual(invalid, order.last_event) self.assertTrue(order.is_completed) def test_apply_order_denied_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) denied = OrderDenied( order.client_order_id, "SOME_REASON", uuid4(), 0, ) # Act order.apply(denied) # Assert self.assertEqual(OrderState.DENIED, order.state) self.assertEqual(2, order.event_count) self.assertEqual(denied, order.last_event) self.assertTrue(order.is_completed) def test_apply_order_submitted_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) submitted = TestStubs.event_order_submitted(order) # Act order.apply(submitted) # Assert self.assertEqual(OrderState.SUBMITTED, order.state) self.assertEqual(2, order.event_count) self.assertEqual(submitted, order.last_event) self.assertFalse(order.is_working) self.assertFalse(order.is_completed) def test_apply_order_accepted_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) order.apply(TestStubs.event_order_submitted(order)) # Act order.apply(TestStubs.event_order_accepted(order)) # Assert self.assertEqual(OrderState.ACCEPTED, order.state) self.assertTrue(order.is_working) self.assertFalse(order.is_completed) self.assertEqual( "MarketOrder(BUY 100,000 AUD/USD.SIM MARKET GTC, state=ACCEPTED, " "client_order_id=O-19700101-000000-000-001-1, venue_order_id=1)", str(order), ) self.assertEqual( "MarketOrder(BUY 100,000 AUD/USD.SIM MARKET GTC, state=ACCEPTED, " "client_order_id=O-19700101-000000-000-001-1, venue_order_id=1)", repr(order), ) def test_apply_order_rejected_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) order.apply(TestStubs.event_order_submitted(order)) # Act order.apply(TestStubs.event_order_rejected(order)) # Assert self.assertEqual(OrderState.REJECTED, order.state) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) def test_apply_order_expired_event(self): # Arrange order = self.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("0.99990"), TimeInForce.GTD, expire_time=UNIX_EPOCH, ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) # Act order.apply(TestStubs.event_order_expired(order)) # Assert self.assertEqual(OrderState.EXPIRED, order.state) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) def test_apply_order_triggered_event(self): # Arrange order = self.order_factory.stop_limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00000"), Price("0.99990"), TimeInForce.GTD, expire_time=UNIX_EPOCH, ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) # Act order.apply(TestStubs.event_order_triggered(order)) # Assert self.assertEqual(OrderState.TRIGGERED, order.state) self.assertTrue(order.is_working) self.assertFalse(order.is_completed) def test_apply_order_cancelled_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) # Act order.apply(TestStubs.event_order_cancelled(order)) # Assert self.assertEqual(OrderState.CANCELLED, order.state) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) def test_apply_order_amended_event_to_stop_order(self): # Arrange order = self.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) updated = OrderUpdated( self.account_id, order.client_order_id, VenueOrderId("1"), Quantity(120000), Price("1.00001"), 0, uuid4(), 0, ) # Act order.apply(updated) # Assert self.assertEqual(OrderState.ACCEPTED, order.state) self.assertEqual(VenueOrderId("1"), order.venue_order_id) self.assertEqual(Quantity(120000), order.quantity) self.assertEqual(Price("1.00001"), order.price) self.assertTrue(order.is_working) self.assertFalse(order.is_completed) self.assertEqual(4, order.event_count) def test_apply_order_updated_venue_id_change(self): # Arrange order = self.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) updated = OrderUpdated( self.account_id, order.client_order_id, VenueOrderId("2"), Quantity(120000), Price("1.00001"), 0, uuid4(), 0, ) # Act order.apply(updated) # Assert self.assertEqual(VenueOrderId("2"), order.venue_order_id) self.assertEqual([VenueOrderId("1")], order.venue_order_ids) def test_apply_order_filled_event_to_order_without_accepted(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) filled = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), last_px=Price("1.00001"), ) # Act order.apply(filled) # Assert self.assertEqual(OrderState.FILLED, order.state) self.assertEqual(Quantity(100000), order.filled_qty) self.assertEqual(Decimal("1.00001"), order.avg_px) self.assertEqual(1, len(order.execution_ids)) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) self.assertEqual(0, order.execution_ns) def test_apply_order_filled_event_to_market_order(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) filled = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), last_px=Price("1.00001"), ) # Act order.apply(filled) # Assert self.assertEqual(OrderState.FILLED, order.state) self.assertEqual(Quantity(100000), order.filled_qty) self.assertEqual(Decimal("1.00001"), order.avg_px) self.assertEqual(1, len(order.execution_ids)) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) self.assertEqual(0, order.execution_ns) def test_apply_partial_fill_events_to_market_order_results_in_partially_filled( self, ): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) fill1 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("1"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), last_px=Price("1.00001"), last_qty=Quantity(20000), ) fill2 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("2"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), last_px=Price("1.00002"), last_qty=Quantity(40000), ) # Act order.apply(fill1) order.apply(fill2) # Assert self.assertEqual(OrderState.PARTIALLY_FILLED, order.state) self.assertEqual(Quantity(60000), order.filled_qty) self.assertEqual(Decimal("1.000014"), order.avg_px) self.assertEqual(2, len(order.execution_ids)) self.assertTrue(order.is_working) self.assertFalse(order.is_completed) self.assertEqual(0, order.execution_ns) def test_apply_filled_events_to_market_order_results_in_filled(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) fill1 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("1"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), last_px=Price("1.00001"), last_qty=Quantity(20000), ) fill2 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("2"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), last_px=Price("1.00002"), last_qty=Quantity(40000), ) fill3 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("3"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), last_px=Price("1.00003"), last_qty=Quantity(40000), ) # Act order.apply(fill1) order.apply(fill2) order.apply(fill3) # Assert self.assertEqual(OrderState.FILLED, order.state) self.assertEqual(Quantity(100000), order.filled_qty) self.assertEqual(Decimal("1.000018571428571428571428571"), order.avg_px) self.assertEqual(3, len(order.execution_ids)) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) self.assertEqual(0, order.execution_ns) def test_apply_order_filled_event_to_buy_limit_order(self): # Arrange order = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) filled = OrderFilled( self.account_id, order.client_order_id, VenueOrderId("1"), ExecutionId("E-1"), PositionId("P-1"), StrategyId.null(), order.instrument_id, order.side, order.quantity, Price("1.00001"), order.quantity, Quantity(), AUDUSD_SIM.quote_currency, AUDUSD_SIM.is_inverse, Money(0, USD), LiquiditySide.MAKER, 0, uuid4(), 0, ) # Act order.apply(filled) # Assert self.assertEqual(OrderState.FILLED, order.state) self.assertEqual(Quantity(100000), order.filled_qty) self.assertEqual(Price("1.00000"), order.price) self.assertEqual(Decimal("1.00001"), order.avg_px) self.assertEqual(Decimal("0.00001"), order.slippage) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) self.assertEqual(0, order.execution_ns) def test_apply_order_partially_filled_event_to_buy_limit_order(self): # Arrange order = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) partially = OrderFilled( self.account_id, order.client_order_id, VenueOrderId("1"), ExecutionId("E-1"), PositionId("P-1"), StrategyId.null(), order.instrument_id, order.side, Quantity(50000), Price("0.999999"), Quantity(50000), Quantity(50000), AUDUSD_SIM.quote_currency, AUDUSD_SIM.is_inverse, Money(0, USD), LiquiditySide.MAKER, 1_000_000_000, uuid4(), 1_000_000_000, ) # Act order.apply(partially) # Assert self.assertEqual(OrderState.PARTIALLY_FILLED, order.state) self.assertEqual(Quantity(50000), order.filled_qty) self.assertEqual(Price("1.00000"), order.price) self.assertEqual(Decimal("0.999999"), order.avg_px) self.assertEqual(Decimal("-0.000001"), order.slippage) self.assertTrue(order.is_working) self.assertFalse(order.is_completed) self.assertEqual(1_000_000_000, order.execution_ns)
class OrderTests(unittest.TestCase): def setUp(self): # Fixture Setup self.account_id = TestStubs.account_id() self.order_factory = OrderFactory(id_tag_trader=IdTag('001'), id_tag_strategy=IdTag('001'), clock=TestClock(), guid_factory=TestGuidFactory()) def test_market_order_with_quantity_zero_raises_exception(self): # Arrange # Act self.assertRaises(ValueError, Order, OrderId('O-123456'), AUDUSD_FXCM, OrderSide.BUY, OrderType.MARKET, Quantity(), GUID(uuid.uuid4()), UNIX_EPOCH) def test_priced_order_with_GTD_time_in_force_and_expire_time_none_raises_exception( self): # Arrange # Act self.assertRaises(ValueError, Order, OrderId('O-123456'), AUDUSD_FXCM, OrderSide.BUY, OrderType.LIMIT, Quantity(100000), GUID(uuid.uuid4()), UNIX_EPOCH, price=Price(1.00000, 5), time_in_force=TimeInForce.GTD, expire_time=None) def test_market_order_with_price_input_raises_exception(self): # Arrange # Act self.assertRaises(ValueError, Order, OrderId('O-123456'), AUDUSD_FXCM, OrderSide.BUY, OrderType.MARKET, Quantity(100000), GUID(uuid.uuid4()), UNIX_EPOCH, price=Price(1.00000, 5)) def test_stop_order_with_no_price_input_raises_exception(self): # Arrange # Act self.assertRaises(ValueError, Order, OrderId('O-123456'), AUDUSD_FXCM, OrderSide.BUY, OrderType.STOP, Quantity(100000), GUID(uuid.uuid4()), UNIX_EPOCH) def test_stop_order_with_zero_price_input_raises_exception(self): # Arrange # Act self.assertRaises(ValueError, Order, OrderId('O-123456'), AUDUSD_FXCM, OrderSide.BUY, OrderType.STOP, Quantity(100000), GUID(uuid.uuid4()), UNIX_EPOCH, price=None) def test_can_reset_order_factory(self): # Arrange self.order_factory.limit(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00000, 5)) # Act self.order_factory.reset() order2 = self.order_factory.limit(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00000, 5)) self.assertEqual(OrderId('O-19700101-000000-001-001-1'), order2.id) def test_limit_order_can_create_expected_decimal_price(self): # Arrange # Act order1 = self.order_factory.limit(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00000, 5)) order2 = self.order_factory.limit(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00000, 5)) order3 = self.order_factory.limit(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00000, 5)) order4 = self.order_factory.limit(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00001, 5)) # Assert self.assertEqual(Price(1.00000, 5), order1.price) self.assertEqual(Price(1.00000, 5), order2.price) self.assertEqual(Price(1.00000, 5), order3.price) self.assertEqual(Price(1.00001, 5), order4.price) def test_can_initialize_buy_market_order(self): # Arrange # Act order = self.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), ) # Assert self.assertEqual(OrderType.MARKET, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(1, order.event_count) self.assertTrue(isinstance(order.last_event, OrderInitialized)) self.assertFalse(order.is_working) self.assertFalse(order.is_completed) self.assertTrue(order.is_buy) self.assertFalse(order.is_sell) self.assertEqual(None, order.filled_timestamp) def test_can_initialize_sell_market_order(self): # Arrange # Act order = self.order_factory.market( AUDUSD_FXCM, OrderSide.SELL, Quantity(100000), ) # Assert self.assertEqual(OrderType.MARKET, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(1, order.event_count) self.assertTrue(isinstance(order.last_event, OrderInitialized)) self.assertFalse(order.is_working) self.assertFalse(order.is_completed) self.assertFalse(order.is_buy) self.assertTrue(order.is_sell) self.assertEqual(None, order.filled_timestamp) def test_order_str_and_repr(self): # Arrange # Act order = self.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) # Assert self.assertEqual( 'Order(id=O-19700101-000000-001-001-1, state=INITIALIZED, BUY 100K AUDUSD.FXCM MARKET DAY)', str(order)) self.assertTrue( repr(order).startswith( '<Order(id=O-19700101-000000-001-001-1, state=INITIALIZED, BUY 100K AUDUSD.FXCM MARKET DAY) object at' )) def test_can_initialize_limit_order(self): # Arrange # Act order = self.order_factory.limit(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00000, 5)) # Assert self.assertEqual(OrderType.LIMIT, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(TimeInForce.DAY, order.time_in_force) self.assertFalse(order.is_completed) def test_can_initialize_limit_order_with_expire_time(self): # Arrange # Act order = self.order_factory.limit(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00000, 5), Label('U1_TP'), OrderPurpose.NONE, TimeInForce.GTD, UNIX_EPOCH) # Assert self.assertEqual(AUDUSD_FXCM, order.symbol) self.assertEqual(OrderType.LIMIT, order.type) self.assertEqual(Price(1.00000, 5), order.price) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(TimeInForce.GTD, order.time_in_force) self.assertEqual(UNIX_EPOCH, order.expire_time) self.assertFalse(order.is_completed) def test_can_initialize_stop_market_order(self): # Arrange # Act order = self.order_factory.stop(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00000, 5)) # Assert self.assertEqual(OrderType.STOP, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(TimeInForce.DAY, order.time_in_force) self.assertFalse(order.is_completed) def test_can_initialize_stop_limit_order(self): # Arrange # Act order = self.order_factory.stop_limit(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00000, 5)) # Assert self.assertEqual(OrderType.STOP_LIMIT, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertFalse(order.is_completed) def test_can_initialize_market_if_touched_order(self): # Arrange # Act order = self.order_factory.market_if_touched(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00000, 5)) # Assert self.assertEqual(OrderType.MIT, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertFalse(order.is_completed) def test_can_initialize_fill_or_kill_order(self): # Arrange # Act order = self.order_factory.fill_or_kill(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) # Assert self.assertEqual(OrderType.MARKET, order.type) self.assertEqual(TimeInForce.FOC, order.time_in_force) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertFalse(order.is_completed) def test_can_initialize_immediate_or_cancel_order(self): # Arrange # Act order = self.order_factory.immediate_or_cancel(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) # Assert self.assertEqual(OrderType.MARKET, order.type) self.assertEqual(TimeInForce.IOC, order.time_in_force) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertFalse(order.is_completed) def test_can_initialize_atomic_order_market_with_no_take_profit_or_label( self): # Arrange # Act atomic_order = self.order_factory.atomic_market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(0.99990, 5)) # Assert self.assertEqual(AUDUSD_FXCM, atomic_order.stop_loss.symbol) self.assertFalse(atomic_order.has_take_profit) self.assertEqual(OrderId('O-19700101-000000-001-001-1'), atomic_order.entry.id) self.assertEqual(OrderId('O-19700101-000000-001-001-2'), atomic_order.stop_loss.id) self.assertEqual(OrderSide.SELL, atomic_order.stop_loss.side) self.assertEqual(Quantity(100000), atomic_order.entry.quantity) self.assertEqual(Quantity(100000), atomic_order.stop_loss.quantity) self.assertEqual(Price(0.99990, 5), atomic_order.stop_loss.price) self.assertEqual(None, atomic_order.entry.label) self.assertEqual(None, atomic_order.stop_loss.label) self.assertEqual(TimeInForce.GTC, atomic_order.stop_loss.time_in_force) self.assertEqual(None, atomic_order.entry.expire_time) self.assertEqual(None, atomic_order.stop_loss.expire_time) self.assertEqual(AtomicOrderId('AO-19700101-000000-001-001-1'), atomic_order.id) self.assertEqual(UNIX_EPOCH, atomic_order.timestamp) def test_can_initialize_atomic_order_market_with_take_profit_and_label( self): # Arrange # Act atomic_order = self.order_factory.atomic_market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(0.99990, 5), Price(1.00010, 5), Label('U1')) # Assert self.assertEqual(AUDUSD_FXCM, atomic_order.stop_loss.symbol) self.assertTrue(atomic_order.has_take_profit) self.assertEqual(AUDUSD_FXCM, atomic_order.take_profit.symbol) self.assertEqual(OrderId('O-19700101-000000-001-001-1'), atomic_order.entry.id) self.assertEqual(OrderId('O-19700101-000000-001-001-2'), atomic_order.stop_loss.id) self.assertEqual(OrderId('O-19700101-000000-001-001-3'), atomic_order.take_profit.id) self.assertEqual(OrderSide.SELL, atomic_order.stop_loss.side) self.assertEqual(OrderSide.SELL, atomic_order.take_profit.side) self.assertEqual(Quantity(100000), atomic_order.stop_loss.quantity) self.assertEqual(Quantity(100000), atomic_order.take_profit.quantity) self.assertEqual(Price(0.99990, 5), atomic_order.stop_loss.price) self.assertEqual(Price(1.00010, 5), atomic_order.take_profit.price) self.assertEqual(Label('U1_E'), atomic_order.entry.label) self.assertEqual(Label('U1_SL'), atomic_order.stop_loss.label) self.assertEqual(Label('U1_TP'), atomic_order.take_profit.label) self.assertEqual(TimeInForce.GTC, atomic_order.stop_loss.time_in_force) self.assertEqual(TimeInForce.GTC, atomic_order.take_profit.time_in_force) self.assertEqual(None, atomic_order.entry.expire_time) self.assertEqual(None, atomic_order.stop_loss.expire_time) self.assertEqual(None, atomic_order.take_profit.expire_time) self.assertEqual(AtomicOrderId('AO-19700101-000000-001-001-1'), atomic_order.id) self.assertEqual(UNIX_EPOCH, atomic_order.timestamp) def test_atomic_order_str_and_repr(self): # Arrange # Act atomic_order = self.order_factory.atomic_market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(0.99990, 5), Price(1.00010, 5), Label('U1')) # Assert self.assertEqual( 'AtomicOrder(id=AO-19700101-000000-001-001-1, EntryOrder(id=O-19700101-000000-001-001-1, state=INITIALIZED, label=U1_E, BUY 100K AUDUSD.FXCM MARKET DAY), SL=0.99990, TP=1.00010)', str(atomic_order)) self.assertTrue( repr(atomic_order).startswith( '<AtomicOrder(id=AO-19700101-000000-001-001-1, EntryOrder(id=O-19700101-000000-001-001-1, state=INITIALIZED, label=U1_E, BUY 100K AUDUSD.FXCM MARKET DAY), SL=0.99990, TP=1.00010) object at' )) self.assertTrue(repr(atomic_order).endswith('>')) def test_can_apply_order_submitted_event_to_order(self): # Arrange order = self.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) event = OrderSubmitted(self.account_id, order.id, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) # Act order.apply(event) # Assert self.assertEqual(OrderState.SUBMITTED, order.state) self.assertEqual(2, order.event_count) self.assertEqual(event, order.last_event) self.assertFalse(order.is_completed) def test_can_apply_order_accepted_event_to_order(self): # Arrange order = self.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) event = OrderAccepted(self.account_id, order.id, OrderIdBroker('B' + order.id.value), Label('E'), UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) # Act order.apply(event) # Assert self.assertEqual(OrderState.ACCEPTED, order.state) self.assertFalse(order.is_completed) def test_can_apply_order_rejected_event_to_order(self): # Arrange order = self.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) event = OrderRejected(self.account_id, order.id, UNIX_EPOCH, ValidString('ORDER ID INVALID'), GUID(uuid.uuid4()), UNIX_EPOCH) # Act order.apply(event) # Assert self.assertEqual(OrderState.REJECTED, order.state) self.assertTrue(order.is_completed) def test_can_apply_order_working_event_to_order(self): # Arrange order = self.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) event = OrderWorking(self.account_id, order.id, OrderIdBroker('SOME_BROKER_ID'), order.symbol, order.label, order.side, order.type, order.quantity, Price(1.0, 1), order.time_in_force, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH, order.expire_time) # Act order.apply(event) # Assert # print(order) self.assertEqual(OrderState.WORKING, order.state) self.assertEqual(OrderIdBroker('SOME_BROKER_ID'), order.id_broker) self.assertFalse(order.is_completed) self.assertTrue(order.is_working) self.assertEqual(None, order.filled_timestamp) def test_can_apply_order_expired_event_to_order(self): # Arrange order = self.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) event = OrderExpired(self.account_id, order.id, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) # Act order.apply(event) # Assert self.assertEqual(OrderState.EXPIRED, order.state) self.assertTrue(order.is_completed) def test_can_apply_order_cancelled_event_to_order(self): # Arrange order = self.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) event = OrderCancelled(self.account_id, order.id, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) # Act order.apply(event) # Assert self.assertEqual(OrderState.CANCELLED, order.state) self.assertTrue(order.is_completed) def test_can_apply_order_cancel_reject_event_to_order(self): # Arrange order = self.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) event = OrderCancelReject(self.account_id, order.id, UNIX_EPOCH, ValidString('REJECT_RESPONSE'), ValidString('ORDER DOES NOT EXIST'), GUID(uuid.uuid4()), UNIX_EPOCH) # Act order.apply(event) # Assert self.assertEqual(OrderState.INITIALIZED, order.state) def test_can_apply_order_modified_event_to_order(self): # Arrange order = self.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) order_working = OrderWorking(self.account_id, order.id, OrderIdBroker('SOME_BROKER_ID_1'), order.symbol, order.label, order.side, order.type, order.quantity, Price(1.00000, 5), order.time_in_force, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH, order.expire_time) order_modified = OrderModified(self.account_id, order.id, OrderIdBroker('SOME_BROKER_ID_2'), Quantity(120000), Price(1.00001, 5), UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) order.apply(order_working) # Act order.apply(order_modified) # Assert self.assertEqual(OrderState.WORKING, order.state) self.assertEqual(OrderIdBroker('SOME_BROKER_ID_2'), order.id_broker) self.assertEqual(Quantity(120000), order.quantity) self.assertEqual(Price(1.00001, 5), order.price) self.assertTrue(order.is_working) self.assertFalse(order.is_completed) self.assertEqual(3, order.event_count) def test_can_apply_order_filled_event_to_market_order(self): # Arrange order = self.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) event = OrderFilled(self.account_id, order.id, ExecutionId('SOME_EXEC_ID_1'), PositionIdBroker('SOME_EXEC_TICKET_1'), order.symbol, order.side, order.quantity, Price(1.00001, 5), Currency.USD, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) # Act order.apply(event) # Assert self.assertEqual(OrderState.FILLED, order.state) self.assertEqual(Quantity(100000), order.filled_quantity) self.assertEqual(Price(1.00001, 5), order.average_price) self.assertTrue(order.is_completed) self.assertEqual(UNIX_EPOCH, order.filled_timestamp) def test_can_apply_order_filled_event_to_buy_limit_order(self): # Arrange order = self.order_factory.limit(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00000, 5)) event = OrderFilled(self.account_id, order.id, ExecutionId('SOME_EXEC_ID_1'), PositionIdBroker('SOME_EXEC_TICKET_1'), order.symbol, order.side, order.quantity, Price(1.00001, 5), Currency.USD, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) # Act order.apply(event) # Assert self.assertEqual(OrderState.FILLED, order.state) self.assertEqual(Quantity(100000), order.filled_quantity) self.assertEqual(Price(1.00000, 5), order.price) self.assertEqual(Price(1.00001, 5), order.average_price) self.assertEqual(Decimal(0.00001, 5), order.slippage) self.assertTrue(order.is_completed) self.assertEqual(UNIX_EPOCH, order.filled_timestamp) def test_can_apply_order_partially_filled_event_to_buy_limit_order(self): # Arrange order = self.order_factory.limit(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00000, 5)) event = OrderPartiallyFilled(self.account_id, order.id, ExecutionId('SOME_EXEC_ID_1'), PositionIdBroker('SOME_EXEC_TICKET_1'), order.symbol, order.side, Quantity(50000), Quantity(50000), Price(0.999999, 6), Currency.USD, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) # Act order.apply(event) # Assert self.assertEqual(OrderState.PARTIALLY_FILLED, order.state) self.assertEqual(Quantity(50000), order.filled_quantity) self.assertEqual(Price(1.00000, 5), order.price) self.assertEqual(Price(0.999999, 6), order.average_price) self.assertEqual(Decimal(-0.000001, 6), order.slippage) self.assertFalse(order.is_completed) self.assertEqual(UNIX_EPOCH, order.filled_timestamp) def test_can_apply_order_overfilled_event_to_buy_limit_order(self): # Arrange order = self.order_factory.limit(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00000, 5)) event = OrderFilled(self.account_id, order.id, ExecutionId('SOME_EXEC_ID_1'), PositionIdBroker('SOME_EXEC_TICKET_1'), order.symbol, order.side, Quantity(150000), Price(0.99999, 5), Currency.USD, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) # Act order.apply(event) # Assert self.assertEqual(OrderState.OVER_FILLED, order.state) self.assertEqual(Quantity(150000), order.filled_quantity) self.assertFalse(order.is_completed) self.assertEqual(UNIX_EPOCH, order.filled_timestamp)