def test_generate_order_fills_report(self):
        # Arrange
        report_provider = ReportProvider()
        order1 = self.order_factory.limit(AUDUSD_FXCM, OrderSide.BUY,
                                          Quantity(1500000), Price(0.80010, 5))

        order2 = self.order_factory.limit(AUDUSD_FXCM, OrderSide.SELL,
                                          Quantity(1500000), Price(0.80000, 5))

        event = OrderFilled(self.account_id, order1.id,
                            ExecutionId('SOME_EXEC_ID_1'),
                            PositionIdBroker('SOME_EXEC_TICKET_1'),
                            order1.symbol, order1.side, order1.quantity,
                            Price(0.80011, 5), Currency.AUD, UNIX_EPOCH,
                            GUID(uuid.uuid4()), UNIX_EPOCH)

        order1.apply(event)

        orders = {order1.id: order1, order2.id: order2}
        # Act
        report = report_provider.generate_order_fills_report(orders)

        # Assert
        # print(report.iloc[0])
        self.assertEqual(1, len(report))
        self.assertEqual('order_id', report.index.name)
        self.assertEqual(order1.id.value, report.index[0])
        self.assertEqual('AUDUSD', report.iloc[0]['symbol'])
        self.assertEqual('BUY', report.iloc[0]['side'])
        self.assertEqual('LIMIT', report.iloc[0]['type'])
        self.assertEqual(1500000, report.iloc[0]['quantity'])
        self.assertAlmostEqual(0.80011, report.iloc[0]['avg_price'])
        self.assertEqual(0.00001, report.iloc[0]['slippage'])
    def test_serialize_and_deserialize_order_filled_events(self):
        # Arrange
        event = OrderFilled(
            self.account_id,
            ClientOrderId("O-123456"),
            OrderId("1"),
            ExecutionId("E123456"),
            PositionId("T123456"),
            StrategyId("S", "001"),
            AUDUSD_SIM.symbol,
            OrderSide.SELL,
            Quantity(100000),
            Quantity(100000),
            Quantity(),
            Price("1.00000"),
            AUDUSD_SIM.quote_currency,
            AUDUSD_SIM.is_inverse,
            Money(0, USD),
            LiquiditySide.TAKER,
            UNIX_EPOCH,
            uuid4(),
            UNIX_EPOCH,
        )

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

        # Assert
        self.assertEqual(deserialized, event)
    def test_serialize_and_deserialize_order_filled_events(self):
        # Arrange
        event = OrderFilled(
            self.account_id,
            ClientOrderId("O-123456"),
            VenueOrderId("1"),
            ExecutionId("E123456"),
            PositionId("T123456"),
            StrategyId("S-001"),
            AUDUSD_SIM.id,
            OrderSide.SELL,
            Quantity(100000, precision=0),
            Price(1.00000, precision=5),
            AUDUSD_SIM.quote_currency,
            Money(0, USD),
            LiquiditySide.TAKER,
            0,
            uuid4(),
            0,
        )

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

        # Assert
        assert deserialized == event
Example #4
0
    def test_position_filled_with_buy_order_returns_expected_attributes(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000))

        order_filled = OrderFilled(
            self.account_id,
            order.id,
            ExecutionId('E123456'),
            PositionIdBroker('T123456'),
            order.symbol,
            order.side,
            order.quantity,
            Price(1.00001, 5),
            Currency.USD,
            UNIX_EPOCH,
            GUID(uuid.uuid4()),
            UNIX_EPOCH)

        last = Tick(AUDUSD_FXCM,
                    Price(1.00050, 5),
                    Price(1.00048, 5),
                    Volume(1),
                    Volume(1),
                    UNIX_EPOCH)

        # Act
        position = Position(PositionId('P-123456'), order_filled)

        # Assert
        self.assertEqual(OrderId('O-19700101-000000-001-001-1'), position.from_order_id)
        self.assertEqual(Quantity(100000), position.quantity)
        self.assertEqual(Quantity(100000), position.peak_quantity)
        self.assertEqual(OrderSide.BUY, position.entry_direction)
        self.assertEqual(MarketPosition.LONG, position.market_position)
        self.assertEqual(UNIX_EPOCH, position.opened_time)
        self.assertIsNone(position.open_duration)
        self.assertEqual(1.00001, position.average_open_price)
        self.assertEqual(1, position.event_count)
        self.assertEqual([order.id], position.get_order_ids())
        self.assertEqual([ExecutionId('E123456')], position.get_execution_ids())
        self.assertEqual(ExecutionId('E123456'), position.last_execution_id)
        self.assertEqual(PositionIdBroker('T123456'), position.id_broker)
        self.assertTrue(position.is_long)
        self.assertFalse(position.is_short)
        self.assertFalse(position.is_closed)
        self.assertEqual(0.0, position.realized_points)
        self.assertEqual(0.0, position.realized_return)
        self.assertEqual(Money(0, Currency.USD), position.realized_pnl)
        self.assertEqual(0.0004899999999998794, position.unrealized_points(last))
        self.assertEqual(0.0004899951000488789, position.unrealized_return(last))
        self.assertEqual(Money(49.00, Currency.USD), position.unrealized_pnl(last))
        self.assertEqual(0.0004899999999998794, position.total_points(last))
        self.assertEqual(0.0004899951000488789, position.total_return(last))
        self.assertEqual(Money(49.00, Currency.USD), position.total_pnl(last))
