コード例 #1
0
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_undefined_raises_value_error(self):
        # Arrange
        # Act
        # Assert
        self.assertRaises(ValueError, Order.opposite_side, OrderSide.UNDEFINED)

    def test_flatten_side_given_undefined_or_flat_raises_value_error(self):
        # Arrange
        # Act
        # Assert
        self.assertRaises(ValueError, Order.flatten_side, PositionSide.UNDEFINED)
        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_exception(self):
        # Arrange
        # Act
        self.assertRaises(
            ValueError,
            MarketOrder,
            ClientOrderId("O-123456"),
            StrategyId("S", "001"),
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(),
            TimeInForce.DAY,
            uuid4(),
            UNIX_EPOCH,
        )

    def test_market_order_with_invalid_tif_raises_exception(self):
        # Arrange
        # Act
        self.assertRaises(
            ValueError,
            MarketOrder,
            ClientOrderId("O-123456"),
            StrategyId("S", "001"),
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100),
            TimeInForce.GTD,
            uuid4(),
            UNIX_EPOCH,
        )

    def test_stop_order_with_gtd_and_expire_time_none_raises_exception(self):
        # Arrange
        # Act
        self.assertRaises(
            TypeError,
            StopMarketOrder,
            ClientOrderId("O-123456"),
            StrategyId("S", "001"),
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
            price=Price("1.00000"),
            init_id=uuid4(),
            timestamp=UNIX_EPOCH,
            time_in_force=TimeInForce.GTD,
            expire_time=None,
        )

    def test_reset_order_factory(self):
        # Arrange
        self.order_factory.limit(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
        )

        # Act
        self.order_factory.reset()

        order2 = self.order_factory.limit(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
        )

        self.assertEqual(ClientOrderId("O-19700101-000000-000-001-1"), order2.cl_ord_id)

    def test_limit_order_can_create_expected_decimal_price(self):
        # Arrange
        # Act
        order1 = self.order_factory.limit(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
        )

        order2 = self.order_factory.limit(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
        )

        order3 = self.order_factory.limit(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
        )

        order4 = self.order_factory.limit(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00001"),
        )

        # Assert
        self.assertEqual(Price("1.00000"), order1.price)
        self.assertEqual(Price("1.00000"), order2.price)
        self.assertEqual(Price("1.00000"), order3.price)
        self.assertEqual(Price("1.00001"), order4.price)

    def test_initialize_buy_market_order(self):
        # Arrange
        # Act
        order = self.order_factory.market(
            AUDUSD_SIM.symbol,
            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.assertFalse(order.is_passive)
        self.assertTrue(order.is_aggressive)
        self.assertEqual(None, order.filled_timestamp)
        self.assertEqual(UNIX_EPOCH, order.last_event.timestamp)
        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.symbol,
            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.assertTrue(order.is_active)
        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)
        self.assertEqual(OrderInitialized, type(order.init_event))

    def test_order_equality(self):
        # Arrange
        # Act
        order = self.order_factory.market(
            AUDUSD_SIM.symbol,
            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.symbol,
            OrderSide.BUY,
            Quantity(100000),
        )

        # Assert
        self.assertEqual("MarketOrder(cl_ord_id=O-19700101-000000-000-001-1, id=NULL, state=INITIALIZED, BUY 100,000 AUD/USD.SIM MARKET GTC)", str(order))  # noqa
        self.assertEqual("MarketOrder(cl_ord_id=O-19700101-000000-000-001-1, id=NULL, state=INITIALIZED, BUY 100,000 AUD/USD.SIM MARKET GTC)", repr(order))  # noqa

    def test_initialize_limit_order(self):
        # Arrange
        # Act
        order = self.order_factory.limit(
            AUDUSD_SIM.symbol,
            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.assertTrue(order.is_active)
        self.assertFalse(order.is_aggressive)
        self.assertFalse(order.is_completed)
        self.assertEqual(OrderInitialized, type(order.init_event))

    def test_initialize_limit_order_with_expire_time(self):
        # Arrange
        # Act
        order = self.order_factory.limit(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
            TimeInForce.GTD,
            UNIX_EPOCH,
        )

        # Assert
        self.assertEqual(AUDUSD_SIM.symbol, order.symbol)
        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_order(self):
        # Arrange
        # Act
        order = self.order_factory.stop_market(
            AUDUSD_SIM.symbol,
            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))

    def test_bracket_order_equality(self):
        # Arrange
        entry1 = self.order_factory.market(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
        )

        entry2 = self.order_factory.market(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
        )

        bracket_order1 = self.order_factory.bracket(entry1, Price("1.00000"))
        bracket_order2 = self.order_factory.bracket(entry2, Price("1.00000"))

        # Act
        # Assert
        self.assertTrue(bracket_order1 == bracket_order1)
        self.assertTrue(bracket_order1 != bracket_order2)

    def test_initialize_bracket_order_market_with_no_take_profit(self):
        # Arrange
        entry_order = self.order_factory.market(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
        )

        # Act
        bracket_order = self.order_factory.bracket(entry_order, Price("0.99990"))

        # Assert
        self.assertEqual(AUDUSD_SIM.symbol, bracket_order.stop_loss.symbol)
        self.assertFalse(bracket_order.take_profit is not None)
        self.assertEqual(ClientOrderId("O-19700101-000000-000-001-1"), bracket_order.entry.cl_ord_id)
        self.assertEqual(ClientOrderId("O-19700101-000000-000-001-2"), bracket_order.stop_loss.cl_ord_id)
        self.assertEqual(OrderSide.SELL, bracket_order.stop_loss.side)
        self.assertEqual(Quantity(100000), bracket_order.entry.quantity)
        self.assertEqual(Quantity(100000), bracket_order.stop_loss.quantity)
        self.assertEqual(Price("0.99990"), bracket_order.stop_loss.price)
        self.assertEqual(TimeInForce.GTC, bracket_order.stop_loss.time_in_force)
        self.assertEqual(None, bracket_order.stop_loss.expire_time)
        self.assertEqual(BracketOrderId("BO-19700101-000000-000-001-1"), bracket_order.id)
        self.assertEqual(UNIX_EPOCH, bracket_order.timestamp)

    def test_initialize_bracket_order_stop_with_take_profit(self):
        # Arrange
        entry_order = self.order_factory.stop_market(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
            Price("0.99995"),
        )

        # Act
        bracket_order = self.order_factory.bracket(
            entry_order,
            Price("0.99990"),
            Price("1.00010"),
        )

        # Assert
        self.assertEqual(AUDUSD_SIM.symbol, bracket_order.stop_loss.symbol)
        self.assertTrue(bracket_order.take_profit is not None)
        self.assertEqual(AUDUSD_SIM.symbol, bracket_order.take_profit.symbol)
        self.assertEqual(ClientOrderId("O-19700101-000000-000-001-1"), bracket_order.entry.cl_ord_id)
        self.assertEqual(ClientOrderId("O-19700101-000000-000-001-2"), bracket_order.stop_loss.cl_ord_id)
        self.assertEqual(ClientOrderId("O-19700101-000000-000-001-3"), bracket_order.take_profit.cl_ord_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(UNIX_EPOCH, bracket_order.timestamp)

    def test_bracket_order_str_and_repr(self):
        # Arrange
        # Act
        entry_order = self.order_factory.market(
            AUDUSD_SIM.symbol,
            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(cl_ord_id=O-19700101-000000-000-001-1, id=NULL, state=INITIALIZED, BUY 100,000 AUD/USD.SIM MARKET GTC), SL=0.99990, TP=1.00010)", str(bracket_order))  # noqa
        self.assertEqual("BracketOrder(id=BO-19700101-000000-000-001-1, EntryMarketOrder(cl_ord_id=O-19700101-000000-000-001-1, id=NULL, state=INITIALIZED, BUY 100,000 AUD/USD.SIM MARKET GTC), 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.symbol,
            OrderSide.BUY,
            Quantity(100000),
        )

        invalid = OrderInvalid(
            order.cl_ord_id,
            "SOME_REASON",
            uuid4(),
            UNIX_EPOCH,
        )

        # Act
        order.apply(invalid)

        # Assert
        self.assertEqual(OrderState.INVALID, order.state)
        self.assertEqual(2, order.event_count)
        self.assertEqual(invalid, order.last_event)
        self.assertFalse(order.is_active)
        self.assertTrue(order.is_completed)

    def test_apply_order_denied_event(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
        )

        denied = OrderDenied(
            order.cl_ord_id,
            "SOME_REASON",
            uuid4(),
            UNIX_EPOCH,
        )

        # Act
        order.apply(denied)

        # Assert
        self.assertEqual(OrderState.DENIED, order.state)
        self.assertEqual(2, order.event_count)
        self.assertEqual(denied, order.last_event)
        self.assertFalse(order.is_active)
        self.assertTrue(order.is_completed)

    def test_apply_order_submitted_event(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_SIM.symbol,
            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.assertTrue(order.is_active)
        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.symbol,
            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_active)
        self.assertTrue(order.is_working)
        self.assertFalse(order.is_completed)

    def test_apply_order_rejected_event(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_SIM.symbol,
            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_active)
        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.symbol,
            OrderSide.BUY,
            Quantity(100000),
            Price("0.99990"),
            TimeInForce.GTD,
            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_active)
        self.assertFalse(order.is_working)
        self.assertTrue(order.is_completed)

    def test_apply_order_cancelled_event(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_SIM.symbol,
            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_active)
        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.symbol,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
        )

        order.apply(TestStubs.event_order_submitted(order))
        order.apply(TestStubs.event_order_accepted(order))

        amended = OrderAmended(
            self.account_id,
            order.cl_ord_id,
            OrderId("1"),
            Quantity(120000),
            Price("1.00001"),
            UNIX_EPOCH,
            uuid4(),
            UNIX_EPOCH,
        )

        # Act
        order.apply(amended)

        # Assert
        self.assertEqual(OrderState.ACCEPTED, order.state)
        self.assertEqual(OrderId("1"), order.id)
        self.assertEqual(Quantity(120000), order.quantity)
        self.assertEqual(Price("1.00001"), order.price)
        self.assertTrue(order.is_active)
        self.assertTrue(order.is_working)
        self.assertFalse(order.is_completed)
        self.assertEqual(4, order.event_count)

    def test_apply_order_filled_event_to_order_without_accepted(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_SIM.symbol,
            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"),
            fill_price=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_price)
        self.assertEqual(1, len(order.execution_ids))
        self.assertFalse(order.is_active)
        self.assertFalse(order.is_working)
        self.assertTrue(order.is_completed)
        self.assertEqual(UNIX_EPOCH, order.filled_timestamp)

    def test_apply_order_filled_event_to_market_order(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_SIM.symbol,
            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"),
            fill_price=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_price)
        self.assertEqual(1, len(order.execution_ids))
        self.assertFalse(order.is_active)
        self.assertFalse(order.is_working)
        self.assertTrue(order.is_completed)
        self.assertEqual(UNIX_EPOCH, order.filled_timestamp)

    def test_apply_partial_fill_events_to_market_order_results_in_partially_filled(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_SIM.symbol,
            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,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S", "001"),
            fill_price=Price("1.00001"),
            fill_qty=Quantity(20000),
        )

        fill2 = TestStubs.event_order_filled(
            order,
            instrument=AUDUSD_SIM,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S", "001"),
            fill_price=Price("1.00002"),
            fill_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_price)
        self.assertEqual(2, len(order.execution_ids))
        self.assertTrue(order.is_active)
        self.assertTrue(order.is_working)
        self.assertFalse(order.is_completed)
        self.assertEqual(UNIX_EPOCH, order.filled_timestamp)

    def test_apply_filled_events_to_market_order_results_in_filled(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_SIM.symbol,
            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,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S", "001"),
            fill_price=Price("1.00001"),
            fill_qty=Quantity(20000),
        )

        fill2 = TestStubs.event_order_filled(
            order,
            instrument=AUDUSD_SIM,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S", "001"),
            fill_price=Price("1.00002"),
            fill_qty=Quantity(40000),
        )

        fill3 = TestStubs.event_order_filled(
            order,
            instrument=AUDUSD_SIM,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S", "001"),
            fill_price=Price("1.00003"),
            fill_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_price)
        self.assertEqual(3, len(order.execution_ids))
        self.assertFalse(order.is_active)
        self.assertFalse(order.is_working)
        self.assertTrue(order.is_completed)
        self.assertEqual(UNIX_EPOCH, order.filled_timestamp)

    def test_apply_order_filled_event_to_buy_limit_order(self):
        # Arrange
        order = self.order_factory.limit(
            AUDUSD_SIM.symbol,
            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.cl_ord_id,
            OrderId("1"),
            ExecutionId("E-1"),
            PositionId("P-1"),
            StrategyId.null(),
            order.symbol,
            order.side,
            order.quantity,
            order.quantity,
            Quantity(),
            Price("1.00001"),
            AUDUSD_SIM.quote_currency,
            AUDUSD_SIM.is_inverse,
            Money(0, USD),
            LiquiditySide.MAKER,
            UNIX_EPOCH,
            uuid4(),
            UNIX_EPOCH,
        )

        # 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_price)
        self.assertEqual(Decimal("0.00001"), order.slippage)
        self.assertFalse(order.is_active)
        self.assertFalse(order.is_working)
        self.assertTrue(order.is_completed)
        self.assertEqual(UNIX_EPOCH, order.filled_timestamp)

    def test_apply_order_partially_filled_event_to_buy_limit_order(self):
        # Arrange
        order = self.order_factory.limit(
            AUDUSD_SIM.symbol,
            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.cl_ord_id,
            OrderId("1"),
            ExecutionId("E-1"),
            PositionId("P-1"),
            StrategyId.null(),
            order.symbol,
            order.side,
            Quantity(50000),
            Quantity(50000),
            Quantity(50000),
            Price("0.999999"),
            AUDUSD_SIM.quote_currency,
            AUDUSD_SIM.is_inverse,
            Money(0, USD),
            LiquiditySide.MAKER,
            UNIX_EPOCH,
            uuid4(),
            UNIX_EPOCH,
        )

        # 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_price)
        self.assertEqual(Decimal("-0.000001"), order.slippage)
        self.assertTrue(order.is_active)
        self.assertTrue(order.is_working)
        self.assertFalse(order.is_completed)
        self.assertEqual(UNIX_EPOCH, order.filled_timestamp)
