Exemple #1
0
    def test_generate_positions_report(self):
        # Arrange
        report_provider = ReportProvider()

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

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

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

        fill2 = TestStubs.event_order_filled(
            order2,
            instrument=AUDUSD_SIM,
            position_id=PositionId("P-123457"),
            strategy_id=StrategyId("S", "001"),
            fill_price=Price("1.00010"),
        )

        position1 = Position(fill1)
        position1.apply(fill2)

        position2 = Position(fill1)
        position2.apply(fill2)

        positions = [position1, position2]

        # Act
        report = report_provider.generate_positions_report(positions)

        # Assert
        self.assertEqual(2, len(report))
        self.assertEqual("position_id", report.index.name)
        self.assertEqual(position1.id.value, report.index[0])
        self.assertEqual("AUD/USD", report.iloc[0]["symbol"])
        self.assertEqual("BUY", report.iloc[0]["entry"])
        self.assertEqual(100000, report.iloc[0]["peak_quantity"])
        self.assertEqual(1.0001, report.iloc[0]["avg_open"])
        self.assertEqual(1.0001, report.iloc[0]["avg_close"])
        self.assertEqual(UNIX_EPOCH, report.iloc[0]["opened_time"])
        self.assertEqual(UNIX_EPOCH, report.iloc[0]["closed_time"])
        self.assertEqual(0, report.iloc[0]["realized_points"])
        self.assertEqual(0, report.iloc[0]["realized_return"])
    def test_generate_positions_report(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 = TestStubs.event_order_filled(
            order1,
            instrument=AUDUSD_SIM,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("1.00010"),
        )

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

        position1 = Position(instrument=AUDUSD_SIM, fill=fill1)
        position1.apply(fill2)

        position2 = Position(instrument=AUDUSD_SIM, fill=fill1)
        position2.apply(fill2)

        positions = [position1, position2]

        # Act
        report = ReportProvider.generate_positions_report(positions)

        # Assert
        assert len(report) == 2
        assert report.index.name == "position_id"
        assert report.index[0] == position1.id.value
        assert report.iloc[0]["instrument_id"] == "AUD/USD.SIM"
        assert report.iloc[0]["entry"] == "BUY"
        assert report.iloc[0]["side"] == "FLAT"
        assert report.iloc[0]["peak_qty"] == "100000"
        assert report.iloc[0]["avg_px_open"] == "1.00010"
        assert report.iloc[0]["avg_px_close"] == "1.00010"
        assert report.iloc[0]["ts_opened"] == UNIX_EPOCH
        assert report.iloc[0]["ts_closed"] == UNIX_EPOCH
        assert report.iloc[0]["realized_points"] == "0.00000"
        assert report.iloc[0]["realized_return"] == "0.00000"
    def test_flatten_all_positions(self):
        # Arrange
        strategy = TradingStrategy(order_id_tag="001")
        strategy.register_trader(
            TraderId("TESTER", "000"),
            clock=self.clock,
            uuid_factory=self.uuid_factory,
            logger=self.logger,
        )
        self.exec_engine.register_strategy(strategy)

        order1 = strategy.order_factory.market(
            USDJPY_FXCM,
            OrderSide.BUY,
            Quantity(100000),
        )

        order2 = strategy.order_factory.market(
            USDJPY_FXCM,
            OrderSide.BUY,
            Quantity(100000),
        )

        strategy.submit_order(order1)
        strategy.submit_order(order2)

        filled1 = TestStubs.event_order_filled(
            order1,
            position_id=PositionId("B-USD/JPY-1"),
            strategy_id=strategy.id,
        )

        filled2 = TestStubs.event_order_filled(
            order2,
            position_id=PositionId("B-USD/JPY-2"),
            strategy_id=strategy.id,
        )

        position1 = Position(filled1)
        position2 = Position(filled2)

        # Act
        strategy.flatten_all_positions(USDJPY_FXCM)

        # Assert
        self.assertTrue(order1 in strategy.execution.orders())
        self.assertTrue(order2 in strategy.execution.orders())
        self.assertEqual(OrderState.FILLED, strategy.execution.orders()[0].state())
        self.assertEqual(OrderState.FILLED, strategy.execution.orders()[1].state())
        self.assertEqual(PositionSide.FLAT, strategy.execution.positions()[0].side)
        self.assertEqual(PositionSide.FLAT, strategy.execution.positions()[1].side)
        self.assertTrue(position1.id in strategy.execution.position_closed_ids())
        self.assertTrue(position2.id in strategy.execution.position_closed_ids())
        self.assertTrue(strategy.execution.is_completely_flat())
def nautilus_objects() -> List[Any]:
    """A list of nautilus instances for testing serialization"""
    instrument = TestInstrumentProvider.default_fx_ccy("AUD/USD")
    position_id = PositionId("P-001")
    buy = TestExecStubs.limit_order()
    buy_submitted, buy_accepted, buy_filled = _make_order_events(
        buy,
        instrument=instrument,
        position_id=position_id,
        trade_id=TradeId("BUY"),
    )
    sell = TestExecStubs.limit_order(order_side=OrderSide.SELL)
    _, _, sell_filled = _make_order_events(
        sell,
        instrument=instrument,
        position_id=position_id,
        trade_id=TradeId("SELL"),
    )
    open_position = Position(instrument=instrument, fill=buy_filled)
    closed_position = Position(instrument=instrument, fill=buy_filled)
    closed_position.apply(sell_filled)

    return [
        TestDataStubs.ticker(),
        TestDataStubs.quote_tick_5decimal(),
        TestDataStubs.trade_tick_5decimal(),
        TestDataStubs.bar_5decimal(),
        TestDataStubs.venue_status_update(),
        TestDataStubs.instrument_status_update(),
        TestEventStubs.component_state_changed(),
        TestEventStubs.trading_state_changed(),
        TestEventStubs.betting_account_state(),
        TestEventStubs.cash_account_state(),
        TestEventStubs.margin_account_state(),
        # ORDERS
        TestEventStubs.order_accepted(buy),
        TestEventStubs.order_rejected(buy),
        TestEventStubs.order_pending_update(buy_accepted),
        TestEventStubs.order_pending_cancel(buy_accepted),
        TestEventStubs.order_filled(
            order=buy,
            instrument=instrument,
            position_id=open_position.id,
        ),
        TestEventStubs.order_canceled(buy_accepted),
        TestEventStubs.order_expired(buy),
        TestEventStubs.order_triggered(buy),
        # POSITIONS
        TestEventStubs.position_opened(open_position),
        TestEventStubs.position_changed(open_position),
        TestEventStubs.position_closed(closed_position),
    ]
    def test_calculate_pnl_for_inverse1(self):
        # Arrange
        order = self.order_factory.market(
            XBTUSD_BITMEX.id,
            OrderSide.SELL,
            Quantity.from_int(100000),
        )

        fill = TestStubs.event_order_filled(
            order,
            instrument=XBTUSD_BITMEX,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("10000.00"),
        )

        position = Position(instrument=XBTUSD_BITMEX, fill=fill)

        # Act
        pnl = position.calculate_pnl(
            avg_px_open=Price.from_str("10000.00"),
            avg_px_close=Price.from_str("11000.00"),
            quantity=Quantity.from_int(100000),
        )

        # Assert
        self.assertEqual(Money(-0.90909091, BTC), pnl)
        self.assertEqual(Money(-0.90909091, BTC),
                         position.unrealized_pnl(Price.from_str("11000.00")))
        self.assertEqual(Money(-0.00750000, BTC), position.realized_pnl)
        self.assertEqual(Money(9.09090909, BTC),
                         position.notional_value(Price.from_str("11000.00")))
    def test_calculate_pnl_for_long_position_win(self):
        # Arrange
        order = self.order_factory.market(
            BTCUSDT_BINANCE.id,
            OrderSide.BUY,
            Quantity.from_int(12),
        )

        fill = TestStubs.event_order_filled(
            order,
            instrument=BTCUSDT_BINANCE,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("10500.00"),
        )

        position = Position(instrument=BTCUSDT_BINANCE, fill=fill)

        # Act
        pnl = position.calculate_pnl(
            avg_px_open=Price.from_str("10500.00"),
            avg_px_close=Price.from_str("10510.00"),
            quantity=Quantity.from_int(12),
        )

        # Assert
        self.assertEqual(Money(120.00000000, USDT), pnl)
        self.assertEqual(Money(-126.00000000, USDT), position.realized_pnl)
        self.assertEqual(
            Money(120.00000000, USDT),
            position.unrealized_pnl(Price.from_str("10510.00")),
        )
        self.assertEqual(Money(-6.00000000, USDT),
                         position.total_pnl(Price.from_str("10510.00")))
        self.assertEqual([Money(126.00000000, USDT)], position.commissions())
    def test_can_flush(self):
        # Arrange
        order1 = self.strategy.order_factory.market(AUDUSD_FXCM, OrderSide.BUY,
                                                    Quantity(100000))
        position1_id = self.strategy.position_id_generator.generate()
        self.database.add_order(order1, self.strategy.id, position1_id)

        order1_filled = TestStubs.event_order_filled(order1,
                                                     fill_price=Price(
                                                         1.00000, 5))
        position1 = Position(position1_id, order1_filled)
        self.database.update_order(order1)
        self.database.add_position(position1, self.strategy.id)

        order2 = self.strategy.order_factory.market(AUDUSD_FXCM, OrderSide.BUY,
                                                    Quantity(100000))
        position2_id = self.strategy.position_id_generator.generate()
        self.database.add_order(order2, self.strategy.id, position2_id)
        order2_working = TestStubs.event_order_working(order2)
        order2.apply(order2_working)

        self.database.update_order(order2)

        # Act
        self.database.reset()
        self.database.flush()
Exemple #8
0
    def position(number=1, entry_price=None) -> Position:
        if entry_price is None:
            entry_price = Price("1.00000")

        generator = PositionIdGenerator(id_tag_trader=IdTag("001"))

        for _i in range(number):
            generator.generate(TestStubs.symbol_audusd_fxcm())

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

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

        position_id = PositionId(TestStubs.symbol_audusd_fxcm().value)
        order_filled = TestStubs.event_order_filled(
            order,
            position_id=position_id,
            fill_price=entry_price,
        )

        position = Position(event=order_filled)

        return position
    def test_calculate_pnl_for_inverse2(self):
        # Arrange
        order = self.order_factory.market(
            ETHUSD_BITMEX.symbol,
            OrderSide.SELL,
            Quantity(100000),
        )

        fill = TestStubs.event_order_filled(
            order,
            instrument=ETHUSD_BITMEX,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S", "001"),
            fill_price=Price("375.95"),
        )

        position = Position(fill)

        # Act
        pnl = position.calculate_pnl(
            Price("375.95"),
            Price("365.50"),
            Quantity(100000),
            # xrate=Decimal("0.0294337")  # Currently not handling quanto settlement
        )

        # Assert
        self.assertEqual(Money(1582.66, USD), position.unrealized_pnl(Price("370.00")))
        self.assertEqual(Money(100000.00, USD), position.notional_value(Price("370.00")))
    def test_calculate_pnl_for_short_position_loss(self):
        # Arrange
        order = self.order_factory.market(
            BTCUSDT_BINANCE.symbol,
            OrderSide.SELL,
            Quantity("10"),
        )

        fill = TestStubs.event_order_filled(
            order,
            instrument=BTCUSDT_BINANCE,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S", "001"),
            fill_price=Price("10500.00"),
        )

        position = Position(fill)

        # Act
        pnl = position.calculate_pnl(
            Price("10500.00"),
            Price("10670.50"),
            Quantity("10.000000"),
        )

        # Assert
        self.assertEqual(Money("-1705.00000000", USDT), pnl)
        self.assertEqual(Money("-1705.00000000", USDT), position.unrealized_pnl(Price("10670.50")))
        self.assertEqual(Money("-105.00000000", USDT), position.realized_pnl)
        self.assertEqual([Money("105.00000000", USDT)], position.commissions())
        self.assertEqual(Money("105.00000000", USDT), position.commission)
        self.assertEqual(Money("106705.00000000", USDT), position.notional_value(Price("10670.50")))
Exemple #11
0
    def test_update_position_when_not_already_exists_logs(self):
        # Arrange
        order = self.strategy.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
        )

        self.database.add_order(order)

        position_id = PositionId("P-1")
        fill = TestStubs.event_order_filled(
            order,
            instrument=AUDUSD_SIM,
            position_id=position_id,
            last_px=Price.from_str("1.00000"),
        )

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

        # Act
        self.database.update_position(position)

        # Assert
        assert True  # No exception raised
