Пример #1
0
    def test_apply_order_filled_event_to_order_without_accepted(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
        )

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

        filled = TestStubs.event_order_filled(
            order,
            instrument=AUDUSD_SIM,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("1.00001"),
        )

        # Act
        order.apply(filled)

        # Assert
        assert order.status == OrderStatus.FILLED
        assert order.filled_qty == Quantity.from_int(100000)
        assert order.leaves_qty == Quantity.zero()
        assert order.avg_px == Decimal("1.00001")
        assert len(order.execution_ids) == 1
        assert not order.is_active
        assert not order.is_inflight
        assert not order.is_working
        assert order.is_completed
        assert order.ts_last == 0
Пример #2
0
    def test_add_order_state_report(self):
        # Arrange
        report = ExecutionMassStatus(
            client_id=ClientId("IB"),
            account_id=TestStubs.account_id(),
            timestamp_ns=0,
        )

        venue_order_id = VenueOrderId("1")
        order_report = OrderStatusReport(
            client_order_id=ClientOrderId("O-123456"),
            venue_order_id=venue_order_id,
            order_state=OrderState.REJECTED,
            filled_qty=Quantity.zero(),
            timestamp_ns=0,
        )

        # Act
        report.add_order_report(order_report)

        # Assert
        assert report.order_reports()[venue_order_id] == order_report
        assert (
            repr(report) ==
            "ExecutionMassStatus(client_id=IB, account_id=SIM-000, timestamp_ns=0, order_reports={VenueOrderId('1'): OrderStatusReport(client_order_id=O-123456, venue_order_id=1, order_state=REJECTED, filled_qty=0, timestamp_ns=0)}, exec_reports={}, position_reports={})"  # noqa
        )
        assert (
            repr(order_report) ==
            "OrderStatusReport(client_order_id=O-123456, venue_order_id=1, order_state=REJECTED, filled_qty=0, timestamp_ns=0)"  # noqa
        )
Пример #3
0
    def test_add_position_state_report(self):
        report = ExecutionMassStatus(
            client_id=ClientId("IB"),
            account_id=TestStubs.account_id(),
            timestamp_ns=0,
        )

        position_report = PositionStatusReport(
            instrument_id=AUDUSD_SIM,
            position_side=PositionSide.FLAT,
            qty=Quantity.zero(),
            timestamp_ns=0,
        )

        # Act
        report.add_position_report(position_report)

        # Assert
        assert report.position_reports()[AUDUSD_SIM] == position_report
        assert (
            repr(report) ==
            "ExecutionMassStatus(client_id=IB, account_id=SIM-000, timestamp_ns=0, order_reports={}, exec_reports={}, position_reports={InstrumentId('AUD/USD.SIM'): PositionStatusReport(instrument_id=AUD/USD.SIM, side=FLAT, qty=0, timestamp_ns=0)})"  # noqa
        )  # noqa
        assert (
            repr(position_report) ==
            "PositionStatusReport(instrument_id=AUD/USD.SIM, side=FLAT, qty=0, timestamp_ns=0)"  # noqa
        )  # noqa
Пример #4
0
    def test_zero_returns_zero_quantity(self):
        # Arrange, Act
        qty = Quantity.zero()

        # Assert
        assert qty == 0
        assert str(qty) == "0"
        assert qty.precision == 0
Пример #5
0
async def generate_order_status_report(self, order) -> Optional[OrderStatusReport]:
    return [
        OrderStatusReport(
            client_order_id=ClientOrderId(),
            venue_order_id=VenueOrderId(),
            order_status=OrderStatus(),
            filled_qty=Quantity.zero(),
            ts_init=int(pd.Timestamp(order["timestamp"]).to_datetime64()),
        )
        for order in self.client().betting.list_current_orders()["currentOrders"]
    ]