コード例 #2
0
class BacktestExecClientTests(unittest.TestCase):
    def setUp(self):
        # Fixture Setup
        self.clock = TestClock()
        self.uuid_factory = UUIDFactory()
        self.logger = TestLogger(self.clock)

        self.trader_id = TraderId("TESTER", "000")
        self.account_id = AccountId("BINANCE", "000")

        self.portfolio = Portfolio(
            clock=self.clock,
            logger=self.logger,
        )
        self.portfolio.register_cache(DataCache(self.logger))

        self.analyzer = PerformanceAnalyzer()

        database = BypassExecutionDatabase(
            trader_id=self.trader_id,
            logger=self.logger,
        )

        self.exec_engine = ExecutionEngine(
            database=database,
            portfolio=self.portfolio,
            clock=self.clock,
            logger=self.logger,
        )

        self.exchange = SimulatedExchange(
            venue=Venue("BINANCE"),
            oms_type=OMSType.NETTING,
            generate_position_ids=True,
            is_frozen_account=False,
            starting_balances=[Money(1_000_000, USD)],
            instruments=[ETHUSDT_BINANCE],
            modules=[],
            exec_cache=self.exec_engine.cache,
            fill_model=FillModel(),
            clock=self.clock,
            logger=self.logger,
        )

        self.exec_client = BacktestExecClient(
            exchange=self.exchange,
            account_id=self.account_id,
            engine=self.exec_engine,
            clock=self.clock,
            logger=self.logger,
        )

        self.order_factory = OrderFactory(
            trader_id=self.trader_id,
            strategy_id=StrategyId("SCALPER", "000"),
            clock=self.clock,
        )

    def test_is_connected_when_not_connected_returns_false(self):
        # Arrange

        # Act
        # Assert
        self.assertFalse(self.exec_client.is_connected())

    def test_connect(self):
        # Arrange
        # Act
        self.exec_client.connect()

        # Assert
        self.assertTrue(self.exec_client.is_connected())

    def test_disconnect(self):
        # Arrange
        self.exec_client.connect()

        # Act
        self.exec_client.disconnect()

        # Assert
        self.assertFalse(self.exec_client.is_connected())

    def test_reset(self):
        # Arrange
        # Act
        self.exec_client.reset()

        # Assert
        self.assertFalse(
            self.exec_client.is_connected())  # No exceptions raised

    def test_dispose(self):
        # Arrange
        # Act
        self.exec_client.dispose()

        # Assert
        self.assertFalse(
            self.exec_client.is_connected())  # No exceptions raised

    def test_submit_order_when_not_connected_logs_and_does_not_send(self):
        # Arrange
        strategy = TradingStrategy("000")
        order = self.order_factory.market(
            ETHUSDT_BINANCE.symbol,
            OrderSide.BUY,
            Quantity(100),
        )

        command = SubmitOrder(
            BINANCE,
            self.trader_id,
            self.account_id,
            strategy.id,
            PositionId.null(),
            order,
            self.uuid_factory.generate(),
            self.clock.utc_now(),
        )

        # Act
        self.exec_client.submit_order(command)

        # Assert
        self.assertEqual(OrderState.INITIALIZED, order.state)

    def test_submit_bracket_order_when_not_connected_logs_and_does_not_send(
            self):
        # Arrange
        strategy = TradingStrategy("000")
        entry = self.order_factory.market(
            ETHUSDT_BINANCE.symbol,
            OrderSide.BUY,
            Quantity(100),
        )

        bracket = self.order_factory.bracket(entry, Price("500.00000"))

        command = SubmitBracketOrder(
            BINANCE,
            self.trader_id,
            self.account_id,
            strategy.id,
            bracket,
            self.uuid_factory.generate(),
            self.clock.utc_now(),
        )

        # Act
        self.exec_client.submit_bracket_order(command)

        # Assert
        self.assertEqual(OrderState.INITIALIZED, entry.state)

    def test_cancel_order_when_not_connected_logs_and_does_not_send(self):
        # Arrange
        order = self.order_factory.market(
            ETHUSDT_BINANCE.symbol,
            OrderSide.BUY,
            Quantity(100),
        )

        command = CancelOrder(
            BINANCE,
            self.trader_id,
            self.account_id,
            order.cl_ord_id,
            self.uuid_factory.generate(),
            self.clock.utc_now(),
        )

        # Act
        self.exec_client.cancel_order(command)

        # Assert
        self.assertTrue(True)  # No exceptions raised

    def test_modify_order_when_not_connected_logs_and_does_not_send(self):
        # Arrange
        order = self.order_factory.stop_market(
            ETHUSDT_BINANCE.symbol,
            OrderSide.BUY,
            Quantity(100),
            Price("1000.00"),
        )

        command = ModifyOrder(
            BINANCE,
            self.trader_id,
            self.account_id,
            order.cl_ord_id,
            Quantity(100),
            Price("1010.00"),
            self.uuid_factory.generate(),
            self.clock.utc_now(),
        )

        # Act
        self.exec_client.modify_order(command)

        # Assert
        self.assertTrue(True)  # No exceptions raised