Example #5
0
    def event_order_filled(
        order,
        instrument,
        venue_order_id=None,
        execution_id=None,
        position_id=None,
        strategy_id=None,
        last_qty=None,
        last_px=None,
        liquidity_side=LiquiditySide.TAKER,
        execution_ns=0,
    ) -> OrderFilled:
        if venue_order_id is None:
            venue_order_id = VenueOrderId("1")
        if execution_id is None:
            execution_id = ExecutionId(
                order.client_order_id.value.replace("O", "E"))
        if position_id is None:
            position_id = order.position_id
        if strategy_id is None:
            strategy_id = order.strategy_id
        if last_px is None:
            last_px = Price("1.00000")
        if last_qty is None:
            last_qty = order.quantity

        commission = instrument.calculate_commission(
            last_qty=order.quantity,
            last_px=last_px,
            liquidity_side=liquidity_side,
        )

        return OrderFilled(
            account_id=TestStubs.account_id(),
            client_order_id=order.client_order_id,
            venue_order_id=venue_order_id,
            execution_id=execution_id,
            position_id=position_id,
            strategy_id=strategy_id,
            instrument_id=order.instrument_id,
            order_side=order.side,
            last_qty=last_qty,
            last_px=order.price if last_px is None else last_px,
            cum_qty=Quantity(order.filled_qty + last_qty),
            leaves_qty=Quantity(
                max(0, order.quantity - order.filled_qty - last_qty)),
            currency=instrument.quote_currency,
            is_inverse=instrument.is_inverse,
            commission=commission,
            liquidity_side=liquidity_side,
            execution_ns=execution_ns,
            event_id=uuid4(),
            timestamp_ns=0,
        )
Example #6
0
    def test_position_filled_with_sell_order_returns_expected_attributes(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_FXCM,
            OrderSide.SELL,
            Quantity(100000))

        order_filled = OrderFilled(
            self.account_id,
            order.id,
            ExecutionId('E123456'),
            PositionIdBroker('T123456'),
            order.symbol,
            order.side,
            order.quantity,
            Price(1.00001, 5),
            Currency.USD,
            UNIX_EPOCH,
            GUID(uuid.uuid4()),
            UNIX_EPOCH)

        last = Tick(AUDUSD_FXCM,
                    Price(1.00050, 5),
                    Price(1.00048, 5),
                    Volume(1),
                    Volume(1),
                    UNIX_EPOCH)

        # Act
        position = Position(PositionId('P-123456'), order_filled)

        # Assert
        self.assertEqual(Quantity(100000), position.quantity)
        self.assertEqual(Quantity(100000), position.peak_quantity)
        self.assertEqual(MarketPosition.SHORT, position.market_position)
        self.assertEqual(UNIX_EPOCH, position.opened_time)
        self.assertEqual(1.00001, position.average_open_price)
        self.assertEqual(1, position.event_count)
        self.assertEqual(ExecutionId('E123456'), position.last_execution_id)
        self.assertEqual(PositionIdBroker('T123456'), position.id_broker)
        self.assertFalse(position.is_long)
        self.assertTrue(position.is_short)
        self.assertFalse(position.is_closed)
        self.assertEqual(0.0, position.realized_points)
        self.assertEqual(0.0, position.realized_return)
        self.assertEqual(Money(0, Currency.USD), position.realized_pnl)
        self.assertEqual(-0.00046999999999997044, position.unrealized_points(last))
        self.assertEqual(-0.0004699953000469699, position.unrealized_return(last))
        self.assertEqual(Money(-47.00, Currency.USD), position.unrealized_pnl(last))
        self.assertEqual(-0.00046999999999997044, position.total_points(last))
        self.assertEqual(-0.0004699953000469699, position.total_return(last))
        self.assertEqual(Money(-47.00, Currency.USD), position.total_pnl(last))