Пример #6
0
async def generate_order_status_report(self, order) -> Optional[OrderStatusReport]:
    return [
        OrderStatusReport(
            client_order_id=ClientOrderId(),
            venue_order_id=VenueOrderId(),
            order_state=OrderState(),
            filled_qty=Quantity.zero(),
            timestamp_ns=millis_to_nanos(),
        )
        for order in self.client().betting.list_current_orders()["currentOrders"]
    ]
    async def test_reconcile_state_when_order_completed_returns_true_with_warning1(
            self):
        # Arrange
        self.exec_engine.start()
        self.risk_engine.start()

        strategy = TradingStrategy()
        strategy.register(
            trader_id=self.trader_id,
            portfolio=self.portfolio,
            msgbus=self.msgbus,
            cache=self.cache,
            clock=self.clock,
            logger=self.logger,
        )

        order = strategy.order_factory.stop_market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
            Price.from_str("1.00000"),
        )

        submit_order = SubmitOrder(
            self.trader_id,
            strategy.id,
            None,
            order,
            self.uuid_factory.generate(),
            self.clock.timestamp_ns(),
        )

        self.risk_engine.execute(submit_order)
        await asyncio.sleep(0)  # Process queue
        self.exec_engine.process(TestStubs.event_order_submitted(order))
        await asyncio.sleep(0)  # Process queue
        self.exec_engine.process(TestStubs.event_order_accepted(order))
        await asyncio.sleep(0)  # Process queue
        self.exec_engine.process(TestStubs.event_order_canceled(order))
        await asyncio.sleep(0)  # Process queue

        report = OrderStatusReport(
            client_order_id=order.client_order_id,
            venue_order_id=VenueOrderId("1"),  # <-- from stub event
            order_status=OrderStatus.CANCELED,
            filled_qty=Quantity.zero(),
            ts_init=0,
        )

        # Act
        result = await self.client.reconcile_state(report, order)

        # Assert
        assert result
Пример #8
0
    async def test_reconcile_state_when_expired_reconciles(self):
        # Arrange
        self.exec_engine.start()

        strategy = TradingStrategy()
        strategy.register(
            trader_id=self.trader_id,
            portfolio=self.portfolio,
            msgbus=self.msgbus,
            cache=self.cache,
            clock=self.clock,
            logger=self.logger,
        )

        order = strategy.order_factory.limit(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
            Price.from_str("1.00000"),
        )

        submit_order = SubmitOrder(
            self.trader_id,
            strategy.id,
            None,
            order,
            self.uuid_factory.generate(),
            self.clock.timestamp_ns(),
        )

        self.exec_engine.execute(submit_order)
        self.exec_engine.process(TestStubs.event_order_submitted(order))
        self.exec_engine.process(TestStubs.event_order_accepted(order))

        report = OrderStatusReport(
            client_order_id=order.client_order_id,
            venue_order_id=VenueOrderId("1"),  # <-- from stub event
            order_status=OrderStatus.EXPIRED,
            filled_qty=Quantity.zero(),
            ts_init=0,
        )

        self.client.add_order_status_report(report)

        await asyncio.sleep(0.1)  # Allow processing time

        # Act
        result = await self.exec_engine.reconcile_state(timeout_secs=10)
        self.exec_engine.stop()

        # Assert
        assert result
Пример #9
0
        async def run_test():
            # Arrange
            self.exec_engine.start()

            strategy = TradingStrategy(order_id_tag="001")
            strategy.register_trader(
                TraderId("TESTER-000"),
                self.clock,
                self.logger,
            )

            self.exec_engine.register_strategy(strategy)

            order = strategy.order_factory.limit(
                AUDUSD_SIM.id,
                OrderSide.BUY,
                Quantity.from_int(100000),
                Price.from_str("1.00000"),
            )

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

            self.exec_engine.execute(submit_order)
            self.exec_engine.process(TestStubs.event_order_submitted(order))
            self.exec_engine.process(TestStubs.event_order_accepted(order))

            report = OrderStatusReport(
                client_order_id=order.client_order_id,
                venue_order_id=VenueOrderId("1"),  # <-- from stub event
                order_state=OrderState.EXPIRED,
                filled_qty=Quantity.zero(),
                timestamp_ns=0,
            )

            self.client.add_order_status_report(report)

            await asyncio.sleep(0.01)

            # Act
            result = await self.exec_engine.reconcile_state(timeout_secs=10)
            self.exec_engine.stop()

            # Assert
            assert result