コード例 #3
0
class ExecutionClientTests(unittest.TestCase):

    def setUp(self):
        # Fixture Setup
        self.clock = TestClock()
        self.uuid_factory = UUIDFactory()
        self.logger = TestLogger(self.clock)

        self.trader_id = TraderId("TESTER", "000")
        self.account_id = TestStubs.account_id()

        portfolio = Portfolio(
            clock=self.clock,
            logger=self.logger,
        )
        portfolio.register_cache(DataCache(self.logger))

        database = BypassExecutionDatabase(trader_id=self.trader_id, logger=self.logger)
        self.exec_engine = ExecutionEngine(
            database=database,
            portfolio=portfolio,
            clock=self.clock,
            logger=self.logger,
        )

        self.venue = Venue("SIM")

        self.client = ExecutionClient(
            venue=self.venue,
            account_id=self.account_id,
            engine=self.exec_engine,
            clock=self.clock,
            logger=self.logger,
        )

        self.order_factory = OrderFactory(
            trader_id=TraderId("TESTER", "000"),
            strategy_id=StrategyId("S", "001"),
            clock=TestClock(),
        )

    def test_connect_when_not_implemented_raises_exception(self):
        self.assertRaises(NotImplementedError, self.client.connect)

    def test_disconnect_when_not_implemented_raises_exception(self):
        self.assertRaises(NotImplementedError, self.client.disconnect)

    def test_reset_when_not_implemented_raises_exception(self):
        self.assertRaises(NotImplementedError, self.client.reset)

    def test_dispose_when_not_implemented_raises_exception(self):
        self.assertRaises(NotImplementedError, self.client.dispose)

    def test_submit_order_raises_exception(self):
        order = self.order_factory.limit(
            AUDUSD_SIM.symbol,
            OrderSide.SELL,
            Quantity(100000),
            Price("1.00000"),
        )

        command = SubmitOrder(
            self.venue,
            self.trader_id,
            self.account_id,
            StrategyId("SCALPER", "001"),
            PositionId.null(),
            order,
            self.uuid_factory.generate(),
            self.clock.utc_now(),
        )

        self.assertRaises(NotImplementedError, self.client.submit_order, command)

    def test_submit_bracket_order_raises_not_implemented_error(self):
        entry_order = self.order_factory.stop_market(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
            Price("0.99995"),
        )

        # Act
        bracket_order = self.order_factory.bracket(
            entry_order,
            Price("0.99990"),
            Price("1.00010"),
        )

        command = SubmitBracketOrder(
            self.venue,
            self.trader_id,
            self.account_id,
            StrategyId("SCALPER", "001"),
            bracket_order,
            self.uuid_factory.generate(),
            self.clock.utc_now(),
        )

        self.assertRaises(NotImplementedError, self.client.submit_bracket_order, command)

    def test_amend_order_raises_not_implemented_error(self):
        # Arrange
        # Act
        command = AmendOrder(
            self.venue,
            self.trader_id,
            self.account_id,
            ClientOrderId("O-123456789"),
            Quantity(120000),
            Price("1.00000"),
            self.uuid_factory.generate(),
            self.clock.utc_now(),
        )

        # Assert
        self.assertRaises(NotImplementedError, self.client.amend_order, command)

    def test_cancel_order_raises_not_implemented_error(self):
        # Arrange
        # Act
        command = CancelOrder(
            self.venue,
            self.trader_id,
            self.account_id,
            ClientOrderId("O-123456789"),
            OrderId("001"),
            self.uuid_factory.generate(),
            self.clock.utc_now(),
        )

        # Assert
        self.assertRaises(NotImplementedError, self.client.cancel_order, command)

    def test_handle_event_sends_to_execution_engine(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
        )

        fill = TestStubs.event_order_filled(
            order,
            AUDUSD_SIM,
            PositionId("P-123456"),
            StrategyId("S", "001"),
            Price("1.00001"),
        )

        # Act
        self.client._handle_event_py(fill)  # Accessing protected method

        # Assert
        self.assertEqual(1, self.exec_engine.event_count)