Example #7
0
    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"),
        )

        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.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,
        )

        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(Decimal("0.999999"), order.avg_price)
        self.assertEqual(Decimal("-0.000001"), order.slippage)
        self.assertFalse(order.is_completed)
        self.assertEqual(UNIX_EPOCH, order.filled_timestamp)
    def event_order_filled(
        order,
        instrument,
        venue_order_id=None,
        execution_id=None,
        position_id=None,
        strategy_id=None,
        last_qty=None,
        last_px=None,
        liquidity_side=LiquiditySide.TAKER,
        ts_filled_ns=0,
    ) -> OrderFilled:
        if venue_order_id is None:
            venue_order_id = VenueOrderId("1")
        if execution_id is None:
            execution_id = ExecutionId(
                order.client_order_id.value.replace("O", "E"))
        if position_id is None:
            position_id = order.position_id
        if strategy_id is None:
            strategy_id = order.strategy_id
        if last_px is None:
            last_px = Price.from_str(f"{1:.{instrument.price_precision}f}")
        if last_qty is None:
            last_qty = order.quantity

        commission = instrument.calculate_commission(
            last_qty=order.quantity,
            last_px=last_px,
            liquidity_side=liquidity_side,
        )

        return OrderFilled(
            account_id=TestStubs.account_id(),
            client_order_id=order.client_order_id,
            venue_order_id=venue_order_id,
            execution_id=execution_id,
            position_id=position_id,
            strategy_id=strategy_id,
            instrument_id=order.instrument_id,
            order_side=order.side,
            last_qty=last_qty,
            last_px=order.price if last_px is None else last_px,
            currency=instrument.quote_currency,
            commission=commission,
            liquidity_side=liquidity_side,
            ts_filled_ns=ts_filled_ns,
            event_id=uuid4(),
            timestamp_ns=0,
        )
    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)
Example #10
0
    def event_order_filled(
        order,
        instrument,
        position_id=None,
        strategy_id=None,
        fill_price=None,
        fill_qty=None,
        liquidity_side=LiquiditySide.TAKER,
    ) -> OrderFilled:
        if position_id is None:
            position_id = PositionId(order.cl_ord_id.value.replace("P", "T"))
        if strategy_id is None:
            strategy_id = StrategyId.null()
        if fill_price is None:
            fill_price = Price("1.00000")
        if fill_qty is None:
            fill_qty = order.quantity

        commission = instrument.calculate_commission(
            quantity=order.quantity,
            avg_price=fill_price,
            liquidity_side=liquidity_side,
        )

        return OrderFilled(
            account_id=TestStubs.account_id(),
            cl_ord_id=order.cl_ord_id,
            order_id=OrderId("1"),
            execution_id=ExecutionId(order.cl_ord_id.value.replace("O", "E")),
            position_id=position_id,
            strategy_id=strategy_id,
            symbol=order.symbol,
            order_side=order.side,
            fill_qty=fill_qty,
            cum_qty=Quantity(order.filled_qty + fill_qty),
            leaves_qty=Quantity(
                max(0, order.quantity - order.filled_qty - fill_qty)),
            fill_price=order.price if fill_price is None else fill_price,
            currency=instrument.quote_currency,
            is_inverse=instrument.is_inverse,
            commission=commission,
            liquidity_side=liquidity_side,
            execution_time=UNIX_EPOCH,
            event_id=uuid4(),
            event_timestamp=UNIX_EPOCH,
        )
    def test_apply_order_filled_event_to_buy_limit_order(self):
        # Arrange
        order = self.order_factory.limit(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
        )

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

        filled = OrderFilled(
            self.account_id,
            order.client_order_id,
            VenueOrderId("1"),
            ExecutionId("E-1"),
            PositionId("P-1"),
            StrategyId.null(),
            order.instrument_id,
            order.side,
            order.quantity,
            Price("1.00001"),
            order.quantity,
            Quantity(),
            AUDUSD_SIM.quote_currency,
            AUDUSD_SIM.is_inverse,
            Money(0, USD),
            LiquiditySide.MAKER,
            0,
            uuid4(),
            0,
        )

        # Act
        order.apply(filled)

        # Assert
        self.assertEqual(OrderState.FILLED, order.state)
        self.assertEqual(Quantity(100000), order.filled_qty)
        self.assertEqual(Price("1.00000"), order.price)
        self.assertEqual(Decimal("1.00001"), order.avg_px)
        self.assertEqual(Decimal("0.00001"), order.slippage)
        self.assertFalse(order.is_working)
        self.assertTrue(order.is_completed)
        self.assertEqual(0, order.execution_ns)
Example #12
0
    def event_order_filled(
        order,
        position_id=None,
        strategy_id=None,
        fill_price=None,
        filled_qty=None,
        leaves_qty=None,
        base_currency=USD,
        quote_currency=JPY,
        commission=0,
    ) -> OrderFilled:
        if position_id is None:
            position_id = PositionId(order.cl_ord_id.value.replace("P", "T"))
        if strategy_id is None:
            strategy_id = StrategyId("S", "NULL")
        if fill_price is None:
            fill_price = Price("1.00000")
        if filled_qty is None:
            filled_qty = order.quantity
        if leaves_qty is None:
            leaves_qty = Quantity()

        return OrderFilled(
            TestStubs.account_id(),
            order.cl_ord_id,
            OrderId("1"),
            ExecutionId(order.cl_ord_id.value.replace("O", "E")),
            position_id,
            strategy_id,
            order.symbol,
            order.side,
            filled_qty,
            leaves_qty,
            order.price if fill_price is None else fill_price,
            Money(commission, base_currency),
            LiquiditySide.TAKER,
            base_currency,  # Stub event
            quote_currency,  # Stub event
            UNIX_EPOCH,
            uuid4(),
            UNIX_EPOCH,
        )
