def setUp(self): # Fixture Setup self.venue = Venue("SIM") self.trader_id = TestStubs.trader_id() self.account_id = TestStubs.account_id() self.serializer = MsgPackCommandSerializer() self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=StrategyId("S", "001"), clock=TestClock(), ) self.order = self.order_factory.market( AUDUSD, OrderSide.BUY, Quantity(100000), ) self.command = SubmitOrder( self.venue, self.trader_id, self.account_id, StrategyId("SCALPER", "01"), PositionId("P-123456"), self.order, uuid4(), UNIX_EPOCH, )
def setUp(self): # Fixture Setup self.venue = Venue("SIM") self.trader_id = TestStubs.trader_id() self.account_id = TestStubs.account_id() self.serializer = MsgPackCommandSerializer() self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=StrategyId("S", "001"), clock=TestClock(), )
def 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 setUp(self): # Fixture Setup clock = LiveClock() guid_factory = LiveGuidFactory() logger = LiveLogger() self.context = zmq.Context() self.client_sink = [] self.server_sink = [] self.server = MessageServer( ServerId("Server-001"), TEST_RECV_PORT, TEST_SEND_PORT, MsgPackDictionarySerializer(), MsgPackRequestSerializer(), MsgPackResponseSerializer(), CompressorBypass(), EncryptionSettings(), clock, guid_factory, LoggerAdapter('MessageServer', logger)) # Register test handlers self.server.register_handler(MessageType.STRING, self.server_sink.append) self.server.start() self.command_serializer = MsgPackCommandSerializer() self.server.register_handler(MessageType.COMMAND, self.command_handler) self.client = MessageClient( ClientId("Trader-001"), LOCALHOST, TEST_RECV_PORT, TEST_SEND_PORT, MsgPackDictionarySerializer(), MsgPackRequestSerializer(), MsgPackResponseSerializer(), CompressorBypass(), EncryptionSettings(), clock, guid_factory, LoggerAdapter('MessageClient', logger)) self.client.register_handler(self.client_sink.append)
class SerializationPerformanceTests(unittest.TestCase): def setUp(self): # Fixture Setup self.venue = Venue("SIM") self.trader_id = TestStubs.trader_id() self.account_id = TestStubs.account_id() self.serializer = MsgPackCommandSerializer() self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=StrategyId("S", "001"), clock=TestClock(), ) self.order = self.order_factory.market( AUDUSD, OrderSide.BUY, Quantity(100000), ) self.command = SubmitOrder( self.venue, self.trader_id, self.account_id, StrategyId("SCALPER", "01"), PositionId("P-123456"), self.order, uuid4(), UNIX_EPOCH, ) def serialize_submit_order(self): # Arrange self.serializer.serialize(self.command) def test_make_builtin_uuid(self): PerformanceHarness.profile_function(self.serialize_submit_order, 10000, 1)
def setUp(self): # Fixture Setup clock = TestClock() logger = TestLogger() self.trader_id = TraderId('TESTER', '000') self.strategy = EmptyStrategy(order_id_tag='001') self.strategy.change_clock(clock) self.strategy.change_logger(logger) self.database = RedisExecutionDatabase( trader_id=self.trader_id, host='localhost', port=6379, command_serializer=MsgPackCommandSerializer(), event_serializer=MsgPackEventSerializer(), logger=logger) self.test_redis = redis.Redis(host='localhost', port=6379, db=0)
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 __init__( self, strategies: List[TradingStrategy], config: Dict[str, object], ): """ Initialize a new instance of the TradingNode class. Parameters ---------- strategies : list[TradingStrategy] The list of strategies to run on the trading node. config : dict[str, object] The configuration for the trading node. Raises ------ ValueError If strategies is None or empty. ValueError If config is None or empty. """ PyCondition.not_none(strategies, "strategies") PyCondition.not_none(config, "config") PyCondition.not_empty(strategies, "strategies") PyCondition.not_empty(config, "config") # Extract configs config_trader = config.get("trader", {}) config_log = config.get("logging", {}) config_exec_db = config.get("exec_database", {}) config_strategy = config.get("strategy", {}) config_adapters = config.get("adapters", {}) self._uuid_factory = UUIDFactory() self._loop = asyncio.get_event_loop() self._executor = concurrent.futures.ThreadPoolExecutor() self._loop.set_default_executor(self._executor) self._clock = LiveClock(loop=self._loop) self.created_time = self._clock.utc_now() self._is_running = False # Uncomment for debugging # self._loop.set_debug(True) # Setup identifiers self.trader_id = TraderId( name=config_trader["name"], tag=config_trader["id_tag"], ) # Setup logging self._logger = LiveLogger( clock=self._clock, name=self.trader_id.value, level_console=LogLevelParser.from_str_py(config_log.get("log_level_console")), level_file=LogLevelParser.from_str_py(config_log.get("log_level_file")), level_store=LogLevelParser.from_str_py(config_log.get("log_level_store")), run_in_process=config_log.get("run_in_process", True), # Run logger in a separate process log_thread=config_log.get("log_thread_id", False), log_to_file=config_log.get("log_to_file", False), log_file_path=config_log.get("log_file_path", ""), ) self._log = LoggerAdapter(component_name=self.__class__.__name__, logger=self._logger) self._log_header() self._log.info("Building...") self._setup_loop() # Requires the logger to be initialized self.portfolio = Portfolio( clock=self._clock, logger=self._logger, ) self._data_engine = LiveDataEngine( loop=self._loop, portfolio=self.portfolio, clock=self._clock, logger=self._logger, config={"qsize": 10000}, ) self.portfolio.register_cache(self._data_engine.cache) self.analyzer = PerformanceAnalyzer() if config_exec_db["type"] == "redis": exec_db = RedisExecutionDatabase( trader_id=self.trader_id, logger=self._logger, command_serializer=MsgPackCommandSerializer(), event_serializer=MsgPackEventSerializer(), config={ "host": config_exec_db["host"], "port": config_exec_db["port"], } ) else: exec_db = BypassExecutionDatabase( trader_id=self.trader_id, logger=self._logger, ) self._exec_engine = LiveExecutionEngine( loop=self._loop, database=exec_db, portfolio=self.portfolio, clock=self._clock, logger=self._logger, config={"qsize": 10000}, ) self._exec_engine.load_cache() self._setup_adapters(config_adapters, self._logger) self.trader = Trader( trader_id=self.trader_id, strategies=strategies, portfolio=self.portfolio, data_engine=self._data_engine, exec_engine=self._exec_engine, clock=self._clock, logger=self._logger, ) self._check_residuals_delay = config_trader.get("check_residuals_delay", 5.0) self._load_strategy_state = config_strategy.get("load_state", True) self._save_strategy_state = config_strategy.get("save_state", True) if self._load_strategy_state: self.trader.load() self._log.info("state=INITIALIZED.") self.time_to_initialize = self._clock.delta(self.created_time) self._log.info(f"Initialized in {self.time_to_initialize.total_seconds():.3f}s.")
def __init__( self, strategies: List[TradingStrategy], config: Dict[str, object], ): """ Initialize a new instance of the TradingNode class. Parameters ---------- strategies : list[TradingStrategy] The list of strategies to run on the trading node. config : dict[str, object] The configuration for the trading node. """ if strategies is None: strategies = [] config_trader = config.get("trader", {}) config_log = config.get("logging", {}) config_exec_db = config.get("exec_database", {}) config_strategy = config.get("strategy", {}) config_data_clients = config.get("data_clients", {}) config_exec_clients = config.get("exec_clients", {}) self._clock = LiveClock() self._uuid_factory = UUIDFactory() self._loop = asyncio.get_event_loop() self._executor = concurrent.futures.ThreadPoolExecutor() self._loop.set_default_executor(self._executor) self._loop.set_debug(False) # TODO: Development self._is_running = False # Setup identifiers self.trader_id = TraderId( name=config_trader["name"], tag=config_trader["id_tag"], ) # Setup logging logger = LiveLogger( clock=self._clock, name=self.trader_id.value, level_console=LogLevelParser.from_str_py( config_log.get("log_level_console")), level_file=LogLevelParser.from_str_py( config_log.get("log_level_file")), level_store=LogLevelParser.from_str_py( config_log.get("log_level_store")), log_thread=config_log.get("log_thread_id", True), log_to_file=config_log.get("log_to_file", False), log_file_path=config_log.get("log_file_path", ""), ) self._log = LoggerAdapter(component_name=self.__class__.__name__, logger=logger) self._log_header() self._log.info("Building...") self.portfolio = Portfolio( clock=self._clock, logger=logger, ) self._data_engine = LiveDataEngine( loop=self._loop, portfolio=self.portfolio, clock=self._clock, logger=logger, ) self.portfolio.register_cache(self._data_engine.cache) self.analyzer = PerformanceAnalyzer() if config_exec_db["type"] == "redis": exec_db = RedisExecutionDatabase( trader_id=self.trader_id, logger=logger, command_serializer=MsgPackCommandSerializer(), event_serializer=MsgPackEventSerializer(), config={ "host": config_exec_db["host"], "port": config_exec_db["port"], }) else: exec_db = BypassExecutionDatabase( trader_id=self.trader_id, logger=logger, ) self._exec_engine = LiveExecutionEngine( loop=self._loop, database=exec_db, portfolio=self.portfolio, clock=self._clock, logger=logger, ) self._exec_engine.load_cache() self._setup_data_clients(config_data_clients, logger) self._setup_exec_clients(config_exec_clients, logger) self.trader = Trader( trader_id=self.trader_id, strategies=strategies, data_engine=self._data_engine, exec_engine=self._exec_engine, clock=self._clock, logger=logger, ) self._check_residuals_delay = 2.0 # Hard coded delay (refactor) self._load_strategy_state = config_strategy.get("load_state", True) self._save_strategy_state = config_strategy.get("save_state", True) if self._load_strategy_state: self.trader.load() self._setup_loop() self._log.info("state=INITIALIZED.")
class MsgPackCommandSerializerTests(unittest.TestCase): def setUp(self): # Fixture Setup self.venue = Venue("SIM") self.trader_id = TestStubs.trader_id() self.account_id = TestStubs.account_id() self.serializer = MsgPackCommandSerializer() self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=StrategyId("S", "001"), clock=TestClock(), ) def test_serialize_and_deserialize_submit_order_commands(self): # Arrange order = self.order_factory.market(AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000)) command = SubmitOrder( self.venue, self.trader_id, self.account_id, StrategyId("SCALPER", "01"), PositionId("P-123456"), order, uuid4(), UNIX_EPOCH, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert self.assertEqual(command, deserialized) self.assertEqual(order, deserialized.order) print(command) print(len(serialized)) print(serialized) print(b64encode(serialized)) def test_serialize_and_deserialize_submit_bracket_order_no_take_profit_commands( self): # Arrange entry_order = self.order_factory.market(AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000)) bracket_order = self.order_factory.bracket( entry_order, stop_loss=Price("0.99900"), ) command = SubmitBracketOrder( self.venue, self.trader_id, self.account_id, StrategyId("SCALPER", "01"), bracket_order, uuid4(), UNIX_EPOCH, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert self.assertEqual(command, deserialized) self.assertEqual(bracket_order, deserialized.bracket_order) print(b64encode(serialized)) print(command) def test_serialize_and_deserialize_submit_bracket_order_with_take_profit_commands( self): # Arrange entry_order = self.order_factory.limit( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) bracket_order = self.order_factory.bracket( entry_order, stop_loss=Price("0.99900"), take_profit=Price("1.00010"), ) command = SubmitBracketOrder( self.venue, self.trader_id, self.account_id, StrategyId("SCALPER", "01"), bracket_order, uuid4(), UNIX_EPOCH, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert self.assertEqual(command, deserialized) self.assertEqual(bracket_order, deserialized.bracket_order) print(b64encode(serialized)) print(command) def test_serialize_and_deserialize_modify_order_commands(self): # Arrange command = ModifyOrder( self.venue, self.trader_id, self.account_id, ClientOrderId("O-123456"), Quantity(100000), Price("1.00001"), uuid4(), UNIX_EPOCH, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert self.assertEqual(command, deserialized) print(b64encode(serialized)) print(command) def test_serialize_and_deserialize_cancel_order_commands(self): # Arrange command = CancelOrder( self.venue, self.trader_id, self.account_id, ClientOrderId("O-123456"), uuid4(), UNIX_EPOCH, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert self.assertEqual(command, deserialized) print(b64encode(serialized)) print(command)
def __init__( self, strategies: List[TradingStrategy], config: Dict[str, object], ): """ Initialize a new instance of the TradingNode class. Parameters ---------- strategies : list[TradingStrategy] The list of strategies to run on the trading node. config : dict[str, object] The configuration for the trading node. Raises ------ ValueError If strategies is None or empty. ValueError If config is None or empty. """ PyCondition.not_none(strategies, "strategies") PyCondition.not_none(config, "config") PyCondition.not_empty(strategies, "strategies") PyCondition.not_empty(config, "config") self._config = config # Extract configs config_trader = config.get("trader", {}) config_system = config.get("system", {}) config_log = config.get("logging", {}) config_exec_db = config.get("exec_database", {}) config_risk = config.get("risk", {}) config_strategy = config.get("strategy", {}) # System config self._connection_timeout = config_system.get("connection_timeout", 5.0) self._disconnection_timeout = config_system.get( "disconnection_timeout", 5.0) self._check_residuals_delay = config_system.get( "check_residuals_delay", 5.0) self._load_strategy_state = config_strategy.get("load_state", True) self._save_strategy_state = config_strategy.get("save_state", True) # Setup loop self._loop = asyncio.get_event_loop() self._executor = concurrent.futures.ThreadPoolExecutor() self._loop.set_default_executor(self._executor) self._loop.set_debug(config_system.get("loop_debug", False)) # Components self._clock = LiveClock(loop=self._loop) self._uuid_factory = UUIDFactory() self.system_id = self._uuid_factory.generate() self.created_time = self._clock.utc_now() self._is_running = False # Setup identifiers self.trader_id = TraderId( name=config_trader["name"], tag=config_trader["id_tag"], ) # Setup logging level_stdout = LogLevelParser.from_str_py( config_log.get("level_stdout")) self._logger = LiveLogger( loop=self._loop, clock=self._clock, trader_id=self.trader_id, system_id=self.system_id, level_stdout=level_stdout, ) self._log = LoggerAdapter( component=self.__class__.__name__, logger=self._logger, ) self._log_header() self._log.info("Building...") if platform.system() != "Windows": # Requires the logger to be initialized # Windows does not support signal handling # https://stackoverflow.com/questions/45987985/asyncio-loops-add-signal-handler-in-windows self._setup_loop() # Build platform # ---------------------------------------------------------------------- self.portfolio = Portfolio( clock=self._clock, logger=self._logger, ) self._data_engine = LiveDataEngine( loop=self._loop, portfolio=self.portfolio, clock=self._clock, logger=self._logger, config={"qsize": 10000}, ) self.portfolio.register_cache(self._data_engine.cache) self.analyzer = PerformanceAnalyzer() if config_exec_db["type"] == "redis": exec_db = RedisExecutionDatabase( trader_id=self.trader_id, logger=self._logger, command_serializer=MsgPackCommandSerializer(), event_serializer=MsgPackEventSerializer(), config={ "host": config_exec_db["host"], "port": config_exec_db["port"], }, ) else: exec_db = BypassExecutionDatabase( trader_id=self.trader_id, logger=self._logger, ) self._exec_engine = LiveExecutionEngine( loop=self._loop, database=exec_db, portfolio=self.portfolio, clock=self._clock, logger=self._logger, config={"qsize": 10000}, ) self._risk_engine = LiveRiskEngine( loop=self._loop, exec_engine=self._exec_engine, portfolio=self.portfolio, clock=self._clock, logger=self._logger, config=config_risk, ) self._exec_engine.load_cache() self._exec_engine.register_risk_engine(self._risk_engine) self.trader = Trader( trader_id=self.trader_id, strategies=strategies, portfolio=self.portfolio, data_engine=self._data_engine, exec_engine=self._exec_engine, risk_engine=self._risk_engine, clock=self._clock, logger=self._logger, ) if self._load_strategy_state: self.trader.load() self._builder = TradingNodeBuilder( data_engine=self._data_engine, exec_engine=self._exec_engine, risk_engine=self._risk_engine, clock=self._clock, logger=self._logger, log=self._log, ) self._log.info("state=INITIALIZED.") self.time_to_initialize = self._clock.delta(self.created_time) self._log.info( f"Initialized in {self.time_to_initialize.total_seconds():.3f}s.") self._is_built = False
class MessageClientTests(unittest.TestCase): def setUp(self): # Fixture Setup clock = LiveClock() guid_factory = LiveGuidFactory() logger = LiveLogger() self.context = zmq.Context() self.client_sink = [] self.server_sink = [] self.server = MessageServer( ServerId("Server-001"), TEST_RECV_PORT, TEST_SEND_PORT, MsgPackDictionarySerializer(), MsgPackRequestSerializer(), MsgPackResponseSerializer(), CompressorBypass(), EncryptionSettings(), clock, guid_factory, LoggerAdapter('MessageServer', logger)) # Register test handlers self.server.register_handler(MessageType.STRING, self.server_sink.append) self.server.start() self.command_serializer = MsgPackCommandSerializer() self.server.register_handler(MessageType.COMMAND, self.command_handler) self.client = MessageClient( ClientId("Trader-001"), LOCALHOST, TEST_RECV_PORT, TEST_SEND_PORT, MsgPackDictionarySerializer(), MsgPackRequestSerializer(), MsgPackResponseSerializer(), CompressorBypass(), EncryptionSettings(), clock, guid_factory, LoggerAdapter('MessageClient', logger)) self.client.register_handler(self.client_sink.append) def tearDown(self): # Tear Down self.client.disconnect() self.server.stop() # Allowing the garbage collector to clean up resources avoids threading # errors caused by the continuous disposal of sockets. Thus for testing # we're avoiding calling .dispose() on the sockets. def command_handler(self, message): command = self.command_serializer.deserialize(message) self.server_sink.append(command) def test_can_connect_to_server_and_receive_response(self): # Arrange # Act self.client.connect() time.sleep(0.1) # Assert self.assertTrue(self.client.is_connected()) def test_can_send_one_string_message(self): # Arrange self.client.connect() # Act self.client.send_string('hello') time.sleep(0.1) # Assert self.assertEqual(2, self.client.sent_count) self.assertEqual(2, self.client.recv_count) self.assertEqual(2, self.server.sent_count) self.assertEqual(2, self.server.recv_count) self.assertEqual(1, len(self.client_sink)) self.assertEqual(1, len(self.server_sink)) self.assertEqual('hello', self.server_sink[0]) self.assertEqual('OK', self.client_sink[0]) def test_can_send_multiple_messages_and_receive_correctly_ordered_responses(self): # Arrange self.client.connect() # Act self.client.send_string('hello1') self.client.send_string('hello2') self.client.send_string('hello3') time.sleep(0.1) # Assert self.assertEqual(4, self.client.sent_count) self.assertEqual(4, self.client.recv_count) self.assertEqual(4, self.server.sent_count) self.assertEqual(4, self.server.recv_count) self.assertEqual(3, len(self.client_sink)) self.assertEqual(3, len(self.server_sink)) self.assertEqual('hello1', self.server_sink[0]) self.assertEqual('hello2', self.server_sink[1]) self.assertEqual('hello3', self.server_sink[2]) self.assertEqual('OK', self.client_sink[0]) self.assertEqual('OK', self.client_sink[1]) self.assertEqual('OK', self.client_sink[2])
def setUp(self): # Fixture Setup trader_id = TraderId('TESTER', '000') account_id = TestStubs.account_id() clock = LiveClock() guid_factory = LiveGuidFactory() logger = LiveLogger() self.command_server = MessageServer( server_id=ServerId("CommandServer-001"), recv_port=TEST_COMMANDS_REQ_PORT, send_port=TEST_COMMANDS_REP_PORT, header_serializer=MsgPackDictionarySerializer(), request_serializer=MsgPackRequestSerializer(), response_serializer=MsgPackResponseSerializer(), compressor=CompressorBypass(), encryption=EncryptionSettings(), clock=clock, guid_factory=guid_factory, logger=LoggerAdapter('CommandServer', logger)) self.command_serializer = MsgPackCommandSerializer() self.command_server_sink = [] self.command_server.register_handler(MessageType.COMMAND, self.command_handler) self.command_server.start() time.sleep(0.1) self.portfolio = Portfolio( currency=Currency.USD, clock=clock, guid_factory=guid_factory, logger=logger) self.analyzer = PerformanceAnalyzer() self.exec_db = InMemoryExecutionDatabase( trader_id=trader_id, logger=logger) self.exec_engine = LiveExecutionEngine( trader_id=trader_id, account_id=account_id, database=self.exec_db, portfolio=self.portfolio, clock=clock, guid_factory=guid_factory, logger=logger) self.exec_engine.handle_event(TestStubs.account_event()) self.exec_client = LiveExecClient( exec_engine=self.exec_engine, host=LOCALHOST, command_req_port=TEST_COMMANDS_REQ_PORT, command_res_port=TEST_COMMANDS_REP_PORT, event_pub_port=TEST_EVENTS_PUB_PORT, compressor=CompressorBypass(), encryption=EncryptionSettings(), command_serializer=MsgPackCommandSerializer(), header_serializer=MsgPackDictionarySerializer(), request_serializer=MsgPackRequestSerializer(), response_serializer=MsgPackResponseSerializer(), event_serializer=MsgPackEventSerializer(), clock=clock, guid_factory=guid_factory, logger=logger) self.exec_engine.register_client(self.exec_client) self.exec_client.connect() time.sleep(0.1) self.bar_type = TestStubs.bartype_audusd_1min_bid() self.strategy = TestStrategy1(self.bar_type, id_tag_strategy='001') self.strategy.change_logger(logger) self.exec_engine.register_strategy(self.strategy)
class LiveExecutionTests(unittest.TestCase): def setUp(self): # Fixture Setup trader_id = TraderId('TESTER', '000') account_id = TestStubs.account_id() clock = LiveClock() guid_factory = LiveGuidFactory() logger = LiveLogger() self.command_server = MessageServer( server_id=ServerId("CommandServer-001"), recv_port=TEST_COMMANDS_REQ_PORT, send_port=TEST_COMMANDS_REP_PORT, header_serializer=MsgPackDictionarySerializer(), request_serializer=MsgPackRequestSerializer(), response_serializer=MsgPackResponseSerializer(), compressor=CompressorBypass(), encryption=EncryptionSettings(), clock=clock, guid_factory=guid_factory, logger=LoggerAdapter('CommandServer', logger)) self.command_serializer = MsgPackCommandSerializer() self.command_server_sink = [] self.command_server.register_handler(MessageType.COMMAND, self.command_handler) self.command_server.start() time.sleep(0.1) self.portfolio = Portfolio( currency=Currency.USD, clock=clock, guid_factory=guid_factory, logger=logger) self.analyzer = PerformanceAnalyzer() self.exec_db = InMemoryExecutionDatabase( trader_id=trader_id, logger=logger) self.exec_engine = LiveExecutionEngine( trader_id=trader_id, account_id=account_id, database=self.exec_db, portfolio=self.portfolio, clock=clock, guid_factory=guid_factory, logger=logger) self.exec_engine.handle_event(TestStubs.account_event()) self.exec_client = LiveExecClient( exec_engine=self.exec_engine, host=LOCALHOST, command_req_port=TEST_COMMANDS_REQ_PORT, command_res_port=TEST_COMMANDS_REP_PORT, event_pub_port=TEST_EVENTS_PUB_PORT, compressor=CompressorBypass(), encryption=EncryptionSettings(), command_serializer=MsgPackCommandSerializer(), header_serializer=MsgPackDictionarySerializer(), request_serializer=MsgPackRequestSerializer(), response_serializer=MsgPackResponseSerializer(), event_serializer=MsgPackEventSerializer(), clock=clock, guid_factory=guid_factory, logger=logger) self.exec_engine.register_client(self.exec_client) self.exec_client.connect() time.sleep(0.1) self.bar_type = TestStubs.bartype_audusd_1min_bid() self.strategy = TestStrategy1(self.bar_type, id_tag_strategy='001') self.strategy.change_logger(logger) self.exec_engine.register_strategy(self.strategy) def tearDown(self): # Tear Down self.exec_client.disconnect() self.command_server.stop() # Allowing the garbage collector to clean up resources avoids threading # errors caused by the continuous disposal of sockets. Thus for testing # we're avoiding calling .dispose() on the sockets. def command_handler(self, message): command = self.command_serializer.deserialize(message) self.command_server_sink.append(command) def test_can_send_submit_order_command(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) # Act self.strategy.submit_order(order, self.strategy.position_id_generator.generate()) time.sleep(0.3) # # Assert self.assertEqual(order, self.strategy.order(order.id)) self.assertEqual(2, self.command_server.recv_count) self.assertEqual(1, self.command_server.sent_count) self.assertEqual(SubmitOrder, type(self.command_server_sink[0])) def test_can_send_submit_atomic_order(self): # Arrange atomic_order = self.strategy.order_factory.atomic_market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(0.99900, 5)) # Act self.strategy.submit_atomic_order(atomic_order, self.strategy.position_id_generator.generate()) time.sleep(0.3) # Assert self.assertEqual(atomic_order.entry, self.strategy.order(atomic_order.entry.id)) self.assertEqual(atomic_order.stop_loss, self.strategy.order(atomic_order.stop_loss.id)) self.assertEqual(2, self.command_server.recv_count) self.assertEqual(1, self.command_server.sent_count) self.assertEqual(SubmitAtomicOrder, type(self.command_server_sink[0])) def test_can_send_cancel_order_command(self): # Arrange order = self.strategy.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) # Act self.strategy.submit_order(order, self.strategy.position_id_generator.generate()) self.strategy.cancel_order(order, 'SIGNAL_GONE') time.sleep(0.3) # Assert self.assertEqual(order, self.strategy.order(order.id)) self.assertEqual(3, self.command_server.recv_count) self.assertEqual(1, self.command_server.sent_count) self.assertEqual(SubmitOrder, type(self.command_server_sink[0])) self.assertEqual(CancelOrder, type(self.command_server_sink[1])) def test_can_send_modify_order_command(self): # Arrange order = self.strategy.order_factory.limit( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000), Price(1.00000, 5)) # Act self.strategy.submit_order(order, self.strategy.position_id_generator.generate()) self.strategy.modify_order(order, Quantity(110000), Price(1.00001, 5)) time.sleep(0.3) # Assert self.assertEqual(order, self.strategy.order(order.id)) self.assertEqual(3, self.command_server.recv_count) self.assertEqual(1, self.command_server.sent_count) self.assertEqual(SubmitOrder, type(self.command_server_sink[0])) self.assertEqual(ModifyOrder, type(self.command_server_sink[1])) def test_can_send_account_inquiry_command(self): # Arrange # Act self.strategy.account_inquiry() time.sleep(0.3) # Assert self.assertEqual(2, self.command_server.recv_count) self.assertEqual(1, self.command_server.sent_count) self.assertEqual(AccountInquiry, type(self.command_server_sink[0]))
class TestMsgPackCommandSerializer: def setup(self): # Fixture Setup self.venue = Venue("SIM") self.trader_id = TestStubs.trader_id() self.account_id = TestStubs.account_id() self.serializer = MsgPackCommandSerializer() self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=StrategyId("S", "001"), clock=TestClock(), ) def test_serialize_and_deserialize_submit_order_commands(self): # Arrange order = self.order_factory.market(AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000)) command = SubmitOrder( order.instrument_id.venue.client_id, self.trader_id, self.account_id, StrategyId("SCALPER", "01"), PositionId("P-123456"), order, uuid4(), 0, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert assert deserialized == command assert deserialized.order == order print(command) print(len(serialized)) print(serialized) print(b64encode(serialized)) def test_serialize_and_deserialize_submit_bracket_order_no_take_profit_commands( self, ): # Arrange entry_order = self.order_factory.market(AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000)) bracket_order = self.order_factory.bracket( entry_order, stop_loss=Price("0.99900"), take_profit=Price("1.00100"), ) command = SubmitBracketOrder( entry_order.instrument_id.venue.client_id, self.trader_id, self.account_id, StrategyId("SCALPER", "01"), bracket_order, uuid4(), 0, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert assert deserialized == command assert deserialized.bracket_order == bracket_order print(b64encode(serialized)) print(command) def test_serialize_and_deserialize_submit_bracket_order_with_take_profit_commands( self, ): # Arrange entry_order = self.order_factory.limit( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("1.00000"), ) bracket_order = self.order_factory.bracket( entry_order, stop_loss=Price("0.99900"), take_profit=Price("1.00010"), ) command = SubmitBracketOrder( entry_order.instrument_id.venue.client_id, self.trader_id, self.account_id, StrategyId("SCALPER", "01"), bracket_order, uuid4(), 0, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert assert deserialized == command assert deserialized.bracket_order == bracket_order print(b64encode(serialized)) print(command) def test_serialize_and_deserialize_amend_order_commands(self): # Arrange command = UpdateOrder( AUDUSD_SIM.id.venue.client_id, self.trader_id, self.account_id, AUDUSD_SIM.id, ClientOrderId("O-123456"), Quantity(100000), Price("1.00001"), uuid4(), 0, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert assert deserialized == command print(b64encode(serialized)) print(command) def test_serialize_and_deserialize_cancel_order_commands(self): # Arrange command = CancelOrder( AUDUSD_SIM.id.venue.client_id, self.trader_id, self.account_id, AUDUSD_SIM.id, ClientOrderId("O-123456"), VenueOrderId("001"), uuid4(), 0, ) # Act serialized = self.serializer.serialize(command) deserialized = self.serializer.deserialize(serialized) # Assert assert deserialized == command print(b64encode(serialized)) print(command)