Exemple #12
0
    def test_serialize_and_deserialize_position_opened_events(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
        )

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

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

        uuid = UUID4()
        event = PositionOpened.create(position, fill, uuid, 0)

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

        # Assert
        assert deserialized == event
Exemple #13
0
    def test_add_position(self):
        # Arrange
        order = self.strategy.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity(100000),
        )

        self.database.add_order(order)

        position_id = PositionId("P-1")
        fill = TestStubs.event_order_filled(
            order,
            instrument=AUDUSD_SIM,
            position_id=position_id,
            last_px=Price("1.00000"),
        )

        position = Position(fill=fill)

        # Act
        self.database.add_position(position)

        # Assert
        self.assertEqual(position, self.database.load_position(position.id))
    def test_position_opened_event_to_from_dict_and_str_repr(self):
        # Arrange
        order = self.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
        )

        fill = 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"),
        )

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

        uuid = UUID4()
        event = PositionOpened.create(position, fill, uuid, 0)

        # Act, Assert
        assert PositionOpened.from_dict(PositionOpened.to_dict(event)) == event
        assert (
            str(event) ==
            "PositionOpened(instrument_id=AUD/USD.SIM, position_id=P-123456, account_id=SIM-000, from_order=O-19700101-000000-000-001-1, strategy_id=S-001, entry=BUY, side=LONG, net_qty=100_000, quantity=100_000, peak_qty=100_000, currency=USD, avg_px_open=1.00001, avg_px_close=None, realized_points=0, realized_return=0.00000, realized_pnl=-2.00 USD, unrealized_pnl=0.00 USD, ts_opened=0, ts_last=0, ts_closed=0, duration_ns=0)"  # noqa
        )
        assert (
            repr(event) ==
            f"PositionOpened(trader_id=TESTER-000, strategy_id=S-001, instrument_id=AUD/USD.SIM, position_id=P-123456, account_id=SIM-000, from_order=O-19700101-000000-000-001-1, strategy_id=S-001, entry=BUY, side=LONG, net_qty=100_000, quantity=100_000, peak_qty=100_000, currency=USD, avg_px_open=1.00001, avg_px_close=None, realized_points=0, realized_return=0.00000, realized_pnl=-2.00 USD, unrealized_pnl=0.00 USD, ts_opened=0, ts_last=0, ts_closed=0, duration_ns=0, event_id={uuid})"  # noqa
        )
