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_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_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_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)
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_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")))
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)]
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_position_filled_with_buy_order_returns_expected_attributes(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"), ) last = Price.from_str("1.00050") # Act position = Position(instrument=AUDUSD_SIM, fill=fill) # Assert assert position.symbol == AUDUSD_SIM.id.symbol assert position.venue == AUDUSD_SIM.id.venue assert not position.is_opposite_side(fill.order_side) assert not position != position # Equality operator test assert position.from_order == ClientOrderId( "O-19700101-000000-000-001-1") assert position.quantity == Quantity.from_int(100000) assert position.peak_qty == Quantity.from_int(100000) assert position.entry == OrderSide.BUY assert position.side == PositionSide.LONG assert position.ts_opened == 0 assert position.duration_ns == 0 assert position.avg_px_open == Decimal("1.00001") assert position.event_count == 1 assert position.client_order_ids == [order.client_order_id] assert position.venue_order_ids == [VenueOrderId("1")] assert position.execution_ids == [ ExecutionId("E-19700101-000000-000-001-1") ] assert position.last_execution_id == ExecutionId( "E-19700101-000000-000-001-1") assert position.id == PositionId("P-123456") assert len(position.events) == 1 assert position.is_long assert not position.is_short assert position.is_open assert not position.is_closed assert position.realized_points == 0 assert position.realized_return == 0 assert position.realized_pnl == Money(-2.00, USD) assert position.unrealized_pnl(last) == Money(49.00, USD) assert position.total_pnl(last) == Money(47.00, USD) assert position.commissions() == [Money(2.00, USD)] assert repr( position) == "Position(LONG 100_000 AUD/USD.SIM, id=P-123456)"
def test_position_filled_with_buy_order_returns_expected_attributes(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"), ) last = Price.from_str("1.00050") # Act position = Position(instrument=AUDUSD_SIM, fill=fill) # Assert assert position.symbol == AUDUSD_SIM.id.symbol assert position.venue == AUDUSD_SIM.id.venue assert not position.is_opposite_side(fill.order_side) self.assertFalse(position != position) # Equality operator test self.assertEqual(ClientOrderId("O-19700101-000000-000-001-1"), position.from_order) self.assertEqual(Quantity.from_int(100000), position.quantity) self.assertEqual(Quantity.from_int(100000), position.peak_qty) self.assertEqual(OrderSide.BUY, position.entry) self.assertEqual(PositionSide.LONG, position.side) self.assertEqual(0, position.opened_timestamp_ns) self.assertEqual(0, position.open_duration_ns) self.assertEqual(Decimal("1.00001"), position.avg_px_open) self.assertEqual(1, position.event_count) self.assertEqual([order.client_order_id], position.client_order_ids) self.assertEqual([VenueOrderId("1")], position.venue_order_ids) self.assertEqual([ExecutionId("E-19700101-000000-000-001-1")], position.execution_ids) self.assertEqual(ExecutionId("E-19700101-000000-000-001-1"), position.last_execution_id) self.assertEqual(PositionId("P-123456"), position.id) self.assertEqual(1, len(position.events)) self.assertTrue(position.is_long) self.assertFalse(position.is_short) self.assertTrue(position.is_open) self.assertFalse(position.is_closed) self.assertEqual(0, position.realized_points) self.assertEqual(0, position.realized_return) self.assertEqual(Money(-2.00, USD), position.realized_pnl) self.assertEqual(Money(49.00, USD), position.unrealized_pnl(last)) self.assertEqual(Money(47.00, USD), position.total_pnl(last)) self.assertEqual([Money(2.00, USD)], position.commissions()) self.assertEqual("Position(LONG 100_000 AUD/USD.SIM, id=P-123456)", repr(position))
def test_position_partial_fills_with_sell_order_returns_expected_attributes( self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.SELL, Quantity(100000), ) fill1 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("1"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), last_px=Price("1.00001"), last_qty=Quantity(50000), ) fill2 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("2"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), last_px=Price("1.00002"), last_qty=Quantity(50000), ) position = Position(fill=fill1) last = Price("1.00050") # Act position.apply(fill2) # Assert self.assertEqual(Quantity(100000), position.quantity) self.assertEqual(PositionSide.SHORT, position.side) self.assertEqual(0, position.opened_timestamp_ns) self.assertEqual(Decimal("1.000015"), position.avg_px_open) self.assertEqual(2, position.event_count) self.assertFalse(position.is_long) self.assertTrue(position.is_short) self.assertTrue(position.is_open) self.assertFalse(position.is_closed) self.assertEqual(0, position.realized_points) self.assertEqual(0, position.realized_return) self.assertEqual(Money(-4.00, USD), position.realized_pnl) self.assertEqual(Money(-48.50, USD), position.unrealized_pnl(last)) self.assertEqual(Money(-52.50, USD), position.total_pnl(last)) self.assertEqual([Money(4.00, USD)], position.commissions()) self.assertEqual(Money(4.00, USD), position.commission) self.assertEqual("Position(SHORT 100,000 AUD/USD.SIM, id=P-123456)", repr(position))
def test_position_filled_with_buy_order_returns_expected_attributes(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) fill = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00001"), ) last = Price("1.00050") # Act position = Position(fill) # Assert self.assertFalse(position != position) # Equality operator test self.assertEqual(ClientOrderId("O-19700101-000000-000-001-1"), position.from_order) self.assertEqual(Quantity(100000), position.quantity) self.assertEqual(Quantity(100000), position.peak_quantity) self.assertEqual(OrderSide.BUY, position.entry) self.assertEqual(PositionSide.LONG, position.side) self.assertEqual(UNIX_EPOCH, position.opened_time) self.assertIsNone(position.open_duration) self.assertEqual(Decimal("1.00001"), position.avg_open) self.assertEqual(1, position.event_count) self.assertEqual([order.cl_ord_id], position.cl_ord_ids) self.assertEqual([OrderId.null()], position.order_ids) self.assertEqual([ExecutionId("E-19700101-000000-000-001-1")], position.execution_ids) self.assertEqual(ExecutionId("E-19700101-000000-000-001-1"), position.last_execution_id) self.assertEqual(PositionId("P-123456"), position.id) self.assertEqual(1, len(position.events)) self.assertTrue(position.is_long) self.assertFalse(position.is_short) self.assertTrue(position.is_open) self.assertFalse(position.is_closed) self.assertEqual(0, position.realized_points) self.assertEqual(0, position.realized_return) self.assertEqual(Money(-2.00, USD), position.realized_pnl) self.assertEqual(Money(49.00, USD), position.unrealized_pnl(last)) self.assertEqual(Money(47.00, USD), position.total_pnl(last)) self.assertEqual(Money(2.00, USD), position.commission) self.assertEqual([Money(2.00, USD)], position.commissions()) self.assertEqual("Position(id=P-123456, LONG 100,000 AUD/USD.SIM)", repr(position))
def test_position_partial_fills_with_sell_order_returns_expected_attributes( self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.SELL, Quantity.from_int(100000), ) fill1 = TestEventStubs.order_filled( order, instrument=AUDUSD_SIM, trade_id=TradeId("1"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00001"), last_qty=Quantity.from_int(50000), ) fill2 = TestEventStubs.order_filled( order, instrument=AUDUSD_SIM, trade_id=TradeId("2"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00002"), last_qty=Quantity.from_int(50000), ) position = Position(instrument=AUDUSD_SIM, fill=fill1) last = Price.from_str("1.00050") # Act position.apply(fill2) # Assert assert position.quantity == Quantity.from_int(100000) assert position.side == PositionSide.SHORT assert position.ts_opened == 0 assert position.avg_px_open == Decimal("1.000015") assert position.event_count == 2 assert not position.is_long assert position.is_short assert position.is_open assert not 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(-48.50, USD) assert position.total_pnl(last) == Money(-52.50, USD) assert position.commissions() == [Money(4.00, USD)] assert repr( position) == "Position(SHORT 100_000 AUD/USD.SIM, id=P-123456)"
def test_position_filled_with_sell_order_returns_expected_attributes(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.SELL, 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"), ) last = Price.from_str("1.00050") # Act position = Position(instrument=AUDUSD_SIM, fill=fill) # Assert assert position.quantity == Quantity.from_int(100000) assert position.peak_qty == Quantity.from_int(100000) assert position.side == PositionSide.SHORT assert position.ts_opened == 0 assert position.avg_px_open == Decimal("1.00001") assert position.event_count == 1 assert position.execution_ids == [ ExecutionId("E-19700101-000000-000-001-1") ] assert position.last_execution_id == ExecutionId( "E-19700101-000000-000-001-1") assert position.id == PositionId("P-123456") assert not position.is_long assert position.is_short assert position.is_open assert not position.is_closed assert position.realized_points == 0 assert position.realized_return == 0 assert position.realized_pnl == Money(-2.00, USD) assert position.unrealized_pnl(last) == Money(-49.00, USD) assert position.total_pnl(last) == Money(-51.00, USD) assert position.commissions() == [Money(2.00, USD)] assert repr( position) == "Position(SHORT 100_000 AUD/USD.SIM, id=P-123456)"
def test_position_filled_with_sell_order_returns_expected_attributes(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.SELL, 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"), ) last = Price.from_str("1.00050") # Act position = Position(instrument=AUDUSD_SIM, fill=fill) # Assert self.assertEqual(Quantity.from_int(100000), position.quantity) self.assertEqual(Quantity.from_int(100000), position.peak_qty) self.assertEqual(PositionSide.SHORT, position.side) self.assertEqual(0, position.opened_timestamp_ns) self.assertEqual(Decimal("1.00001"), position.avg_px_open) self.assertEqual(1, position.event_count) self.assertEqual([ExecutionId("E-19700101-000000-000-001-1")], position.execution_ids) self.assertEqual(ExecutionId("E-19700101-000000-000-001-1"), position.last_execution_id) self.assertEqual(PositionId("P-123456"), position.id) self.assertFalse(position.is_long) self.assertTrue(position.is_short) self.assertTrue(position.is_open) self.assertFalse(position.is_closed) self.assertEqual(0, position.realized_points) self.assertEqual(0, position.realized_return) self.assertEqual(Money(-2.00, USD), position.realized_pnl) self.assertEqual(Money(-49.00, USD), position.unrealized_pnl(last)) self.assertEqual(Money(-51.00, USD), position.total_pnl(last)) self.assertEqual([Money(2.00, USD)], position.commissions()) self.assertEqual("Position(SHORT 100_000 AUD/USD.SIM, id=P-123456)", repr(position))
def test_position_partial_fills_with_buy_order_returns_expected_attributes( self): # Arrange order = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) fill = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00001"), fill_qty=Quantity(50000), ) last = Price("1.00048") position = Position(fill) # Act # Assert self.assertEqual(Quantity(50000), position.quantity) self.assertEqual(Quantity(50000), position.peak_quantity) self.assertEqual(PositionSide.LONG, position.side) self.assertEqual(UNIX_EPOCH, position.opened_time) self.assertEqual(Decimal("1.00001"), position.avg_open) self.assertEqual(1, position.event_count) self.assertTrue(position.is_long) self.assertFalse(position.is_short) self.assertTrue(position.is_open) self.assertFalse(position.is_closed) self.assertEqual(0, position.realized_points) self.assertEqual(0, position.realized_return) self.assertEqual(Money(-2.00, USD), position.realized_pnl) self.assertEqual(Money(23.50, USD), position.unrealized_pnl(last)) self.assertEqual(Money(21.50, USD), position.total_pnl(last)) self.assertEqual(Money(2.00, USD), position.commission) self.assertEqual([Money(2.00, USD)], position.commissions()) self.assertEqual("Position(id=P-123456, LONG 50,000 AUD/USD.SIM)", repr(position))
def test_position_partial_fills_with_buy_order_returns_expected_attributes( 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"), last_qty=Quantity.from_int(50000), ) last = Price.from_str("1.00048") position = Position(instrument=AUDUSD_SIM, fill=fill) # Act, Assert assert position.quantity == Quantity.from_int(50000) assert position.peak_qty == Quantity.from_int(50000) assert position.side == PositionSide.LONG assert position.ts_opened == 0 assert position.avg_px_open == Decimal("1.00001") assert position.event_count == 1 assert position.is_long assert not position.is_short assert position.is_open assert not position.is_closed assert position.realized_points == 0 assert position.realized_return == 0 assert position.realized_pnl == Money(-2.00, USD) assert position.unrealized_pnl(last) == Money(23.50, USD) assert position.total_pnl(last) == Money(21.50, USD) assert position.commissions() == [Money(2.00, USD)] assert repr( position) == "Position(LONG 50_000 AUD/USD.SIM, id=P-123456)"
def test_calculate_unrealized_pnl_for_long(self): # Arrange order1 = self.order_factory.market( BTCUSDT_BINANCE.symbol, OrderSide.BUY, Quantity("2.000000"), ) order2 = self.order_factory.market( BTCUSDT_BINANCE.symbol, OrderSide.BUY, Quantity("2.000000"), ) fill1 = TestStubs.event_order_filled( order1, instrument=BTCUSDT_BINANCE, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("10500.00"), ) fill2 = TestStubs.event_order_filled( order2, instrument=BTCUSDT_BINANCE, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("10500.00"), ) position = Position(fill1) position.apply(fill2) # Act pnl = position.unrealized_pnl(Price("11505.60")) # Assert self.assertEqual(Money("4022.40000000", USDT), pnl) self.assertEqual(Money("-42.00000000", USDT), position.realized_pnl) self.assertEqual([Money("42.00000000", USDT)], position.commissions()) self.assertEqual(Money("42.00000000", USDT), position.commission)
def test_calculate_unrealized_pnl_for_long(self): # Arrange order1 = self.order_factory.market( BTCUSDT_BINANCE.id, OrderSide.BUY, Quantity.from_str("2.000000"), ) order2 = self.order_factory.market( BTCUSDT_BINANCE.id, OrderSide.BUY, Quantity.from_str("2.000000"), ) fill1 = TestEventStubs.order_filled( order1, instrument=BTCUSDT_BINANCE, position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("10500.00"), ) fill2 = TestEventStubs.order_filled( order2, 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=fill1) position.apply(fill2) # Act pnl = position.unrealized_pnl(Price.from_str("11505.60")) # Assert assert pnl == Money(4022.40000000, USDT) assert position.realized_pnl == Money(-42.00000000, USDT) assert position.commissions() == [Money(42.00000000, USDT)]
def test_calculate_pnl_for_short_position_winning(self): # Arrange order = self.order_factory.market( BTCUSDT_BINANCE.id, OrderSide.SELL, Quantity.from_str("10.150000"), ) 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( Price.from_str("10500.00"), Price.from_str("10390.00"), Quantity.from_str("10.150000"), ) # Assert self.assertEqual(Money(1116.50000000, USDT), pnl) self.assertEqual( Money(1116.50000000, USDT), position.unrealized_pnl(Price.from_str("10390.00")), ) self.assertEqual(Money(-106.57500000, USDT), position.realized_pnl) self.assertEqual([Money(106.57500000, USDT)], position.commissions()) self.assertEqual( Money(105458.50000000, USDT), position.notional_value(Price.from_str("10390.00")), )
def test_calculate_unrealized_pnl_for_short(self): # Arrange order = self.order_factory.market( BTCUSDT_BINANCE.id, OrderSide.SELL, Quantity.from_str("5.912000"), ) fill = TestEventStubs.order_filled( order, instrument=BTCUSDT_BINANCE, position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("10505.60"), ) position = Position(instrument=BTCUSDT_BINANCE, fill=fill) pnl = position.unrealized_pnl(Price.from_str("10407.15")) # Assert assert pnl == Money(582.03640000, USDT) assert position.realized_pnl == Money(-62.10910720, USDT) assert position.commissions() == [Money(62.10910720, USDT)]
def test_position_long_with_multiple_filled_orders_returns_expected_attributes(self): # Arrange order1 = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) order2 = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) order3 = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.SELL, Quantity(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"), fill_price=Price("1.00001"), ) fill3 = TestStubs.event_order_filled( order3, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00010"), ) last = Price("1.00050") # Act position = Position(fill1) position.apply(fill2) position.apply(fill3) # Assert self.assertEqual(Quantity(), position.quantity) self.assertEqual(PositionSide.FLAT, position.side) self.assertEqual(UNIX_EPOCH, position.opened_time) self.assertEqual(Decimal("1.000005"), position.avg_open) self.assertEqual(3, position.event_count) self.assertEqual([order1.cl_ord_id, order2.cl_ord_id, order3.cl_ord_id], position.cl_ord_ids) self.assertEqual(UNIX_EPOCH, position.closed_time) self.assertEqual(Decimal("1.0001"), 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(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(Money(8.00, USD), position.commission) self.assertEqual("Position(id=P-123456, FLAT AUD/USD.SIM)", repr(position))
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_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)"
def test_position_filled_with_sell_order_then_buy_order_returns_expected_attributes( self, ): # Arrange order1 = self.order_factory.market( AUDUSD_SIM.id, OrderSide.SELL, Quantity.from_int(100000), ) order2 = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) fill1 = TestStubs.event_order_filled( order1, instrument=AUDUSD_SIM, position_id=PositionId("P-19700101-000000-000-001-1"), ) position = Position(instrument=AUDUSD_SIM, fill=fill1) fill2 = TestStubs.event_order_filled( order2, instrument=AUDUSD_SIM, execution_id=ExecutionId("1"), position_id=PositionId("P-19700101-000000-000-001-1"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00001"), last_qty=Quantity.from_int(50000), ) fill3 = TestStubs.event_order_filled( order2, instrument=AUDUSD_SIM, execution_id=ExecutionId("2"), position_id=PositionId("P-19700101-000000-000-001-1"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00003"), last_qty=Quantity.from_int(50000), ) last = Price.from_str("1.00050") # Act 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.0"), position.avg_px_open) self.assertEqual(3, position.event_count) self.assertEqual([order1.client_order_id, order2.client_order_id], position.client_order_ids) self.assertEqual(0, position.closed_timestamp_ns) self.assertEqual(Decimal("1.00002"), 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(-8.00, USD), position.realized_pnl) self.assertEqual(Money(0, USD), position.unrealized_pnl(last)) self.assertEqual(Money(-8.000, USD), position.total_pnl(last)) self.assertEqual([Money(6.00, USD)], position.commissions()) self.assertEqual( "Position(FLAT AUD/USD.SIM, id=P-19700101-000000-000-001-1)", repr(position))
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))
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)"
def test_position_filled_with_no_change_returns_expected_attributes(self): # Arrange order1 = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) order2 = self.order_factory.market( AUDUSD_SIM.id, OrderSide.SELL, Quantity(100000), ) fill1 = TestStubs.event_order_filled( order1, instrument=AUDUSD_SIM, position_id=PositionId("P-19700101-000000-000-001-1"), ) position = Position(fill1) fill2 = TestStubs.event_order_filled( order2, instrument=AUDUSD_SIM, position_id=PositionId("P-19700101-000000-000-001-1"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00000"), ) 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(Decimal("1.0"), position.avg_open) self.assertEqual(2, position.event_count) self.assertEqual([order1.cl_ord_id, order2.cl_ord_id], position.cl_ord_ids) self.assertEqual([ ExecutionId("E-19700101-000000-000-001-1"), ExecutionId("E-19700101-000000-000-001-2") ], position.execution_ids, ) self.assertEqual(UNIX_EPOCH, position.closed_time) self.assertEqual(Decimal("1.0"), 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(0, position.realized_points) self.assertEqual(0, position.realized_return) self.assertEqual(Money(-4.00, USD), position.realized_pnl) self.assertEqual(Money(0, USD), position.unrealized_pnl(last)) self.assertEqual(Money(-4.00, USD), position.total_pnl(last)) self.assertEqual([Money(4.00, USD)], position.commissions()) self.assertEqual(Money(4.00, USD), position.commission) self.assertEqual("Position(id=P-19700101-000000-000-001-1, FLAT AUD/USD.SIM)", repr(position))
def test_position_closed_and_reopened_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("P-123456"), 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, ) position.apply(fill2) fill3 = OrderFilled( self.trader_id, StrategyId("S-001"), self.account_id, order.instrument_id, order.client_order_id, VenueOrderId("2"), TradeId("E3"), PositionId("P-123456"), OrderSide.BUY, OrderType.MARKET, order.quantity, Price.from_str("1.00012"), AUDUSD_SIM.quote_currency, Money(0, USD), LiquiditySide.TAKER, UUID4(), 3_000_000_000, 0, ) # Act position.apply(fill3) # Assert last = Price.from_str("1.00030") assert position.is_opposite_side(fill2.order_side) assert position.quantity == Quantity.from_int(150000) assert position.side == PositionSide.LONG assert position.ts_opened == 1_000_000_000 assert position.duration_ns == 0 assert position.avg_px_open == Decimal("1.00001") assert position.event_count == 3 assert position.ts_closed == 0 assert position.avg_px_close == Decimal("1.00011") assert position.is_long assert position.is_open assert not position.is_short assert not 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(43.50, USD) assert position.total_pnl(last) == Money(55.50, USD) assert position.commissions() == [Money(3.00, USD)] assert repr( position) == "Position(LONG 150_000 AUD/USD.SIM, id=P-123456)"