def test_generate_order_fills_report(self): # Arrange report_provider = ReportProvider() order1 = self.order_factory.limit(AUDUSD_FXCM, OrderSide.BUY, Quantity(1500000), Price(0.80010, 5)) order2 = self.order_factory.limit(AUDUSD_FXCM, OrderSide.SELL, Quantity(1500000), Price(0.80000, 5)) event = OrderFilled(self.account_id, order1.id, ExecutionId('SOME_EXEC_ID_1'), PositionIdBroker('SOME_EXEC_TICKET_1'), order1.symbol, order1.side, order1.quantity, Price(0.80011, 5), Currency.AUD, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) order1.apply(event) orders = {order1.id: order1, order2.id: order2} # Act report = report_provider.generate_order_fills_report(orders) # Assert # print(report.iloc[0]) self.assertEqual(1, len(report)) self.assertEqual('order_id', report.index.name) self.assertEqual(order1.id.value, report.index[0]) self.assertEqual('AUDUSD', report.iloc[0]['symbol']) self.assertEqual('BUY', report.iloc[0]['side']) self.assertEqual('LIMIT', report.iloc[0]['type']) self.assertEqual(1500000, report.iloc[0]['quantity']) self.assertAlmostEqual(0.80011, report.iloc[0]['avg_price']) self.assertEqual(0.00001, report.iloc[0]['slippage'])
def test_serialize_and_deserialize_order_filled_events(self): # Arrange event = OrderFilled( self.account_id, ClientOrderId("O-123456"), OrderId("1"), ExecutionId("E123456"), PositionId("T123456"), StrategyId("S", "001"), AUDUSD_SIM.symbol, OrderSide.SELL, Quantity(100000), Quantity(100000), Quantity(), Price("1.00000"), AUDUSD_SIM.quote_currency, AUDUSD_SIM.is_inverse, Money(0, USD), LiquiditySide.TAKER, UNIX_EPOCH, uuid4(), UNIX_EPOCH, ) # Act serialized = self.serializer.serialize(event) deserialized = self.serializer.deserialize(serialized) # Assert self.assertEqual(deserialized, event)
def test_serialize_and_deserialize_order_filled_events(self): # Arrange event = OrderFilled( self.account_id, ClientOrderId("O-123456"), VenueOrderId("1"), ExecutionId("E123456"), PositionId("T123456"), StrategyId("S-001"), AUDUSD_SIM.id, OrderSide.SELL, Quantity(100000, precision=0), Price(1.00000, precision=5), AUDUSD_SIM.quote_currency, Money(0, USD), LiquiditySide.TAKER, 0, uuid4(), 0, ) # Act serialized = self.serializer.serialize(event) deserialized = self.serializer.deserialize(serialized) # Assert assert deserialized == event
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 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_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_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 event_order_filled( order, instrument, position_id=None, strategy_id=None, fill_price=None, fill_qty=None, liquidity_side=LiquiditySide.TAKER, ) -> OrderFilled: if position_id is None: position_id = PositionId(order.cl_ord_id.value.replace("P", "T")) if strategy_id is None: strategy_id = StrategyId.null() if fill_price is None: fill_price = Price("1.00000") if fill_qty is None: fill_qty = order.quantity commission = instrument.calculate_commission( quantity=order.quantity, avg_price=fill_price, liquidity_side=liquidity_side, ) return OrderFilled( account_id=TestStubs.account_id(), cl_ord_id=order.cl_ord_id, order_id=OrderId("1"), execution_id=ExecutionId(order.cl_ord_id.value.replace("O", "E")), position_id=position_id, strategy_id=strategy_id, symbol=order.symbol, order_side=order.side, fill_qty=fill_qty, cum_qty=Quantity(order.filled_qty + fill_qty), leaves_qty=Quantity( max(0, order.quantity - order.filled_qty - fill_qty)), fill_price=order.price if fill_price is None else fill_price, currency=instrument.quote_currency, is_inverse=instrument.is_inverse, commission=commission, liquidity_side=liquidity_side, execution_time=UNIX_EPOCH, event_id=uuid4(), event_timestamp=UNIX_EPOCH, )
def test_apply_order_filled_event_to_buy_limit_order(self): # Arrange order = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) filled = OrderFilled( self.account_id, order.client_order_id, VenueOrderId("1"), ExecutionId("E-1"), PositionId("P-1"), StrategyId.null(), order.instrument_id, order.side, order.quantity, Price("1.00001"), order.quantity, Quantity(), AUDUSD_SIM.quote_currency, AUDUSD_SIM.is_inverse, Money(0, USD), LiquiditySide.MAKER, 0, uuid4(), 0, ) # Act order.apply(filled) # Assert self.assertEqual(OrderState.FILLED, order.state) self.assertEqual(Quantity(100000), order.filled_qty) self.assertEqual(Price("1.00000"), order.price) self.assertEqual(Decimal("1.00001"), order.avg_px) self.assertEqual(Decimal("0.00001"), order.slippage) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) self.assertEqual(0, order.execution_ns)
def event_order_filled( order, position_id=None, strategy_id=None, fill_price=None, filled_qty=None, leaves_qty=None, base_currency=USD, quote_currency=JPY, commission=0, ) -> OrderFilled: if position_id is None: position_id = PositionId(order.cl_ord_id.value.replace("P", "T")) if strategy_id is None: strategy_id = StrategyId("S", "NULL") if fill_price is None: fill_price = Price("1.00000") if filled_qty is None: filled_qty = order.quantity if leaves_qty is None: leaves_qty = Quantity() return OrderFilled( TestStubs.account_id(), order.cl_ord_id, OrderId("1"), ExecutionId(order.cl_ord_id.value.replace("O", "E")), position_id, strategy_id, order.symbol, order.side, filled_qty, leaves_qty, order.price if fill_price is None else fill_price, Money(commission, base_currency), LiquiditySide.TAKER, base_currency, # Stub event quote_currency, # Stub event UNIX_EPOCH, uuid4(), UNIX_EPOCH, )
def test_can_apply_order_overfilled_event_to_buy_limit_order(self): # Arrange order = self.order_factory.limit(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00000, 5)) event = OrderFilled(self.account_id, order.id, ExecutionId('SOME_EXEC_ID_1'), PositionIdBroker('SOME_EXEC_TICKET_1'), order.symbol, order.side, Quantity(150000), Price(0.99999, 5), Currency.USD, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) # Act order.apply(event) # Assert self.assertEqual(OrderState.OVER_FILLED, order.state) self.assertEqual(Quantity(150000), order.filled_quantity) self.assertFalse(order.is_completed) self.assertEqual(UNIX_EPOCH, order.filled_timestamp)
def test_can_apply_order_filled_event_to_market_order(self): # Arrange order = self.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) event = OrderFilled(self.account_id, order.id, ExecutionId('SOME_EXEC_ID_1'), PositionIdBroker('SOME_EXEC_TICKET_1'), order.symbol, order.side, order.quantity, Price(1.00001, 5), Currency.USD, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) # Act order.apply(event) # Assert self.assertEqual(OrderState.FILLED, order.state) self.assertEqual(Quantity(100000), order.filled_quantity) self.assertEqual(Price(1.00001, 5), order.average_price) self.assertTrue(order.is_completed) self.assertEqual(UNIX_EPOCH, order.filled_timestamp)
def test_order_filled(self): # Arrange uuid = uuid4() event = OrderFilled( account_id=AccountId("SIM", "000"), client_order_id=ClientOrderId("O-2020872378423"), venue_order_id=VenueOrderId("123456"), execution_id=ExecutionId("1"), position_id=PositionId("2"), strategy_id=StrategyId("SCALPER", "001"), instrument_id=InstrumentId(Symbol("BTC/USDT"), Venue("BINANCE")), order_side=OrderSide.BUY, last_qty=Quantity("0.561000"), last_px=Price("15600.12445"), cum_qty=Quantity("0.561000"), leaves_qty=Quantity(0), currency=USDT, is_inverse=False, commission=Money("12.20000000", USDT), liquidity_side=LiquiditySide.MAKER, execution_ns=0, event_id=uuid, timestamp_ns=0, ) print(event) # Act assert ( f"OrderFilled(account_id=SIM-000, client_order_id=O-2020872378423, " f"venue_order_id=123456, position_id=2, strategy_id=SCALPER-001, " f"instrument_id=BTC/USDT.BINANCE, side=BUY-MAKER, last_qty=0.561000, " f"last_px=15600.12445 USDT, cum_qty=0.561000, leaves_qty=0, " f"commission=12.20000000 USDT, event_id={uuid})" == str(event)) assert ( f"OrderFilled(account_id=SIM-000, client_order_id=O-2020872378423, " f"venue_order_id=123456, position_id=2, strategy_id=SCALPER-001, " f"instrument_id=BTC/USDT.BINANCE, side=BUY-MAKER, last_qty=0.561000, " f"last_px=15600.12445 USDT, cum_qty=0.561000, leaves_qty=0, " f"commission=12.20000000 USDT, event_id={uuid})" == repr(event))
def test_order_filled(self): # Arrange uuid = uuid4() event = OrderFilled( account_id=AccountId("SIM", "000"), cl_ord_id=ClientOrderId("O-2020872378423"), order_id=OrderId("123456"), execution_id=ExecutionId("1"), position_id=PositionId("2"), strategy_id=StrategyId("SCALPER", "001"), symbol=Symbol("BTC/USDT", Exchange("BINANCE")), order_side=OrderSide.BUY, fill_qty=Quantity("0.561000"), cum_qty=Quantity("0.561000"), leaves_qty=Quantity(0), fill_price=Price("15600.12445"), currency=USDT, is_inverse=False, commission=Money("12.20000000", USDT), liquidity_side=LiquiditySide.MAKER, execution_time=UNIX_EPOCH, event_id=uuid, event_timestamp=UNIX_EPOCH, ) # Act self.assertEqual( f"OrderFilled(account_id=SIM-000, cl_ord_id=O-2020872378423, " f"order_id=123456, position_id=2, strategy_id=SCALPER-001, " f"symbol=BTC/USDT.BINANCE, side=BUY-MAKER, fill_qty=0.561000, " f"fill_price=15600.12445 USDT, cum_qty=0.561000, leaves_qty=0, " f"commission=12.20000000 USDT, id={uuid})", str(event)) # noqa self.assertEqual( f"OrderFilled(account_id=SIM-000, cl_ord_id=O-2020872378423, " f"order_id=123456, position_id=2, strategy_id=SCALPER-001, " f"symbol=BTC/USDT.BINANCE, side=BUY-MAKER, fill_qty=0.561000, " f"fill_price=15600.12445 USDT, cum_qty=0.561000, leaves_qty=0, " f"commission=12.20000000 USDT, id={uuid})", repr(event)) # noqa
def test_position_filled_with_buy_order_then_sell_order_returns_expected_attributes(self): # Arrange order = self.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) fill1 = TestStubs.event_order_filled( order, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00001"), ) position = Position(fill1) fill2 = OrderFilled( self.account_id, order.cl_ord_id, OrderId("2"), ExecutionId("E2"), PositionId("T123456"), StrategyId("S", "001"), order.symbol, OrderSide.SELL, order.quantity, Quantity(), Price("1.00001"), Money(0, USD), LiquiditySide.TAKER, AUD, USD, UNIX_EPOCH + timedelta(minutes=1), uuid4(), UNIX_EPOCH, ) last = QuoteTick( AUDUSD_FXCM, Price("1.00050"), Price("1.00048"), Quantity(1), Quantity(1), UNIX_EPOCH, ) # Act position.apply(fill2) # Assert self.assertEqual(Quantity(), position.quantity) self.assertEqual(PositionSide.FLAT, position.side) self.assertEqual(UNIX_EPOCH, position.opened_time) self.assertEqual(timedelta(minutes=1), position.open_duration) self.assertEqual(1.00001, position.avg_open_price) self.assertEqual(2, position.event_count()) self.assertEqual(datetime(1970, 1, 1, 0, 1, tzinfo=pytz.utc), position.closed_time) self.assertEqual(1.00001, position.avg_close_price) self.assertFalse(position.is_long()) self.assertFalse(position.is_short()) self.assertTrue(position.is_closed()) self.assertEqual(0.0, position.realized_points) self.assertEqual(0.0, position.realized_return) self.assertEqual(Money(0, USD), position.realized_pnl) self.assertEqual(Money(0, USD), position.unrealized_pnl(last)) self.assertEqual(Money(0, USD), position.total_pnl(last))
def position_which_is_closed(position_id, close_price=None) -> Position: if close_price is None: close_price = Price("1.0001") order_factory = OrderFactory( strategy_id=StrategyId("S", "001"), id_tag_trader=IdTag("001"), id_tag_strategy=IdTag("001"), ) order = order_factory.market( TestStubs.symbol_audusd_fxcm(), OrderSide.SELL, Quantity(100000), ) filled1 = OrderFilled( TestStubs.account_id(), order.cl_ord_id, OrderId("1"), ExecutionId(order.cl_ord_id.value.replace('O', 'E')), position_id, StrategyId("S", "1"), order.symbol, order.side, order.quantity, Quantity(), close_price, Money(0, USD), LiquiditySide.TAKER, USD, # Stub event USD, # Stub event UNIX_EPOCH + timedelta(minutes=5), uuid4(), UNIX_EPOCH + timedelta(minutes=5), ) filled2 = OrderFilled( TestStubs.account_id(), order.cl_ord_id, OrderId("2"), ExecutionId(order.cl_ord_id.value.replace('O', 'E')), position_id, StrategyId("S", "1"), order.symbol, OrderSide.BUY, order.quantity, Quantity(), close_price, Money(0, USD), LiquiditySide.TAKER, USD, # Stub event USD, # Stub event UNIX_EPOCH + timedelta(minutes=5), uuid4(), UNIX_EPOCH + timedelta(minutes=5), ) position = Position(filled1) position.apply(filled2) return position
def test_position_filled_with_buy_order_then_sell_order_returns_expected_attributes(self): # Arrange order = self.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) order_filled1 = OrderFilled( self.account_id, order.id, ExecutionId('E1'), PositionIdBroker('T123456'), order.symbol, OrderSide.BUY, order.quantity, Price(1.00001, 5), Currency.USD, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) position = Position(PositionId('P-123456'), order_filled1) order_filled2 = OrderFilled( self.account_id, order.id, ExecutionId('E2'), PositionIdBroker('T123456'), order.symbol, OrderSide.SELL, order.quantity, Price(1.00001, 5), Currency.USD, UNIX_EPOCH + timedelta(minutes=1), GUID(uuid.uuid4()), UNIX_EPOCH) last = Tick(AUDUSD_FXCM, Price(1.00050, 5), Price(1.00048, 5), Volume(1), Volume(1), UNIX_EPOCH) # Act position.apply(order_filled2) # Assert self.assertEqual(Quantity(), position.quantity) self.assertEqual(MarketPosition.FLAT, position.market_position) self.assertEqual(UNIX_EPOCH, position.opened_time) self.assertEqual(timedelta(minutes=1), position.open_duration) self.assertEqual(1.00001, position.average_open_price) self.assertEqual(2, position.event_count) self.assertEqual(ExecutionId('E2'), position.last_execution_id) self.assertEqual(PositionIdBroker('T123456'), position.id_broker) self.assertEqual(datetime.datetime(1970, 1, 1, 0, 1, tzinfo=datetime.timezone.utc), position.closed_time) self.assertEqual(1.00001, position.average_close_price) self.assertFalse(position.is_long) self.assertFalse(position.is_short) self.assertTrue(position.is_closed) self.assertEqual(0.0, position.realized_points) self.assertEqual(0.0, position.realized_return) self.assertEqual(Money(0, Currency.USD), position.realized_pnl) self.assertEqual(0.0, position.unrealized_points(last)) self.assertEqual(0.0, position.unrealized_return(last)) self.assertEqual(Money(0, Currency.USD), position.unrealized_pnl(last)) self.assertEqual(0.0, position.total_points(last)) self.assertEqual(0.0, position.total_return(last)) self.assertEqual(Money(0, Currency.USD), position.total_pnl(last))
def test_position_filled_with_buy_order_then_sell_order_returns_expected_attributes(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(150000), ) fill1 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00001"), ) position = Position(fill1) fill2 = OrderFilled( self.account_id, order.cl_ord_id, OrderId("2"), ExecutionId("E2"), PositionId("T123456"), StrategyId("S", "001"), order.symbol, OrderSide.SELL, order.quantity, order.quantity, Quantity(), Price("1.00011"), AUDUSD_SIM.quote_currency, AUDUSD_SIM.is_inverse, Money(0, USD), LiquiditySide.TAKER, UNIX_EPOCH + timedelta(minutes=1), uuid4(), UNIX_EPOCH, ) last = Price("1.00050") # Act position.apply(fill2) # Assert self.assertEqual(Quantity(), position.quantity) self.assertEqual(PositionSide.FLAT, position.side) self.assertEqual(UNIX_EPOCH, position.opened_time) self.assertEqual(timedelta(minutes=1), position.open_duration) self.assertEqual(Decimal("1.00001"), position.avg_open) self.assertEqual(2, position.event_count) self.assertEqual(datetime(1970, 1, 1, 0, 1, tzinfo=pytz.utc), position.closed_time) self.assertEqual(Decimal("1.00011"), position.avg_close) self.assertFalse(position.is_long) self.assertFalse(position.is_short) self.assertFalse(position.is_open) self.assertTrue(position.is_closed) self.assertEqual(Decimal("0.00010"), position.realized_points) self.assertEqual(Decimal('0.00009999900000999990000099999000'), position.realized_return) self.assertEqual(Money(12.00, USD), position.realized_pnl) self.assertEqual(Money(0, USD), position.unrealized_pnl(last)) self.assertEqual(Money(12.00, USD), position.total_pnl(last)) self.assertEqual([Money(3.00, USD)], position.commissions()) self.assertEqual(Money(3.00, USD), position.commission) self.assertEqual("Position(id=P-123456, FLAT AUD/USD.SIM)", repr(position))
def test_multiple_strategy_positions_one_active_one_closed(self): # Arrange strategy1 = TradingStrategy(order_id_tag='001') strategy2 = TradingStrategy(order_id_tag='002') position_id1 = strategy1.position_id_generator.generate() position_id2 = strategy2.position_id_generator.generate() self.exec_engine.register_strategy(strategy1) self.exec_engine.register_strategy(strategy2) order1 = strategy1.order_factory.stop(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00000, 5)) order2 = strategy1.order_factory.stop(AUDUSD_FXCM, OrderSide.SELL, Quantity(100000), Price(1.00000, 5)) order3 = strategy2.order_factory.stop(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00000, 5)) submit_order1 = SubmitOrder(self.trader_id, self.account_id, strategy1.id, position_id1, order1, self.guid_factory.generate(), self.clock.time_now()) submit_order2 = SubmitOrder(self.trader_id, self.account_id, strategy1.id, position_id1, order2, self.guid_factory.generate(), self.clock.time_now()) submit_order3 = SubmitOrder(self.trader_id, self.account_id, strategy2.id, position_id2, order3, self.guid_factory.generate(), self.clock.time_now()) order1_filled = TestStubs.event_order_filled(order1) order2_filled = TestStubs.event_order_filled(order2) order3_filled = OrderFilled(self.account_id, order3.id, ExecutionId('E3'), PositionIdBroker('T3'), AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00000, 5), Currency.USD, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) # Act self.exec_engine.execute_command(submit_order1) self.exec_engine.execute_command(submit_order2) self.exec_engine.execute_command(submit_order3) self.exec_engine.handle_event(order1_filled) self.exec_engine.handle_event(order2_filled) self.exec_engine.handle_event(order3_filled) # Assert # Already tested .is_position_active and .is_position_closed above self.assertTrue(self.exec_db.position_exists(position_id1)) self.assertTrue(self.exec_db.position_exists(position_id2)) self.assertTrue(self.exec_engine.is_strategy_flat(strategy1.id)) self.assertFalse(self.exec_engine.is_strategy_flat(strategy2.id)) self.assertFalse(self.exec_engine.is_flat()) self.assertTrue( position_id1 in self.exec_db.get_positions(strategy1.id)) self.assertTrue( position_id2 in self.exec_db.get_positions(strategy2.id)) self.assertTrue(position_id1 in self.exec_db.get_positions()) self.assertTrue(position_id2 in self.exec_db.get_positions()) self.assertEqual(0, len(self.exec_db.get_positions_open(strategy1.id))) self.assertEqual(1, len(self.exec_db.get_positions_open(strategy2.id))) self.assertEqual(1, len(self.exec_db.get_positions_open())) self.assertEqual(1, len(self.exec_db.get_positions_closed())) self.assertEqual(2, len(self.exec_db.get_positions())) self.assertTrue( position_id1 not in self.exec_db.get_positions_open(strategy1.id)) self.assertTrue( position_id2 in self.exec_db.get_positions_open(strategy2.id)) self.assertTrue(position_id1 not in self.exec_db.get_positions_open()) self.assertTrue(position_id2 in self.exec_db.get_positions_open()) self.assertTrue( position_id1 in self.exec_db.get_positions_closed(strategy1.id)) self.assertTrue(position_id2 not in self.exec_db.get_positions_closed( strategy2.id)) self.assertTrue(position_id1 in self.exec_db.get_positions_closed()) self.assertTrue( position_id2 not in self.exec_db.get_positions_closed()) self.assertEqual(2, self.exec_db.count_positions_total()) self.assertEqual(1, self.exec_db.count_positions_open()) self.assertEqual(1, self.exec_db.count_positions_closed())
def test_position_long_with_multiple_filled_orders_returns_expected_attributes(self): # Arrange order1 = self.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) order2 = self.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) order3 = self.order_factory.market( AUDUSD_FXCM, OrderSide.SELL, Quantity(200000)) order1_filled = OrderFilled( self.account_id, order1.id, ExecutionId('E1'), PositionIdBroker('T123456'), order1.symbol, order1.side, order1.quantity, Price(1.00000, 5), Currency.USD, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) order2_filled = OrderFilled( self.account_id, order2.id, ExecutionId('E2'), PositionIdBroker('T123456'), order2.symbol, order2.side, order2.quantity, Price(1.00001, 5), Currency.USD, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) order3_filled = OrderFilled( self.account_id, order3.id, ExecutionId('E3'), PositionIdBroker('T123456'), order3.symbol, order3.side, order3.quantity, Price(1.00010, 5), Currency.USD, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) last = Tick(AUDUSD_FXCM, Price(1.00050, 5), Price(1.00048, 5), Volume(1), Volume(1), UNIX_EPOCH) # Act position = Position(PositionId('P-123456'), order1_filled) position.apply(order2_filled) position.apply(order3_filled) # Assert self.assertEqual(Quantity(), position.quantity) self.assertEqual(MarketPosition.FLAT, position.market_position) self.assertEqual(UNIX_EPOCH, position.opened_time) self.assertEqual(1.000005, position.average_open_price) self.assertEqual(3, position.event_count) self.assertEqual([order1.id, order2.id, order3.id], position.get_order_ids()) self.assertEqual(ExecutionId('E3'), position.last_execution_id) self.assertEqual(PositionIdBroker('T123456'), position.id_broker) self.assertEqual(UNIX_EPOCH, position.closed_time) self.assertEqual(1.0001, position.average_close_price) self.assertFalse(position.is_long) self.assertFalse(position.is_short) self.assertTrue(position.is_closed) self.assertEqual(9.499999999995623e-05, position.realized_points) self.assertEqual(9.499952500233122e-05, position.realized_return) self.assertEqual(Money(19.000, Currency.USD), position.realized_pnl) self.assertEqual(0.0, position.unrealized_points(last)) self.assertEqual(0.0, position.unrealized_return(last)) self.assertEqual(Money(00, Currency.USD), position.unrealized_pnl(last)) self.assertEqual(9.499999999995623e-05, position.total_points(last)) self.assertEqual(9.499952500233122e-05, position.total_return(last)) self.assertEqual(Money(19.000, Currency.USD), position.total_pnl(last))
def test_position_filled_with_sell_order_then_buy_order_returns_expected_attributes(self): # Arrange order1 = self.order_factory.market( AUDUSD_FXCM, OrderSide.SELL, Quantity(100000)) order2 = self.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) order_filled1 = OrderFilled( self.account_id, order1.id, ExecutionId('E123456'), PositionIdBroker('T123456'), order1.symbol, order1.side, order1.quantity, Price(1.00000, 5), Currency.USD, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) position = Position(PositionId('P-123456'), order_filled1) order_filled2 = OrderPartiallyFilled( self.account_id, order2.id, ExecutionId('E1234561'), PositionIdBroker('T123456'), order2.symbol, order2.side, Quantity(50000), Quantity(50000), Price(1.00001, 5), Currency.USD, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) order_filled3 = OrderPartiallyFilled( self.account_id, order2.id, ExecutionId('E1234562'), PositionIdBroker('T123456'), order2.symbol, order2.side, Quantity(100000), Quantity(), Price(1.00003, 5), Currency.USD, UNIX_EPOCH, GUID(uuid.uuid4()), UNIX_EPOCH) last = Tick(AUDUSD_FXCM, Price(1.00050, 5), Price(1.00048, 5), Volume(1), Volume(1), UNIX_EPOCH) # Act position.apply(order_filled2) position.apply(order_filled3) # Assert self.assertEqual(Quantity(), position.quantity) self.assertEqual(MarketPosition.FLAT, position.market_position) self.assertEqual(UNIX_EPOCH, position.opened_time) self.assertEqual(1.0, position.average_open_price) self.assertEqual(3, position.event_count) self.assertEqual([order1.id, order2.id], position.get_order_ids()) self.assertEqual(ExecutionId('E1234562'), position.last_execution_id) self.assertEqual(PositionIdBroker('T123456'), position.id_broker) self.assertEqual(UNIX_EPOCH, position.closed_time) self.assertEqual(1.00003, position.average_close_price) self.assertFalse(position.is_long) self.assertFalse(position.is_short) self.assertTrue(position.is_closed) self.assertEqual(-2.999999999997449e-05, position.realized_points) self.assertEqual(-2.999999999997449e-05, position.realized_return) self.assertEqual(Money(-3.000, Currency.USD), position.realized_pnl) self.assertEqual(0.0, position.unrealized_points(last)) self.assertEqual(0.0, position.unrealized_return(last)) self.assertEqual(Money(00, Currency.USD), position.unrealized_pnl(last)) self.assertEqual(-2.999999999997449e-05, position.total_points(last)) self.assertEqual(-2.999999999997449e-05, position.total_return(last)) self.assertEqual(Money(-3.000, Currency.USD), position.total_pnl(last))