Exemple #15
0
    def test_calculate_pnl_for_long_position_loss(self):
        # Arrange
        order = self.order_factory.market(
            BTCUSDT_BINANCE.id,
            OrderSide.BUY,
            Quantity.from_int(12),
        )

        fill = TestEventStubs.order_filled(
            order,
            instrument=BTCUSDT_BINANCE,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("10500.00"),
        )

        position = Position(instrument=BTCUSDT_BINANCE, fill=fill)

        # Act
        pnl = position.calculate_pnl(
            avg_px_open=Price.from_str("10500.00"),
            avg_px_close=Price.from_str("10480.50"),
            quantity=Quantity.from_int(10),
        )

        # Assert
        assert pnl == Money(-195.00000000, USDT)
        assert position.realized_pnl == Money(-126.00000000, USDT)
        assert position.unrealized_pnl(Price.from_str("10480.50")) == Money(
            -234.00000000, USDT)
        assert position.total_pnl(Price.from_str("10480.50")) == Money(
            -360.00000000, USDT)
        assert position.commissions() == [Money(126.00000000, USDT)]
Exemple #16
0
    def test_calculate_pnl_for_short_position_loss(self):
        # Arrange
        order = self.order_factory.market(
            BTCUSDT_BINANCE.id,
            OrderSide.SELL,
            Quantity.from_str("10"),
        )

        fill = TestEventStubs.order_filled(
            order,
            instrument=BTCUSDT_BINANCE,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("10500.00"),
        )

        position = Position(instrument=BTCUSDT_BINANCE, fill=fill)

        # Act
        pnl = position.calculate_pnl(
            Price.from_str("10500.00"),
            Price.from_str("10670.50"),
            Quantity.from_str("10.000000"),
        )

        # Assert
        assert pnl == Money(-1705.00000000, USDT)
        assert position.unrealized_pnl(Price.from_str("10670.50")) == Money(
            -1705.00000000, USDT)
        assert position.realized_pnl == Money(-105.00000000, USDT)
        assert position.commissions() == [Money(105.00000000, USDT)]
        assert position.notional_value(Price.from_str("10670.50")) == Money(
            106705.00000000, USDT)
    def test_can_add_position(self):
        # Arrange
        order = self.strategy.order_factory.market(AUDUSD_FXCM, OrderSide.BUY,
                                                   Quantity(100000))
        position_id = self.strategy.position_id_generator.generate()
        self.database.add_order(order, self.strategy.id, position_id)

        order_filled = TestStubs.event_order_filled(order,
                                                    fill_price=Price(
                                                        1.00000, 5))
        position = Position(position_id, order_filled)

        # Act
        self.database.add_position(position, self.strategy.id)

        # Assert
        self.assertTrue(self.database.position_exists_for_order(order.id))
        self.assertTrue(self.database.position_exists(position.id))
        self.assertTrue(position.id in self.database.get_position_ids())
        self.assertTrue(position.id in self.database.get_positions())
        self.assertTrue(
            position.id in self.database.get_positions_open(self.strategy.id))
        self.assertTrue(position.id in self.database.get_positions_open())
        self.assertTrue(position.id not in self.database.get_positions_closed(
            self.strategy.id))
        self.assertTrue(
            position.id not in self.database.get_positions_closed())
    def test_load_position(self):
        # Arrange
        order = self.strategy.order_factory.market(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
        )

        position_id = PositionId('P-1')
        self.cache.add_order(order, position_id)

        order_filled = TestStubs.event_order_filled(
            order,
            instrument=AUDUSD_SIM,
            position_id=PositionId('P-1'),
            fill_price=Price("1.00000"),
        )

        position = Position(order_filled)
        self.cache.add_position(position)

        # Act
        result = self.cache.load_position(position.id)

        # Assert
        self.assertEqual(position, result)
    def test_calculate_pnl_for_long_position_loss(self):
        # Arrange
        order = self.order_factory.market(
            BTCUSDT_BINANCE.symbol,
            OrderSide.BUY,
            Quantity(12),
        )

        fill = TestStubs.event_order_filled(
            order,
            instrument=BTCUSDT_BINANCE,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S", "001"),
            fill_price=Price("10500.00"),
        )

        position = Position(fill)

        # Act
        pnl = position.calculate_pnl(
            avg_open=Price("10500.00"),
            avg_close=Price("10480.50"),
            quantity=Quantity(10),
        )

        # Assert
        self.assertEqual(Money("-195.00000000", USDT), pnl)
        self.assertEqual(Money("-126.00000000", USDT), position.realized_pnl)
        self.assertEqual(Money("-234.00000000", USDT), position.unrealized_pnl(Price("10480.50")))
        self.assertEqual(Money("-360.00000000", USDT), position.total_pnl(Price("10480.50")))
        self.assertEqual([Money("126.00000000", USDT)], position.commissions())
        self.assertEqual(Money("126.00000000", USDT), position.commission)