Пример #10
0
 def test_market_order_with_invalid_tif_raises_value_error(self):
     # Arrange, Act, Assert
     with pytest.raises(ValueError):
         MarketOrder(
             self.trader_id,
             self.strategy_id,
             AUDUSD_SIM.id,
             ClientOrderId("O-123456"),
             OrderSide.BUY,
             Quantity.zero(),
             TimeInForce.GTD,  # <-- invalid
             UUID4(),
             0,
         )
Пример #11
0
    def test_calculate_with_zero_risk_returns_quantity_zero(self):
        # Arrange
        equity = Money(0, USD)  # No equity

        # Act
        result = self.sizer.calculate(
            entry=Price.from_str("1.00100"),
            stop_loss=Price.from_str("1.00100"),
            equity=equity,
            risk=Decimal("0.001"),  # 0.1%
            exchange_rate=Decimal("0"),
        )

        # Assert
        assert result == Quantity.zero()
Пример #12
0
    def test_calculate_single_unit_size_when_risk_too_high(self):
        # Arrange
        equity = Money(100000, USD)

        # Act
        result = self.sizer.calculate(
            entry=Price.from_str("3.00000"),
            stop_loss=Price.from_str("1.00000"),
            equity=equity,
            risk=Decimal("0.01"),  # 1%
            unit_batch_size=Decimal(1000),
        )

        # Assert
        assert result == Quantity.zero()
Пример #13
0
 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,
     )
Пример #14
0
    def test_position_long_with_multiple_filled_orders_returns_expected_attributes(
        self, ):
        # Arrange
        order1 = self.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
        )

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

        order3 = self.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.SELL,
            Quantity.from_int(200000),
        )

        fill1 = TestStubs.event_order_filled(
            order1,
            instrument=AUDUSD_SIM,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
        )

        fill2 = TestStubs.event_order_filled(
            order2,
            instrument=AUDUSD_SIM,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("1.00001"),
        )

        fill3 = TestStubs.event_order_filled(
            order3,
            instrument=AUDUSD_SIM,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("1.00010"),
        )

        last = Price.from_str("1.00050")

        # Act
        position = Position(instrument=AUDUSD_SIM, fill=fill1)
        position.apply(fill2)
        position.apply(fill3)

        # Assert
        self.assertEqual(Quantity.zero(), position.quantity)
        self.assertEqual(PositionSide.FLAT, position.side)
        self.assertEqual(0, position.opened_timestamp_ns)
        self.assertEqual(Decimal("1.000005"), position.avg_px_open)
        self.assertEqual(3, position.event_count)
        self.assertEqual(
            [
                order1.client_order_id, order2.client_order_id,
                order3.client_order_id
            ],
            position.client_order_ids,
        )
        self.assertEqual(0, position.closed_timestamp_ns)
        self.assertEqual(Decimal("1.0001"), position.avg_px_close)
        self.assertFalse(position.is_long)
        self.assertFalse(position.is_short)
        self.assertFalse(position.is_open)
        self.assertTrue(position.is_closed)
        self.assertEqual(Money(11.00, USD), position.realized_pnl)
        self.assertEqual(Money(0, USD), position.unrealized_pnl(last))
        self.assertEqual(Money(11.00, USD), position.total_pnl(last))
        self.assertEqual([Money(8.00, USD)], position.commissions())
        self.assertEqual("Position(FLAT AUD/USD.SIM, id=P-123456)",
                         repr(position))