class TestMsgPackCommandSerializer:
    def setup(self):
        # Fixture Setup
        self.venue = Venue("SIM")
        self.trader_id = TestStubs.trader_id()
        self.account_id = TestStubs.account_id()
        self.serializer = MsgPackCommandSerializer()
        self.order_factory = OrderFactory(
            trader_id=self.trader_id,
            strategy_id=StrategyId("S-001"),
            clock=TestClock(),
        )

    def test_serialize_and_deserialize_submit_order_commands(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity(100000, precision=0),
        )

        command = SubmitOrder(
            self.trader_id,
            StrategyId("SCALPER-001"),
            PositionId("P-123456"),
            order,
            uuid4(),
            0,
        )

        # Act
        serialized = self.serializer.serialize(command)
        deserialized = self.serializer.deserialize(serialized)

        # Assert
        assert deserialized == command
        assert deserialized.order == order
        print(command)
        print(len(serialized))
        print(serialized)
        print(b64encode(serialized))

    def test_serialize_and_deserialize_submit_bracket_order_no_take_profit_commands(
        self, ):
        # Arrange
        entry_order = self.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity(100000, precision=0),
        )

        bracket_order = self.order_factory.bracket(
            entry_order,
            stop_loss=Price(0.99900, precision=5),
            take_profit=Price(1.00100, precision=5),
        )

        command = SubmitBracketOrder(
            self.trader_id,
            StrategyId("SCALPER-001"),
            bracket_order,
            uuid4(),
            0,
        )

        # Act
        serialized = self.serializer.serialize(command)
        deserialized = self.serializer.deserialize(serialized)

        # Assert
        assert deserialized == command
        assert deserialized.bracket_order == bracket_order
        print(b64encode(serialized))
        print(command)

    def test_serialize_and_deserialize_submit_bracket_order_with_take_profit_commands(
        self, ):
        # Arrange
        entry_order = self.order_factory.limit(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity(100000, precision=0),
            Price(1.00000, precision=5),
        )

        bracket_order = self.order_factory.bracket(
            entry_order,
            stop_loss=Price(0.99900, precision=5),
            take_profit=Price(1.00010, precision=5),
        )

        command = SubmitBracketOrder(
            self.trader_id,
            StrategyId("SCALPER-001"),
            bracket_order,
            uuid4(),
            0,
        )

        # Act
        serialized = self.serializer.serialize(command)
        deserialized = self.serializer.deserialize(serialized)

        # Assert
        assert deserialized == command
        assert deserialized.bracket_order == bracket_order
        print(b64encode(serialized))
        print(command)

    def test_serialize_and_deserialize_amend_order_commands(self):
        # Arrange
        command = UpdateOrder(
            self.trader_id,
            StrategyId("SCALPER-001"),
            AUDUSD_SIM.id,
            ClientOrderId("O-123456"),
            VenueOrderId("001"),
            Quantity(100000, precision=0),
            Price(1.00001, precision=5),
            None,
            uuid4(),
            0,
        )

        # Act
        serialized = self.serializer.serialize(command)
        deserialized = self.serializer.deserialize(serialized)

        # Assert
        assert deserialized == command
        print(b64encode(serialized))
        print(command)

    def test_serialize_and_deserialize_cancel_order_commands(self):
        # Arrange
        command = CancelOrder(
            self.trader_id,
            StrategyId("SCALPER-001"),
            AUDUSD_SIM.id,
            ClientOrderId("O-123456"),
            VenueOrderId("001"),
            uuid4(),
            0,
        )

        # Act
        serialized = self.serializer.serialize(command)
        deserialized = self.serializer.deserialize(serialized)

        # Assert
        assert deserialized == command
        print(b64encode(serialized))
        print(command)