Example #13
0
    def test_can_apply_order_overfilled_event_to_buy_limit_order(self):
        # Arrange
        order = self.order_factory.limit(AUDUSD_FXCM, OrderSide.BUY,
                                         Quantity(100000), Price(1.00000, 5))

        event = OrderFilled(self.account_id, order.id,
                            ExecutionId('SOME_EXEC_ID_1'),
                            PositionIdBroker('SOME_EXEC_TICKET_1'),
                            order.symbol, order.side, Quantity(150000),
                            Price(0.99999, 5), Currency.USD, UNIX_EPOCH,
                            GUID(uuid.uuid4()), UNIX_EPOCH)

        # Act
        order.apply(event)

        # Assert
        self.assertEqual(OrderState.OVER_FILLED, order.state)
        self.assertEqual(Quantity(150000), order.filled_quantity)
        self.assertFalse(order.is_completed)
        self.assertEqual(UNIX_EPOCH, order.filled_timestamp)
Example #14
0
    def test_can_apply_order_filled_event_to_market_order(self):
        # Arrange
        order = self.order_factory.market(AUDUSD_FXCM, OrderSide.BUY,
                                          Quantity(100000))

        event = OrderFilled(self.account_id, order.id,
                            ExecutionId('SOME_EXEC_ID_1'),
                            PositionIdBroker('SOME_EXEC_TICKET_1'),
                            order.symbol, order.side, order.quantity,
                            Price(1.00001, 5), Currency.USD, UNIX_EPOCH,
                            GUID(uuid.uuid4()), UNIX_EPOCH)

        # Act
        order.apply(event)

        # Assert
        self.assertEqual(OrderState.FILLED, order.state)
        self.assertEqual(Quantity(100000), order.filled_quantity)
        self.assertEqual(Price(1.00001, 5), order.average_price)
        self.assertTrue(order.is_completed)
        self.assertEqual(UNIX_EPOCH, order.filled_timestamp)
Example #15
0
    def test_order_filled(self):
        # Arrange
        uuid = uuid4()
        event = OrderFilled(
            account_id=AccountId("SIM", "000"),
            client_order_id=ClientOrderId("O-2020872378423"),
            venue_order_id=VenueOrderId("123456"),
            execution_id=ExecutionId("1"),
            position_id=PositionId("2"),
            strategy_id=StrategyId("SCALPER", "001"),
            instrument_id=InstrumentId(Symbol("BTC/USDT"), Venue("BINANCE")),
            order_side=OrderSide.BUY,
            last_qty=Quantity("0.561000"),
            last_px=Price("15600.12445"),
            cum_qty=Quantity("0.561000"),
            leaves_qty=Quantity(0),
            currency=USDT,
            is_inverse=False,
            commission=Money("12.20000000", USDT),
            liquidity_side=LiquiditySide.MAKER,
            execution_ns=0,
            event_id=uuid,
            timestamp_ns=0,
        )

        print(event)
        # Act
        assert (
            f"OrderFilled(account_id=SIM-000, client_order_id=O-2020872378423, "
            f"venue_order_id=123456, position_id=2, strategy_id=SCALPER-001, "
            f"instrument_id=BTC/USDT.BINANCE, side=BUY-MAKER, last_qty=0.561000, "
            f"last_px=15600.12445 USDT, cum_qty=0.561000, leaves_qty=0, "
            f"commission=12.20000000 USDT, event_id={uuid})" == str(event))
        assert (
            f"OrderFilled(account_id=SIM-000, client_order_id=O-2020872378423, "
            f"venue_order_id=123456, position_id=2, strategy_id=SCALPER-001, "
            f"instrument_id=BTC/USDT.BINANCE, side=BUY-MAKER, last_qty=0.561000, "
            f"last_px=15600.12445 USDT, cum_qty=0.561000, leaves_qty=0, "
            f"commission=12.20000000 USDT, event_id={uuid})" == repr(event))
    def test_order_filled(self):
        # Arrange
        uuid = uuid4()
        event = OrderFilled(
            account_id=AccountId("SIM", "000"),
            cl_ord_id=ClientOrderId("O-2020872378423"),
            order_id=OrderId("123456"),
            execution_id=ExecutionId("1"),
            position_id=PositionId("2"),
            strategy_id=StrategyId("SCALPER", "001"),
            symbol=Symbol("BTC/USDT", Exchange("BINANCE")),
            order_side=OrderSide.BUY,
            fill_qty=Quantity("0.561000"),
            cum_qty=Quantity("0.561000"),
            leaves_qty=Quantity(0),
            fill_price=Price("15600.12445"),
            currency=USDT,
            is_inverse=False,
            commission=Money("12.20000000", USDT),
            liquidity_side=LiquiditySide.MAKER,
            execution_time=UNIX_EPOCH,
            event_id=uuid,
            event_timestamp=UNIX_EPOCH,
        )

        # Act
        self.assertEqual(
            f"OrderFilled(account_id=SIM-000, cl_ord_id=O-2020872378423, "
            f"order_id=123456, position_id=2, strategy_id=SCALPER-001, "
            f"symbol=BTC/USDT.BINANCE, side=BUY-MAKER, fill_qty=0.561000, "
            f"fill_price=15600.12445 USDT, cum_qty=0.561000, leaves_qty=0, "
            f"commission=12.20000000 USDT, id={uuid})", str(event))  # noqa
        self.assertEqual(
            f"OrderFilled(account_id=SIM-000, cl_ord_id=O-2020872378423, "
            f"order_id=123456, position_id=2, strategy_id=SCALPER-001, "
            f"symbol=BTC/USDT.BINANCE, side=BUY-MAKER, fill_qty=0.561000, "
            f"fill_price=15600.12445 USDT, cum_qty=0.561000, leaves_qty=0, "
            f"commission=12.20000000 USDT, id={uuid})", repr(event))  # noqa
    def test_position_filled_with_buy_order_then_sell_order_returns_expected_attributes(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000))

        fill1 = TestStubs.event_order_filled(
            order,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S", "001"),
            fill_price=Price("1.00001"),
        )

        position = Position(fill1)

        fill2 = OrderFilled(
            self.account_id,
            order.cl_ord_id,
            OrderId("2"),
            ExecutionId("E2"),
            PositionId("T123456"),
            StrategyId("S", "001"),
            order.symbol,
            OrderSide.SELL,
            order.quantity,
            Quantity(),
            Price("1.00001"),
            Money(0, USD),
            LiquiditySide.TAKER,
            AUD,
            USD,
            UNIX_EPOCH + timedelta(minutes=1),
            uuid4(),
            UNIX_EPOCH,
        )

        last = QuoteTick(
            AUDUSD_FXCM,
            Price("1.00050"),
            Price("1.00048"),
            Quantity(1),
            Quantity(1),
            UNIX_EPOCH,
        )

        # Act
        position.apply(fill2)

        # Assert
        self.assertEqual(Quantity(), position.quantity)
        self.assertEqual(PositionSide.FLAT, position.side)
        self.assertEqual(UNIX_EPOCH, position.opened_time)
        self.assertEqual(timedelta(minutes=1), position.open_duration)
        self.assertEqual(1.00001, position.avg_open_price)
        self.assertEqual(2, position.event_count())
        self.assertEqual(datetime(1970, 1, 1, 0, 1, tzinfo=pytz.utc), position.closed_time)
        self.assertEqual(1.00001, position.avg_close_price)
        self.assertFalse(position.is_long())
        self.assertFalse(position.is_short())
        self.assertTrue(position.is_closed())
        self.assertEqual(0.0, position.realized_points)
        self.assertEqual(0.0, position.realized_return)
        self.assertEqual(Money(0, USD), position.realized_pnl)
        self.assertEqual(Money(0, USD), position.unrealized_pnl(last))
        self.assertEqual(Money(0, USD), position.total_pnl(last))
