class OrderTests(unittest.TestCase): def setUp(self): # Fixture Setup self.account_id = TestStubs.account_id() self.order_factory = OrderFactory( trader_id=TraderId("TESTER", "000"), strategy_id=StrategyId("S", "001"), clock=TestClock(), ) def test_opposite_side_given_undefined_raises_value_error(self): # Arrange # Act # Assert self.assertRaises(ValueError, Order.opposite_side, OrderSide.UNDEFINED) def test_flatten_side_given_undefined_or_flat_raises_value_error(self): # Arrange # Act # Assert self.assertRaises(ValueError, Order.flatten_side, PositionSide.UNDEFINED) self.assertRaises(ValueError, Order.flatten_side, PositionSide.FLAT) @parameterized.expand([ [OrderSide.BUY, OrderSide.SELL], [OrderSide.SELL, OrderSide.BUY], ]) def test_opposite_side_returns_expected_sides(self, side, expected): # Arrange # Act result = Order.opposite_side(side) # Assert self.assertEqual(expected, result) @parameterized.expand([ [PositionSide.LONG, OrderSide.SELL], [PositionSide.SHORT, OrderSide.BUY], ]) def test_flatten_side_returns_expected_sides(self, side, expected): # Arrange # Act result = Order.flatten_side(side) # Assert self.assertEqual(expected, result) def test_market_order_with_quantity_zero_raises_exception(self): # Arrange # Act self.assertRaises( ValueError, MarketOrder, ClientOrderId("O-123456"), StrategyId("S", "001"), AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(), TimeInForce.DAY, uuid4(), UNIX_EPOCH, ) def test_market_order_with_invalid_tif_raises_exception(self): # Arrange # Act self.assertRaises( ValueError, MarketOrder, ClientOrderId("O-123456"), StrategyId("S", "001"), AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100), TimeInForce.GTD, uuid4(), UNIX_EPOCH, ) def test_stop_order_with_gtd_and_expire_time_none_raises_exception(self): # Arrange # Act self.assertRaises( TypeError, StopMarketOrder, ClientOrderId("O-123456"), StrategyId("S", "001"), AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), price=Price("1.00000"), init_id=uuid4(), timestamp=UNIX_EPOCH, time_in_force=TimeInForce.GTD, expire_time=None, ) def test_reset_order_factory(self): # Arrange self.order_factory.limit( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) # Act self.order_factory.reset() order2 = self.order_factory.limit( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) self.assertEqual(ClientOrderId("O-19700101-000000-000-001-1"), order2.cl_ord_id) def test_limit_order_can_create_expected_decimal_price(self): # Arrange # Act order1 = self.order_factory.limit( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) order2 = self.order_factory.limit( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) order3 = self.order_factory.limit( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) order4 = self.order_factory.limit( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00001"), ) # Assert self.assertEqual(Price("1.00000"), order1.price) self.assertEqual(Price("1.00000"), order2.price) self.assertEqual(Price("1.00000"), order3.price) self.assertEqual(Price("1.00001"), order4.price) def test_initialize_buy_market_order(self): # Arrange # Act order = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) # Assert self.assertEqual(OrderType.MARKET, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(1, order.event_count) self.assertTrue(isinstance(order.last_event, OrderInitialized)) self.assertFalse(order.is_working) self.assertFalse(order.is_completed) self.assertTrue(order.is_buy) self.assertFalse(order.is_sell) self.assertFalse(order.is_passive) self.assertTrue(order.is_aggressive) self.assertEqual(None, order.filled_timestamp) self.assertEqual(UNIX_EPOCH, order.last_event.timestamp) self.assertEqual(OrderInitialized, type(order.init_event)) self.assertTrue(order == order) self.assertFalse(order != order) def test_initialize_sell_market_order(self): # Arrange # Act order = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.SELL, Quantity(100000), ) # Assert self.assertEqual(OrderType.MARKET, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(1, order.event_count) self.assertTrue(isinstance(order.last_event, OrderInitialized)) self.assertEqual(1, len(order.events)) self.assertTrue(order.is_active) self.assertFalse(order.is_working) self.assertFalse(order.is_completed) self.assertFalse(order.is_buy) self.assertTrue(order.is_sell) self.assertEqual(None, order.filled_timestamp) self.assertEqual(OrderInitialized, type(order.init_event)) def test_order_equality(self): # Arrange # Act order = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) # Assert self.assertTrue(order == order) self.assertFalse(order != order) def test_order_str_and_repr(self): # Arrange # Act order = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) # Assert self.assertEqual("MarketOrder(cl_ord_id=O-19700101-000000-000-001-1, id=NULL, state=INITIALIZED, BUY 100,000 AUD/USD.SIM MARKET GTC)", str(order)) # noqa self.assertEqual("MarketOrder(cl_ord_id=O-19700101-000000-000-001-1, id=NULL, state=INITIALIZED, BUY 100,000 AUD/USD.SIM MARKET GTC)", repr(order)) # noqa def test_initialize_limit_order(self): # Arrange # Act order = self.order_factory.limit( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) # Assert self.assertEqual(OrderType.LIMIT, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(TimeInForce.GTC, order.time_in_force) self.assertTrue(order.is_passive) self.assertTrue(order.is_active) self.assertFalse(order.is_aggressive) self.assertFalse(order.is_completed) self.assertEqual(OrderInitialized, type(order.init_event)) def test_initialize_limit_order_with_expire_time(self): # Arrange # Act order = self.order_factory.limit( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00000"), TimeInForce.GTD, UNIX_EPOCH, ) # Assert self.assertEqual(AUDUSD_SIM.symbol, order.symbol) self.assertEqual(OrderType.LIMIT, order.type) self.assertEqual(Price("1.00000"), order.price) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(TimeInForce.GTD, order.time_in_force) self.assertEqual(UNIX_EPOCH, order.expire_time) self.assertFalse(order.is_completed) self.assertEqual(OrderInitialized, type(order.init_event)) def test_initialize_stop_order(self): # Arrange # Act order = self.order_factory.stop_market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) # Assert self.assertEqual(OrderType.STOP_MARKET, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(TimeInForce.GTC, order.time_in_force) self.assertTrue(order.is_passive) self.assertFalse(order.is_aggressive) self.assertFalse(order.is_completed) self.assertEqual(OrderInitialized, type(order.init_event)) def test_bracket_order_equality(self): # Arrange entry1 = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) entry2 = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) bracket_order1 = self.order_factory.bracket(entry1, Price("1.00000")) bracket_order2 = self.order_factory.bracket(entry2, Price("1.00000")) # Act # Assert self.assertTrue(bracket_order1 == bracket_order1) self.assertTrue(bracket_order1 != bracket_order2) def test_initialize_bracket_order_market_with_no_take_profit(self): # Arrange entry_order = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) # Act bracket_order = self.order_factory.bracket(entry_order, Price("0.99990")) # Assert self.assertEqual(AUDUSD_SIM.symbol, bracket_order.stop_loss.symbol) self.assertFalse(bracket_order.take_profit is not None) self.assertEqual(ClientOrderId("O-19700101-000000-000-001-1"), bracket_order.entry.cl_ord_id) self.assertEqual(ClientOrderId("O-19700101-000000-000-001-2"), bracket_order.stop_loss.cl_ord_id) self.assertEqual(OrderSide.SELL, bracket_order.stop_loss.side) self.assertEqual(Quantity(100000), bracket_order.entry.quantity) self.assertEqual(Quantity(100000), bracket_order.stop_loss.quantity) self.assertEqual(Price("0.99990"), bracket_order.stop_loss.price) self.assertEqual(TimeInForce.GTC, bracket_order.stop_loss.time_in_force) self.assertEqual(None, bracket_order.stop_loss.expire_time) self.assertEqual(BracketOrderId("BO-19700101-000000-000-001-1"), bracket_order.id) self.assertEqual(UNIX_EPOCH, bracket_order.timestamp) def test_initialize_bracket_order_stop_with_take_profit(self): # Arrange entry_order = self.order_factory.stop_market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("0.99995"), ) # Act bracket_order = self.order_factory.bracket( entry_order, Price("0.99990"), Price("1.00010"), ) # Assert self.assertEqual(AUDUSD_SIM.symbol, bracket_order.stop_loss.symbol) self.assertTrue(bracket_order.take_profit is not None) self.assertEqual(AUDUSD_SIM.symbol, bracket_order.take_profit.symbol) self.assertEqual(ClientOrderId("O-19700101-000000-000-001-1"), bracket_order.entry.cl_ord_id) self.assertEqual(ClientOrderId("O-19700101-000000-000-001-2"), bracket_order.stop_loss.cl_ord_id) self.assertEqual(ClientOrderId("O-19700101-000000-000-001-3"), bracket_order.take_profit.cl_ord_id) self.assertEqual(OrderSide.SELL, bracket_order.stop_loss.side) self.assertEqual(OrderSide.SELL, bracket_order.take_profit.side) self.assertEqual(Quantity(100000), bracket_order.stop_loss.quantity) self.assertEqual(Quantity(100000), bracket_order.take_profit.quantity) self.assertEqual(Price("0.99990"), bracket_order.stop_loss.price) self.assertEqual(Price("1.00010"), bracket_order.take_profit.price) self.assertEqual(TimeInForce.GTC, bracket_order.stop_loss.time_in_force) self.assertEqual(TimeInForce.GTC, bracket_order.take_profit.time_in_force) self.assertEqual(None, bracket_order.entry.expire_time) self.assertEqual(None, bracket_order.stop_loss.expire_time) self.assertEqual(None, bracket_order.take_profit.expire_time) self.assertEqual(BracketOrderId("BO-19700101-000000-000-001-1"), bracket_order.id) self.assertEqual(UNIX_EPOCH, bracket_order.timestamp) def test_bracket_order_str_and_repr(self): # Arrange # Act entry_order = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) bracket_order = self.order_factory.bracket( entry_order, Price("0.99990"), Price("1.00010"), ) # Assert self.assertEqual("BracketOrder(id=BO-19700101-000000-000-001-1, EntryMarketOrder(cl_ord_id=O-19700101-000000-000-001-1, id=NULL, state=INITIALIZED, BUY 100,000 AUD/USD.SIM MARKET GTC), SL=0.99990, TP=1.00010)", str(bracket_order)) # noqa self.assertEqual("BracketOrder(id=BO-19700101-000000-000-001-1, EntryMarketOrder(cl_ord_id=O-19700101-000000-000-001-1, id=NULL, state=INITIALIZED, BUY 100,000 AUD/USD.SIM MARKET GTC), SL=0.99990, TP=1.00010)", repr(bracket_order)) # noqa def test_apply_order_invalid_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) invalid = OrderInvalid( order.cl_ord_id, "SOME_REASON", uuid4(), UNIX_EPOCH, ) # Act order.apply(invalid) # Assert self.assertEqual(OrderState.INVALID, order.state) self.assertEqual(2, order.event_count) self.assertEqual(invalid, order.last_event) self.assertFalse(order.is_active) self.assertTrue(order.is_completed) def test_apply_order_denied_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) denied = OrderDenied( order.cl_ord_id, "SOME_REASON", uuid4(), UNIX_EPOCH, ) # Act order.apply(denied) # Assert self.assertEqual(OrderState.DENIED, order.state) self.assertEqual(2, order.event_count) self.assertEqual(denied, order.last_event) self.assertFalse(order.is_active) self.assertTrue(order.is_completed) def test_apply_order_submitted_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) submitted = TestStubs.event_order_submitted(order) # Act order.apply(submitted) # Assert self.assertEqual(OrderState.SUBMITTED, order.state) self.assertEqual(2, order.event_count) self.assertEqual(submitted, order.last_event) self.assertTrue(order.is_active) self.assertFalse(order.is_working) self.assertFalse(order.is_completed) def test_apply_order_accepted_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) order.apply(TestStubs.event_order_submitted(order)) # Act order.apply(TestStubs.event_order_accepted(order)) # Assert self.assertEqual(OrderState.ACCEPTED, order.state) self.assertTrue(order.is_active) self.assertTrue(order.is_working) self.assertFalse(order.is_completed) def test_apply_order_rejected_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) order.apply(TestStubs.event_order_submitted(order)) # Act order.apply(TestStubs.event_order_rejected(order)) # Assert self.assertEqual(OrderState.REJECTED, order.state) self.assertFalse(order.is_active) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) def test_apply_order_expired_event(self): # Arrange order = self.order_factory.stop_market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("0.99990"), TimeInForce.GTD, UNIX_EPOCH, ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) # Act order.apply(TestStubs.event_order_expired(order)) # Assert self.assertEqual(OrderState.EXPIRED, order.state) self.assertFalse(order.is_active) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) def test_apply_order_cancelled_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) # Act order.apply(TestStubs.event_order_cancelled(order)) # Assert self.assertEqual(OrderState.CANCELLED, order.state) self.assertFalse(order.is_active) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) def test_apply_order_amended_event_to_stop_order(self): # Arrange order = self.order_factory.stop_market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) amended = OrderAmended( self.account_id, order.cl_ord_id, OrderId("1"), Quantity(120000), Price("1.00001"), UNIX_EPOCH, uuid4(), UNIX_EPOCH, ) # Act order.apply(amended) # Assert self.assertEqual(OrderState.ACCEPTED, order.state) self.assertEqual(OrderId("1"), order.id) self.assertEqual(Quantity(120000), order.quantity) self.assertEqual(Price("1.00001"), order.price) self.assertTrue(order.is_active) self.assertTrue(order.is_working) self.assertFalse(order.is_completed) self.assertEqual(4, order.event_count) def test_apply_order_filled_event_to_order_without_accepted(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) filled = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00001"), ) # Act order.apply(filled) # Assert self.assertEqual(OrderState.FILLED, order.state) self.assertEqual(Quantity(100000), order.filled_qty) self.assertEqual(Decimal("1.00001"), order.avg_price) self.assertEqual(1, len(order.execution_ids)) self.assertFalse(order.is_active) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) self.assertEqual(UNIX_EPOCH, order.filled_timestamp) def test_apply_order_filled_event_to_market_order(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) filled = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00001"), ) # Act order.apply(filled) # Assert self.assertEqual(OrderState.FILLED, order.state) self.assertEqual(Quantity(100000), order.filled_qty) self.assertEqual(Decimal("1.00001"), order.avg_price) self.assertEqual(1, len(order.execution_ids)) self.assertFalse(order.is_active) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) self.assertEqual(UNIX_EPOCH, order.filled_timestamp) def test_apply_partial_fill_events_to_market_order_results_in_partially_filled(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.symbol, 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, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00001"), fill_qty=Quantity(20000), ) fill2 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00002"), fill_qty=Quantity(40000), ) # Act order.apply(fill1) order.apply(fill2) # Assert self.assertEqual(OrderState.PARTIALLY_FILLED, order.state) self.assertEqual(Quantity(60000), order.filled_qty) self.assertEqual(Decimal("1.000014"), order.avg_price) self.assertEqual(2, len(order.execution_ids)) self.assertTrue(order.is_active) self.assertTrue(order.is_working) self.assertFalse(order.is_completed) self.assertEqual(UNIX_EPOCH, order.filled_timestamp) def test_apply_filled_events_to_market_order_results_in_filled(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.symbol, 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, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00001"), fill_qty=Quantity(20000), ) fill2 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00002"), fill_qty=Quantity(40000), ) fill3 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00003"), fill_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_price) self.assertEqual(3, len(order.execution_ids)) self.assertFalse(order.is_active) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) self.assertEqual(UNIX_EPOCH, order.filled_timestamp) def test_apply_order_filled_event_to_buy_limit_order(self): # Arrange order = self.order_factory.limit( AUDUSD_SIM.symbol, 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.symbol, 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_active) 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.symbol, 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.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, ) # 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.assertTrue(order.is_active) self.assertTrue(order.is_working) self.assertFalse(order.is_completed) self.assertEqual(UNIX_EPOCH, order.filled_timestamp)
class BacktestExecClientTests(unittest.TestCase): def setUp(self): # Fixture Setup self.clock = TestClock() self.uuid_factory = UUIDFactory() self.logger = TestLogger(self.clock) self.trader_id = TraderId("TESTER", "000") self.account_id = AccountId("BINANCE", "000") self.portfolio = Portfolio( clock=self.clock, logger=self.logger, ) self.portfolio.register_cache(DataCache(self.logger)) self.analyzer = PerformanceAnalyzer() database = BypassExecutionDatabase( trader_id=self.trader_id, logger=self.logger, ) self.exec_engine = ExecutionEngine( database=database, portfolio=self.portfolio, clock=self.clock, logger=self.logger, ) self.exchange = SimulatedExchange( venue=Venue("BINANCE"), oms_type=OMSType.NETTING, generate_position_ids=True, is_frozen_account=False, starting_balances=[Money(1_000_000, USD)], instruments=[ETHUSDT_BINANCE], modules=[], exec_cache=self.exec_engine.cache, fill_model=FillModel(), clock=self.clock, logger=self.logger, ) self.exec_client = BacktestExecClient( exchange=self.exchange, account_id=self.account_id, engine=self.exec_engine, clock=self.clock, logger=self.logger, ) self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=StrategyId("SCALPER", "000"), clock=self.clock, ) def test_is_connected_when_not_connected_returns_false(self): # Arrange # Act # Assert self.assertFalse(self.exec_client.is_connected()) def test_connect(self): # Arrange # Act self.exec_client.connect() # Assert self.assertTrue(self.exec_client.is_connected()) def test_disconnect(self): # Arrange self.exec_client.connect() # Act self.exec_client.disconnect() # Assert self.assertFalse(self.exec_client.is_connected()) def test_reset(self): # Arrange # Act self.exec_client.reset() # Assert self.assertFalse( self.exec_client.is_connected()) # No exceptions raised def test_dispose(self): # Arrange # Act self.exec_client.dispose() # Assert self.assertFalse( self.exec_client.is_connected()) # No exceptions raised def test_submit_order_when_not_connected_logs_and_does_not_send(self): # Arrange strategy = TradingStrategy("000") order = self.order_factory.market( ETHUSDT_BINANCE.symbol, OrderSide.BUY, Quantity(100), ) command = SubmitOrder( BINANCE, self.trader_id, self.account_id, strategy.id, PositionId.null(), order, self.uuid_factory.generate(), self.clock.utc_now(), ) # Act self.exec_client.submit_order(command) # Assert self.assertEqual(OrderState.INITIALIZED, order.state) def test_submit_bracket_order_when_not_connected_logs_and_does_not_send( self): # Arrange strategy = TradingStrategy("000") entry = self.order_factory.market( ETHUSDT_BINANCE.symbol, OrderSide.BUY, Quantity(100), ) bracket = self.order_factory.bracket(entry, Price("500.00000")) command = SubmitBracketOrder( BINANCE, self.trader_id, self.account_id, strategy.id, bracket, self.uuid_factory.generate(), self.clock.utc_now(), ) # Act self.exec_client.submit_bracket_order(command) # Assert self.assertEqual(OrderState.INITIALIZED, entry.state) def test_cancel_order_when_not_connected_logs_and_does_not_send(self): # Arrange order = self.order_factory.market( ETHUSDT_BINANCE.symbol, OrderSide.BUY, Quantity(100), ) command = CancelOrder( BINANCE, self.trader_id, self.account_id, order.cl_ord_id, self.uuid_factory.generate(), self.clock.utc_now(), ) # Act self.exec_client.cancel_order(command) # Assert self.assertTrue(True) # No exceptions raised def test_modify_order_when_not_connected_logs_and_does_not_send(self): # Arrange order = self.order_factory.stop_market( ETHUSDT_BINANCE.symbol, OrderSide.BUY, Quantity(100), Price("1000.00"), ) command = ModifyOrder( BINANCE, self.trader_id, self.account_id, order.cl_ord_id, Quantity(100), Price("1010.00"), self.uuid_factory.generate(), self.clock.utc_now(), ) # Act self.exec_client.modify_order(command) # Assert self.assertTrue(True) # No exceptions raised
class ExecutionClientTests(unittest.TestCase): def setUp(self): # Fixture Setup self.clock = TestClock() self.uuid_factory = UUIDFactory() self.logger = TestLogger(self.clock) self.trader_id = TraderId("TESTER", "000") self.account_id = TestStubs.account_id() portfolio = Portfolio( clock=self.clock, logger=self.logger, ) portfolio.register_cache(DataCache(self.logger)) database = BypassExecutionDatabase(trader_id=self.trader_id, logger=self.logger) self.exec_engine = ExecutionEngine( database=database, portfolio=portfolio, clock=self.clock, logger=self.logger, ) self.venue = Venue("SIM") self.client = ExecutionClient( venue=self.venue, account_id=self.account_id, engine=self.exec_engine, clock=self.clock, logger=self.logger, ) self.order_factory = OrderFactory( trader_id=TraderId("TESTER", "000"), strategy_id=StrategyId("S", "001"), clock=TestClock(), ) def test_connect_when_not_implemented_raises_exception(self): self.assertRaises(NotImplementedError, self.client.connect) def test_disconnect_when_not_implemented_raises_exception(self): self.assertRaises(NotImplementedError, self.client.disconnect) def test_reset_when_not_implemented_raises_exception(self): self.assertRaises(NotImplementedError, self.client.reset) def test_dispose_when_not_implemented_raises_exception(self): self.assertRaises(NotImplementedError, self.client.dispose) def test_submit_order_raises_exception(self): order = self.order_factory.limit( AUDUSD_SIM.symbol, OrderSide.SELL, Quantity(100000), Price("1.00000"), ) command = SubmitOrder( self.venue, self.trader_id, self.account_id, StrategyId("SCALPER", "001"), PositionId.null(), order, self.uuid_factory.generate(), self.clock.utc_now(), ) self.assertRaises(NotImplementedError, self.client.submit_order, command) def test_submit_bracket_order_raises_not_implemented_error(self): entry_order = self.order_factory.stop_market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("0.99995"), ) # Act bracket_order = self.order_factory.bracket( entry_order, Price("0.99990"), Price("1.00010"), ) command = SubmitBracketOrder( self.venue, self.trader_id, self.account_id, StrategyId("SCALPER", "001"), bracket_order, self.uuid_factory.generate(), self.clock.utc_now(), ) self.assertRaises(NotImplementedError, self.client.submit_bracket_order, command) def test_amend_order_raises_not_implemented_error(self): # Arrange # Act command = AmendOrder( self.venue, self.trader_id, self.account_id, ClientOrderId("O-123456789"), Quantity(120000), Price("1.00000"), self.uuid_factory.generate(), self.clock.utc_now(), ) # Assert self.assertRaises(NotImplementedError, self.client.amend_order, command) def test_cancel_order_raises_not_implemented_error(self): # Arrange # Act command = CancelOrder( self.venue, self.trader_id, self.account_id, ClientOrderId("O-123456789"), OrderId("001"), self.uuid_factory.generate(), self.clock.utc_now(), ) # Assert self.assertRaises(NotImplementedError, self.client.cancel_order, command) def test_handle_event_sends_to_execution_engine(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) fill = TestStubs.event_order_filled( order, AUDUSD_SIM, PositionId("P-123456"), StrategyId("S", "001"), Price("1.00001"), ) # Act self.client._handle_event_py(fill) # Accessing protected method # Assert self.assertEqual(1, self.exec_engine.event_count)
class TestMsgPackCommandSerializer: def setup(self): # Fixture Setup self.venue = Venue("SIM") self.trader_id = TestStubs.trader_id() self.account_id = TestStubs.account_id() self.serializer = MsgPackCommandSerializer() self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=StrategyId("S-001"), clock=TestClock(), ) def test_serialize_and_deserialize_submit_order_commands(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000, precision=0), ) command = SubmitOrder( self.trader_id, StrategyId("SCALPER-001"), PositionId("P-123456"), order, uuid4(), 0, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert assert deserialized == command assert deserialized.order == order print(command) print(len(serialized)) print(serialized) print(b64encode(serialized)) def test_serialize_and_deserialize_submit_bracket_order_no_take_profit_commands( self, ): # Arrange entry_order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000, precision=0), ) bracket_order = self.order_factory.bracket( entry_order, stop_loss=Price(0.99900, precision=5), take_profit=Price(1.00100, precision=5), ) command = SubmitBracketOrder( self.trader_id, StrategyId("SCALPER-001"), bracket_order, uuid4(), 0, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert assert deserialized == command assert deserialized.bracket_order == bracket_order print(b64encode(serialized)) print(command) def test_serialize_and_deserialize_submit_bracket_order_with_take_profit_commands( self, ): # Arrange entry_order = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000, precision=0), Price(1.00000, precision=5), ) bracket_order = self.order_factory.bracket( entry_order, stop_loss=Price(0.99900, precision=5), take_profit=Price(1.00010, precision=5), ) command = SubmitBracketOrder( self.trader_id, StrategyId("SCALPER-001"), bracket_order, uuid4(), 0, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert assert deserialized == command assert deserialized.bracket_order == bracket_order print(b64encode(serialized)) print(command) def test_serialize_and_deserialize_amend_order_commands(self): # Arrange command = UpdateOrder( self.trader_id, StrategyId("SCALPER-001"), AUDUSD_SIM.id, ClientOrderId("O-123456"), VenueOrderId("001"), Quantity(100000, precision=0), Price(1.00001, precision=5), None, uuid4(), 0, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert assert deserialized == command print(b64encode(serialized)) print(command) def test_serialize_and_deserialize_cancel_order_commands(self): # Arrange command = CancelOrder( self.trader_id, StrategyId("SCALPER-001"), AUDUSD_SIM.id, ClientOrderId("O-123456"), VenueOrderId("001"), uuid4(), 0, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert assert deserialized == command print(b64encode(serialized)) print(command)
class MsgPackCommandSerializerTests(unittest.TestCase): def setUp(self): # Fixture Setup self.venue = Venue("SIM") self.trader_id = TestStubs.trader_id() self.account_id = TestStubs.account_id() self.serializer = MsgPackCommandSerializer() self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=StrategyId("S", "001"), clock=TestClock(), ) def test_serialize_and_deserialize_submit_order_commands(self): # Arrange order = self.order_factory.market(AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000)) command = SubmitOrder( self.venue, self.trader_id, self.account_id, StrategyId("SCALPER", "01"), PositionId("P-123456"), order, uuid4(), UNIX_EPOCH, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert self.assertEqual(command, deserialized) self.assertEqual(order, deserialized.order) print(command) print(len(serialized)) print(serialized) print(b64encode(serialized)) def test_serialize_and_deserialize_submit_bracket_order_no_take_profit_commands( self): # Arrange entry_order = self.order_factory.market(AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000)) bracket_order = self.order_factory.bracket( entry_order, stop_loss=Price("0.99900"), ) command = SubmitBracketOrder( self.venue, self.trader_id, self.account_id, StrategyId("SCALPER", "01"), bracket_order, uuid4(), UNIX_EPOCH, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert self.assertEqual(command, deserialized) self.assertEqual(bracket_order, deserialized.bracket_order) print(b64encode(serialized)) print(command) def test_serialize_and_deserialize_submit_bracket_order_with_take_profit_commands( self): # Arrange entry_order = self.order_factory.limit( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) bracket_order = self.order_factory.bracket( entry_order, stop_loss=Price("0.99900"), take_profit=Price("1.00010"), ) command = SubmitBracketOrder( self.venue, self.trader_id, self.account_id, StrategyId("SCALPER", "01"), bracket_order, uuid4(), UNIX_EPOCH, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert self.assertEqual(command, deserialized) self.assertEqual(bracket_order, deserialized.bracket_order) print(b64encode(serialized)) print(command) def test_serialize_and_deserialize_modify_order_commands(self): # Arrange command = ModifyOrder( self.venue, self.trader_id, self.account_id, ClientOrderId("O-123456"), Quantity(100000), Price("1.00001"), uuid4(), UNIX_EPOCH, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert self.assertEqual(command, deserialized) print(b64encode(serialized)) print(command) def test_serialize_and_deserialize_cancel_order_commands(self): # Arrange command = CancelOrder( self.venue, self.trader_id, self.account_id, ClientOrderId("O-123456"), uuid4(), UNIX_EPOCH, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert self.assertEqual(command, deserialized) print(b64encode(serialized)) print(command)
class ExecutionClientTests(unittest.TestCase): def setUp(self): # Fixture Setup self.clock = TestClock() self.uuid_factory = UUIDFactory() self.logger = Logger(self.clock) self.trader_id = TraderId("TESTER-000") self.account_id = TestStubs.account_id() self.cache = TestStubs.cache() self.portfolio = Portfolio( cache=self.cache, clock=self.clock, logger=self.logger, ) self.exec_engine = ExecutionEngine( portfolio=self.portfolio, cache=self.cache, clock=self.clock, logger=self.logger, ) self.venue = Venue("SIM") self.client = ExecutionClient( client_id=ClientId(self.venue.value), venue_type=VenueType.ECN, account_id=TestStubs.account_id(), account_type=AccountType.MARGIN, base_currency=USD, engine=self.exec_engine, clock=self.clock, logger=self.logger, ) self.order_factory = OrderFactory( trader_id=TraderId("TESTER-000"), strategy_id=StrategyId("S-001"), clock=TestClock(), ) def test_venue_when_brokerage_returns_client_id_value_as_venue(self): assert self.client.venue == self.venue def test_venue_when_brokerage_multi_venue_returns_none(self): # Arrange client = ExecutionClient( client_id=ClientId("IB"), venue_type=VenueType.BROKERAGE_MULTI_VENUE, account_id=AccountId("IB", "U1258001"), account_type=AccountType.MARGIN, base_currency=USD, engine=self.exec_engine, clock=self.clock, logger=self.logger, ) # Act, Assert assert client.venue is None def test_connect_when_not_implemented_raises_exception(self): self.assertRaises(NotImplementedError, self.client.connect) def test_disconnect_when_not_implemented_raises_exception(self): self.assertRaises(NotImplementedError, self.client.disconnect) def test_reset_when_not_implemented_raises_exception(self): self.assertRaises(NotImplementedError, self.client.reset) def test_dispose_when_not_implemented_raises_exception(self): self.assertRaises(NotImplementedError, self.client.dispose) def test_submit_order_raises_exception(self): order = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.SELL, Quantity.from_int(100000), Price.from_str("1.00000"), ) command = SubmitOrder( self.trader_id, order.strategy_id, PositionId.null(), order, self.uuid_factory.generate(), self.clock.timestamp_ns(), ) self.assertRaises(NotImplementedError, self.client.submit_order, command) def test_submit_bracket_order_raises_not_implemented_error(self): entry_order = self.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("0.99995"), ) # Act bracket_order = self.order_factory.bracket( entry_order, Price.from_str("0.99990"), Price.from_str("1.00010"), ) command = SubmitBracketOrder( self.trader_id, entry_order.strategy_id, bracket_order, self.uuid_factory.generate(), self.clock.timestamp_ns(), ) self.assertRaises(NotImplementedError, self.client.submit_bracket_order, command) def test_update_order_raises_not_implemented_error(self): # Arrange # Act command = UpdateOrder( self.trader_id, StrategyId("SCALPER-001"), AUDUSD_SIM.id, ClientOrderId("O-123456789"), VenueOrderId("001"), Quantity.from_int(120000), Price.from_str("1.00000"), None, self.uuid_factory.generate(), self.clock.timestamp_ns(), ) # Assert self.assertRaises(NotImplementedError, self.client.update_order, command) def test_cancel_order_raises_not_implemented_error(self): # Arrange # Act command = CancelOrder( self.trader_id, StrategyId("SCALPER-001"), AUDUSD_SIM.id, ClientOrderId("O-123456789"), VenueOrderId("001"), self.uuid_factory.generate(), self.clock.timestamp_ns(), ) # Assert self.assertRaises(NotImplementedError, self.client.cancel_order, command)
class OrderTests(unittest.TestCase): def setUp(self): # Fixture Setup self.account_id = TestStubs.account_id() self.order_factory = OrderFactory( strategy_id=StrategyId("S", "001"), id_tag_trader=IdTag("001"), id_tag_strategy=IdTag("001"), clock=TestClock(), uuid_factory=TestUUIDFactory(), ) def test_get_opposite_side_returns_expected_sides(self): # Arrange # Act result1 = opposite_side(OrderSide.BUY) result2 = opposite_side(OrderSide.SELL) # Assert self.assertEqual(OrderSide.SELL, result1) self.assertEqual(OrderSide.BUY, result2) def test_get_flatten_side_with_long_or_short_position_side_returns_expected_sides(self): # Arrange # Act result1 = flatten_side(PositionSide.LONG) result2 = flatten_side(PositionSide.SHORT) # Assert self.assertEqual(OrderSide.SELL, result1) self.assertEqual(OrderSide.BUY, result2) def test_market_order_with_quantity_zero_raises_exception(self): # Arrange # Act self.assertRaises( ValueError, MarketOrder, ClientOrderId("O-123456"), StrategyId("S", "001"), AUDUSD_FXCM, OrderSide.BUY, Quantity(), TimeInForce.DAY, uuid4(), UNIX_EPOCH, ) def test_market_order_with_invalid_tif_raises_exception(self): # Arrange # Act self.assertRaises( ValueError, MarketOrder, ClientOrderId("O-123456"), StrategyId("S", "001"), AUDUSD_FXCM, OrderSide.BUY, Quantity(100), TimeInForce.GTD, uuid4(), UNIX_EPOCH, ) def test_stop_order_with_gtd_and_expire_time_none_raises_exception(self): # Arrange # Act self.assertRaises( TypeError, StopMarketOrder, ClientOrderId("O-123456"), StrategyId("S", "001"), AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), price=Price("1.00000"), init_id=uuid4(), timestamp=UNIX_EPOCH, time_in_force=TimeInForce.GTD, expire_time=None, ) def test_reset_order_factory(self): # Arrange self.order_factory.limit( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) # Act self.order_factory.reset() order2 = self.order_factory.limit( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) self.assertEqual(ClientOrderId("O-19700101-000000-001-001-1"), order2.cl_ord_id) def test_limit_order_can_create_expected_decimal_price(self): # Arrange # Act order1 = self.order_factory.limit( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) order2 = self.order_factory.limit( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) order3 = self.order_factory.limit( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) order4 = self.order_factory.limit( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price("1.00001"), ) # Assert self.assertEqual(Price("1.00000"), order1.price) self.assertEqual(Price("1.00000"), order2.price) self.assertEqual(Price("1.00000"), order3.price) self.assertEqual(Price("1.00001"), order4.price) def test_initialize_buy_market_order(self): # Arrange # Act order = self.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), ) # Assert self.assertEqual(OrderType.MARKET, order.type) self.assertEqual(OrderState.INITIALIZED, order.state()) self.assertEqual(1, order.event_count()) self.assertTrue(isinstance(order.last_event(), OrderInitialized)) self.assertFalse(order.is_working()) self.assertFalse(order.is_completed()) self.assertTrue(order.is_buy()) self.assertFalse(order.is_sell()) self.assertEqual(None, order.filled_timestamp) self.assertEqual(UNIX_EPOCH, order.last_event().timestamp) def test_initialize_sell_market_order(self): # Arrange # Act order = self.order_factory.market( AUDUSD_FXCM, OrderSide.SELL, Quantity(100000),) # Assert self.assertEqual(OrderType.MARKET, order.type) self.assertEqual(OrderState.INITIALIZED, order.state()) self.assertEqual(1, order.event_count()) self.assertTrue(isinstance(order.last_event(), OrderInitialized)) self.assertFalse(order.is_working()) self.assertFalse(order.is_completed()) self.assertFalse(order.is_buy()) self.assertTrue(order.is_sell()) self.assertEqual(None, order.filled_timestamp) # def test_order_str_and_repr(self): # # Arrange # # Act # order = self.order_factory.market( # AUDUSD_FXCM, # OrderSide.BUY, # Quantity(100000), # ) # Assert TODO: String formatting # self.assertEqual("MarketOrder(cl_ord_id=O-19700101-000000-001-001-1, state=INITIALIZED, BUY 100K AUD/USD.FXCM MARKET DAY)", str(order)) # noqa # self.assertTrue(repr(order).startswith("<MarketOrder(cl_ord_id=O-19700101-000000-001-001-1, state=INITIALIZED, BUY 100K AUD/USD.FXCM MARKET DAY) object at")) # noqa def test_initialize_limit_order(self): # Arrange # Act order = self.order_factory.limit( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) # Assert self.assertEqual(OrderType.LIMIT, order.type) self.assertEqual(OrderState.INITIALIZED, order.state()) self.assertEqual(TimeInForce.DAY, order.time_in_force) self.assertFalse(order.is_completed()) def test_initialize_limit_order_with_expire_time(self): # Arrange # Act order = self.order_factory.limit( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price("1.00000"), TimeInForce.GTD, UNIX_EPOCH, ) # Assert self.assertEqual(AUDUSD_FXCM, order.symbol) self.assertEqual(OrderType.LIMIT, order.type) self.assertEqual(Price("1.00000"), order.price) self.assertEqual(OrderState.INITIALIZED, order.state()) self.assertEqual(TimeInForce.GTD, order.time_in_force) self.assertEqual(UNIX_EPOCH, order.expire_time) self.assertFalse(order.is_completed()) def test_initialize_stop_order(self): # Arrange # Act order = self.order_factory.stop( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) # Assert self.assertEqual(OrderType.STOP_MARKET, order.type) self.assertEqual(OrderState.INITIALIZED, order.state()) self.assertEqual(TimeInForce.DAY, order.time_in_force) self.assertFalse(order.is_completed()) def test_initialize_bracket_order_market_with_no_take_profit(self): # Arrange entry_order = self.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) # Act bracket_order = self.order_factory.bracket(entry_order, Price("0.99990")) # Assert self.assertEqual(AUDUSD_FXCM, bracket_order.stop_loss.symbol) self.assertFalse(bracket_order.has_take_profit) self.assertEqual(ClientOrderId("O-19700101-000000-001-001-1"), bracket_order.entry.cl_ord_id) self.assertEqual(ClientOrderId("O-19700101-000000-001-001-2"), bracket_order.stop_loss.cl_ord_id) self.assertEqual(OrderSide.SELL, bracket_order.stop_loss.side) self.assertEqual(Quantity(100000), bracket_order.entry.quantity) self.assertEqual(Quantity(100000), bracket_order.stop_loss.quantity) self.assertEqual(Price("0.99990"), bracket_order.stop_loss.price) self.assertEqual(TimeInForce.GTC, bracket_order.stop_loss.time_in_force) self.assertEqual(None, bracket_order.stop_loss.expire_time) self.assertEqual(BracketOrderId("BO-19700101-000000-001-001-1"), bracket_order.id) self.assertEqual(UNIX_EPOCH, bracket_order.timestamp) def test_can_initialize_bracket_order_stop_with_take_profit(self): # Arrange entry_order = self.order_factory.stop( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price("0.99995"), ) # Act bracket_order = self.order_factory.bracket( entry_order, Price("0.99990"), Price("1.00010"), ) # Assert self.assertEqual(AUDUSD_FXCM, bracket_order.stop_loss.symbol) self.assertTrue(bracket_order.has_take_profit) self.assertEqual(AUDUSD_FXCM, bracket_order.take_profit.symbol) self.assertEqual(ClientOrderId("O-19700101-000000-001-001-1"), bracket_order.entry.cl_ord_id) self.assertEqual(ClientOrderId("O-19700101-000000-001-001-2"), bracket_order.stop_loss.cl_ord_id) self.assertEqual(ClientOrderId("O-19700101-000000-001-001-3"), bracket_order.take_profit.cl_ord_id) self.assertEqual(OrderSide.SELL, bracket_order.stop_loss.side) self.assertEqual(OrderSide.SELL, bracket_order.take_profit.side) self.assertEqual(Quantity(100000), bracket_order.stop_loss.quantity) self.assertEqual(Quantity(100000), bracket_order.take_profit.quantity) self.assertEqual(Price("0.99990"), bracket_order.stop_loss.price) self.assertEqual(Price("1.00010"), bracket_order.take_profit.price) self.assertEqual(TimeInForce.GTC, bracket_order.stop_loss.time_in_force) self.assertEqual(TimeInForce.GTC, bracket_order.take_profit.time_in_force) self.assertEqual(None, bracket_order.entry.expire_time) self.assertEqual(None, bracket_order.stop_loss.expire_time) self.assertEqual(None, bracket_order.take_profit.expire_time) self.assertEqual(BracketOrderId("BO-19700101-000000-001-001-1"), bracket_order.id) self.assertEqual(UNIX_EPOCH, bracket_order.timestamp) # def test_bracket_order_str_and_repr(self): # # Arrange # # Act # entry_order = self.order_factory.market( # AUDUSD_FXCM, # OrderSide.BUY, # Quantity(100000), # ) # # bracket_order = self.order_factory.bracket( # entry_order, # Price("0.99990"), # Price("1.00010"), # ) # Assert # TODO: Fix string formatting # self.assertEqual("BracketOrder(id=BO-19700101-000000-001-001-1, EntryMarketOrder(cl_ord_id=O-19700101-000000-001-001-1, state=INITIALIZED, BUY 100K AUD/USD.FXCM MARKET DAY), SL=0.99990, TP=1.00010)", str(bracket_order)) # noqa # self.assertTrue(repr(bracket_order).startswith("<BracketOrder(id=BO-19700101-000000-001-001-1, EntryMarketOrder(cl_ord_id=O-19700101-000000-001-001-1, state=INITIALIZED, BUY 100K AUD/USD.FXCM MARKET DAY), SL=0.99990, TP=1.00010) object at")) # noqa # self.assertTrue(repr(bracket_order).endswith(">")) def test_can_apply_order_submitted_event_to_order(self): # Arrange order = self.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), ) submitted = TestStubs.event_order_submitted(order) # Act order.apply(submitted) # Assert self.assertEqual(OrderState.SUBMITTED, order.state()) self.assertEqual(2, order.event_count()) self.assertEqual(submitted, order.last_event()) self.assertFalse(order.is_completed()) def test_can_apply_order_accepted_event_to_order(self): # Arrange order = self.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) submitted = TestStubs.event_order_submitted(order) accepted = TestStubs.event_order_accepted(order) order.apply(submitted) # Act order.apply(accepted) # Assert self.assertEqual(OrderState.ACCEPTED, order.state()) self.assertFalse(order.is_completed()) def test_can_apply_order_rejected_event_to_order(self): # Arrange order = self.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) submitted = TestStubs.event_order_submitted(order) rejected = TestStubs.event_order_rejected(order) order.apply(submitted) # Act order.apply(rejected) # Assert self.assertEqual(OrderState.REJECTED, order.state()) self.assertTrue(order.is_completed()) def test_can_apply_order_working_event_to_stop_order(self): # Arrange order = self.order_factory.stop( 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) order.apply(submitted) order.apply(accepted) # Act order.apply(working) # Assert # print(order) self.assertEqual(OrderState.WORKING, order.state()) self.assertEqual(OrderId("1"), order.id) self.assertFalse(order.is_completed()) self.assertTrue(order.is_working()) self.assertEqual(None, order.filled_timestamp) def test_can_apply_order_expired_event_to_stop_order(self): # Arrange order = self.order_factory.stop( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price("0.99990"), TimeInForce.GTD, UNIX_EPOCH) submitted = TestStubs.event_order_submitted(order) accepted = TestStubs.event_order_accepted(order) working = TestStubs.event_order_working(order) expired = TestStubs.event_order_expired(order) order.apply(submitted) order.apply(accepted) order.apply(working) # Act order.apply(expired) # Assert self.assertEqual(OrderState.EXPIRED, order.state()) self.assertTrue(order.is_completed()) def test_can_apply_order_cancelled_event_to_order(self): # Arrange order = self.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) submitted = TestStubs.event_order_submitted(order) accepted = TestStubs.event_order_accepted(order) cancelled = TestStubs.event_order_cancelled(order) order.apply(submitted) order.apply(accepted) # Act order.apply(cancelled) # Assert self.assertEqual(OrderState.CANCELLED, order.state()) self.assertTrue(order.is_completed()) def test_can_apply_order_modified_event_to_stop_order(self): # Arrange order = self.order_factory.stop( 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) modified = OrderModified( self.account_id, order.cl_ord_id, OrderId("1"), Quantity(120000), Price("1.00001"), UNIX_EPOCH, uuid4(), UNIX_EPOCH) order.apply(submitted) order.apply(accepted) order.apply(working) # Act order.apply(modified) # Assert self.assertEqual(OrderState.WORKING, order.state()) self.assertEqual(OrderId("1"), order.id) self.assertEqual(Quantity(120000), order.quantity) self.assertEqual(Price("1.00001"), order.price) self.assertTrue(order.is_working()) self.assertFalse(order.is_completed()) self.assertEqual(5, order.event_count()) def test_can_apply_order_filled_event_to_market_order(self): # Arrange order = self.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) submitted = TestStubs.event_order_submitted(order) accepted = TestStubs.event_order_accepted(order) filled = TestStubs.event_order_filled( order, PositionId("P-123456"), StrategyId("S", "001"), Price("1.00001")) order.apply(submitted) order.apply(accepted) # Act order.apply(filled) # Assert self.assertEqual(OrderState.FILLED, order.state()) self.assertEqual(Quantity(100000), order.filled_qty) self.assertEqual(Price("1.00001"), order.avg_price) self.assertTrue(order.is_completed()) self.assertEqual(UNIX_EPOCH, order.filled_timestamp) 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 test_can_apply_order_partially_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) partially = OrderFilled( self.account_id, order.cl_ord_id, OrderId("1"), ExecutionId("E-1"), PositionId("P-1"), StrategyId("S", "NULL"), order.symbol, order.side, Quantity(50000), Quantity(50000), Price("0.999999"), Money(0, USD), LiquiditySide.MAKER, USD, USD, 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(Price("0.999999"), order.avg_price) self.assertEqual(Decimal("-0.000001"), order.slippage) self.assertFalse(order.is_completed()) self.assertEqual(UNIX_EPOCH, order.filled_timestamp)
class TestBacktestExecClientTests: def setup(self): # Fixture Setup self.clock = TestClock() self.uuid_factory = UUIDFactory() self.logger = Logger(self.clock) self.trader_id = TraderId("TESTER-000") self.account_id = AccountId("BINANCE", "000") self.cache = TestStubs.cache() self.portfolio = Portfolio( cache=self.cache, clock=self.clock, logger=self.logger, ) self.exec_engine = ExecutionEngine( portfolio=self.portfolio, cache=self.cache, clock=self.clock, logger=self.logger, ) self.exchange = SimulatedExchange( venue=Venue("BINANCE"), venue_type=VenueType.EXCHANGE, oms_type=OMSType.NETTING, account_type=AccountType.CASH, base_currency=None, # Multi-currency account starting_balances=[Money(1_000_000, USDT)], is_frozen_account=False, instruments=[ETHUSDT_BINANCE], modules=[], cache=self.exec_engine.cache, fill_model=FillModel(), clock=self.clock, logger=self.logger, ) self.exec_client = BacktestExecClient( exchange=self.exchange, account_id=self.account_id, account_type=AccountType.CASH, base_currency=None, # Multi-currency account engine=self.exec_engine, clock=self.clock, logger=self.logger, ) self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=StrategyId("SCALPER-001"), clock=self.clock, ) def test_is_connected_when_not_connected_returns_false(self): # Arrange # Act # Assert assert not self.exec_client.is_connected def test_connect(self): # Arrange # Act self.exec_client.connect() # Assert assert self.exec_client.is_connected def test_disconnect(self): # Arrange self.exec_client.connect() # Act self.exec_client.disconnect() # Assert assert not self.exec_client.is_connected def test_reset(self): # Arrange # Act self.exec_client.reset() # Assert assert not self.exec_client.is_connected def test_dispose(self): # Arrange # Act self.exec_client.dispose() # Assert assert not self.exec_client.is_connected def test_submit_order_when_not_connected_logs_and_does_not_send(self): # Arrange strategy = TradingStrategy("000") order = self.order_factory.market( ETHUSDT_BINANCE.id, OrderSide.BUY, Quantity.from_int(100), ) command = SubmitOrder( self.trader_id, strategy.id, PositionId.null(), order, self.uuid_factory.generate(), self.clock.timestamp_ns(), ) # Act self.exec_client.submit_order(command) # Assert assert order.state == OrderState.INITIALIZED def test_submit_bracket_order_when_not_connected_logs_and_does_not_send( self): # Arrange strategy = TradingStrategy("000") entry = self.order_factory.market( ETHUSDT_BINANCE.id, OrderSide.BUY, Quantity.from_int(100), ) bracket = self.order_factory.bracket( entry, Price.from_str("500.00000"), Price.from_str("600.00000"), ) command = SubmitBracketOrder( self.trader_id, strategy.id, bracket, self.uuid_factory.generate(), self.clock.timestamp_ns(), ) # Act self.exec_client.submit_bracket_order(command) # Assert assert entry.state == OrderState.INITIALIZED def test_cancel_order_when_not_connected_logs_and_does_not_send(self): # Arrange order = self.order_factory.market( ETHUSDT_BINANCE.id, OrderSide.BUY, Quantity.from_int(100), ) command = CancelOrder( self.trader_id, self.order_factory.strategy_id, order.instrument_id, order.client_order_id, order.venue_order_id, self.uuid_factory.generate(), self.clock.timestamp_ns(), ) # Act self.exec_client.cancel_order(command) # Assert assert True # No exceptions raised def test_update_order_when_not_connected_logs_and_does_not_send(self): # Arrange order = self.order_factory.stop_market( ETHUSDT_BINANCE.id, OrderSide.BUY, Quantity.from_int(100), Price.from_str("1000.00"), ) command = UpdateOrder( self.trader_id, order.strategy_id, order.instrument_id, order.client_order_id, order.venue_order_id, Quantity.from_int(100), Price.from_str("1010.00"), None, self.uuid_factory.generate(), self.clock.timestamp_ns(), ) # Act self.exec_client.update_order(command) # Assert assert True # No exceptions raised
class OrderTests(unittest.TestCase): def setUp(self): # Fixture Setup self.account_id = TestStubs.account_id() self.order_factory = OrderFactory( trader_id=TraderId("TESTER-000"), strategy_id=StrategyId("S-001"), clock=TestClock(), ) def test_opposite_side_given_invalid_value_raises_value_error(self): # Arrange # Act # Assert self.assertRaises(ValueError, Order.opposite_side, 0) def test_flatten_side_given_invalid_value_or_flat_raises_value_error(self): # Arrange # Act self.assertRaises(ValueError, Order.flatten_side, 0) self.assertRaises(ValueError, Order.flatten_side, PositionSide.FLAT) @parameterized.expand([ [OrderSide.BUY, OrderSide.SELL], [OrderSide.SELL, OrderSide.BUY], ]) def test_opposite_side_returns_expected_sides(self, side, expected): # Arrange # Act result = Order.opposite_side(side) # Assert self.assertEqual(expected, result) @parameterized.expand([ [PositionSide.LONG, OrderSide.SELL], [PositionSide.SHORT, OrderSide.BUY], ]) def test_flatten_side_returns_expected_sides(self, side, expected): # Arrange # Act result = Order.flatten_side(side) # Assert self.assertEqual(expected, result) def test_market_order_with_quantity_zero_raises_value_error(self): # Arrange # Act self.assertRaises( ValueError, MarketOrder, ClientOrderId("O-123456"), StrategyId("S-001"), AUDUSD_SIM.id, OrderSide.BUY, Quantity.zero(), TimeInForce.DAY, uuid4(), 0, ) def test_market_order_with_invalid_tif_raises_value_error(self): # Arrange # Act self.assertRaises( ValueError, MarketOrder, ClientOrderId("O-123456"), StrategyId("S-001"), AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100), TimeInForce.GTD, uuid4(), 0, ) def test_stop_market_order_with_gtd_and_expire_time_none_raises_type_error( self): # Arrange # Act self.assertRaises( TypeError, StopMarketOrder, ClientOrderId("O-123456"), StrategyId("S-001"), AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), price=Price.from_str("1.00000"), init_id=uuid4(), timestamp_ns=0, time_in_force=TimeInForce.GTD, expire_time=None, ) def test_stop_limit_buy_order_with_gtd_and_expire_time_none_raises_type_error( self): # Arrange # Act self.assertRaises( TypeError, StopLimitOrder, ClientOrderId("O-123456"), StrategyId("S-001"), AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), price=Price.from_str("1.00001"), trigger=Price.from_str("1.00000"), init_id=uuid4(), timestamp_ns=0, time_in_force=TimeInForce.GTD, expire_time=None, ) def test_reset_order_factory(self): # Arrange self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) # Act self.order_factory.reset() order2 = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) self.assertEqual(ClientOrderId("O-19700101-000000-000-001-1"), order2.client_order_id) def test_limit_order_can_create_expected_decimal_price(self): # Arrange # Act order1 = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) order2 = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00001"), ) # Assert self.assertEqual(Price.from_str("1.00000"), order1.price) self.assertEqual(Price.from_str("1.00001"), order2.price) def test_initialize_buy_market_order(self): # Arrange # Act order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) # Assert self.assertEqual(AUDUSD_SIM.id.symbol, order.symbol) self.assertEqual(AUDUSD_SIM.id.venue, order.venue) self.assertEqual(OrderType.MARKET, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(1, order.event_count) self.assertTrue(isinstance(order.last_event, OrderInitialized)) self.assertFalse(order.is_working) self.assertFalse(order.is_completed) self.assertTrue(order.is_buy) self.assertFalse(order.is_sell) self.assertFalse(order.is_passive) self.assertTrue(order.is_aggressive) self.assertEqual(0, order.execution_ns) self.assertEqual(0, order.last_event.timestamp_ns) self.assertEqual(OrderInitialized, type(order.init_event)) self.assertTrue(order == order) self.assertFalse(order != order) def test_initialize_sell_market_order(self): # Arrange # Act order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.SELL, Quantity.from_int(100000), ) # Assert self.assertEqual(OrderType.MARKET, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(1, order.event_count) self.assertTrue(isinstance(order.last_event, OrderInitialized)) self.assertEqual(1, len(order.events)) self.assertFalse(order.is_working) self.assertFalse(order.is_completed) self.assertFalse(order.is_buy) self.assertTrue(order.is_sell) self.assertEqual(0, order.execution_ns) self.assertEqual(OrderInitialized, type(order.init_event)) def test_order_equality(self): # Arrange # Act order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) # Assert self.assertTrue(order == order) self.assertFalse(order != order) def test_order_str_and_repr(self): # Arrange # Act order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) # Assert self.assertEqual( "MarketOrder(BUY 100_000 AUD/USD.SIM MARKET GTC, state=INITIALIZED, " "client_order_id=O-19700101-000000-000-001-1)", str(order), ) self.assertEqual( "MarketOrder(BUY 100_000 AUD/USD.SIM MARKET GTC, state=INITIALIZED, " "client_order_id=O-19700101-000000-000-001-1)", repr(order), ) def test_initialize_limit_order(self): # Arrange # Act order = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) # Assert self.assertEqual(OrderType.LIMIT, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(TimeInForce.GTC, order.time_in_force) self.assertTrue(order.is_passive) self.assertFalse(order.is_aggressive) self.assertFalse(order.is_completed) self.assertEqual(OrderInitialized, type(order.init_event)) self.assertEqual( "LimitOrder(BUY 100_000 AUD/USD.SIM LIMIT @ 1.00000 GTC, " "state=INITIALIZED, client_order_id=O-19700101-000000-000-001-1)", str(order), ) self.assertEqual( "LimitOrder(BUY 100_000 AUD/USD.SIM LIMIT @ 1.00000 GTC, " "state=INITIALIZED, client_order_id=O-19700101-000000-000-001-1)", repr(order), ) def test_initialize_limit_order_with_expire_time(self): # Arrange # Act order = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), TimeInForce.GTD, expire_time=UNIX_EPOCH, ) # Assert self.assertEqual(AUDUSD_SIM.id, order.instrument_id) self.assertEqual(OrderType.LIMIT, order.type) self.assertEqual(Price.from_str("1.00000"), order.price) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(TimeInForce.GTD, order.time_in_force) self.assertEqual(UNIX_EPOCH, order.expire_time) self.assertFalse(order.is_completed) self.assertEqual(OrderInitialized, type(order.init_event)) def test_initialize_stop_market_order(self): # Arrange # Act order = self.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) # Assert self.assertEqual(OrderType.STOP_MARKET, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(TimeInForce.GTC, order.time_in_force) self.assertTrue(order.is_passive) self.assertFalse(order.is_aggressive) self.assertFalse(order.is_completed) self.assertEqual(OrderInitialized, type(order.init_event)) self.assertEqual( "StopMarketOrder(BUY 100_000 AUD/USD.SIM STOP_MARKET @ 1.00000 GTC, " "state=INITIALIZED, client_order_id=O-19700101-000000-000-001-1)", str(order), ) self.assertEqual( "StopMarketOrder(BUY 100_000 AUD/USD.SIM STOP_MARKET @ 1.00000 GTC, " "state=INITIALIZED, client_order_id=O-19700101-000000-000-001-1)", repr(order), ) def test_initialize_stop_limit_order(self): # Arrange # Act order = self.order_factory.stop_limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), Price.from_str("1.10010"), ) # Assert self.assertEqual(OrderType.STOP_LIMIT, order.type) self.assertEqual(OrderState.INITIALIZED, order.state) self.assertEqual(TimeInForce.GTC, order.time_in_force) self.assertTrue(order.is_passive) self.assertFalse(order.is_aggressive) self.assertFalse(order.is_completed) self.assertEqual(OrderInitialized, type(order.init_event)) self.assertEqual( "StopLimitOrder(BUY 100_000 AUD/USD.SIM STOP_LIMIT @ 1.00000 GTC, " "trigger=1.10010, state=INITIALIZED, client_order_id=O-19700101-000000-000-001-1)", str(order), ) self.assertEqual( "StopLimitOrder(BUY 100_000 AUD/USD.SIM STOP_LIMIT @ 1.00000 GTC, " "trigger=1.10010, state=INITIALIZED, client_order_id=O-19700101-000000-000-001-1)", repr(order), ) def test_bracket_order_equality(self): # Arrange entry1 = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) entry2 = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) bracket_order1 = self.order_factory.bracket(entry1, Price.from_str("1.00000"), Price.from_str("1.00010")) bracket_order2 = self.order_factory.bracket(entry2, Price.from_str("1.00000"), Price.from_str("1.00010")) # Act # Assert self.assertTrue(bracket_order1 == bracket_order1) self.assertTrue(bracket_order1 != bracket_order2) def test_initialize_bracket_order(self): # Arrange entry_order = self.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("0.99995"), ) # Act bracket_order = self.order_factory.bracket( entry_order, Price.from_str("0.99990"), Price.from_str("1.00010"), TimeInForce.GTC, TimeInForce.GTC, ) # Assert self.assertEqual(AUDUSD_SIM.id, bracket_order.stop_loss.instrument_id) self.assertTrue(bracket_order.take_profit is not None) self.assertEqual(AUDUSD_SIM.id, bracket_order.take_profit.instrument_id) self.assertEqual( ClientOrderId("O-19700101-000000-000-001-1"), bracket_order.entry.client_order_id, ) self.assertEqual( ClientOrderId("O-19700101-000000-000-001-2"), bracket_order.stop_loss.client_order_id, ) self.assertEqual( ClientOrderId("O-19700101-000000-000-001-3"), bracket_order.take_profit.client_order_id, ) self.assertEqual(OrderSide.SELL, bracket_order.stop_loss.side) self.assertEqual(OrderSide.SELL, bracket_order.take_profit.side) self.assertEqual(Quantity.from_int(100000), bracket_order.stop_loss.quantity) self.assertEqual(Quantity.from_int(100000), bracket_order.take_profit.quantity) self.assertEqual(Price.from_str("0.99990"), bracket_order.stop_loss.price) self.assertEqual(Price.from_str("1.00010"), bracket_order.take_profit.price) self.assertEqual(TimeInForce.GTC, bracket_order.stop_loss.time_in_force) self.assertEqual(TimeInForce.GTC, bracket_order.take_profit.time_in_force) self.assertEqual(None, bracket_order.entry.expire_time) self.assertEqual(None, bracket_order.stop_loss.expire_time) self.assertEqual(None, bracket_order.take_profit.expire_time) self.assertEqual(ClientOrderLinkId("BO-19700101-000000-000-001-1"), bracket_order.id) self.assertEqual(0, bracket_order.timestamp_ns) def test_bracket_order_str_and_repr(self): # Arrange # Act entry_order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) bracket_order = self.order_factory.bracket( entry_order, Price.from_str("0.99990"), Price.from_str("1.00010"), ) # Assert self.assertEqual( "BracketOrder(id=BO-19700101-000000-000-001-1, " "EntryMarketOrder(BUY 100_000 AUD/USD.SIM MARKET GTC, " "state=INITIALIZED, client_order_id=O-19700101-000000-000-001-1), " "SL=0.99990, TP=1.00010)", str(bracket_order), ) # noqa self.assertEqual( "BracketOrder(id=BO-19700101-000000-000-001-1, " "EntryMarketOrder(BUY 100_000 AUD/USD.SIM MARKET GTC, " "state=INITIALIZED, client_order_id=O-19700101-000000-000-001-1), " "SL=0.99990, TP=1.00010)", repr(bracket_order), ) # noqa def test_apply_order_invalid_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) invalid = OrderInvalid( order.client_order_id, "SOME_REASON", uuid4(), 0, ) # Act order.apply(invalid) # Assert self.assertEqual(OrderState.INVALID, order.state) self.assertEqual(2, order.event_count) self.assertEqual(invalid, order.last_event) self.assertTrue(order.is_completed) def test_apply_order_denied_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) denied = OrderDenied( order.client_order_id, "SOME_REASON", uuid4(), 0, ) # Act order.apply(denied) # Assert self.assertEqual(OrderState.DENIED, order.state) self.assertEqual(2, order.event_count) self.assertEqual(denied, order.last_event) self.assertTrue(order.is_completed) def test_apply_order_submitted_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) submitted = TestStubs.event_order_submitted(order) # Act order.apply(submitted) # Assert self.assertEqual(OrderState.SUBMITTED, order.state) self.assertEqual(2, order.event_count) self.assertEqual(submitted, order.last_event) self.assertFalse(order.is_working) self.assertFalse(order.is_completed) def test_apply_order_accepted_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) order.apply(TestStubs.event_order_submitted(order)) # Act order.apply(TestStubs.event_order_accepted(order)) # Assert self.assertEqual(OrderState.ACCEPTED, order.state) self.assertTrue(order.is_working) self.assertFalse(order.is_completed) self.assertEqual( "MarketOrder(BUY 100_000 AUD/USD.SIM MARKET GTC, state=ACCEPTED, " "client_order_id=O-19700101-000000-000-001-1, venue_order_id=1)", str(order), ) self.assertEqual( "MarketOrder(BUY 100_000 AUD/USD.SIM MARKET GTC, state=ACCEPTED, " "client_order_id=O-19700101-000000-000-001-1, venue_order_id=1)", repr(order), ) def test_apply_order_rejected_event(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) order.apply(TestStubs.event_order_submitted(order)) # Act order.apply(TestStubs.event_order_rejected(order)) # Assert self.assertEqual(OrderState.REJECTED, order.state) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) def test_apply_order_expired_event(self): # Arrange order = self.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("0.99990"), TimeInForce.GTD, expire_time=UNIX_EPOCH, ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) # Act order.apply(TestStubs.event_order_expired(order)) # Assert self.assertEqual(OrderState.EXPIRED, order.state) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) def test_apply_order_triggered_event(self): # Arrange order = self.order_factory.stop_limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), Price.from_str("0.99990"), TimeInForce.GTD, expire_time=UNIX_EPOCH, ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) # Act order.apply(TestStubs.event_order_triggered(order)) # Assert self.assertEqual(OrderState.TRIGGERED, order.state) self.assertTrue(order.is_working) self.assertFalse(order.is_completed) def test_apply_order_canceled_event(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)) order.apply(TestStubs.event_order_pending_cancel(order)) # Act order.apply(TestStubs.event_order_canceled(order)) # Assert self.assertEqual(OrderState.CANCELED, order.state) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) self.assertEqual(5, order.event_count) def test_apply_order_updated_event_to_stop_order(self): # Arrange order = self.order_factory.stop_market( 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)) order.apply(TestStubs.event_order_pending_replace(order)) updated = OrderUpdated( self.account_id, order.client_order_id, VenueOrderId("1"), Quantity.from_int(120000), Price.from_str("1.00001"), 0, uuid4(), 0, ) # Act order.apply(updated) # Assert self.assertEqual(OrderState.ACCEPTED, order.state) self.assertEqual(VenueOrderId("1"), order.venue_order_id) self.assertEqual(Quantity.from_int(120000), order.quantity) self.assertEqual(Price.from_str("1.00001"), order.price) self.assertTrue(order.is_working) self.assertFalse(order.is_completed) self.assertEqual(5, order.event_count) def test_apply_order_updated_venue_id_change(self): # Arrange order = self.order_factory.stop_market( 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)) order.apply(TestStubs.event_order_pending_replace(order)) updated = OrderUpdated( self.account_id, order.client_order_id, VenueOrderId("2"), Quantity.from_int(120000), Price.from_str("1.00001"), 0, uuid4(), 0, ) # Act order.apply(updated) # Assert self.assertEqual(VenueOrderId("2"), order.venue_order_id) self.assertEqual([VenueOrderId("1")], order.venue_order_ids) def test_apply_order_filled_event_to_order_without_accepted(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)) filled = 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"), ) # Act order.apply(filled) # Assert self.assertEqual(OrderState.FILLED, order.state) self.assertEqual(Quantity.from_int(100000), order.filled_qty) self.assertEqual(Decimal("1.00001"), order.avg_px) self.assertEqual(1, len(order.execution_ids)) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) self.assertEqual(0, order.execution_ns) def test_apply_order_filled_event_to_market_order(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)) filled = 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"), ) # Act order.apply(filled) # Assert self.assertEqual(OrderState.FILLED, order.state) self.assertEqual(Quantity.from_int(100000), order.filled_qty) self.assertEqual(Decimal("1.00001"), order.avg_px) self.assertEqual(1, len(order.execution_ids)) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) self.assertEqual(0, order.execution_ns) 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 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 self.assertEqual(OrderState.FILLED, order.state) self.assertEqual(Quantity.from_int(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_apply_order_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)) 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.from_str("1.00001"), AUDUSD_SIM.quote_currency, Money(0, USD), LiquiditySide.MAKER, 0, uuid4(), 0, ) # Act order.apply(filled) # Assert self.assertEqual(OrderState.FILLED, order.state) self.assertEqual(Quantity.from_int(100000), order.filled_qty) self.assertEqual(Price.from_str("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 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( self.account_id, order.client_order_id, VenueOrderId("1"), ExecutionId("E-1"), PositionId("P-1"), StrategyId.null(), order.instrument_id, order.side, Quantity.from_int(50000), Price.from_str("0.999999"), AUDUSD_SIM.quote_currency, 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.from_int(50000), order.filled_qty) self.assertEqual(Price.from_str("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)