def test_can_close_position_on_order_fill(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() order1 = strategy.order_factory.stop(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00000, 5)) order2 = strategy.order_factory.stop(AUDUSD_FXCM, OrderSide.SELL, Quantity(100000), Price(1.00000, 5)) submit_order1 = SubmitOrder(self.trader_id, self.account_id, strategy.id, position_id, order1, self.guid_factory.generate(), self.clock.time_now()) submit_order2 = SubmitOrder(self.trader_id, self.account_id, strategy.id, position_id, order2, self.guid_factory.generate(), self.clock.time_now()) self.exec_engine.execute_command(submit_order1) self.exec_engine.execute_command(submit_order2) order1_filled = TestStubs.event_order_filled(order1) order2_filled = TestStubs.event_order_filled(order2) # Act self.exec_engine.handle_event(order1_filled) self.exec_engine.handle_event(order2_filled) # # Assert self.assertTrue(self.exec_db.position_exists(position_id)) self.assertFalse(self.exec_db.is_position_open(position_id)) self.assertTrue(self.exec_db.is_position_closed(position_id)) self.assertTrue(self.exec_engine.is_strategy_flat(strategy.id)) self.assertTrue(self.exec_engine.is_flat()) self.assertEqual(position_id, self.exec_db.get_position(position_id).id) self.assertTrue(position_id in self.exec_db.get_positions(strategy.id)) self.assertTrue(position_id in self.exec_db.get_positions()) self.assertEqual(0, len(self.exec_db.get_positions_open(strategy.id))) self.assertEqual(0, len(self.exec_db.get_positions_open())) self.assertTrue( position_id in self.exec_db.get_positions_closed(strategy.id)) self.assertTrue(position_id in self.exec_db.get_positions_closed()) self.assertTrue( position_id not in self.exec_db.get_positions_open(strategy.id)) self.assertTrue(position_id not in self.exec_db.get_positions_open()) self.assertEqual(1, self.exec_db.count_positions_total()) self.assertEqual(0, self.exec_db.count_positions_open()) self.assertEqual(1, self.exec_db.count_positions_closed())
def test_can_change_clock(self): # Arrange clock = TestClock() strategy = TradingStrategy(order_id_tag='001') # Act strategy.change_clock(clock) # Assert self.assertEqual(UNIX_EPOCH, strategy.time_now()) self.assertEqual(PositionId('P-19700101-000000-000-001-1'), strategy.position_id_generator.generate())
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_can_submit_order(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()) # Act self.exec_engine.execute_command(submit_order) # Assert self.assertIn(submit_order, self.exec_client.received_commands) self.assertTrue(self.exec_db.order_exists(order.id)) self.assertEqual(position_id, self.exec_db.get_position_id(order.id))
class InMemoryExecutionDatabaseTests(unittest.TestCase): def setUp(self): # Fixture Setup clock = TestClock() logger = TestLogger() self.trader_id = TraderId('TESTER', '000') self.account_id = TestStubs.account_id() self.strategy = TradingStrategy(order_id_tag='001') self.strategy.change_clock(clock) self.strategy.change_logger(logger) self.database = InMemoryExecutionDatabase(trader_id=self.trader_id, logger=logger) def test_can_add_order(self): # Arrange order = self.strategy.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) position_id = self.strategy.position_id_generator.generate() # Act self.database.add_order(order, self.strategy.id, position_id) # Assert self.assertTrue(order.id in self.database.get_order_ids()) self.assertEqual(order, self.database.get_orders()[order.id]) def test_can_add_position(self): # Arrange order = self.strategy.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) position_id = self.strategy.position_id_generator.generate() self.database.add_order(order, self.strategy.id, position_id) order_filled = TestStubs.event_order_filled(order, fill_price=Price( 1.00000, 5)) position = Position(position_id, order_filled) # Act self.database.add_position(position, self.strategy.id) # Assert self.assertTrue(self.database.position_exists_for_order(order.id)) self.assertTrue(self.database.position_exists(position.id)) self.assertTrue(position.id in self.database.get_position_ids()) self.assertTrue(position.id in self.database.get_positions()) self.assertTrue( position.id in self.database.get_positions_open(self.strategy.id)) self.assertTrue(position.id in self.database.get_positions_open()) self.assertTrue(position.id not in self.database.get_positions_closed( self.strategy.id)) self.assertTrue( position.id not in self.database.get_positions_closed()) def test_can_update_order_for_working_order(self): # Arrange order = self.strategy.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) position_id = self.strategy.position_id_generator.generate() self.database.add_order(order, self.strategy.id, position_id) order_working = TestStubs.event_order_working(order) order.apply(order_working) # Act self.database.update_order(order) # Assert self.assertTrue(self.database.order_exists(order.id)) self.assertTrue(order.id in self.database.get_order_ids()) self.assertTrue(order.id in self.database.get_orders()) self.assertTrue( order.id in self.database.get_orders_working(self.strategy.id)) self.assertTrue(order.id in self.database.get_orders_working()) self.assertTrue(order.id not in self.database.get_orders_completed( self.strategy.id)) self.assertTrue(order.id not in self.database.get_orders_completed()) def test_can_update_order_for_completed_order(self): # Arrange order = self.strategy.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) position_id = self.strategy.position_id_generator.generate() self.database.add_order(order, self.strategy.id, position_id) order_filled = TestStubs.event_order_filled(order, fill_price=Price( 1.00001, 5)) order.apply(order_filled) # Act self.database.update_order(order) # Assert self.assertTrue(self.database.order_exists(order.id)) self.assertTrue(order.id in self.database.get_order_ids()) self.assertTrue(order.id in self.database.get_orders()) self.assertTrue( order.id in self.database.get_orders_completed(self.strategy.id)) self.assertTrue(order.id in self.database.get_orders_completed()) self.assertTrue( order.id not in self.database.get_orders_working(self.strategy.id)) self.assertTrue(order.id not in self.database.get_orders_working()) def test_can_update_position_for_closed_position(self): # Arrange order1 = self.strategy.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) position_id = self.strategy.position_id_generator.generate() self.database.add_order(order1, self.strategy.id, position_id) order1_filled = TestStubs.event_order_filled(order1, fill_price=Price( 1.00001, 5)) order1.apply(order1_filled) position = Position(position_id, order1.last_event) self.database.add_position(position, self.strategy.id) order2 = self.strategy.order_factory.market(AUDUSD_FXCM, OrderSide.SELL, Quantity(100000)) order2_filled = TestStubs.event_order_filled(order2, fill_price=Price( 1.00001, 5)) position.apply(order2_filled) # Act self.database.update_position(position) # Assert self.assertTrue(self.database.position_exists(position.id)) self.assertTrue(position.id in self.database.get_position_ids()) self.assertTrue(position.id in self.database.get_positions()) self.assertTrue(position.id in self.database.get_positions_closed( self.strategy.id)) self.assertTrue(position.id in self.database.get_positions_closed()) self.assertTrue(position.id not in self.database.get_positions_open( self.strategy.id)) self.assertTrue(position.id not in self.database.get_positions_open()) self.assertEqual(position, self.database.get_position_for_order(order1.id)) def test_can_add_account(self): # Arrange event = AccountStateEvent( AccountId.py_from_string('SIMULATED-123456-SIMULATED'), Currency.USD, Money(1000000, Currency.USD), Money(1000000, Currency.USD), Money(0, Currency.USD), Money(0, Currency.USD), Money(0, Currency.USD), Decimal(0), ValidString('N'), GUID(uuid.uuid4()), UNIX_EPOCH) account = Account(event) # Act self.database.add_account(account) # Assert self.assertTrue(True) # Did not raise exception def test_can_update_account(self): # Arrange event = AccountStateEvent( AccountId.py_from_string('SIMULATED-123456-SIMULATED'), Currency.USD, Money(1000000, Currency.USD), Money(1000000, Currency.USD), Money(0, Currency.USD), Money(0, Currency.USD), Money(0, Currency.USD), Decimal(0), ValidString('N'), GUID(uuid.uuid4()), UNIX_EPOCH) account = Account(event) self.database.add_account(account) # Act self.database.update_account(account) # Assert self.assertTrue(True) # Did not raise exception def test_can_delete_strategy(self): # Arrange self.database.update_strategy(self.strategy) # Act self.database.delete_strategy(self.strategy) # Assert self.assertTrue( self.strategy.id not in self.database.get_strategy_ids()) def test_can_check_residuals(self): # Arrange order1 = self.strategy.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) position1_id = self.strategy.position_id_generator.generate() self.database.add_order(order1, self.strategy.id, position1_id) order1_filled = TestStubs.event_order_filled(order1, fill_price=Price( 1.00000, 5)) position1 = Position(position1_id, order1_filled) self.database.update_order(order1) self.database.add_position(position1, self.strategy.id) order2 = self.strategy.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) position2_id = self.strategy.position_id_generator.generate() self.database.add_order(order2, self.strategy.id, position2_id) order2_working = TestStubs.event_order_working(order2) order2.apply(order2_working) self.database.update_order(order2) # Act self.database.check_residuals() # Does not raise exception def test_can_reset(self): # Arrange order1 = self.strategy.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) position1_id = self.strategy.position_id_generator.generate() self.database.add_order(order1, self.strategy.id, position1_id) order1_filled = TestStubs.event_order_filled(order1, fill_price=Price( 1.00000, 5)) position1 = Position(position1_id, order1_filled) self.database.update_order(order1) self.database.add_position(position1, self.strategy.id) order2 = self.strategy.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) position2_id = self.strategy.position_id_generator.generate() self.database.add_order(order2, self.strategy.id, position2_id) order2_working = TestStubs.event_order_working(order2) order2.apply(order2_working) self.database.update_order(order2) # Act self.database.reset() # Assert self.assertEqual(0, len(self.database.get_strategy_ids())) self.assertEqual(0, self.database.count_orders_total()) self.assertEqual(0, self.database.count_positions_total()) def test_can_flush(self): # Arrange order1 = self.strategy.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) position1_id = self.strategy.position_id_generator.generate() self.database.add_order(order1, self.strategy.id, position1_id) order1_filled = TestStubs.event_order_filled(order1, fill_price=Price( 1.00000, 5)) position1 = Position(position1_id, order1_filled) self.database.update_order(order1) self.database.add_position(position1, self.strategy.id) order2 = self.strategy.order_factory.market(AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) position2_id = self.strategy.position_id_generator.generate() self.database.add_order(order2, self.strategy.id, position2_id) order2_working = TestStubs.event_order_working(order2) order2.apply(order2_working) self.database.update_order(order2) # Act self.database.reset() self.database.flush() # Assert # Does not raise exception def test_get_strategy_ids_with_no_ids_returns_empty_set(self): # Arrange # Act result = self.database.get_strategy_ids() # Assert self.assertEqual(set(), result) def test_get_strategy_ids_with_id_returns_correct_set(self): # Arrange self.database.update_strategy(self.strategy) # Act result = self.database.get_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.database.position_exists(PositionId('P-123456'))) def test_order_exists_when_no_order_returns_false(self): # Arrange # Act # Assert self.assertFalse(self.database.order_exists(OrderId('O-123456'))) def test_position_for_order_when_not_found_returns_none(self): # Arrange # Act # Assert self.assertIsNone( self.database.get_position_for_order(OrderId('O-123456'))) def test_position_indexed_for_order_when_no_indexing_returns_false(self): # Arrange # Act # Assert self.assertFalse( self.database.position_indexed_for_order(OrderId('O-123456'))) def test_get_order_when_no_order_returns_none(self): # Arrange position_id = PositionId('P-123456') # Act result = self.database.get_position(position_id) # Assert self.assertIsNone(result) def test_get_position_when_no_position_returns_none(self): # Arrange order_id = OrderId('O-201908080101-000-001') # Act result = self.database.get_order(order_id) # Assert self.assertIsNone(result)