Exemple #20
0
    def test_load_position(self):
        # Arrange
        order = self.strategy.order_factory.market(
            AUDUSD_SIM.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
        )

        position_id = PositionId("P-1")
        self.cache.add_order(order, position_id)

        fill = TestStubs.event_order_filled(
            order,
            instrument=AUDUSD_SIM,
            position_id=PositionId("P-1"),
            last_px=Price.from_str("1.00000"),
        )

        position = Position(instrument=AUDUSD_SIM, fill=fill)
        self.cache.add_position(position)

        # Act
        result = self.cache.load_position(position.id)

        # Assert
        self.assertEqual(position, result)
    def test_calculate_pnl_for_inverse1(self):
        # Arrange
        order = self.order_factory.market(
            XBTUSD_BITMEX.symbol,
            OrderSide.SELL,
            Quantity(100000),
        )

        fill = TestStubs.event_order_filled(
            order,
            instrument=XBTUSD_BITMEX,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S", "001"),
            fill_price=Price("10000.00"),
        )

        position = Position(fill)

        # Act
        pnl = position.calculate_pnl(
            Price("10000.00"),
            Price("11000.00"),
            Quantity(100000),
        )

        # Assert
        self.assertEqual(Money(-10000.00, USD), pnl)
        self.assertEqual(Money(-10000.00, USD), position.unrealized_pnl(Price("11000.00")))
        self.assertEqual(Money(0.00, USD), position.realized_pnl)
        self.assertEqual(Money(0.00, USD), position.commission)
        self.assertEqual(Money(100000.00, USD), position.notional_value(Price("11000.00")))
    def test_calculate_unrealized_pnl_for_long_inverse(self):
        # Arrange
        order = self.order_factory.market(
            XBTUSD_BITMEX.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
        )

        fill = TestStubs.event_order_filled(
            order,
            instrument=XBTUSD_BITMEX,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("10500.00"),
        )

        position = Position(XBTUSD_BITMEX, fill)

        # Act

        pnl = position.unrealized_pnl(Price.from_str("11505.60"))

        # Assert
        self.assertEqual(Money(0.83238969, BTC), pnl)
        self.assertEqual(Money(-0.00714286, BTC), position.realized_pnl)
        self.assertEqual([Money(0.00714286, BTC)], position.commissions())
    def test_calculate_unrealized_pnl_for_short(self):
        # Arrange
        order = self.order_factory.market(
            BTCUSDT_BINANCE.symbol,
            OrderSide.SELL,
            Quantity("5.912000"),
        )

        fill = TestStubs.event_order_filled(
            order,
            instrument=BTCUSDT_BINANCE,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S", "001"),
            fill_price=Price("10505.60"),
        )

        position = Position(fill)

        pnl = position.unrealized_pnl(Price("10407.15"))

        # Assert
        self.assertEqual(Money("582.03640000", USDT), pnl)
        self.assertEqual(Money("-62.10910720", USDT), position.realized_pnl)
        self.assertEqual([Money("62.10910720", USDT)], position.commissions())
        self.assertEqual(Money("62.10910720", USDT), position.commission)
    def test_load_order_when_position_in_database_returns_position(self):
        # Arrange
        self.database.add_instrument(AUDUSD_SIM)

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

        self.database.add_order(order)

        position_id = PositionId("P-1")
        fill = TestStubs.event_order_filled(
            order,
            instrument=AUDUSD_SIM,
            position_id=position_id,
            last_px=Price.from_str("1.00000"),
        )

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

        self.database.add_position(position)

        # Act
        result = self.database.load_position(position_id)

        # Assert
        assert result == position