Пример #15
0
    def test_position_filled_with_no_change_returns_expected_attributes(self):
        # Arrange
        order1 = self.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
        )

        order2 = self.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.SELL,
            Quantity.from_int(100000),
        )

        fill1 = TestEventStubs.order_filled(
            order1,
            instrument=AUDUSD_SIM,
            position_id=PositionId("P-19700101-000000-000-001-1"),
        )

        position = Position(instrument=AUDUSD_SIM, fill=fill1)

        fill2 = TestEventStubs.order_filled(
            order2,
            instrument=AUDUSD_SIM,
            position_id=PositionId("P-19700101-000000-000-001-1"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("1.00000"),
        )

        last = Price.from_str("1.00050")

        # Act
        position.apply(fill2)

        # Assert
        assert position.quantity == Quantity.zero()
        assert position.side == PositionSide.FLAT
        assert position.ts_opened == 0
        assert position.avg_px_open == Decimal("1.0")
        assert position.event_count == 2
        assert position.client_order_ids == [
            order1.client_order_id, order2.client_order_id
        ]
        assert position.trade_ids == [
            TradeId("E-19700101-000000-000-001-1"),
            TradeId("E-19700101-000000-000-001-2"),
        ]
        assert position.ts_closed == 0
        assert position.avg_px_close == Decimal("1.0")
        assert not position.is_long
        assert not position.is_short
        assert not position.is_open
        assert position.is_closed
        assert position.realized_points == 0
        assert position.realized_return == 0
        assert position.realized_pnl == Money(-4.00, USD)
        assert position.unrealized_pnl(last) == Money(0, USD)
        assert position.total_pnl(last) == Money(-4.00, USD)
        assert position.commissions() == [Money(4.00, USD)]
        assert repr(
            position
        ) == "Position(FLAT AUD/USD.SIM, id=P-19700101-000000-000-001-1)"
Пример #16
0
    def test_position_long_with_multiple_filled_orders_returns_expected_attributes(
        self, ):
        # Arrange
        order1 = self.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
        )

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

        order3 = self.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.SELL,
            Quantity.from_int(200000),
        )

        fill1 = TestEventStubs.order_filled(
            order1,
            instrument=AUDUSD_SIM,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
        )

        fill2 = TestEventStubs.order_filled(
            order2,
            instrument=AUDUSD_SIM,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("1.00001"),
        )

        fill3 = TestEventStubs.order_filled(
            order3,
            instrument=AUDUSD_SIM,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("1.00010"),
        )

        last = Price.from_str("1.00050")

        # Act
        position = Position(instrument=AUDUSD_SIM, fill=fill1)
        position.apply(fill2)
        position.apply(fill3)

        # Assert
        assert position.quantity == Quantity.zero()
        assert position.side == PositionSide.FLAT
        assert position.ts_opened == 0
        assert position.avg_px_open == Decimal("1.000005")
        assert position.event_count == 3
        assert position.client_order_ids == [
            order1.client_order_id,
            order2.client_order_id,
            order3.client_order_id,
        ]
        assert position.ts_closed == 0
        assert position.avg_px_close == Decimal("1.0001")
        assert not position.is_long
        assert not position.is_short
        assert not position.is_open
        assert position.is_closed
        assert position.realized_pnl == Money(11.00, USD)
        assert position.unrealized_pnl(last) == Money(0, USD)
        assert position.total_pnl(last) == Money(11.00, USD)
        assert position.commissions() == [Money(8.00, USD)]
        assert repr(position) == "Position(FLAT AUD/USD.SIM, id=P-123456)"