コード例 #5
0
class MsgPackCommandSerializerTests(unittest.TestCase):
    def setUp(self):
        # Fixture Setup
        self.venue = Venue("SIM")
        self.trader_id = TestStubs.trader_id()
        self.account_id = TestStubs.account_id()
        self.serializer = MsgPackCommandSerializer()
        self.order_factory = OrderFactory(
            trader_id=self.trader_id,
            strategy_id=StrategyId("S", "001"),
            clock=TestClock(),
        )

    def test_serialize_and_deserialize_submit_order_commands(self):
        # Arrange
        order = self.order_factory.market(AUDUSD_SIM.symbol, OrderSide.BUY,
                                          Quantity(100000))

        command = SubmitOrder(
            self.venue,
            self.trader_id,
            self.account_id,
            StrategyId("SCALPER", "01"),
            PositionId("P-123456"),
            order,
            uuid4(),
            UNIX_EPOCH,
        )

        # Act
        serialized = self.serializer.serialize(command)
        deserialized = self.serializer.deserialize(serialized)

        # Assert
        self.assertEqual(command, deserialized)
        self.assertEqual(order, deserialized.order)
        print(command)
        print(len(serialized))
        print(serialized)
        print(b64encode(serialized))

    def test_serialize_and_deserialize_submit_bracket_order_no_take_profit_commands(
            self):
        # Arrange
        entry_order = self.order_factory.market(AUDUSD_SIM.symbol,
                                                OrderSide.BUY,
                                                Quantity(100000))

        bracket_order = self.order_factory.bracket(
            entry_order,
            stop_loss=Price("0.99900"),
        )

        command = SubmitBracketOrder(
            self.venue,
            self.trader_id,
            self.account_id,
            StrategyId("SCALPER", "01"),
            bracket_order,
            uuid4(),
            UNIX_EPOCH,
        )

        # Act
        serialized = self.serializer.serialize(command)
        deserialized = self.serializer.deserialize(serialized)

        # Assert
        self.assertEqual(command, deserialized)
        self.assertEqual(bracket_order, deserialized.bracket_order)
        print(b64encode(serialized))
        print(command)

    def test_serialize_and_deserialize_submit_bracket_order_with_take_profit_commands(
            self):
        # Arrange
        entry_order = self.order_factory.limit(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
        )

        bracket_order = self.order_factory.bracket(
            entry_order,
            stop_loss=Price("0.99900"),
            take_profit=Price("1.00010"),
        )

        command = SubmitBracketOrder(
            self.venue,
            self.trader_id,
            self.account_id,
            StrategyId("SCALPER", "01"),
            bracket_order,
            uuid4(),
            UNIX_EPOCH,
        )

        # Act
        serialized = self.serializer.serialize(command)
        deserialized = self.serializer.deserialize(serialized)

        # Assert
        self.assertEqual(command, deserialized)
        self.assertEqual(bracket_order, deserialized.bracket_order)
        print(b64encode(serialized))
        print(command)

    def test_serialize_and_deserialize_modify_order_commands(self):
        # Arrange
        command = ModifyOrder(
            self.venue,
            self.trader_id,
            self.account_id,
            ClientOrderId("O-123456"),
            Quantity(100000),
            Price("1.00001"),
            uuid4(),
            UNIX_EPOCH,
        )

        # Act
        serialized = self.serializer.serialize(command)
        deserialized = self.serializer.deserialize(serialized)

        # Assert
        self.assertEqual(command, deserialized)
        print(b64encode(serialized))
        print(command)

    def test_serialize_and_deserialize_cancel_order_commands(self):
        # Arrange
        command = CancelOrder(
            self.venue,
            self.trader_id,
            self.account_id,
            ClientOrderId("O-123456"),
            uuid4(),
            UNIX_EPOCH,
        )

        # Act
        serialized = self.serializer.serialize(command)
        deserialized = self.serializer.deserialize(serialized)

        # Assert
        self.assertEqual(command, deserialized)
        print(b64encode(serialized))
        print(command)
コード例 #6
0
class ExecutionClientTests(unittest.TestCase):
    def setUp(self):
        # Fixture Setup
        self.clock = TestClock()
        self.uuid_factory = UUIDFactory()
        self.logger = Logger(self.clock)

        self.trader_id = TraderId("TESTER-000")
        self.account_id = TestStubs.account_id()

        self.cache = TestStubs.cache()

        self.portfolio = Portfolio(
            cache=self.cache,
            clock=self.clock,
            logger=self.logger,
        )

        self.exec_engine = ExecutionEngine(
            portfolio=self.portfolio,
            cache=self.cache,
            clock=self.clock,
            logger=self.logger,
        )

        self.venue = Venue("SIM")

        self.client = ExecutionClient(
            client_id=ClientId(self.venue.value),
            venue_type=VenueType.ECN,
            account_id=TestStubs.account_id(),
            account_type=AccountType.MARGIN,
            base_currency=USD,
            engine=self.exec_engine,
            clock=self.clock,
            logger=self.logger,
        )

        self.order_factory = OrderFactory(
            trader_id=TraderId("TESTER-000"),
            strategy_id=StrategyId("S-001"),
            clock=TestClock(),
        )

    def test_venue_when_brokerage_returns_client_id_value_as_venue(self):
        assert self.client.venue == self.venue

    def test_venue_when_brokerage_multi_venue_returns_none(self):
        # Arrange
        client = ExecutionClient(
            client_id=ClientId("IB"),
            venue_type=VenueType.BROKERAGE_MULTI_VENUE,
            account_id=AccountId("IB", "U1258001"),
            account_type=AccountType.MARGIN,
            base_currency=USD,
            engine=self.exec_engine,
            clock=self.clock,
            logger=self.logger,
        )

        # Act, Assert
        assert client.venue is None

    def test_connect_when_not_implemented_raises_exception(self):
        self.assertRaises(NotImplementedError, self.client.connect)

    def test_disconnect_when_not_implemented_raises_exception(self):
        self.assertRaises(NotImplementedError, self.client.disconnect)

    def test_reset_when_not_implemented_raises_exception(self):
        self.assertRaises(NotImplementedError, self.client.reset)

    def test_dispose_when_not_implemented_raises_exception(self):
        self.assertRaises(NotImplementedError, self.client.dispose)

    def test_submit_order_raises_exception(self):
        order = self.order_factory.limit(
            AUDUSD_SIM.id,
            OrderSide.SELL,
            Quantity.from_int(100000),
            Price.from_str("1.00000"),
        )

        command = SubmitOrder(
            self.trader_id,
            order.strategy_id,
            PositionId.null(),
            order,
            self.uuid_factory.generate(),
            self.clock.timestamp_ns(),
        )

        self.assertRaises(NotImplementedError, self.client.submit_order,
                          command)

    def test_submit_bracket_order_raises_not_implemented_error(self):
        entry_order = self.order_factory.stop_market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
            Price.from_str("0.99995"),
        )

        # Act
        bracket_order = self.order_factory.bracket(
            entry_order,
            Price.from_str("0.99990"),
            Price.from_str("1.00010"),
        )

        command = SubmitBracketOrder(
            self.trader_id,
            entry_order.strategy_id,
            bracket_order,
            self.uuid_factory.generate(),
            self.clock.timestamp_ns(),
        )

        self.assertRaises(NotImplementedError,
                          self.client.submit_bracket_order, command)

    def test_update_order_raises_not_implemented_error(self):
        # Arrange
        # Act
        command = UpdateOrder(
            self.trader_id,
            StrategyId("SCALPER-001"),
            AUDUSD_SIM.id,
            ClientOrderId("O-123456789"),
            VenueOrderId("001"),
            Quantity.from_int(120000),
            Price.from_str("1.00000"),
            None,
            self.uuid_factory.generate(),
            self.clock.timestamp_ns(),
        )

        # Assert
        self.assertRaises(NotImplementedError, self.client.update_order,
                          command)

    def test_cancel_order_raises_not_implemented_error(self):
        # Arrange
        # Act
        command = CancelOrder(
            self.trader_id,
            StrategyId("SCALPER-001"),
            AUDUSD_SIM.id,
            ClientOrderId("O-123456789"),
            VenueOrderId("001"),
            self.uuid_factory.generate(),
            self.clock.timestamp_ns(),
        )

        # Assert
        self.assertRaises(NotImplementedError, self.client.cancel_order,
                          command)