Example #18
0
    def position_which_is_closed(position_id, close_price=None) -> Position:

        if close_price is None:
            close_price = Price("1.0001")

        order_factory = OrderFactory(
            strategy_id=StrategyId("S", "001"),
            id_tag_trader=IdTag("001"),
            id_tag_strategy=IdTag("001"),
        )

        order = order_factory.market(
            TestStubs.symbol_audusd_fxcm(),
            OrderSide.SELL,
            Quantity(100000),
        )

        filled1 = OrderFilled(
            TestStubs.account_id(),
            order.cl_ord_id,
            OrderId("1"),
            ExecutionId(order.cl_ord_id.value.replace('O', 'E')),
            position_id,
            StrategyId("S", "1"),
            order.symbol,
            order.side,
            order.quantity,
            Quantity(),
            close_price,
            Money(0, USD),
            LiquiditySide.TAKER,
            USD,  # Stub event
            USD,  # Stub event
            UNIX_EPOCH + timedelta(minutes=5),
            uuid4(),
            UNIX_EPOCH + timedelta(minutes=5),
        )

        filled2 = OrderFilled(
            TestStubs.account_id(),
            order.cl_ord_id,
            OrderId("2"),
            ExecutionId(order.cl_ord_id.value.replace('O', 'E')),
            position_id,
            StrategyId("S", "1"),
            order.symbol,
            OrderSide.BUY,
            order.quantity,
            Quantity(),
            close_price,
            Money(0, USD),
            LiquiditySide.TAKER,
            USD,  # Stub event
            USD,  # Stub event
            UNIX_EPOCH + timedelta(minutes=5),
            uuid4(),
            UNIX_EPOCH + timedelta(minutes=5),
        )

        position = Position(filled1)
        position.apply(filled2)

        return position
