class RedisExecutionDatabaseTests(unittest.TestCase): def setUp(self): # Fixture Setup clock = TestClock() logger = TestLogger(clock) self.trader_id = TraderId("TESTER", "000") self.strategy = TradingStrategy(order_id_tag="001") self.strategy.register_trader( TraderId("TESTER", "000"), clock, logger, ) config = { 'host': 'localhost', 'port': 6379, } self.database = RedisExecutionDatabase( trader_id=self.trader_id, logger=logger, command_serializer=MsgPackCommandSerializer(), event_serializer=MsgPackEventSerializer(), config=config, ) self.test_redis = redis.Redis(host="localhost", port=6379, db=0) def tearDown(self): # Tests will start failing if redis is not flushed on tear down self.test_redis.flushall( ) # Comment this line out to preserve data between tests def test_add_account(self): # Arrange event = TestStubs.event_account_state() account = Account(event) # Act self.database.add_account(account) # Assert self.assertEqual(account, self.database.load_account(account.id)) def test_add_order(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) # Act self.database.add_order(order) # Assert self.assertEqual(order, self.database.load_order(order.cl_ord_id)) def test_add_position(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) self.database.add_order(order) position_id = PositionId('P-1') order_filled = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=position_id, fill_price=Price("1.00000"), ) position = Position(order_filled) # Act self.database.add_position(position) # Assert self.assertEqual(position, self.database.load_position(position.id)) def test_update_account(self): # Arrange event = TestStubs.event_account_state() account = Account(event) self.database.add_account(account) # Act self.database.update_account(account) # Assert self.assertEqual(account, self.database.load_account(account.id)) def test_update_order_for_working_order(self): # Arrange order = self.strategy.order_factory.stop_market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) self.database.add_order(order) order.apply(TestStubs.event_order_submitted(order)) self.database.update_order(order) order.apply(TestStubs.event_order_accepted(order)) self.database.update_order(order) # Act order.apply(TestStubs.event_order_working(order)) self.database.update_order(order) # Assert self.assertEqual(order, self.database.load_order(order.cl_ord_id)) def test_update_order_for_completed_order(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) self.database.add_order(order) order.apply(TestStubs.event_order_submitted(order)) self.database.update_order(order) order.apply(TestStubs.event_order_accepted(order)) self.database.update_order(order) order.apply( TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, fill_price=Price("1.00001"), )) # Act self.database.update_order(order) # Assert self.assertEqual(order, self.database.load_order(order.cl_ord_id)) def test_update_position_for_closed_position(self): # Arrange order1 = self.strategy.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) position_id = PositionId('P-1') self.database.add_order(order1) order1.apply(TestStubs.event_order_submitted(order1)) self.database.update_order(order1) order1.apply(TestStubs.event_order_accepted(order1)) self.database.update_order(order1) order1.apply( TestStubs.event_order_filled( order1, instrument=AUDUSD_SIM, position_id=position_id, fill_price=Price("1.00001"), )) self.database.update_order(order1) # Act position = Position(order1.last_event) self.database.add_position(position) order2 = self.strategy.order_factory.market( AUDUSD_SIM.symbol, OrderSide.SELL, Quantity(100000), ) self.database.add_order(order2) order2.apply(TestStubs.event_order_submitted(order2)) self.database.update_order(order2) order2.apply(TestStubs.event_order_accepted(order2)) self.database.update_order(order2) filled = TestStubs.event_order_filled( order2, instrument=AUDUSD_SIM, position_id=position_id, fill_price=Price("1.00001"), ) order2.apply(filled) self.database.update_order(order2) position.apply(filled) # Act self.database.update_position(position) # Assert self.assertEqual(position, self.database.load_position(position.id)) def test_load_account_when_no_account_in_database_returns_none(self): # Arrange event = TestStubs.event_account_state() account = Account(event) # Act result = self.database.load_account(account.id) # Assert self.assertIsNone(result) def test_load_account_when_account_in_database_returns_account(self): # Arrange event = TestStubs.event_account_state() account = Account(event) self.database.add_account(account) # Act result = self.database.load_account(account.id) # Assert self.assertEqual(account, result) def test_load_order_when_no_order_in_database_returns_none(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) # Act result = self.database.load_order(order.cl_ord_id) # Assert self.assertIsNone(result) def test_load_order_when_market_order_in_database_returns_order(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) self.database.add_order(order) # Act result = self.database.load_order(order.cl_ord_id) # Assert self.assertEqual(order, result) def test_load_order_when_limit_order_in_database_returns_order(self): # Arrange order = self.strategy.order_factory.limit( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) self.database.add_order(order) # Act result = self.database.load_order(order.cl_ord_id) # Assert self.assertEqual(order, result) def test_load_order_when_stop_market_order_in_database_returns_order(self): # Arrange order = self.strategy.order_factory.stop_market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) self.database.add_order(order) # Act result = self.database.load_order(order.cl_ord_id) # Assert self.assertEqual(order, result) def test_load_position_when_no_position_in_database_returns_none(self): # Arrange position_id = PositionId('P-1') # Act result = self.database.load_position(position_id) # Assert self.assertIsNone(result) def test_load_order_when_position_in_database_returns_position(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) self.database.add_order(order) position_id = PositionId('P-1') order_filled = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=position_id, fill_price=Price("1.00000"), ) position = Position(order_filled) self.database.add_position(position) # Act result = self.database.load_position(position_id) # Assert self.assertEqual(position, result) def test_load_accounts_when_no_accounts_returns_empty_dict(self): # Arrange # Act result = self.database.load_accounts() # Assert self.assertEqual({}, result) def test_load_accounts_cache_when_one_account_in_database(self): # Arrange event = TestStubs.event_account_state() account = Account(event) self.database.add_account(account) # Act # Assert self.assertEqual(account, self.database.load_account(account.id)) def test_load_orders_cache_when_no_orders(self): # Arrange # Act self.database.load_orders() # Assert self.assertEqual({}, self.database.load_orders()) def test_load_orders_cache_when_one_order_in_database(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) self.database.add_order(order) # Act result = self.database.load_orders() # Assert self.assertEqual({order.cl_ord_id: order}, result) def test_load_positions_cache_when_no_positions(self): # Arrange # Act self.database.load_positions() # Assert self.assertEqual({}, self.database.load_positions()) def test_load_positions_cache_when_one_position_in_database(self): # Arrange order1 = self.strategy.order_factory.stop_market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) self.database.add_order(order1) position_id = PositionId('P-1') order1.apply(TestStubs.event_order_submitted(order1)) order1.apply(TestStubs.event_order_accepted(order1)) order1.apply(TestStubs.event_order_working(order1)) order1.apply( TestStubs.event_order_filled( order1, instrument=AUDUSD_SIM, position_id=position_id, fill_price=Price("1.00001"), )) position = Position(order1.last_event) self.database.add_position(position) # Act result = self.database.load_positions() # Assert self.assertEqual({position.id: position}, result) def test_delete_strategy(self): # Arrange # Act self.database.delete_strategy(self.strategy.id) result = self.database.load_strategy(self.strategy.id) # Assert self.assertEqual({}, result) def test_flush(self): # Arrange order1 = self.strategy.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) self.database.add_order(order1) position1_id = PositionId('P-1') filled = TestStubs.event_order_filled( order1, instrument=AUDUSD_SIM, position_id=position1_id, fill_price=Price("1.00000"), ) position1 = Position(filled) self.database.update_order(order1) self.database.add_position(position1) order2 = self.strategy.order_factory.stop_market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) self.database.add_order(order2) order2.apply(TestStubs.event_order_submitted(order2)) order2.apply(TestStubs.event_order_accepted(order2)) order2.apply(TestStubs.event_order_working(order2)) self.database.update_order(order2) # Act self.database.flush() # Assert self.assertIsNone(self.database.load_order(order1.cl_ord_id)) self.assertIsNone(self.database.load_order(order2.cl_ord_id)) self.assertIsNone(self.database.load_position(position1.id))
class LiveExecutionPerformanceTests(unittest.TestCase): def setUp(self): # Fixture Setup self.clock = LiveClock() self.uuid_factory = UUIDFactory() self.logger = TestLogger(self.clock, bypass_logging=True) self.trader_id = TraderId("TESTER", "000") self.account_id = AccountId("BINANCE", "001") self.portfolio = Portfolio( clock=self.clock, logger=self.logger, ) self.portfolio.register_cache(DataCache(self.logger)) self.analyzer = PerformanceAnalyzer() # Fresh isolated loop testing pattern self.loop = asyncio.new_event_loop() asyncio.set_event_loop(self.loop) database = BypassExecutionDatabase(trader_id=self.trader_id, logger=self.logger) self.exec_engine = LiveExecutionEngine( loop=self.loop, database=database, portfolio=self.portfolio, clock=self.clock, logger=self.logger, ) exec_client = MockExecutionClient( venue=Venue("BINANCE"), account_id=self.account_id, exec_engine=self.exec_engine, clock=self.clock, logger=self.logger, ) self.exec_engine.register_client(exec_client) self.exec_engine.process(TestStubs.event_account_state( self.account_id)) self.strategy = TradingStrategy(order_id_tag="001") self.strategy.register_trader( TraderId("TESTER", "000"), self.clock, self.logger, ) self.exec_engine.register_strategy(self.strategy) def submit_order(self): order = self.strategy.order_factory.market( BTCUSDT_BINANCE.symbol, OrderSide.BUY, Quantity("1.00000000"), ) self.strategy.submit_order(order) def test_execute_command(self): order = self.strategy.order_factory.market( BTCUSDT_BINANCE.symbol, OrderSide.BUY, Quantity("1.00000000"), ) command = SubmitOrder( order.symbol.venue, self.trader_id, self.account_id, self.strategy.id, PositionId.null(), order, self.uuid_factory.generate(), self.clock.utc_now(), ) def execute_command(): self.exec_engine.execute(command) PerformanceHarness.profile_function(execute_command, 10000, 1) # ~0.0ms / ~0.3μs / 253ns minimum of 10,000 runs @ 1 iteration each run. def test_submit_order(self): self.exec_engine.start() time.sleep(0.1) async def run_test(): def submit_order(): order = self.strategy.order_factory.market( BTCUSDT_BINANCE.symbol, OrderSide.BUY, Quantity("1.00000000"), ) self.strategy.submit_order(order) PerformanceHarness.profile_function(submit_order, 10000, 1) self.loop.run_until_complete(run_test()) # ~0.0ms / ~32.3μs / 32260ns minimum of 10,000 runs @ 1 iteration each run. def test_submit_order_end_to_end(self): self.exec_engine.start() time.sleep(0.1) async def run_test(): for _ in range(10000): order = self.strategy.order_factory.market( BTCUSDT_BINANCE.symbol, OrderSide.BUY, Quantity("1.00000000"), ) self.strategy.submit_order(order) stats_file = "perf_live_execution.prof" cProfile.runctx("self.loop.run_until_complete(run_test())", globals(), locals(), stats_file) s = pstats.Stats(stats_file) s.strip_dirs().sort_stats("time").print_stats()
class ExecutionCacheTests(unittest.TestCase): 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_cache_accounts_with_no_accounts(self): # Arrange # Act self.cache.cache_accounts() # Assert self.assertTrue(True) # No exception raised def test_cache_orders_with_no_orders(self): # Arrange # Act self.cache.cache_orders() # Assert self.assertTrue(True) # No exception raised def test_cache_positions_with_no_positions(self): # Arrange # Act self.cache.cache_positions() # Assert self.assertTrue(True) # No exception raised def test_build_index_with_no_objects(self): # Arrange # Act self.cache.build_index() # Assert self.assertTrue(True) # No exception raised def test_add_account(self): # Arrange initial = TestStubs.event_account_state() account = Account(initial) # Act self.cache.add_account(account) # Assert self.assertEqual(account, self.cache.load_account(account.id)) def test_load_account(self): # Arrange initial = TestStubs.event_account_state() account = Account(initial) self.cache.add_account(account) # Act result = self.cache.load_account(account.id) # Assert self.assertEqual(account, result) def test_account_for_venue(self): # Arrange # Act result = self.cache.account_for_venue(Venue("SIM")) # Assert self.assertIsNone(result) def test_accounts_when_no_accounts_returns_empty_list(self): # Arrange # Act result = self.cache.accounts() # Assert self.assertEqual([], result) def test_get_strategy_ids_with_no_ids_returns_empty_set(self): # Arrange # Act result = self.cache.strategy_ids() # Assert self.assertEqual(set(), result) def test_get_order_ids_with_no_ids_returns_empty_set(self): # Arrange # Act result = self.cache.order_ids() # Assert self.assertEqual(set(), result) def test_get_strategy_ids_with_id_returns_correct_set(self): # Arrange self.cache.update_strategy(self.strategy) # Act result = self.cache.strategy_ids() # Assert self.assertEqual({self.strategy.id}, result) def test_position_exists_when_no_position_returns_false(self): # Arrange # Act # Assert self.assertFalse(self.cache.position_exists(PositionId("P-123456"))) def test_order_exists_when_no_order_returns_false(self): # Arrange # Act # Assert self.assertFalse(self.cache.order_exists(ClientOrderId("O-123456"))) def test_position_when_no_position_returns_none(self): # Arrange position_id = PositionId("P-123456") # Act result = self.cache.position(position_id) # Assert self.assertIsNone(result) def test_order_when_no_order_returns_none(self): # Arrange order_id = ClientOrderId("O-201908080101-000-001") # Act result = self.cache.order(order_id) # Assert self.assertIsNone(result) def test_strategy_id_for_position_when_no_strategy_registered_returns_none( self): # Arrange # Act # Assert self.assertIsNone( self.cache.strategy_id_for_position(PositionId("P-123456"))) def test_add_order(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) position_id = PositionId('P-1') # Act self.cache.add_order(order, position_id) # Assert self.assertIn(order.cl_ord_id, self.cache.order_ids()) self.assertIn(order.cl_ord_id, self.cache.order_ids(instrument_id=order.instrument_id)) self.assertIn(order.cl_ord_id, self.cache.order_ids(strategy_id=self.strategy.id)) self.assertNotIn( order.cl_ord_id, self.cache.order_ids(strategy_id=StrategyId("S", "ZX1"))) self.assertIn( order.cl_ord_id, self.cache.order_ids(instrument_id=order.instrument_id, strategy_id=self.strategy.id)) self.assertIn(order, self.cache.orders()) self.assertEqual(OrderId.null(), self.cache.order_id(order.cl_ord_id)) self.assertIsNone(self.cache.cl_ord_id(order.id)) def test_load_order(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) position_id = PositionId('P-1') self.cache.add_order(order, position_id) # Act result = self.cache.load_order(order.cl_ord_id) # Assert self.assertEqual(order, result) def test_add_position(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) position_id = PositionId('P-1') self.cache.add_order(order, position_id) order_filled = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=PositionId('P-1'), fill_price=Price("1.00000"), ) position = Position(order_filled) # Act self.cache.add_position(position) # Assert self.assertTrue(self.cache.position_exists(position.id)) self.assertIn(position.id, self.cache.position_ids()) self.assertIn(position, self.cache.positions()) self.assertIn(position, self.cache.positions_open()) self.assertIn( position, self.cache.positions_open(instrument_id=position.instrument_id)) self.assertIn(position, self.cache.positions_open(strategy_id=self.strategy.id)) self.assertIn( position, self.cache.positions_open(instrument_id=position.instrument_id, strategy_id=self.strategy.id)) self.assertNotIn(position, self.cache.positions_closed()) self.assertNotIn( position, self.cache.positions_closed(instrument_id=position.instrument_id)) self.assertNotIn( position, self.cache.positions_closed(strategy_id=self.strategy.id)) self.assertNotIn( position, self.cache.positions_closed(instrument_id=position.instrument_id, strategy_id=self.strategy.id)) def test_load_position(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) position_id = PositionId('P-1') self.cache.add_order(order, position_id) order_filled = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=PositionId('P-1'), fill_price=Price("1.00000"), ) position = Position(order_filled) self.cache.add_position(position) # Act result = self.cache.load_position(position.id) # Assert self.assertEqual(position, result) def test_update_order_for_accepted_order(self): # Arrange order = self.strategy.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) position_id = PositionId('P-1') self.cache.add_order(order, position_id) order.apply(TestStubs.event_order_submitted(order)) self.cache.update_order(order) order.apply(TestStubs.event_order_accepted(order)) # Act self.cache.update_order(order) # Assert self.assertTrue(self.cache.order_exists(order.cl_ord_id)) self.assertIn(order.cl_ord_id, self.cache.order_ids()) self.assertIn(order, self.cache.orders()) self.assertIn(order, self.cache.orders_working()) self.assertIn( order, self.cache.orders_working(instrument_id=order.instrument_id)) self.assertIn(order, self.cache.orders_working(strategy_id=self.strategy.id)) self.assertIn( order, self.cache.orders_working(instrument_id=order.instrument_id, strategy_id=self.strategy.id)) self.assertNotIn(order, self.cache.orders_completed()) self.assertNotIn( order, self.cache.orders_completed(instrument_id=order.instrument_id)) self.assertNotIn( order, self.cache.orders_completed(strategy_id=self.strategy.id)) self.assertNotIn( order, self.cache.orders_completed(instrument_id=order.instrument_id, strategy_id=self.strategy.id)) self.assertEqual(1, self.cache.orders_working_count()) self.assertEqual(0, self.cache.orders_completed_count()) self.assertEqual(1, self.cache.orders_total_count()) def test_update_order_for_completed_order(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) position_id = PositionId('P-1') self.cache.add_order(order, position_id) order.apply(TestStubs.event_order_submitted(order)) self.cache.update_order(order) order.apply(TestStubs.event_order_accepted(order)) self.cache.update_order(order) order.apply( TestStubs.event_order_filled(order, instrument=AUDUSD_SIM, fill_price=Price("1.00001")), ) # Act self.cache.update_order(order) # Assert self.assertTrue(self.cache.order_exists(order.cl_ord_id)) self.assertIn(order.cl_ord_id, self.cache.order_ids()) self.assertIn(order, self.cache.orders()) self.assertIn(order, self.cache.orders_completed()) self.assertIn( order, self.cache.orders_completed(instrument_id=order.instrument_id)) self.assertIn( order, self.cache.orders_completed(strategy_id=self.strategy.id)) self.assertIn( order, self.cache.orders_completed(instrument_id=order.instrument_id, strategy_id=self.strategy.id)) self.assertNotIn(order, self.cache.orders_working()) self.assertNotIn( order, self.cache.orders_working(instrument_id=order.instrument_id)) self.assertNotIn( order, self.cache.orders_working(strategy_id=self.strategy.id)) self.assertNotIn( order, self.cache.orders_working(instrument_id=order.instrument_id, strategy_id=self.strategy.id)) self.assertEqual(order.id, self.cache.order_id(order.cl_ord_id)) self.assertEqual(0, self.cache.orders_working_count()) self.assertEqual(1, self.cache.orders_completed_count()) self.assertEqual(1, self.cache.orders_total_count()) def test_update_position_for_open_position(self): # Arrange order1 = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) position_id = PositionId('P-1') self.cache.add_order(order1, position_id) order1.apply(TestStubs.event_order_submitted(order1)) self.cache.update_order(order1) order1.apply(TestStubs.event_order_accepted(order1)) self.cache.update_order(order1) order1_filled = TestStubs.event_order_filled( order1, instrument=AUDUSD_SIM, position_id=PositionId('P-1'), fill_price=Price("1.00001"), ) position = Position(order1_filled) # Act self.cache.add_position(position) # Assert self.assertTrue(self.cache.position_exists(position.id)) self.assertIn(position.id, self.cache.position_ids()) self.assertIn(position, self.cache.positions()) self.assertIn(position, self.cache.positions_open()) self.assertIn( position, self.cache.positions_open(instrument_id=position.instrument_id)) self.assertIn(position, self.cache.positions_open(strategy_id=self.strategy.id)) self.assertIn( position, self.cache.positions_open(instrument_id=position.instrument_id, strategy_id=self.strategy.id)) self.assertNotIn(position, self.cache.positions_closed()) self.assertNotIn( position, self.cache.positions_closed(instrument_id=position.instrument_id)) self.assertNotIn( position, self.cache.positions_closed(strategy_id=self.strategy.id)) self.assertNotIn( position, self.cache.positions_closed(instrument_id=position.instrument_id, strategy_id=self.strategy.id)) self.assertEqual(position, self.cache.position(position_id)) self.assertEqual(1, self.cache.positions_open_count()) self.assertEqual(0, self.cache.positions_closed_count()) self.assertEqual(1, self.cache.positions_total_count()) def test_update_position_for_closed_position(self): # Arrange order1 = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) position_id = PositionId('P-1') self.cache.add_order(order1, position_id) order1.apply(TestStubs.event_order_submitted(order1)) self.cache.update_order(order1) order1.apply(TestStubs.event_order_accepted(order1)) self.cache.update_order(order1) order1_filled = TestStubs.event_order_filled( order1, instrument=AUDUSD_SIM, position_id=PositionId('P-1'), fill_price=Price("1.00001"), ) position = Position(order1_filled) self.cache.add_position(position) order2 = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.SELL, Quantity(100000), ) order2.apply(TestStubs.event_order_submitted(order2)) self.cache.update_order(order2) order2.apply(TestStubs.event_order_accepted(order2)) self.cache.update_order(order2) order2_filled = TestStubs.event_order_filled( order2, instrument=AUDUSD_SIM, position_id=PositionId('P-1'), fill_price=Price("1.00001"), ) position.apply(order2_filled) # Act self.cache.update_position(position) # Assert self.assertTrue(self.cache.position_exists(position.id)) self.assertIn(position.id, self.cache.position_ids()) self.assertIn(position, self.cache.positions()) self.assertIn(position, self.cache.positions_closed()) self.assertIn( position, self.cache.positions_closed(instrument_id=position.instrument_id)) self.assertIn( position, self.cache.positions_closed(strategy_id=self.strategy.id)) self.assertIn( position, self.cache.positions_closed(instrument_id=position.instrument_id, strategy_id=self.strategy.id)) self.assertNotIn(position, self.cache.positions_open()) self.assertNotIn( position, self.cache.positions_open(instrument_id=position.instrument_id)) self.assertNotIn( position, self.cache.positions_open(strategy_id=self.strategy.id)) self.assertNotIn( position, self.cache.positions_open(instrument_id=position.instrument_id, strategy_id=self.strategy.id)) self.assertEqual(position, self.cache.position(position_id)) self.assertEqual(0, self.cache.positions_open_count()) self.assertEqual(1, self.cache.positions_closed_count()) self.assertEqual(1, self.cache.positions_total_count()) def test_update_account(self): # Arrange event = TestStubs.event_account_state() account = Account(event) self.cache.add_account(account) # Act self.cache.update_account(account) # Assert self.assertTrue(True) # No exceptions raised def test_delete_strategy(self): # Arrange self.cache.update_strategy(self.strategy) # Act self.cache.delete_strategy(self.strategy) # Assert self.assertNotIn(self.strategy.id, self.cache.strategy_ids()) def test_check_residuals(self): # Arrange order1 = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) position1_id = PositionId('P-1') self.cache.add_order(order1, position1_id) order1.apply(TestStubs.event_order_submitted(order1)) self.cache.update_order(order1) order1.apply(TestStubs.event_order_accepted(order1)) self.cache.update_order(order1) order1_filled = TestStubs.event_order_filled( order1, instrument=AUDUSD_SIM, position_id=position1_id, fill_price=Price("1.00000"), ) position1 = Position(order1_filled) self.cache.update_order(order1) self.cache.add_position(position1) order2 = self.strategy.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.0000"), ) position2_id = PositionId('P-2') self.cache.add_order(order2, position2_id) order2.apply(TestStubs.event_order_submitted(order2)) self.cache.update_order(order2) order2.apply(TestStubs.event_order_accepted(order2)) self.cache.update_order(order2) # Act self.cache.check_residuals() # Assert self.assertTrue(True) # No exception raised def test_reset(self): # Arrange order1 = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) position1_id = PositionId('P-1') self.cache.add_order(order1, position1_id) order1.apply(TestStubs.event_order_submitted(order1)) self.cache.update_order(order1) order1.apply(TestStubs.event_order_accepted(order1)) self.cache.update_order(order1) order1_filled = TestStubs.event_order_filled( order1, instrument=AUDUSD_SIM, position_id=position1_id, fill_price=Price("1.00000"), ) position1 = Position(order1_filled) self.cache.update_order(order1) self.cache.add_position(position1) order2 = self.strategy.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) position2_id = PositionId('P-2') self.cache.add_order(order2, position2_id) order2.apply(TestStubs.event_order_submitted(order2)) self.cache.update_order(order2) order2.apply(TestStubs.event_order_accepted(order2)) self.cache.update_order(order2) self.cache.update_order(order2) # Act self.cache.reset() # Assert self.assertEqual(0, len(self.cache.strategy_ids())) self.assertEqual(0, self.cache.orders_total_count()) self.assertEqual(0, self.cache.positions_total_count()) def test_flush_db(self): # Arrange order1 = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) position1_id = PositionId('P-1') self.cache.add_order(order1, position1_id) order1.apply(TestStubs.event_order_submitted(order1)) self.cache.update_order(order1) order1.apply(TestStubs.event_order_accepted(order1)) self.cache.update_order(order1) order1_filled = TestStubs.event_order_filled( order1, instrument=AUDUSD_SIM, position_id=position1_id, fill_price=Price("1.00000"), ) position1 = Position(order1_filled) self.cache.update_order(order1) self.cache.add_position(position1) order2 = self.strategy.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) position2_id = PositionId('P-2') self.cache.add_order(order2, position2_id) order2.apply(TestStubs.event_order_submitted(order2)) self.cache.update_order(order2) order2.apply(TestStubs.event_order_accepted(order2)) self.cache.update_order(order2) # Act self.cache.reset() self.cache.flush_db() # Assert self.assertTrue(True) # No exception raised
def test_multiple_strategy_positions_one_active_one_closed(self): # Arrange self.exec_engine.start() strategy1 = TradingStrategy(order_id_tag="001") strategy1.register_trader( TraderId("TESTER", "000"), self.clock, self.logger, ) strategy2 = TradingStrategy(order_id_tag="002") strategy2.register_trader( TraderId("TESTER", "000"), self.clock, self.logger, ) self.exec_engine.register_strategy(strategy1) self.exec_engine.register_strategy(strategy2) order1 = strategy1.order_factory.stop_market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) order2 = strategy1.order_factory.stop_market( AUDUSD_SIM.symbol, OrderSide.SELL, Quantity(100000), Price("1.00000"), ) order3 = strategy2.order_factory.stop_market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) submit_order1 = SubmitOrder( self.venue, self.trader_id, self.account_id, strategy1.id, PositionId.null(), order1, self.uuid_factory.generate(), self.clock.utc_now(), ) position_id1 = PositionId('P-1') submit_order2 = SubmitOrder( self.venue, self.trader_id, self.account_id, strategy1.id, position_id1, order2, self.uuid_factory.generate(), self.clock.utc_now(), ) submit_order3 = SubmitOrder( self.venue, self.trader_id, self.account_id, strategy2.id, PositionId.null(), order3, self.uuid_factory.generate(), self.clock.utc_now(), ) position_id2 = PositionId('P-2') # Act self.exec_engine.execute(submit_order1) self.exec_engine.process(TestStubs.event_order_submitted(order1)) self.exec_engine.process(TestStubs.event_order_accepted(order1)) self.exec_engine.process(TestStubs.event_order_filled(order1, AUDUSD_SIM, position_id1)) self.exec_engine.execute(submit_order2) self.exec_engine.process(TestStubs.event_order_submitted(order2)) self.exec_engine.process(TestStubs.event_order_accepted(order2)) self.exec_engine.process(TestStubs.event_order_filled(order2, AUDUSD_SIM, position_id1)) self.exec_engine.execute(submit_order3) self.exec_engine.process(TestStubs.event_order_submitted(order3)) self.exec_engine.process(TestStubs.event_order_accepted(order3)) self.exec_engine.process(TestStubs.event_order_filled(order3, AUDUSD_SIM, position_id2)) # Assert # Already tested .is_position_active and .is_position_closed above self.assertTrue(self.cache.position_exists(position_id1)) self.assertTrue(self.cache.position_exists(position_id2)) self.assertIn(position_id1, self.cache.position_ids(strategy_id=strategy1.id)) self.assertIn(position_id2, self.cache.position_ids(strategy_id=strategy2.id)) self.assertIn(position_id1, self.cache.position_ids()) self.assertIn(position_id2, self.cache.position_ids()) self.assertEqual(0, len(self.cache.positions_open(strategy_id=strategy1.id))) self.assertEqual(1, len(self.cache.positions_open(strategy_id=strategy2.id))) self.assertEqual(1, len(self.cache.positions_open())) self.assertEqual(1, len(self.cache.positions_closed())) self.assertEqual(2, len(self.cache.positions())) self.assertNotIn(position_id1, self.cache.position_open_ids(strategy_id=strategy1.id)) self.assertIn(position_id2, self.cache.position_open_ids(strategy_id=strategy2.id)) self.assertNotIn(position_id1, self.cache.position_open_ids()) self.assertIn(position_id2, self.cache.position_open_ids()) self.assertIn(position_id1, self.cache.position_closed_ids(strategy_id=strategy1.id)) self.assertNotIn(position_id2, self.cache.position_closed_ids(strategy_id=strategy2.id)) self.assertIn(position_id1, self.cache.position_closed_ids()) self.assertNotIn(position_id2, self.cache.position_closed_ids()) self.assertEqual(2, self.cache.positions_total_count()) self.assertEqual(1, self.cache.positions_open_count()) self.assertEqual(1, self.cache.positions_closed_count())
def test_flip_position_on_opposite_filled_same_position_buy(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) order1 = strategy.order_factory.market( AUDUSD_SIM.symbol, OrderSide.SELL, Quantity(100000), ) order2 = strategy.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(150000), ) submit_order1 = SubmitOrder( self.venue, self.trader_id, self.account_id, strategy.id, PositionId.null(), order1, self.uuid_factory.generate(), self.clock.utc_now(), ) position_id = PositionId("P-000-AUD/USD.SIM-1") self.exec_engine.execute(submit_order1) self.exec_engine.process(TestStubs.event_order_submitted(order1)) self.exec_engine.process(TestStubs.event_order_accepted(order1)) self.exec_engine.process(TestStubs.event_order_filled(order1, AUDUSD_SIM, position_id)) submit_order2 = SubmitOrder( self.venue, self.trader_id, self.account_id, strategy.id, position_id, order2, self.uuid_factory.generate(), self.clock.utc_now(), ) # Act self.exec_engine.execute(submit_order2) self.exec_engine.process(TestStubs.event_order_submitted(order2)) self.exec_engine.process(TestStubs.event_order_accepted(order2)) self.exec_engine.process(TestStubs.event_order_filled(order2, AUDUSD_SIM, position_id)) # Assert position_id_flipped = PositionId("P-000-AUD/USD.SIM-1F") position_flipped = self.cache.position(position_id_flipped) self.assertEqual(50000, position_flipped.relative_quantity) self.assertEqual(50000, position_flipped.last_event.fill_qty) self.assertEqual(150000, position_flipped.last_event.cum_qty) self.assertEqual(0, position_flipped.last_event.leaves_qty) self.assertEqual(Quantity(100000), self.cache.order(order1.cl_ord_id).last_event.cum_qty) self.assertEqual(0, self.cache.order(order1.cl_ord_id).last_event.leaves_qty) self.assertTrue(self.cache.position_exists(position_id)) self.assertTrue(self.cache.position_exists(position_id_flipped)) self.assertTrue(self.cache.is_position_closed(position_id)) self.assertTrue(self.cache.is_position_open(position_id_flipped)) self.assertIn(position_id, self.cache.position_ids()) self.assertIn(position_id, self.cache.position_ids(strategy_id=strategy.id)) self.assertIn(position_id_flipped, self.cache.position_ids()) self.assertIn(position_id_flipped, self.cache.position_ids(strategy_id=strategy.id)) self.assertEqual(2, self.cache.positions_total_count()) self.assertEqual(1, self.cache.positions_open_count()) self.assertEqual(1, self.cache.positions_closed_count())
def test_add_to_existing_position_on_order_fill(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) order1 = strategy.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) order2 = strategy.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) submit_order1 = SubmitOrder( self.venue, self.trader_id, self.account_id, strategy.id, PositionId.null(), order1, self.uuid_factory.generate(), self.clock.utc_now(), ) self.exec_engine.execute(submit_order1) self.exec_engine.process(TestStubs.event_order_submitted(order1)) self.exec_engine.process(TestStubs.event_order_accepted(order1)) self.exec_engine.process(TestStubs.event_order_filled(order1, AUDUSD_SIM)) expected_position_id = PositionId("O-19700101-000000-000-001-1") # Stubbed from order id? submit_order2 = SubmitOrder( self.venue, self.trader_id, self.account_id, strategy.id, expected_position_id, order2, self.uuid_factory.generate(), self.clock.utc_now(), ) # Act self.exec_engine.execute(submit_order2) self.exec_engine.process(TestStubs.event_order_submitted(order2)) self.exec_engine.process(TestStubs.event_order_accepted(order2)) self.exec_engine.process(TestStubs.event_order_filled(order2, AUDUSD_SIM, expected_position_id)) # Assert self.assertTrue(self.cache.position_exists(TestStubs.event_order_filled(order1, AUDUSD_SIM,).position_id)) self.assertTrue(self.cache.is_position_open(expected_position_id)) self.assertFalse(self.cache.is_position_closed(expected_position_id)) self.assertEqual(Position, type(self.cache.position(expected_position_id))) self.assertEqual(0, len(self.cache.positions_closed(strategy_id=strategy.id))) self.assertEqual(0, len(self.cache.positions_closed())) self.assertEqual(1, len(self.cache.positions_open(strategy_id=strategy.id))) self.assertEqual(1, len(self.cache.positions_open())) self.assertEqual(1, self.cache.positions_total_count()) self.assertEqual(1, self.cache.positions_open_count()) self.assertEqual(0, self.cache.positions_closed_count())
def test_close_position_on_order_fill(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) order1 = strategy.order_factory.stop_market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) order2 = strategy.order_factory.stop_market( AUDUSD_SIM.symbol, OrderSide.SELL, Quantity(100000), Price("1.00000"), ) submit_order1 = SubmitOrder( self.venue, self.trader_id, self.account_id, strategy.id, PositionId.null(), order1, self.uuid_factory.generate(), self.clock.utc_now(), ) position_id = PositionId("P-1") self.exec_engine.execute(submit_order1) self.exec_engine.process(TestStubs.event_order_submitted(order1)) self.exec_engine.process(TestStubs.event_order_accepted(order1)) self.exec_engine.process(TestStubs.event_order_filled(order1, AUDUSD_SIM, position_id)) submit_order2 = SubmitOrder( self.venue, self.trader_id, self.account_id, strategy.id, position_id, order2, self.uuid_factory.generate(), self.clock.utc_now(), ) # Act self.exec_engine.execute(submit_order2) self.exec_engine.process(TestStubs.event_order_submitted(order2)) self.exec_engine.process(TestStubs.event_order_accepted(order2)) self.exec_engine.process(TestStubs.event_order_filled(order2, AUDUSD_SIM, position_id)) # # Assert self.assertTrue(self.cache.position_exists(position_id)) self.assertFalse(self.cache.is_position_open(position_id)) self.assertTrue(self.cache.is_position_closed(position_id)) self.assertEqual(position_id, self.cache.position(position_id).id) self.assertEqual(position_id, self.cache.positions(strategy_id=strategy.id)[0].id) self.assertEqual(position_id, self.cache.positions()[0].id) self.assertEqual(0, len(self.cache.positions_open(strategy_id=strategy.id))) self.assertEqual(0, len(self.cache.positions_open())) self.assertEqual(position_id, self.cache.positions_closed(strategy_id=strategy.id)[0].id) self.assertEqual(position_id, self.cache.positions_closed()[0].id) self.assertNotIn(position_id, self.cache.position_open_ids(strategy_id=strategy.id)) self.assertNotIn(position_id, self.cache.position_open_ids()) self.assertEqual(1, self.cache.positions_total_count()) self.assertEqual(0, self.cache.positions_open_count()) self.assertEqual(1, self.cache.positions_closed_count())
def test_flip_position_on_opposite_filled_same_position(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) order1 = strategy.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), ) order2 = strategy.order_factory.market( AUDUSD_FXCM, OrderSide.SELL, Quantity(150000), ) submit_order1 = SubmitOrder( self.venue, self.trader_id, self.account_id, strategy.id, PositionId.py_null(), order1, self.uuid_factory.generate(), self.clock.utc_now(), ) position_id = PositionId("P-000-AUD/USD.FXCM-1") self.exec_engine.execute(submit_order1) self.exec_engine.process(TestStubs.event_order_submitted(order1)) self.exec_engine.process(TestStubs.event_order_accepted(order1)) self.exec_engine.process( TestStubs.event_order_filled(order1, position_id)) submit_order2 = SubmitOrder( self.venue, self.trader_id, self.account_id, strategy.id, position_id, order2, self.uuid_factory.generate(), self.clock.utc_now(), ) # Act self.exec_engine.execute(submit_order2) self.exec_engine.process(TestStubs.event_order_submitted(order2)) self.exec_engine.process(TestStubs.event_order_accepted(order2)) self.exec_engine.process( TestStubs.event_order_filled(order2, position_id)) position_id_flipped = PositionId("P-000-AUD/USD.FXCM-1F") order_id_flipped = ClientOrderId(order2.cl_ord_id.value + 'F') # Assert self.assertTrue(self.cache.position_exists(position_id)) self.assertTrue(self.cache.position_exists(position_id_flipped)) self.assertTrue(self.cache.is_position_closed(position_id)) self.assertTrue(self.cache.is_position_open(position_id_flipped)) self.assertFalse(self.cache.is_flat(strategy_id=strategy.id)) self.assertTrue(position_id in self.cache.position_ids()) self.assertTrue(position_id in self.cache.position_ids( strategy_id=strategy.id)) self.assertTrue(position_id_flipped in self.cache.position_ids()) self.assertTrue(position_id_flipped in self.cache.position_ids( strategy_id=strategy.id)) self.assertTrue(order_id_flipped, self.cache.position_exists_for_order(order_id_flipped)) self.assertEqual(2, self.cache.positions_total_count()) self.assertEqual(1, self.cache.positions_open_count()) self.assertEqual(1, self.cache.positions_closed_count())
def test_multiple_strategy_positions_opened(self): # Arrange strategy1 = TradingStrategy(order_id_tag="001") strategy1.register_trader( TraderId("TESTER", "000"), clock=self.clock, uuid_factory=TestUUIDFactory(), logger=self.logger, ) strategy2 = TradingStrategy(order_id_tag="002") strategy2.register_trader( TraderId("TESTER", "000"), clock=self.clock, uuid_factory=TestUUIDFactory(), logger=self.logger, ) self.exec_engine.register_strategy(strategy1) self.exec_engine.register_strategy(strategy2) order1 = strategy1.order_factory.stop( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) order2 = strategy2.order_factory.stop( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) submit_order1 = SubmitOrder( self.venue, self.trader_id, self.account_id, strategy1.id, PositionId.py_null(), order1, self.uuid_factory.generate(), self.clock.utc_now(), ) submit_order2 = SubmitOrder( self.venue, self.trader_id, self.account_id, strategy2.id, PositionId.py_null(), order2, self.uuid_factory.generate(), self.clock.utc_now(), ) position1_id = PositionId('P-1') position2_id = PositionId('P-2') # Act self.exec_engine.execute(submit_order1) self.exec_engine.execute(submit_order2) self.exec_engine.process(TestStubs.event_order_submitted(order1)) self.exec_engine.process(TestStubs.event_order_accepted(order1)) self.exec_engine.process( TestStubs.event_order_filled(order1, position1_id)) self.exec_engine.process(TestStubs.event_order_submitted(order2)) self.exec_engine.process(TestStubs.event_order_accepted(order2)) self.exec_engine.process( TestStubs.event_order_filled(order2, position2_id)) # Assert self.assertTrue(self.cache.position_exists(position1_id)) self.assertTrue(self.cache.position_exists(position2_id)) self.assertTrue(self.cache.is_position_open(position1_id)) self.assertTrue(self.cache.is_position_open(position2_id)) self.assertFalse(self.cache.is_position_closed(position1_id)) self.assertFalse(self.cache.is_position_closed(position2_id)) self.assertFalse(self.cache.is_flat(strategy_id=strategy1.id)) self.assertFalse(self.cache.is_flat(strategy_id=strategy2.id)) self.assertFalse(self.cache.is_flat()) self.assertEqual(Position, type(self.cache.position(position1_id))) self.assertEqual(Position, type(self.cache.position(position2_id))) self.assertTrue(position1_id in self.cache.position_ids( strategy_id=strategy1.id)) self.assertTrue(position2_id in self.cache.position_ids( strategy_id=strategy2.id)) self.assertTrue(position1_id in self.cache.position_ids()) self.assertTrue(position2_id in self.cache.position_ids()) self.assertEqual(2, len(self.cache.position_open_ids())) self.assertEqual( 1, len(self.cache.positions_open(strategy_id=strategy1.id))) self.assertEqual( 1, len(self.cache.positions_open(strategy_id=strategy2.id))) self.assertEqual( 1, len(self.cache.positions_open(strategy_id=strategy2.id))) self.assertEqual(2, len(self.cache.positions_open())) self.assertEqual( 1, len(self.cache.positions_open(strategy_id=strategy1.id))) self.assertEqual( 1, len(self.cache.positions_open(strategy_id=strategy2.id))) self.assertTrue(position1_id in self.cache.position_open_ids( strategy_id=strategy1.id)) self.assertTrue(position2_id in self.cache.position_open_ids( strategy_id=strategy2.id)) self.assertTrue(position1_id in self.cache.position_open_ids()) self.assertTrue(position2_id in self.cache.position_open_ids()) self.assertTrue(position1_id not in self.cache.position_closed_ids( strategy_id=strategy1.id)) self.assertTrue(position2_id not in self.cache.position_closed_ids( strategy_id=strategy2.id)) self.assertTrue(position1_id not in self.cache.position_closed_ids()) self.assertTrue(position2_id not in self.cache.position_closed_ids()) self.assertEqual(2, self.cache.positions_total_count()) self.assertEqual(2, self.cache.positions_open_count()) self.assertEqual(0, self.cache.positions_closed_count())
def test_handle_order_fill_event(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) order = strategy.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), ) submit_order = SubmitOrder( self.venue, self.trader_id, self.account_id, strategy.id, PositionId.py_null(), order, self.uuid_factory.generate(), self.clock.utc_now(), ) self.exec_engine.execute(submit_order) # Act self.exec_engine.process(TestStubs.event_order_submitted(order)) self.exec_engine.process(TestStubs.event_order_accepted(order)) self.exec_engine.process(TestStubs.event_order_filled(order)) expected_position_id = PositionId( "O-19700101-000000-000-001-1") # Stubbed from order id? # Assert self.assertTrue(self.cache.position_exists(expected_position_id)) self.assertTrue(self.cache.is_position_open(expected_position_id)) self.assertFalse(self.cache.is_position_closed(expected_position_id)) self.assertFalse( self.exec_engine.cache.is_flat(strategy_id=strategy.id)) self.assertFalse(self.exec_engine.cache.is_flat()) self.assertEqual(Position, type(self.cache.position(expected_position_id))) self.assertTrue(expected_position_id in self.cache.position_ids()) self.assertTrue( expected_position_id not in self.cache.position_closed_ids( strategy_id=strategy.id)) self.assertTrue( expected_position_id not in self.cache.position_closed_ids()) self.assertTrue(expected_position_id in self.cache.position_open_ids( strategy_id=strategy.id)) self.assertTrue(expected_position_id in self.cache.position_open_ids()) self.assertEqual(1, self.cache.positions_total_count()) self.assertEqual(1, self.cache.positions_open_count()) self.assertEqual(0, self.cache.positions_closed_count()) self.assertTrue(self.cache.position_exists_for_order(order.cl_ord_id))
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) order = strategy.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) submit_order = SubmitOrder( AUDUSD_SIM.id.venue.client_id, self.trader_id, self.account_id, strategy.id, PositionId.null(), order, self.uuid_factory.generate(), self.clock.timestamp_ns(), ) self.engine.execute(submit_order) self.engine.process(TestStubs.event_order_submitted(order)) self.engine.process(TestStubs.event_order_accepted(order)) report = OrderStatusReport( client_order_id=order.client_order_id, venue_order_id=VenueOrderId("1"), # <-- from stub event order_state=OrderState.FILLED, filled_qty=Quantity(100000), timestamp_ns=0, ) trade1 = ExecutionReport( execution_id=ExecutionId("1"), client_order_id=order.client_order_id, venue_order_id=VenueOrderId("1"), last_qty=Decimal(50000), last_px=Decimal("1.00000"), commission_amount=Decimal("5.0"), commission_currency="USD", liquidity_side=LiquiditySide.MAKER, execution_ns=0, timestamp_ns=0, ) trade2 = ExecutionReport( execution_id=ExecutionId("2"), client_order_id=order.client_order_id, venue_order_id=VenueOrderId("1"), last_qty=Decimal(50000), last_px=Decimal("1.00000"), commission_amount=Decimal("2.0"), commission_currency="USD", liquidity_side=LiquiditySide.MAKER, execution_ns=0, timestamp_ns=0, ) self.client.add_order_status_report(report) self.client.add_trades_list(VenueOrderId("1"), [trade1, trade2]) await asyncio.sleep(0.01) # Act result = await self.engine.reconcile_state() self.engine.stop() # Assert assert result
class TestRedisExecutionDatabase: def setup(self): # Fixture Setup self.clock = TestClock() self.logger = Logger(self.clock) self.trader_id = TraderId("TESTER-000") self.strategy = TradingStrategy(order_id_tag="001") self.strategy.register_trader(self.trader_id, self.clock, self.logger) config = { "host": "localhost", "port": 6379, } self.database = RedisCacheDatabase( trader_id=self.trader_id, logger=self.logger, instrument_serializer=MsgPackInstrumentSerializer(), command_serializer=MsgPackCommandSerializer(), event_serializer=MsgPackEventSerializer(), config=config, ) self.test_redis = redis.Redis(host="localhost", port=6379, db=0) def teardown(self): # Tests will start failing if redis is not flushed on tear down self.test_redis.flushall( ) # Comment this line out to preserve data between tests def test_add_currency(self): # Arrange currency = Currency( code="1INCH", precision=8, iso4217=0, name="1INCH", currency_type=CurrencyType.CRYPTO, ) # Act self.database.add_currency(currency) # Assert assert self.database.load_currency(currency.code) == currency def test_add_account(self): # Arrange event = TestStubs.event_account_state() account = Account(event) # Act self.database.add_account(account) # Assert assert self.database.load_account(account.id) == account def test_add_instrument(self): # Arrange, Act self.database.add_instrument(AUDUSD_SIM) # Assert assert self.database.load_instrument(AUDUSD_SIM.id) == AUDUSD_SIM def test_add_order(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) # Act self.database.add_order(order) # Assert assert self.database.load_order(order.client_order_id) == order def test_add_position(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) self.database.add_instrument(AUDUSD_SIM) self.database.add_order(order) position_id = PositionId("P-1") fill = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=position_id, last_px=Price.from_str("1.00000"), ) position = Position(instrument=AUDUSD_SIM, fill=fill) # Act self.database.add_position(position) # Assert assert self.database.load_position(position.id) == position def test_update_account(self): # Arrange event = TestStubs.event_account_state() account = Account(event) self.database.add_account(account) # Act self.database.update_account(account) # Assert assert self.database.load_account(account.id) == account def test_update_order_for_working_order(self): # Arrange order = self.strategy.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) self.database.add_order(order) order.apply(TestStubs.event_order_submitted(order)) self.database.update_order(order) order.apply(TestStubs.event_order_accepted(order)) # Act self.database.update_order(order) # Assert assert self.database.load_order(order.client_order_id) == order def test_update_order_for_completed_order(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) self.database.add_order(order) order.apply(TestStubs.event_order_submitted(order)) self.database.update_order(order) order.apply(TestStubs.event_order_accepted(order)) self.database.update_order(order) fill = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, last_px=Price.from_str("1.00001"), ) order.apply(fill) # Act self.database.update_order(order) # Assert assert self.database.load_order(order.client_order_id) == order def test_update_position_for_closed_position(self): # Arrange self.database.add_instrument(AUDUSD_SIM) order1 = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) position_id = PositionId("P-1") self.database.add_order(order1) order1.apply(TestStubs.event_order_submitted(order1)) self.database.update_order(order1) order1.apply(TestStubs.event_order_accepted(order1)) self.database.update_order(order1) order1.apply( TestStubs.event_order_filled( order1, instrument=AUDUSD_SIM, position_id=position_id, last_px=Price.from_str("1.00001"), )) self.database.update_order(order1) # Act position = Position(instrument=AUDUSD_SIM, fill=order1.last_event) self.database.add_position(position) order2 = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.SELL, Quantity.from_int(100000), ) self.database.add_order(order2) order2.apply(TestStubs.event_order_submitted(order2)) self.database.update_order(order2) order2.apply(TestStubs.event_order_accepted(order2)) self.database.update_order(order2) filled = TestStubs.event_order_filled( order2, instrument=AUDUSD_SIM, position_id=position_id, last_px=Price.from_str("1.00001"), ) order2.apply(filled) self.database.update_order(order2) position.apply(filled) # Act self.database.update_position(position) # Assert assert self.database.load_position(position.id) == position def test_update_strategy(self): # Arrange strategy = MockStrategy( TestStubs.bartype_btcusdt_binance_100tick_last()) strategy.register_trader(self.trader_id, self.clock, self.logger) # Act self.database.update_strategy(strategy) result = self.database.load_strategy(strategy.id) # Assert assert result == {"UserState": b"1"} def test_load_account_when_no_account_in_database_returns_none(self): # Arrange event = TestStubs.event_account_state() account = Account(event) # Act result = self.database.load_account(account.id) # Assert assert result is None def test_load_account_when_account_in_database_returns_account(self): # Arrange event = TestStubs.event_account_state() account = Account(event) self.database.add_account(account) # Act result = self.database.load_account(account.id) # Assert assert result == account def test_load_order_when_no_order_in_database_returns_none(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) # Act result = self.database.load_order(order.client_order_id) # Assert assert result is None def test_load_order_when_market_order_in_database_returns_order(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) self.database.add_order(order) # Act result = self.database.load_order(order.client_order_id) # Assert assert result == order def test_load_order_when_limit_order_in_database_returns_order(self): # Arrange order = self.strategy.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) self.database.add_order(order) # Act result = self.database.load_order(order.client_order_id) # Assert assert result == order def test_load_order_when_stop_market_order_in_database_returns_order(self): # Arrange order = self.strategy.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) self.database.add_order(order) # Act result = self.database.load_order(order.client_order_id) # Assert assert result == order def test_load_order_when_stop_limit_order_in_database_returns_order(self): # Arrange order = self.strategy.order_factory.stop_limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), price=Price.from_str("1.00000"), trigger=Price.from_str("1.00010"), ) self.database.add_order(order) # Act result = self.database.load_order(order.client_order_id) # Assert assert result == order assert result.price == order.price assert result.trigger == order.trigger def test_load_position_when_no_position_in_database_returns_none(self): # Arrange position_id = PositionId("P-1") # Act result = self.database.load_position(position_id) # Assert assert result is None def test_load_order_when_position_in_database_returns_position(self): # Arrange self.database.add_instrument(AUDUSD_SIM) order = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) self.database.add_order(order) position_id = PositionId("P-1") fill = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=position_id, last_px=Price.from_str("1.00000"), ) position = Position(instrument=AUDUSD_SIM, fill=fill) self.database.add_position(position) # Act result = self.database.load_position(position_id) # Assert assert result == position def test_load_accounts_when_no_accounts_returns_empty_dict(self): # Arrange # Act result = self.database.load_accounts() # Assert assert result == {} def test_load_accounts_cache_when_one_account_in_database(self): # Arrange event = TestStubs.event_account_state() account = Account(event) self.database.add_account(account) # Act # Assert assert self.database.load_accounts() == {account.id: account} def test_load_orders_cache_when_no_orders(self): # Arrange # Act self.database.load_orders() # Assert assert self.database.load_orders() == {} def test_load_orders_cache_when_one_order_in_database(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) self.database.add_order(order) # Act result = self.database.load_orders() # Assert assert result == {order.client_order_id: order} def test_load_positions_cache_when_no_positions(self): # Arrange # Act self.database.load_positions() # Assert assert self.database.load_positions() == {} def test_load_positions_cache_when_one_position_in_database(self): # Arrange self.database.add_instrument(AUDUSD_SIM) order1 = self.strategy.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) self.database.add_order(order1) position_id = PositionId("P-1") order1.apply(TestStubs.event_order_submitted(order1)) order1.apply(TestStubs.event_order_accepted(order1)) order1.apply( TestStubs.event_order_filled( order1, instrument=AUDUSD_SIM, position_id=position_id, last_px=Price.from_str("1.00001"), )) position = Position(instrument=AUDUSD_SIM, fill=order1.last_event) self.database.add_position(position) # Act result = self.database.load_positions() # Assert assert result == {position.id: position} def test_delete_strategy(self): # Arrange # Act self.database.delete_strategy(self.strategy.id) result = self.database.load_strategy(self.strategy.id) # Assert assert result == {} def test_flush(self): # Arrange order1 = self.strategy.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) self.database.add_order(order1) position1_id = PositionId("P-1") fill = TestStubs.event_order_filled( order1, instrument=AUDUSD_SIM, position_id=position1_id, last_px=Price.from_str("1.00000"), ) position1 = Position(instrument=AUDUSD_SIM, fill=fill) self.database.update_order(order1) self.database.add_position(position1) order2 = self.strategy.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), Price.from_str("1.00000"), ) self.database.add_order(order2) order2.apply(TestStubs.event_order_submitted(order2)) order2.apply(TestStubs.event_order_accepted(order2)) self.database.update_order(order2) # Act self.database.flush() # Assert assert self.database.load_order(order1.client_order_id) is None assert self.database.load_order(order2.client_order_id) is None assert self.database.load_position(position1.id) is None