Exemple #25
0
    def test_unrealized_pnl_when_insufficient_data_for_xrate_returns_none(
            self):
        # Arrange
        state = AccountState(
            account_id=AccountId("BITMEX", "01234"),
            account_type=AccountType.MARGIN,
            base_currency=BTC,
            reported=True,
            balances=[
                AccountBalance(
                    BTC,
                    Money(10.00000000, BTC),
                    Money(0.00000000, BTC),
                    Money(10.00000000, BTC),
                ),
                AccountBalance(
                    ETH,
                    Money(20.00000000, ETH),
                    Money(0.00000000, ETH),
                    Money(20.00000000, ETH),
                ),
            ],
            info={},
            event_id=uuid4(),
            updated_ns=0,
            timestamp_ns=0,
        )

        self.exec_engine.process(state)

        order = self.order_factory.market(
            ETHUSD_BITMEX.id,
            OrderSide.BUY,
            Quantity.from_int(100),
        )

        self.exec_engine.cache.add_order(order, PositionId.null())
        self.exec_engine.process(TestStubs.event_order_submitted(order))
        self.exec_engine.process(TestStubs.event_order_accepted(order))

        fill = TestStubs.event_order_filled(
            order=order,
            instrument=ETHUSD_BITMEX,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("376.05"),
        )

        self.exec_engine.process(fill)

        position = Position(instrument=ETHUSD_BITMEX, fill=fill)

        self.portfolio.update_position(
            TestStubs.event_position_opened(position))

        # Act
        result = self.portfolio.unrealized_pnls(BITMEX)

        # # Assert
        self.assertEqual({}, result)
    def test_serialize_and_deserialize_position_events_closed(
            self, position_func):
        instrument = TestInstrumentProvider.default_fx_ccy("GBPUSD")

        open_order = self.order_factory.market(
            instrument.id,
            OrderSide.BUY,
            Quantity.from_int(100000),
        )
        open_fill = TestStubs.event_order_filled(
            open_order,
            instrument=instrument,
            position_id=PositionId("P-3"),
            strategy_id=StrategyId("S-1"),
            last_px=Price.from_str("1.00000"),
        )
        close_order = self.order_factory.market(
            instrument.id,
            OrderSide.SELL,
            Quantity.from_int(100000),
        )
        close_fill = TestStubs.event_order_filled(
            close_order,
            instrument=instrument,
            position_id=PositionId("P-3"),
            strategy_id=StrategyId("S-1"),
            last_px=Price.from_str("1.20000"),
        )

        position = Position(instrument=instrument, fill=open_fill)
        position.apply(close_fill)

        event = position_func(position=position)
        self._test_serialization(obj=event)
    def test_calculate_unrealized_pnl_for_short_inverse(self):
        # Arrange
        order = self.order_factory.market(
            XBTUSD_BITMEX.id,
            OrderSide.SELL,
            Quantity.from_int(1250000),
        )

        fill = TestStubs.event_order_filled(
            order,
            instrument=XBTUSD_BITMEX,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("15500.00"),
        )

        position = Position(XBTUSD_BITMEX, fill)

        # Act

        pnl = position.unrealized_pnl(Price.from_str("12506.65"))

        # Assert
        self.assertEqual(Money(19.30166700, BTC), pnl)
        self.assertEqual(Money(-0.06048387, BTC), position.realized_pnl)
        self.assertEqual([Money(0.06048387, BTC)], position.commissions())
    def test_load_positions_cache_when_one_position_in_database(self):
        # Arrange
        order1 = self.strategy.order_factory.stop_market(
            AUDUSD_SIM.symbol,
            OrderSide.BUY,
            Quantity(100000),
            Price("1.00000"),
        )

        self.database.add_order(order1)

        position_id = PositionId('P-1')
        order1.apply(TestStubs.event_order_submitted(order1))
        order1.apply(TestStubs.event_order_accepted(order1))
        order1.apply(TestStubs.event_order_working(order1))
        order1.apply(
            TestStubs.event_order_filled(
                order1,
                instrument=AUDUSD_SIM,
                position_id=position_id,
                fill_price=Price("1.00001"),
            ))

        position = Position(order1.last_event)
        self.database.add_position(position)

        # Act
        result = self.database.load_positions()

        # Assert
        self.assertEqual({position.id: position}, result)
    def test_load_positions_cache_when_one_position_in_database(self):
        # Arrange
        self.database.add_instrument(AUDUSD_SIM)

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

        self.database.add_order(order1)

        position_id = PositionId("P-1")
        order1.apply(TestStubs.event_order_submitted(order1))
        order1.apply(TestStubs.event_order_accepted(order1))
        order1.apply(
            TestStubs.event_order_filled(
                order1,
                instrument=AUDUSD_SIM,
                position_id=position_id,
                last_px=Price.from_str("1.00001"),
            ))

        position = Position(instrument=AUDUSD_SIM, fill=order1.last_event)
        self.database.add_position(position)

        # Act
        result = self.database.load_positions()

        # Assert
        assert result == {position.id: position}
    def test_calculate_pnl_when_given_position_side_flat_returns_zero(self):
        # Arrange
        order = self.order_factory.market(
            BTCUSDT_BINANCE.id,
            OrderSide.BUY,
            Quantity.from_int(12),
        )

        fill = TestStubs.event_order_filled(
            order,
            instrument=BTCUSDT_BINANCE,
            position_id=PositionId("P-123456"),
            strategy_id=StrategyId("S-001"),
            last_px=Price.from_str("10500.00"),
        )

        position = Position(instrument=BTCUSDT_BINANCE, fill=fill)

        # Act
        result = position.calculate_pnl(
            Price.from_str("10500.00"),
            Price.from_str("10500.00"),
            Quantity.from_int(100000),
        )

        # Assert
        self.assertEqual(Money(0, USDT), result)