Example #19
0
    def test_position_filled_with_buy_order_then_sell_order_returns_expected_attributes(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000))

        order_filled1 = OrderFilled(
            self.account_id,
            order.id,
            ExecutionId('E1'),
            PositionIdBroker('T123456'),
            order.symbol,
            OrderSide.BUY,
            order.quantity,
            Price(1.00001, 5),
            Currency.USD,
            UNIX_EPOCH,
            GUID(uuid.uuid4()),
            UNIX_EPOCH)

        position = Position(PositionId('P-123456'), order_filled1)

        order_filled2 = OrderFilled(
            self.account_id,
            order.id,
            ExecutionId('E2'),
            PositionIdBroker('T123456'),
            order.symbol,
            OrderSide.SELL,
            order.quantity,
            Price(1.00001, 5),
            Currency.USD,
            UNIX_EPOCH + timedelta(minutes=1),
            GUID(uuid.uuid4()),
            UNIX_EPOCH)

        last = Tick(AUDUSD_FXCM,
                    Price(1.00050, 5),
                    Price(1.00048, 5),
                    Volume(1),
                    Volume(1),
                    UNIX_EPOCH)

        # Act
        position.apply(order_filled2)

        # Assert
        self.assertEqual(Quantity(), position.quantity)
        self.assertEqual(MarketPosition.FLAT, position.market_position)
        self.assertEqual(UNIX_EPOCH, position.opened_time)
        self.assertEqual(timedelta(minutes=1), position.open_duration)
        self.assertEqual(1.00001, position.average_open_price)
        self.assertEqual(2, position.event_count)
        self.assertEqual(ExecutionId('E2'), position.last_execution_id)
        self.assertEqual(PositionIdBroker('T123456'), position.id_broker)
        self.assertEqual(datetime.datetime(1970, 1, 1, 0, 1, tzinfo=datetime.timezone.utc), position.closed_time)
        self.assertEqual(1.00001, position.average_close_price)
        self.assertFalse(position.is_long)
        self.assertFalse(position.is_short)
        self.assertTrue(position.is_closed)
        self.assertEqual(0.0, position.realized_points)
        self.assertEqual(0.0, position.realized_return)
        self.assertEqual(Money(0, Currency.USD), position.realized_pnl)
        self.assertEqual(0.0, position.unrealized_points(last))
        self.assertEqual(0.0, position.unrealized_return(last))
        self.assertEqual(Money(0, Currency.USD), position.unrealized_pnl(last))
        self.assertEqual(0.0, position.total_points(last))
        self.assertEqual(0.0, position.total_return(last))
        self.assertEqual(Money(0, Currency.USD), position.total_pnl(last))
    def test_position_filled_with_buy_order_then_sell_order_returns_expected_attributes(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(150000),
        )

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

        position = Position(fill1)

        fill2 = OrderFilled(
            self.account_id,
            order.cl_ord_id,
            OrderId("2"),
            ExecutionId("E2"),
            PositionId("T123456"),
            StrategyId("S", "001"),
            order.symbol,
            OrderSide.SELL,
            order.quantity,
            order.quantity,
            Quantity(),
            Price("1.00011"),
            AUDUSD_SIM.quote_currency,
            AUDUSD_SIM.is_inverse,
            Money(0, USD),
            LiquiditySide.TAKER,
            UNIX_EPOCH + timedelta(minutes=1),
            uuid4(),
            UNIX_EPOCH,
        )

        last = Price("1.00050")

        # Act
        position.apply(fill2)

        # Assert
        self.assertEqual(Quantity(), position.quantity)
        self.assertEqual(PositionSide.FLAT, position.side)
        self.assertEqual(UNIX_EPOCH, position.opened_time)
        self.assertEqual(timedelta(minutes=1), position.open_duration)
        self.assertEqual(Decimal("1.00001"), position.avg_open)
        self.assertEqual(2, position.event_count)
        self.assertEqual(datetime(1970, 1, 1, 0, 1, tzinfo=pytz.utc), position.closed_time)
        self.assertEqual(Decimal("1.00011"), position.avg_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(Money(3.00, USD), position.commission)
        self.assertEqual("Position(id=P-123456, FLAT AUD/USD.SIM)", repr(position))
    def test_multiple_strategy_positions_one_active_one_closed(self):
        # Arrange
        strategy1 = TradingStrategy(order_id_tag='001')
        strategy2 = TradingStrategy(order_id_tag='002')
        position_id1 = strategy1.position_id_generator.generate()
        position_id2 = strategy2.position_id_generator.generate()

        self.exec_engine.register_strategy(strategy1)
        self.exec_engine.register_strategy(strategy2)

        order1 = strategy1.order_factory.stop(AUDUSD_FXCM, OrderSide.BUY,
                                              Quantity(100000),
                                              Price(1.00000, 5))

        order2 = strategy1.order_factory.stop(AUDUSD_FXCM, OrderSide.SELL,
                                              Quantity(100000),
                                              Price(1.00000, 5))

        order3 = strategy2.order_factory.stop(AUDUSD_FXCM, OrderSide.BUY,
                                              Quantity(100000),
                                              Price(1.00000, 5))

        submit_order1 = SubmitOrder(self.trader_id, self.account_id,
                                    strategy1.id, position_id1, order1,
                                    self.guid_factory.generate(),
                                    self.clock.time_now())

        submit_order2 = SubmitOrder(self.trader_id, self.account_id,
                                    strategy1.id, position_id1, order2,
                                    self.guid_factory.generate(),
                                    self.clock.time_now())

        submit_order3 = SubmitOrder(self.trader_id, self.account_id,
                                    strategy2.id, position_id2, order3,
                                    self.guid_factory.generate(),
                                    self.clock.time_now())

        order1_filled = TestStubs.event_order_filled(order1)
        order2_filled = TestStubs.event_order_filled(order2)

        order3_filled = OrderFilled(self.account_id, order3.id,
                                    ExecutionId('E3'), PositionIdBroker('T3'),
                                    AUDUSD_FXCM,
                                    OrderSide.BUY, Quantity(100000),
                                    Price(1.00000,
                                          5), Currency.USD, UNIX_EPOCH,
                                    GUID(uuid.uuid4()), UNIX_EPOCH)

        # Act
        self.exec_engine.execute_command(submit_order1)
        self.exec_engine.execute_command(submit_order2)
        self.exec_engine.execute_command(submit_order3)
        self.exec_engine.handle_event(order1_filled)
        self.exec_engine.handle_event(order2_filled)
        self.exec_engine.handle_event(order3_filled)

        # Assert
        # Already tested .is_position_active and .is_position_closed above
        self.assertTrue(self.exec_db.position_exists(position_id1))
        self.assertTrue(self.exec_db.position_exists(position_id2))
        self.assertTrue(self.exec_engine.is_strategy_flat(strategy1.id))
        self.assertFalse(self.exec_engine.is_strategy_flat(strategy2.id))
        self.assertFalse(self.exec_engine.is_flat())
        self.assertTrue(
            position_id1 in self.exec_db.get_positions(strategy1.id))
        self.assertTrue(
            position_id2 in self.exec_db.get_positions(strategy2.id))
        self.assertTrue(position_id1 in self.exec_db.get_positions())
        self.assertTrue(position_id2 in self.exec_db.get_positions())
        self.assertEqual(0, len(self.exec_db.get_positions_open(strategy1.id)))
        self.assertEqual(1, len(self.exec_db.get_positions_open(strategy2.id)))
        self.assertEqual(1, len(self.exec_db.get_positions_open()))
        self.assertEqual(1, len(self.exec_db.get_positions_closed()))
        self.assertEqual(2, len(self.exec_db.get_positions()))
        self.assertTrue(
            position_id1 not in self.exec_db.get_positions_open(strategy1.id))
        self.assertTrue(
            position_id2 in self.exec_db.get_positions_open(strategy2.id))
        self.assertTrue(position_id1 not in self.exec_db.get_positions_open())
        self.assertTrue(position_id2 in self.exec_db.get_positions_open())
        self.assertTrue(
            position_id1 in self.exec_db.get_positions_closed(strategy1.id))
        self.assertTrue(position_id2 not in self.exec_db.get_positions_closed(
            strategy2.id))
        self.assertTrue(position_id1 in self.exec_db.get_positions_closed())
        self.assertTrue(
            position_id2 not in self.exec_db.get_positions_closed())
        self.assertEqual(2, self.exec_db.count_positions_total())
        self.assertEqual(1, self.exec_db.count_positions_open())
        self.assertEqual(1, self.exec_db.count_positions_closed())
Example #22
0
    def test_position_long_with_multiple_filled_orders_returns_expected_attributes(self):
        # Arrange
        order1 = self.order_factory.market(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000))

        order2 = self.order_factory.market(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000))

        order3 = self.order_factory.market(
            AUDUSD_FXCM,
            OrderSide.SELL,
            Quantity(200000))

        order1_filled = OrderFilled(
            self.account_id,
            order1.id,
            ExecutionId('E1'),
            PositionIdBroker('T123456'),
            order1.symbol,
            order1.side,
            order1.quantity,
            Price(1.00000, 5),
            Currency.USD,
            UNIX_EPOCH,
            GUID(uuid.uuid4()),
            UNIX_EPOCH)

        order2_filled = OrderFilled(
            self.account_id,
            order2.id,
            ExecutionId('E2'),
            PositionIdBroker('T123456'),
            order2.symbol,
            order2.side,
            order2.quantity,
            Price(1.00001, 5),
            Currency.USD,
            UNIX_EPOCH,
            GUID(uuid.uuid4()),
            UNIX_EPOCH)

        order3_filled = OrderFilled(
            self.account_id,
            order3.id,
            ExecutionId('E3'),
            PositionIdBroker('T123456'),
            order3.symbol,
            order3.side,
            order3.quantity,
            Price(1.00010, 5),
            Currency.USD,
            UNIX_EPOCH,
            GUID(uuid.uuid4()),
            UNIX_EPOCH)

        last = Tick(AUDUSD_FXCM,
                    Price(1.00050, 5),
                    Price(1.00048, 5),
                    Volume(1),
                    Volume(1),
                    UNIX_EPOCH)

        # Act
        position = Position(PositionId('P-123456'), order1_filled)
        position.apply(order2_filled)
        position.apply(order3_filled)

        # Assert
        self.assertEqual(Quantity(), position.quantity)
        self.assertEqual(MarketPosition.FLAT, position.market_position)
        self.assertEqual(UNIX_EPOCH, position.opened_time)
        self.assertEqual(1.000005, position.average_open_price)
        self.assertEqual(3, position.event_count)
        self.assertEqual([order1.id, order2.id, order3.id], position.get_order_ids())
        self.assertEqual(ExecutionId('E3'), position.last_execution_id)
        self.assertEqual(PositionIdBroker('T123456'), position.id_broker)
        self.assertEqual(UNIX_EPOCH, position.closed_time)
        self.assertEqual(1.0001, position.average_close_price)
        self.assertFalse(position.is_long)
        self.assertFalse(position.is_short)
        self.assertTrue(position.is_closed)
        self.assertEqual(9.499999999995623e-05, position.realized_points)
        self.assertEqual(9.499952500233122e-05, position.realized_return)
        self.assertEqual(Money(19.000, Currency.USD), position.realized_pnl)
        self.assertEqual(0.0, position.unrealized_points(last))
        self.assertEqual(0.0, position.unrealized_return(last))
        self.assertEqual(Money(00, Currency.USD), position.unrealized_pnl(last))
        self.assertEqual(9.499999999995623e-05, position.total_points(last))
        self.assertEqual(9.499952500233122e-05, position.total_return(last))
        self.assertEqual(Money(19.000, Currency.USD), position.total_pnl(last))