コード例 #7
0
class OrderTests(unittest.TestCase):

    def setUp(self):
        # Fixture Setup
        self.account_id = TestStubs.account_id()
        self.order_factory = OrderFactory(
            strategy_id=StrategyId("S", "001"),
            id_tag_trader=IdTag("001"),
            id_tag_strategy=IdTag("001"),
            clock=TestClock(),
            uuid_factory=TestUUIDFactory(),
        )

    def test_get_opposite_side_returns_expected_sides(self):
        # Arrange
        # Act
        result1 = opposite_side(OrderSide.BUY)
        result2 = opposite_side(OrderSide.SELL)

        # Assert
        self.assertEqual(OrderSide.SELL, result1)
        self.assertEqual(OrderSide.BUY, result2)

    def test_get_flatten_side_with_long_or_short_position_side_returns_expected_sides(self):
        # Arrange
        # Act
        result1 = flatten_side(PositionSide.LONG)
        result2 = flatten_side(PositionSide.SHORT)

        # Assert
        self.assertEqual(OrderSide.SELL, result1)
        self.assertEqual(OrderSide.BUY, result2)

    def test_market_order_with_quantity_zero_raises_exception(self):
        # Arrange
        # Act
        self.assertRaises(
            ValueError,
            MarketOrder,
            ClientOrderId("O-123456"),
            StrategyId("S", "001"),
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(),
            TimeInForce.DAY,
            uuid4(),
            UNIX_EPOCH,
        )

    def test_market_order_with_invalid_tif_raises_exception(self):
        # Arrange
        # Act
        self.assertRaises(
            ValueError,
            MarketOrder,
            ClientOrderId("O-123456"),
            StrategyId("S", "001"),
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100),
            TimeInForce.GTD,
            uuid4(),
            UNIX_EPOCH,
        )

    def test_stop_order_with_gtd_and_expire_time_none_raises_exception(self):
        # Arrange
        # Act
        self.assertRaises(
            TypeError,
            StopMarketOrder,
            ClientOrderId("O-123456"),
            StrategyId("S", "001"),
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000),
            price=Price("1.00000"),
            init_id=uuid4(),
            timestamp=UNIX_EPOCH,
            time_in_force=TimeInForce.GTD,
            expire_time=None,
        )

    def test_reset_order_factory(self):
        # Arrange
        self.order_factory.limit(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
        )

        # Act
        self.order_factory.reset()

        order2 = self.order_factory.limit(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
        )

        self.assertEqual(ClientOrderId("O-19700101-000000-001-001-1"), order2.cl_ord_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"),
        )

        order2 = self.order_factory.limit(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
        )

        order3 = self.order_factory.limit(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
        )

        order4 = self.order_factory.limit(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00001"),
        )

        # Assert
        self.assertEqual(Price("1.00000"), order1.price)
        self.assertEqual(Price("1.00000"), order2.price)
        self.assertEqual(Price("1.00000"), order3.price)
        self.assertEqual(Price("1.00001"), order4.price)

    def test_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)
        self.assertEqual(UNIX_EPOCH, order.last_event().timestamp)

    def test_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 TODO: String formatting
        # self.assertEqual("MarketOrder(cl_ord_id=O-19700101-000000-001-001-1, state=INITIALIZED, BUY 100K AUD/USD.FXCM MARKET DAY)", str(order))  # noqa
        # self.assertTrue(repr(order).startswith("<MarketOrder(cl_ord_id=O-19700101-000000-001-001-1, state=INITIALIZED, BUY 100K AUD/USD.FXCM MARKET DAY) object at"))  # noqa

    def test_initialize_limit_order(self):
        # Arrange
        # Act
        order = self.order_factory.limit(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
        )

        # 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_initialize_limit_order_with_expire_time(self):
        # Arrange
        # Act
        order = self.order_factory.limit(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
            TimeInForce.GTD,
            UNIX_EPOCH,
        )

        # Assert
        self.assertEqual(AUDUSD_FXCM, order.symbol)
        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())

    def test_initialize_stop_order(self):
        # Arrange
        # Act
        order = self.order_factory.stop(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
        )

        # Assert
        self.assertEqual(OrderType.STOP_MARKET, order.type)
        self.assertEqual(OrderState.INITIALIZED, order.state())
        self.assertEqual(TimeInForce.DAY, order.time_in_force)
        self.assertFalse(order.is_completed())

    def test_initialize_bracket_order_market_with_no_take_profit(self):
        # Arrange
        entry_order = self.order_factory.market(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000))

        # Act
        bracket_order = self.order_factory.bracket(entry_order, Price("0.99990"))

        # Assert
        self.assertEqual(AUDUSD_FXCM, bracket_order.stop_loss.symbol)
        self.assertFalse(bracket_order.has_take_profit)
        self.assertEqual(ClientOrderId("O-19700101-000000-001-001-1"), bracket_order.entry.cl_ord_id)
        self.assertEqual(ClientOrderId("O-19700101-000000-001-001-2"), bracket_order.stop_loss.cl_ord_id)
        self.assertEqual(OrderSide.SELL, bracket_order.stop_loss.side)
        self.assertEqual(Quantity(100000), bracket_order.entry.quantity)
        self.assertEqual(Quantity(100000), bracket_order.stop_loss.quantity)
        self.assertEqual(Price("0.99990"), bracket_order.stop_loss.price)
        self.assertEqual(TimeInForce.GTC, bracket_order.stop_loss.time_in_force)
        self.assertEqual(None, bracket_order.stop_loss.expire_time)
        self.assertEqual(BracketOrderId("BO-19700101-000000-001-001-1"), bracket_order.id)
        self.assertEqual(UNIX_EPOCH, bracket_order.timestamp)

    def test_can_initialize_bracket_order_stop_with_take_profit(self):
        # Arrange
        entry_order = self.order_factory.stop(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000),
            Price("0.99995"),
        )

        # Act
        bracket_order = self.order_factory.bracket(
            entry_order,
            Price("0.99990"),
            Price("1.00010"),
        )

        # Assert
        self.assertEqual(AUDUSD_FXCM, bracket_order.stop_loss.symbol)
        self.assertTrue(bracket_order.has_take_profit)
        self.assertEqual(AUDUSD_FXCM, bracket_order.take_profit.symbol)
        self.assertEqual(ClientOrderId("O-19700101-000000-001-001-1"), bracket_order.entry.cl_ord_id)
        self.assertEqual(ClientOrderId("O-19700101-000000-001-001-2"), bracket_order.stop_loss.cl_ord_id)
        self.assertEqual(ClientOrderId("O-19700101-000000-001-001-3"), bracket_order.take_profit.cl_ord_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-001-001-1"), bracket_order.id)
        self.assertEqual(UNIX_EPOCH, bracket_order.timestamp)

    # def test_bracket_order_str_and_repr(self):
    #     # Arrange
    #     # Act
    #     entry_order = self.order_factory.market(
    #         AUDUSD_FXCM,
    #         OrderSide.BUY,
    #         Quantity(100000),
    #     )
    #
    #     bracket_order = self.order_factory.bracket(
    #         entry_order,
    #         Price("0.99990"),
    #         Price("1.00010"),
    #     )

        # Assert # TODO: Fix string formatting
        # self.assertEqual("BracketOrder(id=BO-19700101-000000-001-001-1, EntryMarketOrder(cl_ord_id=O-19700101-000000-001-001-1, state=INITIALIZED, BUY 100K AUD/USD.FXCM MARKET DAY), SL=0.99990, TP=1.00010)", str(bracket_order))  # noqa
        # self.assertTrue(repr(bracket_order).startswith("<BracketOrder(id=BO-19700101-000000-001-001-1, EntryMarketOrder(cl_ord_id=O-19700101-000000-001-001-1, state=INITIALIZED, BUY 100K AUD/USD.FXCM MARKET DAY), SL=0.99990, TP=1.00010) object at"))  # noqa
        # self.assertTrue(repr(bracket_order).endswith(">"))

    def test_can_apply_order_submitted_event_to_order(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_FXCM,
            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_completed())

    def test_can_apply_order_accepted_event_to_order(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000))

        submitted = TestStubs.event_order_submitted(order)
        accepted = TestStubs.event_order_accepted(order)

        order.apply(submitted)

        # Act
        order.apply(accepted)

        # 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))

        submitted = TestStubs.event_order_submitted(order)
        rejected = TestStubs.event_order_rejected(order)

        order.apply(submitted)

        # Act
        order.apply(rejected)

        # Assert
        self.assertEqual(OrderState.REJECTED, order.state())
        self.assertTrue(order.is_completed())

    def test_can_apply_order_working_event_to_stop_order(self):
        # Arrange
        order = self.order_factory.stop(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
        )

        submitted = TestStubs.event_order_submitted(order)
        accepted = TestStubs.event_order_accepted(order)
        working = TestStubs.event_order_working(order)

        order.apply(submitted)
        order.apply(accepted)

        # Act
        order.apply(working)

        # Assert
        # print(order)
        self.assertEqual(OrderState.WORKING, order.state())
        self.assertEqual(OrderId("1"), order.id)
        self.assertFalse(order.is_completed())
        self.assertTrue(order.is_working())
        self.assertEqual(None, order.filled_timestamp)

    def test_can_apply_order_expired_event_to_stop_order(self):
        # Arrange
        order = self.order_factory.stop(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000),
            Price("0.99990"),
            TimeInForce.GTD,
            UNIX_EPOCH)

        submitted = TestStubs.event_order_submitted(order)
        accepted = TestStubs.event_order_accepted(order)
        working = TestStubs.event_order_working(order)
        expired = TestStubs.event_order_expired(order)

        order.apply(submitted)
        order.apply(accepted)
        order.apply(working)

        # Act
        order.apply(expired)

        # 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))

        submitted = TestStubs.event_order_submitted(order)
        accepted = TestStubs.event_order_accepted(order)
        cancelled = TestStubs.event_order_cancelled(order)

        order.apply(submitted)
        order.apply(accepted)

        # Act
        order.apply(cancelled)

        # Assert
        self.assertEqual(OrderState.CANCELLED, order.state())
        self.assertTrue(order.is_completed())

    def test_can_apply_order_modified_event_to_stop_order(self):
        # Arrange
        order = self.order_factory.stop(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"))

        submitted = TestStubs.event_order_submitted(order)
        accepted = TestStubs.event_order_accepted(order)
        working = TestStubs.event_order_working(order)

        modified = OrderModified(
            self.account_id,
            order.cl_ord_id,
            OrderId("1"),
            Quantity(120000),
            Price("1.00001"),
            UNIX_EPOCH,
            uuid4(),
            UNIX_EPOCH)

        order.apply(submitted)
        order.apply(accepted)
        order.apply(working)

        # Act
        order.apply(modified)

        # Assert
        self.assertEqual(OrderState.WORKING, order.state())
        self.assertEqual(OrderId("1"), 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(5, 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))

        submitted = TestStubs.event_order_submitted(order)
        accepted = TestStubs.event_order_accepted(order)

        filled = TestStubs.event_order_filled(
            order,
            PositionId("P-123456"),
            StrategyId("S", "001"),
            Price("1.00001"))

        order.apply(submitted)
        order.apply(accepted)

        # Act
        order.apply(filled)

        # Assert
        self.assertEqual(OrderState.FILLED, order.state())
        self.assertEqual(Quantity(100000), order.filled_qty)
        self.assertEqual(Price("1.00001"), order.avg_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"))

        submitted = TestStubs.event_order_submitted(order)
        accepted = TestStubs.event_order_accepted(order)
        working = TestStubs.event_order_working(order)

        filled = OrderFilled(
            self.account_id,
            order.cl_ord_id,
            OrderId("1"),
            ExecutionId("E-1"),
            PositionId("P-1"),
            StrategyId("S", "NULL"),
            order.symbol,
            order.side,
            order.quantity,
            Quantity(),
            Price("1.00001"),
            Money(0, USD),
            LiquiditySide.MAKER,
            USD,
            USD,
            UNIX_EPOCH,
            uuid4(),
            UNIX_EPOCH,
        )

        order.apply(submitted)
        order.apply(accepted)
        order.apply(working)

        # 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(Price("1.00001"), order.avg_price)
        self.assertEqual(Decimal("0.00001"), 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"))

        submitted = TestStubs.event_order_submitted(order)
        accepted = TestStubs.event_order_accepted(order)
        working = TestStubs.event_order_working(order)

        partially = OrderFilled(
            self.account_id,
            order.cl_ord_id,
            OrderId("1"),
            ExecutionId("E-1"),
            PositionId("P-1"),
            StrategyId("S", "NULL"),
            order.symbol,
            order.side,
            Quantity(50000),
            Quantity(50000),
            Price("0.999999"),
            Money(0, USD),
            LiquiditySide.MAKER,
            USD,
            USD,
            UNIX_EPOCH,
            uuid4(),
            UNIX_EPOCH)

        order.apply(submitted)
        order.apply(accepted)
        order.apply(working)

        # 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(Price("0.999999"), order.avg_price)
        self.assertEqual(Decimal("-0.000001"), order.slippage)
        self.assertFalse(order.is_completed())
        self.assertEqual(UNIX_EPOCH, order.filled_timestamp)
コード例 #8
0
class TestBacktestExecClientTests:
    def setup(self):
        # Fixture Setup
        self.clock = TestClock()
        self.uuid_factory = UUIDFactory()
        self.logger = Logger(self.clock)

        self.trader_id = TraderId("TESTER-000")
        self.account_id = AccountId("BINANCE", "000")

        self.cache = TestStubs.cache()

        self.portfolio = Portfolio(
            cache=self.cache,
            clock=self.clock,
            logger=self.logger,
        )

        self.exec_engine = ExecutionEngine(
            portfolio=self.portfolio,
            cache=self.cache,
            clock=self.clock,
            logger=self.logger,
        )

        self.exchange = SimulatedExchange(
            venue=Venue("BINANCE"),
            venue_type=VenueType.EXCHANGE,
            oms_type=OMSType.NETTING,
            account_type=AccountType.CASH,
            base_currency=None,  # Multi-currency account
            starting_balances=[Money(1_000_000, USDT)],
            is_frozen_account=False,
            instruments=[ETHUSDT_BINANCE],
            modules=[],
            cache=self.exec_engine.cache,
            fill_model=FillModel(),
            clock=self.clock,
            logger=self.logger,
        )

        self.exec_client = BacktestExecClient(
            exchange=self.exchange,
            account_id=self.account_id,
            account_type=AccountType.CASH,
            base_currency=None,  # Multi-currency account
            engine=self.exec_engine,
            clock=self.clock,
            logger=self.logger,
        )

        self.order_factory = OrderFactory(
            trader_id=self.trader_id,
            strategy_id=StrategyId("SCALPER-001"),
            clock=self.clock,
        )

    def test_is_connected_when_not_connected_returns_false(self):
        # Arrange

        # Act
        # Assert
        assert not self.exec_client.is_connected

    def test_connect(self):
        # Arrange
        # Act
        self.exec_client.connect()

        # Assert
        assert self.exec_client.is_connected

    def test_disconnect(self):
        # Arrange
        self.exec_client.connect()

        # Act
        self.exec_client.disconnect()

        # Assert
        assert not self.exec_client.is_connected

    def test_reset(self):
        # Arrange
        # Act
        self.exec_client.reset()

        # Assert
        assert not self.exec_client.is_connected

    def test_dispose(self):
        # Arrange
        # Act
        self.exec_client.dispose()

        # Assert
        assert not self.exec_client.is_connected

    def test_submit_order_when_not_connected_logs_and_does_not_send(self):
        # Arrange
        strategy = TradingStrategy("000")
        order = self.order_factory.market(
            ETHUSDT_BINANCE.id,
            OrderSide.BUY,
            Quantity.from_int(100),
        )

        command = SubmitOrder(
            self.trader_id,
            strategy.id,
            PositionId.null(),
            order,
            self.uuid_factory.generate(),
            self.clock.timestamp_ns(),
        )

        # Act
        self.exec_client.submit_order(command)

        # Assert
        assert order.state == OrderState.INITIALIZED

    def test_submit_bracket_order_when_not_connected_logs_and_does_not_send(
            self):
        # Arrange
        strategy = TradingStrategy("000")
        entry = self.order_factory.market(
            ETHUSDT_BINANCE.id,
            OrderSide.BUY,
            Quantity.from_int(100),
        )

        bracket = self.order_factory.bracket(
            entry,
            Price.from_str("500.00000"),
            Price.from_str("600.00000"),
        )

        command = SubmitBracketOrder(
            self.trader_id,
            strategy.id,
            bracket,
            self.uuid_factory.generate(),
            self.clock.timestamp_ns(),
        )

        # Act
        self.exec_client.submit_bracket_order(command)

        # Assert
        assert entry.state == OrderState.INITIALIZED

    def test_cancel_order_when_not_connected_logs_and_does_not_send(self):
        # Arrange
        order = self.order_factory.market(
            ETHUSDT_BINANCE.id,
            OrderSide.BUY,
            Quantity.from_int(100),
        )

        command = CancelOrder(
            self.trader_id,
            self.order_factory.strategy_id,
            order.instrument_id,
            order.client_order_id,
            order.venue_order_id,
            self.uuid_factory.generate(),
            self.clock.timestamp_ns(),
        )

        # Act
        self.exec_client.cancel_order(command)

        # Assert
        assert True  # No exceptions raised

    def test_update_order_when_not_connected_logs_and_does_not_send(self):
        # Arrange
        order = self.order_factory.stop_market(
            ETHUSDT_BINANCE.id,
            OrderSide.BUY,
            Quantity.from_int(100),
            Price.from_str("1000.00"),
        )

        command = UpdateOrder(
            self.trader_id,
            order.strategy_id,
            order.instrument_id,
            order.client_order_id,
            order.venue_order_id,
            Quantity.from_int(100),
            Price.from_str("1010.00"),
            None,
            self.uuid_factory.generate(),
            self.clock.timestamp_ns(),
        )

        # Act
        self.exec_client.update_order(command)

        # Assert
        assert True  # No exceptions raised
コード例 #9
0
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.zero(),
            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.from_int(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.from_int(100000),
            price=Price.from_str("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.from_int(100000),
            price=Price.from_str("1.00001"),
            trigger=Price.from_str("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.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"),
        )

        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.from_int(100000),
            Price.from_str("1.00000"),
        )

        order2 = self.order_factory.limit(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
            Price.from_str("1.00001"),
        )

        # Assert
        self.assertEqual(Price.from_str("1.00000"), order1.price)
        self.assertEqual(Price.from_str("1.00001"), order2.price)

    def test_initialize_buy_market_order(self):
        # Arrange
        # Act
        order = self.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(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.from_int(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.from_int(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.from_int(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.from_int(100000),
            Price.from_str("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.from_int(100000),
            Price.from_str("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.from_str("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.from_int(100000),
            Price.from_str("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.from_int(100000),
            Price.from_str("1.00000"),
            Price.from_str("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.from_int(100000),
        )

        entry2 = self.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
        )

        bracket_order1 = self.order_factory.bracket(entry1,
                                                    Price.from_str("1.00000"),
                                                    Price.from_str("1.00010"))
        bracket_order2 = self.order_factory.bracket(entry2,
                                                    Price.from_str("1.00000"),
                                                    Price.from_str("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.from_int(100000),
            Price.from_str("0.99995"),
        )

        # Act
        bracket_order = self.order_factory.bracket(
            entry_order,
            Price.from_str("0.99990"),
            Price.from_str("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.from_int(100000),
                         bracket_order.stop_loss.quantity)
        self.assertEqual(Quantity.from_int(100000),
                         bracket_order.take_profit.quantity)
        self.assertEqual(Price.from_str("0.99990"),
                         bracket_order.stop_loss.price)
        self.assertEqual(Price.from_str("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(ClientOrderLinkId("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.from_int(100000),
        )

        bracket_order = self.order_factory.bracket(
            entry_order,
            Price.from_str("0.99990"),
            Price.from_str("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.from_int(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.from_int(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.from_int(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.from_int(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.from_int(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.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
        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.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
        self.assertEqual(OrderState.TRIGGERED, order.state)
        self.assertTrue(order.is_working)
        self.assertFalse(order.is_completed)

    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
        self.assertEqual(OrderState.CANCELED, order.state)
        self.assertFalse(order.is_working)
        self.assertTrue(order.is_completed)
        self.assertEqual(5, order.event_count)

    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_replace(order))

        updated = OrderUpdated(
            self.account_id,
            order.client_order_id,
            VenueOrderId("1"),
            Quantity.from_int(120000),
            Price.from_str("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.from_int(120000), order.quantity)
        self.assertEqual(Price.from_str("1.00001"), order.price)
        self.assertTrue(order.is_working)
        self.assertFalse(order.is_completed)
        self.assertEqual(5, 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.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_replace(order))

        updated = OrderUpdated(
            self.account_id,
            order.client_order_id,
            VenueOrderId("2"),
            Quantity.from_int(120000),
            Price.from_str("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.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
        self.assertEqual(OrderState.FILLED, order.state)
        self.assertEqual(Quantity.from_int(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.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
        self.assertEqual(OrderState.FILLED, order.state)
        self.assertEqual(Quantity.from_int(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.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
        self.assertEqual(OrderState.PARTIALLY_FILLED, order.state)
        self.assertEqual(Quantity.from_int(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.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
        self.assertEqual(OrderState.FILLED, order.state)
        self.assertEqual(Quantity.from_int(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.from_int(100000),
            Price.from_str("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.from_str("1.00001"),
            AUDUSD_SIM.quote_currency,
            Money(0, USD),
            LiquiditySide.MAKER,
            0,
            uuid4(),
            0,
        )

        # Act
        order.apply(filled)

        # Assert
        self.assertEqual(OrderState.FILLED, order.state)
        self.assertEqual(Quantity.from_int(100000), order.filled_qty)
        self.assertEqual(Price.from_str("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.from_int(100000),
            Price.from_str("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.from_int(50000),
            Price.from_str("0.999999"),
            AUDUSD_SIM.quote_currency,
            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.from_int(50000), order.filled_qty)
        self.assertEqual(Price.from_str("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)