def test_message_qsize_at_max_blocks_on_put_event(self): # Arrange self.exec_engine = LiveExecutionEngine( loop=self.loop, portfolio=self.portfolio, cache=self.cache, clock=self.clock, logger=self.logger, config={"qsize": 1}, ) self.exec_engine.register_risk_engine(self.risk_engine) strategy = TradingStrategy(order_id_tag="001") strategy.register_trader( TraderId("TESTER-000"), self.clock, self.logger, ) self.exec_engine.register_strategy(strategy) order = strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) submit_order = SubmitOrder( self.trader_id, strategy.id, PositionId.null(), order, self.uuid_factory.generate(), self.clock.timestamp_ns(), ) event = TestStubs.event_order_submitted(order) # Act self.exec_engine.execute(submit_order) self.exec_engine.process(event) # Add over max size # Assert assert self.exec_engine.qsize() == 1 assert self.exec_engine.command_count == 0
def make_order(engine: MockLiveExecutionEngine) -> LimitOrder: strategy = TradingStrategy(order_id_tag="001") strategy.register_trader( TraderId("TESTER", "000"), BetfairTestStubs.clock(), BetfairTestStubs.logger(), ) engine.register_strategy(strategy) order = strategy.order_factory.limit( BetfairTestStubs.instrument_id(), OrderSide.BUY, Quantity(10), Price("0.50"), ) return order
def test_is_flat_when_strategy_registered_returns_true(self): # Arrange strategy = TradingStrategy(order_id_tag="001") strategy.register_trader( TraderId("TESTER", "000"), clock=self.clock, uuid_factory=TestUUIDFactory(), logger=self.logger, ) # Act self.exec_engine.register_strategy(strategy) # Assert self.assertTrue( self.exec_engine.cache.is_flat(strategy_id=strategy.id)) self.assertTrue(self.exec_engine.cache.is_flat())
async def test_message_qsize_at_max_blocks_on_put_command(self): # Arrange self.msgbus.deregister("RiskEngine.execute", self.risk_engine.execute) self.risk_engine = LiveRiskEngine( loop=self.loop, portfolio=self.portfolio, msgbus=self.msgbus, cache=self.cache, clock=self.clock, logger=self.logger, config=LiveRiskEngineConfig(qsize=1), ) strategy = TradingStrategy() strategy.register( trader_id=self.trader_id, portfolio=self.portfolio, msgbus=self.msgbus, cache=self.cache, clock=self.clock, logger=self.logger, ) order = strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) submit_order = SubmitOrder( self.trader_id, strategy.id, None, order, self.uuid_factory.generate(), self.clock.timestamp_ns(), ) # Act self.risk_engine.execute(submit_order) self.risk_engine.execute(submit_order) await asyncio.sleep(0.1) # Assert assert self.risk_engine.qsize() == 1 assert self.risk_engine.command_count == 0
def test_deregister_strategy(self): # Arrange strategy = TradingStrategy(order_id_tag="001") strategy.register_trader( TraderId("TESTER", "000"), clock=self.clock, uuid_factory=TestUUIDFactory(), logger=self.logger, ) self.exec_engine.register_strategy(strategy) # Act self.exec_engine.deregister_strategy(strategy) # Assert self.assertTrue( strategy.id not in self.exec_engine.registered_strategies())
def test_stop_a_running_trader(self): # Arrange strategies = [ TradingStrategy(TradingStrategyConfig(order_id_tag="001")), TradingStrategy(TradingStrategyConfig(order_id_tag="002")), ] self.trader.add_strategies(strategies) self.trader.start() # Act self.trader.stop() strategy_states = self.trader.strategy_states() # Assert assert self.trader.is_stopped assert strategy_states[StrategyId("TradingStrategy-001")] == "STOPPED" assert strategy_states[StrategyId("TradingStrategy-002")] == "STOPPED"
def setUp(self): # Fixture Setup clock = TestClock() logger = TestLogger(clock) self.trader_id = TraderId("TESTER", "000") self.account_id = TestStubs.account_id() self.strategy = TradingStrategy(order_id_tag="001") self.strategy.register_trader( TraderId("TESTER", "000"), clock, logger, ) exec_db = BypassExecutionDatabase(trader_id=self.trader_id, logger=logger) self.cache = ExecutionCache(database=exec_db, logger=logger)
def test_can_generate_position_id(self): # Arrange strategy = TradingStrategy(order_id_tag='001', clock=TestClock()) # Act result = strategy.position_id_generator.generate() # Assert self.assertEqual(PositionId('P-19700101-000000-000-001-1'), result)
def test_can_register_strategy_with_exec_client(self): # Arrange strategy = TradingStrategy(order_id_tag='001') # Act self.exec_engine.register_strategy(strategy) # Assert self.assertTrue(True) # No exceptions thrown
def test_reset_execution_engine(self): strategy = TradingStrategy(order_id_tag="001") strategy.register_trader( TraderId("TESTER", "000"), clock=self.clock, uuid_factory=TestUUIDFactory(), logger=self.logger, ) self.exec_engine.register_strategy( strategy) # Also registers with portfolio # Act self.exec_engine.reset() # Assert self.assertTrue( strategy.id in self.exec_engine.registered_strategies())
def test_message_qsize_at_max_blocks_on_put_command(self): # Arrange self.risk_engine = LiveRiskEngine( loop=self.loop, exec_engine=self.exec_engine, portfolio=self.portfolio, clock=self.clock, logger=self.logger, config={"qsize": 1}, ) strategy = TradingStrategy(order_id_tag="001") strategy.register_trader( TraderId("TESTER", "000"), self.clock, self.logger, ) self.exec_engine.register_strategy(strategy) order = strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) submit_order = SubmitOrder( order.instrument_id, self.trader_id, self.account_id, strategy.id, PositionId.null(), order, self.uuid_factory.generate(), self.clock.timestamp_ns(), ) # Act self.risk_engine.execute(submit_order) self.risk_engine.execute(submit_order) # Assert assert self.risk_engine.qsize() == 1 assert self.risk_engine.command_count == 0
def test_can_handle_order_fill_event(self): # Arrange strategy = TradingStrategy(order_id_tag='001') strategy.change_clock(self.clock) self.exec_engine.register_strategy(strategy) position_id = strategy.position_id_generator.generate() order = strategy.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) submit_order = SubmitOrder(self.trader_id, self.account_id, strategy.id, position_id, order, self.guid_factory.generate(), self.clock.time_now()) self.exec_engine.execute_command(submit_order) order_filled = TestStubs.event_order_filled(order) # Act self.exec_engine.handle_event(order_filled) # Assert self.assertTrue(self.exec_db.position_exists(position_id)) self.assertTrue(self.exec_db.is_position_open(position_id)) self.assertFalse(self.exec_db.is_position_closed(position_id)) self.assertFalse(self.exec_engine.is_strategy_flat(strategy.id)) self.assertFalse(self.exec_engine.is_flat()) self.assertEqual(Position, type(self.exec_db.get_position(position_id))) self.assertTrue(position_id in self.exec_db.get_positions()) self.assertTrue( position_id not in self.exec_db.get_positions_closed(strategy.id)) self.assertTrue(position_id not in self.exec_db.get_positions_closed()) self.assertTrue( position_id in self.exec_db.get_positions_open(strategy.id)) self.assertTrue(position_id in self.exec_db.get_positions_open()) self.assertEqual(1, self.exec_db.count_positions_total()) self.assertEqual(1, self.exec_db.count_positions_open()) self.assertEqual(0, self.exec_db.count_positions_closed()) self.assertTrue(self.exec_db.position_exists_for_order(order.id)) self.assertEqual(Position, type(self.exec_db.get_position_for_order(order.id)))
def test_message_qsize_at_max_blocks_on_put_event(self): # Arrange self.exec_engine = LiveExecutionEngine(loop=self.loop, database=self.database, portfolio=self.portfolio, clock=self.clock, logger=self.logger, config={"qsize": 1}) strategy = TradingStrategy(order_id_tag="001") strategy.register_trader( TraderId("TESTER", "000"), self.clock, self.logger, ) self.exec_engine.register_strategy(strategy) order = strategy.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) submit_order = SubmitOrder( Venue("SIM"), self.trader_id, self.account_id, strategy.id, PositionId.null(), order, self.uuid_factory.generate(), self.clock.utc_now(), ) event = TestStubs.event_order_submitted(order) # Act self.exec_engine.execute(submit_order) self.exec_engine.process(event) # Add over max size # Assert self.assertEqual(1, self.exec_engine.qsize()) self.assertEqual(0, self.exec_engine.command_count)
def test_flatten_all_positions(self): # Arrange strategy = TradingStrategy(order_id_tag="001") strategy.register_trader( TraderId("TESTER", "000"), clock=self.clock, uuid_factory=self.uuid_factory, logger=self.logger, ) self.exec_engine.register_strategy(strategy) order1 = strategy.order_factory.market( USDJPY_FXCM, OrderSide.BUY, Quantity(100000), ) order2 = strategy.order_factory.market( USDJPY_FXCM, OrderSide.BUY, Quantity(100000), ) strategy.submit_order(order1) strategy.submit_order(order2) filled1 = TestStubs.event_order_filled( order1, position_id=PositionId("B-USD/JPY-1"), strategy_id=strategy.id, ) filled2 = TestStubs.event_order_filled( order2, position_id=PositionId("B-USD/JPY-2"), strategy_id=strategy.id, ) position1 = Position(filled1) position2 = Position(filled2) # Act strategy.flatten_all_positions(USDJPY_FXCM) # Assert self.assertTrue(order1 in strategy.execution.orders()) self.assertTrue(order2 in strategy.execution.orders()) self.assertEqual(OrderState.FILLED, strategy.execution.orders()[0].state()) self.assertEqual(OrderState.FILLED, strategy.execution.orders()[1].state()) self.assertEqual(PositionSide.FLAT, strategy.execution.positions()[0].side) self.assertEqual(PositionSide.FLAT, strategy.execution.positions()[1].side) self.assertTrue(position1.id in strategy.execution.position_closed_ids()) self.assertTrue(position2.id in strategy.execution.position_closed_ids()) self.assertTrue(strategy.execution.is_completely_flat())
def test_is_flat_when_strategy_registered_returns_true(self): # Arrange strategy = TradingStrategy(order_id_tag='001') # Act self.exec_engine.register_strategy(strategy) # Assert self.assertTrue(self.exec_engine.is_strategy_flat(strategy.id)) self.assertTrue(self.exec_engine.is_flat())
def test_can_register_strategy(self): # Arrange strategy = TradingStrategy(order_id_tag='001') # Act self.exec_engine.register_strategy(strategy) # Assert self.assertTrue( strategy.id in self.exec_engine.registered_strategies())
def test_submit_bracket_when_block_all_orders_true_then_denies_order(self): # Arrange self.exec_engine.start() strategy = TradingStrategy(order_id_tag="001") strategy.register_trader( TraderId("TESTER", "000"), self.clock, self.logger, ) self.exec_engine.register_strategy(strategy) entry = strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) bracket = strategy.order_factory.bracket( entry_order=entry, stop_loss=Price("1.00000"), take_profit=Price("1.00010"), ) submit_bracket = SubmitBracketOrder( self.venue, self.trader_id, self.account_id, strategy.id, bracket, self.uuid_factory.generate(), self.clock.utc_now(), ) self.risk_engine.set_block_all_orders() # Act self.exec_engine.execute(submit_bracket) # Assert assert self.exec_client.calls == ['connect'] assert self.exec_engine.event_count == 3
async def run_test(): # Arrange self.engine.start() strategy = TradingStrategy(order_id_tag="001") strategy.register_trader( TraderId("TESTER", "000"), self.clock, self.logger, ) self.engine.register_strategy(strategy) # Act await self.engine.reconcile_state() self.engine.stop() # Assert assert True # No exceptions raised
def test_cancel_all_orders(self): # Arrange strategy = TradingStrategy() strategy.register( trader_id=self.trader_id, portfolio=self.portfolio, msgbus=self.msgbus, cache=self.cache, clock=self.clock, logger=self.logger, ) order1 = strategy.order_factory.stop_market( USDJPY_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("90.007"), ) order2 = strategy.order_factory.stop_market( USDJPY_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("90.006"), ) strategy.submit_order(order1) self.exchange.process(0) strategy.submit_order(order2) self.exchange.process(0) # Act strategy.cancel_all_orders(USDJPY_SIM.id) self.exchange.process(0) # Assert assert order1 in self.cache.orders() assert order2 in self.cache.orders() assert self.cache.orders()[0].status == OrderStatus.CANCELED assert self.cache.orders()[1].status == OrderStatus.CANCELED assert order1 in self.cache.orders_completed() assert order2 in strategy.cache.orders_completed()
def test_submit_order_when_market_order_and_over_max_notional_then_denies( self): # Arrange self.risk_engine.set_max_notional_per_order(AUDUSD_SIM.id, 1_000_000) # Initialize market quote = TestStubs.quote_tick_5decimal(AUDUSD_SIM.id) self.cache.add_quote_tick(quote) self.exec_engine.start() strategy = TradingStrategy() strategy.register( trader_id=self.trader_id, portfolio=self.portfolio, msgbus=self.msgbus, cache=self.cache, clock=self.clock, logger=self.logger, ) order = strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(10000000), ) submit_order = SubmitOrder( self.trader_id, strategy.id, None, order, self.uuid_factory.generate(), self.clock.timestamp_ns(), ) # Act self.risk_engine.execute(submit_order) # Assert assert self.exec_engine.command_count == 0 # <-- command never reaches engine
async def test_reconcile_state_with_no_active_orders(self): # Arrange self.exec_engine.start() strategy = TradingStrategy() strategy.register( trader_id=self.trader_id, portfolio=self.portfolio, msgbus=self.msgbus, cache=self.cache, clock=self.clock, logger=self.logger, ) # Act await self.exec_engine.reconcile_state(timeout_secs=10) self.exec_engine.stop() await asyncio.sleep(0.1) # Assert assert True # No exceptions raised
def test_can_reset_execution_engine(self): strategy = TradingStrategy(order_id_tag='001') self.exec_engine.register_strategy( strategy) # Also registers with portfolio # Act self.exec_engine.reset() # Assert self.assertTrue( strategy.id in self.exec_engine.registered_strategies())
def test_strategy_str_and_repr(self): # Arrange strategy = TradingStrategy(order_id_tag="GBP/USD-MM") # Act result1 = str(strategy) result2 = repr(strategy) # Assert self.assertEqual("TradingStrategy(TradingStrategy-GBP/USD-MM)", result1) self.assertTrue(result2.startswith("<TradingStrategy(TradingStrategy-GBP/USD-MM) object at")) self.assertTrue(result2.endswith(">"))
def test_strategy_equality(self): # Arrange strategy1 = TradingStrategy(order_id_tag="001") strategy2 = TradingStrategy(order_id_tag="AUD/USD-001") strategy3 = TradingStrategy(order_id_tag="AUD/USD-002") # Act result1 = strategy1 == strategy1 result2 = strategy1 == strategy2 result3 = strategy2 == strategy3 result4 = strategy1 != strategy1 result5 = strategy1 != strategy2 result6 = strategy2 != strategy3 # Assert self.assertTrue(result1) self.assertFalse(result2) self.assertFalse(result3) self.assertFalse(result4) self.assertTrue(result5) self.assertTrue(result6)
async def test_execute_command_places_command_on_queue(self): # Arrange self.risk_engine.start() strategy = TradingStrategy() strategy.register( trader_id=self.trader_id, portfolio=self.portfolio, msgbus=self.msgbus, cache=self.cache, clock=self.clock, logger=self.logger, ) order = strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) submit_order = SubmitOrder( self.trader_id, strategy.id, None, order, self.uuid_factory.generate(), self.clock.timestamp_ns(), ) # Act self.risk_engine.execute(submit_order) await asyncio.sleep(0.1) # Assert assert self.risk_engine.qsize() == 0 assert self.risk_engine.command_count == 1 # Tear Down self.risk_engine.stop() await self.risk_engine.get_run_queue_task()
async def run_test(): # Arrange self.exec_engine.start() strategy = TradingStrategy(order_id_tag="001") strategy.register_trader( TraderId("TESTER", "000"), self.clock, self.logger, ) self.exec_engine.register_strategy(strategy) order = strategy.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) submit_order = SubmitOrder( Venue("SIM"), self.trader_id, self.account_id, strategy.id, PositionId.null(), order, self.uuid_factory.generate(), self.clock.utc_now(), ) # Act self.exec_engine.execute(submit_order) await asyncio.sleep(0.1) # Assert self.assertEqual(0, self.exec_engine.qsize()) self.assertEqual(1, self.exec_engine.command_count) # Tear Down self.exec_engine.stop()
async def run_test(): # Arrange self.risk_engine.start() strategy = TradingStrategy(order_id_tag="001") strategy.register_trader( TraderId("TESTER", "000"), self.clock, self.logger, ) self.exec_engine.register_strategy(strategy) order = strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) submit_order = SubmitOrder( order.instrument_id, self.trader_id, self.account_id, strategy.id, PositionId.null(), order, self.uuid_factory.generate(), self.clock.timestamp_ns(), ) # Act self.risk_engine.execute(submit_order) await asyncio.sleep(0.1) # Assert assert self.risk_engine.qsize() == 0 assert self.risk_engine.command_count == 1 # Tear Down self.risk_engine.stop()
def test_submit_order_with_valid_order_successfully_submits(self): # Arrange strategy = TradingStrategy() strategy.register( trader_id=self.trader_id, portfolio=self.portfolio, msgbus=self.msgbus, cache=self.cache, clock=self.clock, logger=self.logger, ) order = strategy.order_factory.market( USDJPY_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) # Act strategy.submit_order(order) self.exchange.process(0) # Assert assert order in strategy.cache.orders() assert strategy.cache.orders()[0].status == OrderStatus.FILLED assert order.client_order_id not in strategy.cache.orders_working() assert not strategy.cache.is_order_working(order.client_order_id) assert strategy.cache.is_order_completed(order.client_order_id)
def test_strategy_can_submit_order(self): # Arrange strategy = TradingStrategy(order_id_tag="001") strategy.register_trader( TraderId("TESTER", "000"), clock=self.clock, uuid_factory=self.uuid_factory, logger=self.logger, ) self.exec_engine.register_strategy(strategy) order = strategy.order_factory.market( USDJPY_FXCM, OrderSide.BUY, Quantity(100000), ) # Act strategy.submit_order(order) # Assert self.assertTrue(order in strategy.execution.orders()) self.assertEqual(OrderState.FILLED, strategy.execution.orders()[0].state()) self.assertTrue(order.cl_ord_id not in strategy.execution.orders_working()) self.assertFalse(strategy.execution.is_order_working(order.cl_ord_id)) self.assertTrue(strategy.execution.is_order_completed(order.cl_ord_id))
def test_submit_order_list_with_valid_order_successfully_submits(self): # Arrange strategy = TradingStrategy() strategy.register( trader_id=self.trader_id, portfolio=self.portfolio, msgbus=self.msgbus, cache=self.cache, clock=self.clock, logger=self.logger, ) bracket = strategy.order_factory.bracket_market( USDJPY_SIM.id, OrderSide.BUY, Quantity.from_int(100000), stop_loss=Price.from_str("90.000"), take_profit=Price.from_str("90.500"), ) # Act strategy.submit_order_list(bracket) # Assert assert bracket.orders[0] in strategy.cache.orders() assert bracket.orders[1] in strategy.cache.orders() assert bracket.orders[2] in strategy.cache.orders()