Example #23
0
    def test_position_filled_with_sell_order_then_buy_order_returns_expected_attributes(self):
        # Arrange
        order1 = self.order_factory.market(
            AUDUSD_FXCM,
            OrderSide.SELL,
            Quantity(100000))

        order2 = self.order_factory.market(
            AUDUSD_FXCM,
            OrderSide.BUY,
            Quantity(100000))

        order_filled1 = OrderFilled(
            self.account_id,
            order1.id,
            ExecutionId('E123456'),
            PositionIdBroker('T123456'),
            order1.symbol,
            order1.side,
            order1.quantity,
            Price(1.00000, 5),
            Currency.USD,
            UNIX_EPOCH,
            GUID(uuid.uuid4()),
            UNIX_EPOCH)

        position = Position(PositionId('P-123456'), order_filled1)

        order_filled2 = OrderPartiallyFilled(
            self.account_id,
            order2.id,
            ExecutionId('E1234561'),
            PositionIdBroker('T123456'),
            order2.symbol,
            order2.side,
            Quantity(50000),
            Quantity(50000),
            Price(1.00001, 5),
            Currency.USD,
            UNIX_EPOCH,
            GUID(uuid.uuid4()),
            UNIX_EPOCH)

        order_filled3 = OrderPartiallyFilled(
            self.account_id,
            order2.id,
            ExecutionId('E1234562'),
            PositionIdBroker('T123456'),
            order2.symbol,
            order2.side,
            Quantity(100000),
            Quantity(),
            Price(1.00003, 5),
            Currency.USD,
            UNIX_EPOCH,
            GUID(uuid.uuid4()),
            UNIX_EPOCH)

        last = Tick(AUDUSD_FXCM,
                    Price(1.00050, 5),
                    Price(1.00048, 5),
                    Volume(1),
                    Volume(1),
                    UNIX_EPOCH)

        # Act
        position.apply(order_filled2)
        position.apply(order_filled3)

        # Assert
        self.assertEqual(Quantity(), position.quantity)
        self.assertEqual(MarketPosition.FLAT, position.market_position)
        self.assertEqual(UNIX_EPOCH, position.opened_time)
        self.assertEqual(1.0, position.average_open_price)
        self.assertEqual(3, position.event_count)
        self.assertEqual([order1.id, order2.id], position.get_order_ids())
        self.assertEqual(ExecutionId('E1234562'), position.last_execution_id)
        self.assertEqual(PositionIdBroker('T123456'), position.id_broker)
        self.assertEqual(UNIX_EPOCH, position.closed_time)
        self.assertEqual(1.00003, position.average_close_price)
        self.assertFalse(position.is_long)
        self.assertFalse(position.is_short)
        self.assertTrue(position.is_closed)
        self.assertEqual(-2.999999999997449e-05, position.realized_points)
        self.assertEqual(-2.999999999997449e-05, position.realized_return)
        self.assertEqual(Money(-3.000, Currency.USD), position.realized_pnl)
        self.assertEqual(0.0, position.unrealized_points(last))
        self.assertEqual(0.0, position.unrealized_return(last))
        self.assertEqual(Money(00, Currency.USD), position.unrealized_pnl(last))
        self.assertEqual(-2.999999999997449e-05, position.total_points(last))
        self.assertEqual(-2.999999999997449e-05, position.total_return(last))
        self.assertEqual(Money(-3.000, Currency.USD), position.total_pnl(last))