def test_position_filled_with_no_change_returns_expected_attributes(self): # Arrange order1 = self.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) order2 = self.order_factory.market( AUDUSD_FXCM, OrderSide.SELL, Quantity(100000)) fill1 = TestStubs.event_order_filled(order1) position = Position(fill1) fill2 = TestStubs.event_order_filled( order2, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00000"), ) 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(1.0, position.avg_open_price) 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-001-001-1"), ExecutionId("E-19700101-000000-001-001-2") }, position.execution_ids(), ) self.assertEqual(UNIX_EPOCH, position.closed_time) self.assertEqual(1.0, 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))
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_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))
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_apply_filled_events_to_market_order_results_in_filled(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) fill1 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("1"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00001"), last_qty=Quantity.from_int(20000), ) fill2 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("2"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00002"), last_qty=Quantity.from_int(40000), ) fill3 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("3"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00003"), last_qty=Quantity.from_int(40000), ) # Act order.apply(fill1) order.apply(fill2) order.apply(fill3) # Assert assert order.status == OrderStatus.FILLED assert order.filled_qty == Quantity.from_int(100000) assert order.avg_px == Decimal("1.000018571428571428571428571") assert len(order.execution_ids) == 3 assert not order.is_active assert not order.is_inflight assert not order.is_working assert order.is_completed assert order.ts_last == 0
def test_apply_filled_events_to_market_order_results_in_filled(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) fill1 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("1"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), last_px=Price("1.00001"), last_qty=Quantity(20000), ) fill2 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("2"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), last_px=Price("1.00002"), last_qty=Quantity(40000), ) fill3 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("3"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), last_px=Price("1.00003"), last_qty=Quantity(40000), ) # Act order.apply(fill1) order.apply(fill2) order.apply(fill3) # Assert self.assertEqual(OrderState.FILLED, order.state) self.assertEqual(Quantity(100000), order.filled_qty) self.assertEqual(Decimal("1.000018571428571428571428571"), order.avg_px) self.assertEqual(3, len(order.execution_ids)) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) self.assertEqual(0, order.execution_ns)
def test_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 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("1"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00001"), last_qty=Quantity.from_int(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.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_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))
def test_position_filled_with_buy_order_returns_expected_attributes(self): # Arrange order = self.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), ) fill = TestStubs.event_order_filled( order, PositionId("P-123456"), StrategyId("S", "001"), Price("1.00001"), ) last = QuoteTick( AUDUSD_FXCM, Price("1.00050"), Price("1.00048"), Quantity(1), Quantity(1), UNIX_EPOCH, ) # Act position = Position(fill) # Assert self.assertEqual(ClientOrderId("O-19700101-000000-001-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(1.00001, position.avg_open_price) self.assertEqual(1, position.event_count()) self.assertEqual({order.cl_ord_id}, position.cl_ord_ids()) self.assertEqual({ExecutionId("E-19700101-000000-001-001-1")}, position.execution_ids()) self.assertEqual(ExecutionId("E-19700101-000000-001-001-1"), position.last_execution_id()) self.assertEqual(PositionId("P-123456"), position.id) 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, USD), position.realized_pnl) self.assertEqual(Money(49.00, USD), position.unrealized_pnl(last)) self.assertEqual(Money(49.00, USD), position.total_pnl(last))
def event_order_filled( order, instrument, strategy_id=None, account_id=None, venue_order_id=None, execution_id=None, position_id=None, last_qty=None, last_px=None, liquidity_side=LiquiditySide.TAKER, ts_filled_ns=0, account=None, ) -> OrderFilled: if strategy_id is None: strategy_id = order.strategy_id if account_id is None: account_id = order.account_id if account_id is None: account_id = TestStubs.account_id() 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 last_px is None: last_px = Price.from_str(f"{1:.{instrument.price_precision}f}") if last_qty is None: last_qty = order.quantity if account is None: account = TestStubs.cash_account() commission = account.calculate_commission( instrument=instrument, last_qty=order.quantity, last_px=last_px, liquidity_side=liquidity_side, ) return OrderFilled( trader_id=TestStubs.trader_id(), strategy_id=strategy_id, account_id=account_id, instrument_id=instrument.id, client_order_id=order.client_order_id, venue_order_id=venue_order_id, execution_id=execution_id, position_id=position_id, order_side=order.side, order_type=order.type, last_qty=last_qty, last_px=last_px or order.price, currency=instrument.quote_currency, commission=commission, liquidity_side=liquidity_side, ts_event=ts_filled_ns, event_id=UUID4(), ts_init=0, )
def test_serialize_and_deserialize_order_partially_filled_events(self): # Arrange event = OrderFilled( self.trader_id, self.strategy_id, self.account_id, AUDUSD_SIM.id, ClientOrderId("O-123456"), VenueOrderId("1"), ExecutionId("E123456"), PositionId("T123456"), OrderSide.SELL, OrderType.MARKET, Quantity(50000, precision=0), Price(1.00000, precision=5), AUDUSD_SIM.quote_currency, Money(0, USD), LiquiditySide.MAKER, UUID4(), 0, 0, ) # Act serialized = self.serializer.serialize(event) deserialized = self.serializer.deserialize(serialized) # Assert assert deserialized == event
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_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'])
async def generate_trades_list( self, venue_order_id: VenueOrderId, symbol: Symbol, since: datetime = None # type: ignore ) -> List[ExecutionReport]: filled = self.client().betting.list_cleared_orders( bet_ids=[venue_order_id], ) if not filled["clearedOrders"]: self._log.warn(f"Found no existing order for {venue_order_id}") return [] fill = filled["clearedOrders"][0] ts_event = int(pd.Timestamp(fill["lastMatchedDate"]).to_datetime64()) return [ ExecutionReport( client_order_id=self.venue_order_id_to_client_order_id[venue_order_id], venue_order_id=VenueOrderId(fill["betId"]), venue_position_id=None, # Can be None execution_id=ExecutionId(fill["lastMatchedDate"]), last_qty=Quantity.from_str(str(fill["sizeSettled"])), # TODO: Incorrect precision? last_px=Price.from_str(str(fill["priceMatched"])), # TODO: Incorrect precision? commission=None, # Can be None liquidity_side=LiquiditySide.NONE, ts_event=ts_event, ts_init=ts_event, ) ]
async def generate_trades_list( self, venue_order_id: VenueOrderId, symbol: Symbol, since: datetime = None) -> List[ExecutionReport]: filled = self.client().betting.list_cleared_orders( bet_ids=[venue_order_id], ) if not filled["clearedOrders"]: self._log.warn(f"Found no existing order for {venue_order_id}") return [] fill = filled["clearedOrders"][0] timestamp_ns = millis_to_nanos( pd.Timestamp(fill["lastMatchedDate"]).timestamp()) return [ ExecutionReport( client_order_id=self. venue_order_id_to_client_order_id[venue_order_id], venue_order_id=VenueOrderId(fill["betId"]), execution_id=ExecutionId(fill["lastMatchedDate"]), last_qty=Decimal(fill["sizeSettled"]), last_px=Decimal(fill["priceMatched"]), commission_amount=None, # Can be None commission_currency=None, # Can be None liquidity_side=LiquiditySide.NONE, execution_ns=timestamp_ns, timestamp_ns=timestamp_ns, ) ]
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
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 = TestStubs.limit_order() buy_submitted, buy_accepted, buy_filled = _make_order_events( buy, instrument=instrument, position_id=position_id, execution_id=ExecutionId("BUY")) sell = TestStubs.limit_order(side=OrderSide.SELL) _, _, sell_filled = _make_order_events(sell, instrument=instrument, position_id=position_id, execution_id=ExecutionId("SELL")) open_position = Position(instrument=instrument, fill=buy_filled) closed_position = Position(instrument=instrument, fill=buy_filled) closed_position.apply(sell_filled) return [ TestStubs.ticker(), TestStubs.quote_tick_5decimal(), TestStubs.trade_tick_5decimal(), TestStubs.bar_5decimal(), TestStubs.venue_status_update(), TestStubs.instrument_status_update(), TestStubs.event_component_state_changed(), TestStubs.event_trading_state_changed(), TestStubs.event_betting_account_state(), TestStubs.event_margin_account_state(), # ORDERS TestStubs.event_order_accepted(buy), TestStubs.event_order_rejected(buy), TestStubs.event_order_pending_update(buy_accepted), TestStubs.event_order_pending_cancel(buy_accepted), TestStubs.event_order_filled(order=buy, instrument=instrument, position_id=open_position.id), TestStubs.event_order_canceled(buy_accepted), TestStubs.event_order_expired(buy), TestStubs.event_order_triggered(buy), # POSITIONS TestStubs.event_position_opened(open_position), TestStubs.event_position_changed(open_position), TestStubs.event_position_closed(closed_position), ]
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_apply_partial_fill_events_to_market_order_results_in_partially_filled( self, ): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) fill1 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("1"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00001"), last_qty=Quantity.from_int(20000), ) fill2 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("2"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00002"), last_qty=Quantity.from_int(40000), ) # Act order.apply(fill1) order.apply(fill2) # Assert self.assertEqual(OrderState.PARTIALLY_FILLED, order.state) self.assertEqual(Quantity.from_int(60000), order.filled_qty) self.assertEqual(Decimal("1.000014"), order.avg_px) self.assertEqual(2, len(order.execution_ids)) self.assertTrue(order.is_working) self.assertFalse(order.is_completed) self.assertEqual(0, order.execution_ns)
def 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, )
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)
def create_execution_id(uo: Dict) -> ExecutionId: data: bytes = orjson.dumps( ( uo["id"], uo["p"], uo["s"], uo["side"], uo["pt"], uo["ot"], uo["pd"], uo.get("md"), uo.get("avp"), uo.get("sm"), ) ) return ExecutionId(hashlib.sha1(data).hexdigest()) # noqa (S303 insecure SHA1)
def test_apply_order_partially_filled_event_to_buy_limit_order(self): # Arrange order = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) partially = OrderFilled( order.trader_id, order.strategy_id, order.account_id, order.instrument_id, order.client_order_id, VenueOrderId("1"), ExecutionId("E-1"), PositionId("P-1"), order.side, order.type, Quantity.from_int(50000), Price.from_str("0.999999"), AUDUSD_SIM.quote_currency, Money(0, USD), LiquiditySide.MAKER, UUID4(), 1_000_000_000, 1_000_000_000, ) # Act order.apply(partially) # Assert assert order.status == OrderStatus.PARTIALLY_FILLED assert order.filled_qty == Quantity.from_int(50000) assert order.price == Price.from_str("1.00000") assert order.avg_px == Decimal("0.999999") assert order.slippage == Decimal("-0.000001") assert order.is_active assert not order.is_inflight assert order.is_working assert not order.is_completed assert order.ts_last == 1_000_000_000, order.ts_last
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.cl_ord_id, OrderId("1"), ExecutionId("E-1"), PositionId("P-1"), StrategyId.null(), order.instrument_id, order.side, order.quantity, order.quantity, Quantity(), Price("1.00001"), AUDUSD_SIM.quote_currency, AUDUSD_SIM.is_inverse, Money(0, USD), LiquiditySide.MAKER, UNIX_EPOCH, uuid4(), UNIX_EPOCH, ) # Act order.apply(filled) # Assert self.assertEqual(OrderState.FILLED, order.state) self.assertEqual(Quantity(100000), order.filled_qty) self.assertEqual(Price("1.00000"), order.price) self.assertEqual(Decimal("1.00001"), order.avg_price) self.assertEqual(Decimal("0.00001"), order.slippage) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) self.assertEqual(UNIX_EPOCH, order.filled_timestamp)
def test_apply_order_partially_filled_event_to_buy_limit_order(self): # Arrange order = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) partially = OrderFilled( self.account_id, order.client_order_id, VenueOrderId("1"), ExecutionId("E-1"), PositionId("P-1"), StrategyId.null(), order.instrument_id, order.side, Quantity(50000), Price("0.999999"), Quantity(50000), Quantity(50000), AUDUSD_SIM.quote_currency, AUDUSD_SIM.is_inverse, Money(0, USD), LiquiditySide.MAKER, 1_000_000_000, uuid4(), 1_000_000_000, ) # Act order.apply(partially) # Assert self.assertEqual(OrderState.PARTIALLY_FILLED, order.state) self.assertEqual(Quantity(50000), order.filled_qty) self.assertEqual(Price("1.00000"), order.price) self.assertEqual(Decimal("0.999999"), order.avg_px) self.assertEqual(Decimal("-0.000001"), order.slippage) self.assertTrue(order.is_working) self.assertFalse(order.is_completed) self.assertEqual(1_000_000_000, order.execution_ns)