Пример #17
0
    def test_position_filled_with_buy_order_then_sell_order_returns_expected_attributes(
        self, ):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(150000),
        )

        fill1 = TestEventStubs.order_filled(
            order,
            instrument=AUDUSD_SIM,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("1.00001"),
            ts_filled_ns=1_000_000_000,
        )

        position = Position(instrument=AUDUSD_SIM, fill=fill1)

        fill2 = OrderFilled(
            self.trader_id,
            StrategyId("S-001"),
            self.account_id,
            order.instrument_id,
            order.client_order_id,
            VenueOrderId("2"),
            TradeId("E2"),
            PositionId("T123456"),
            OrderSide.SELL,
            OrderType.MARKET,
            order.quantity,
            Price.from_str("1.00011"),
            AUDUSD_SIM.quote_currency,
            Money(0, USD),
            LiquiditySide.TAKER,
            UUID4(),
            2_000_000_000,
            0,
        )

        last = Price.from_str("1.00050")

        # Act
        position.apply(fill2)

        # Assert
        assert position.is_opposite_side(fill2.order_side)
        assert position.quantity == Quantity.zero()
        assert position.side == PositionSide.FLAT
        assert position.ts_opened == 1_000_000_000
        assert position.duration_ns == 1_000_000_000
        assert position.avg_px_open == Decimal("1.00001")
        assert position.event_count == 2
        assert position.ts_closed == 2_000_000_000
        assert position.avg_px_close == Decimal("1.00011")
        assert not position.is_long
        assert not position.is_short
        assert not position.is_open
        assert position.is_closed
        assert position.realized_points == Decimal("0.00010")
        assert position.realized_return == Decimal(
            "0.00009999900000999990000099999000")
        assert position.realized_pnl == Money(12.00, USD)
        assert position.unrealized_pnl(last) == Money(0, USD)
        assert position.total_pnl(last) == Money(12.00, USD)
        assert position.commissions() == [Money(3.00, USD)]
        assert repr(position) == "Position(FLAT AUD/USD.SIM, id=P-123456)"
Пример #18
0
    def test_position_filled_with_buy_order_then_sell_order_returns_expected_attributes(
        self, ):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(150000),
        )

        fill1 = 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"),
            execution_ns=1_000_000_000,
        )

        position = Position(instrument=AUDUSD_SIM, fill=fill1)

        fill2 = OrderFilled(
            self.account_id,
            order.client_order_id,
            VenueOrderId("2"),
            ExecutionId("E2"),
            PositionId("T123456"),
            StrategyId("S-001"),
            order.instrument_id,
            OrderSide.SELL,
            order.quantity,
            Price.from_str("1.00011"),
            AUDUSD_SIM.quote_currency,
            Money(0, USD),
            LiquiditySide.TAKER,
            2_000_000_000,
            uuid4(),
            0,
        )

        last = Price.from_str("1.00050")

        # Act
        position.apply(fill2)

        # Assert
        assert position.is_opposite_side(fill2.order_side)
        self.assertEqual(Quantity.zero(), position.quantity)
        self.assertEqual(PositionSide.FLAT, position.side)
        self.assertEqual(1_000_000_000, position.opened_timestamp_ns)
        self.assertEqual(1_000_000_000, position.open_duration_ns)
        self.assertEqual(Decimal("1.00001"), position.avg_px_open)
        self.assertEqual(2, position.event_count)
        self.assertEqual(2_000_000_000, position.closed_timestamp_ns)
        self.assertEqual(Decimal("1.00011"), position.avg_px_close)
        self.assertFalse(position.is_long)
        self.assertFalse(position.is_short)
        self.assertFalse(position.is_open)
        self.assertTrue(position.is_closed)
        self.assertEqual(Decimal("0.00010"), position.realized_points)
        self.assertEqual(Decimal("0.00009999900000999990000099999000"),
                         position.realized_return)
        self.assertEqual(Money(12.00, USD), position.realized_pnl)
        self.assertEqual(Money(0, USD), position.unrealized_pnl(last))
        self.assertEqual(Money(12.00, USD), position.total_pnl(last))
        self.assertEqual([Money(3.00, USD)], position.commissions())
        self.assertEqual("Position(FLAT AUD/USD.SIM, id=P-123456)",
                         repr(position))