def setup(self): # Fixture Setup self.analyzer = PerformanceAnalyzer() self.order_factory = OrderFactory( trader_id=TraderId("TESTER-000"), strategy_id=StrategyId("S-001"), clock=TestClock(), )
def setUp(self): # Fixture Setup self.clock = TestClock() self.guid_factory = TestGuidFactory() logger = TestLogger() self.trader_id = TraderId('TESTER', '000') self.account_id = TestStubs.account_id() self.order_factory = OrderFactory( id_tag_trader=self.trader_id.order_id_tag, id_tag_strategy=IdTag('001'), clock=self.clock) self.portfolio = Portfolio(currency=Currency.USD, clock=self.clock, guid_factory=self.guid_factory, logger=logger) self.analyzer = PerformanceAnalyzer() self.exec_db = InMemoryExecutionDatabase(trader_id=self.trader_id, logger=logger) self.exec_engine = ExecutionEngine(trader_id=self.trader_id, account_id=self.account_id, database=self.exec_db, portfolio=self.portfolio, clock=self.clock, guid_factory=self.guid_factory, logger=logger) self.exec_engine.handle_event(TestStubs.account_event()) self.exec_client = MockExecutionClient(self.exec_engine, logger) self.exec_engine.register_client(self.exec_client)
def setUp(self): # Fixture Setup usdjpy = TestStubs.instrument_usdjpy() data = BacktestDataContainer() data.add_instrument(usdjpy) data.add_bars(usdjpy.symbol, BarStructure.MINUTE, PriceType.BID, TestDataProvider.usdjpy_1min_bid()[:2000]) data.add_bars(usdjpy.symbol, BarStructure.MINUTE, PriceType.ASK, TestDataProvider.usdjpy_1min_ask()[:2000]) clock = TestClock() guid_factory = TestGuidFactory() logger = TestLogger() trader_id = TraderId('TESTER', '000') account_id = TestStubs.account_id() data_client = BacktestDataClient(data=data, tick_capacity=100, clock=clock, logger=logger) 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 = ExecutionEngine(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_client = BacktestExecClient( exec_engine=self.exec_engine, instruments={usdjpy.symbol: usdjpy}, config=BacktestConfig(), fill_model=FillModel(), clock=clock, guid_factory=guid_factory, logger=logger) self.exec_engine.register_client(self.exec_client) strategies = [EmptyStrategy('001'), EmptyStrategy('002')] self.trader = Trader(trader_id=trader_id, account_id=account_id, strategies=strategies, data_client=data_client, exec_engine=self.exec_engine, clock=clock, guid_factory=guid_factory, logger=logger)
def setup(self): # Fixture Setup self.clock = LiveClock() self.uuid_factory = UUIDFactory() self.logger = Logger(self.clock) self.trader_id = TraderId("TESTER", "000") self.account_id = TestStubs.account_id() self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=StrategyId("S", "001"), clock=self.clock, ) self.random_order_factory = OrderFactory( trader_id=TraderId("RANDOM", "042"), strategy_id=StrategyId("S", "042"), clock=self.clock, ) 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) self.database = BypassExecutionDatabase(trader_id=self.trader_id, logger=self.logger) self.engine = LiveExecutionEngine( loop=self.loop, database=self.database, portfolio=self.portfolio, clock=self.clock, logger=self.logger, ) self.instrument_provider = InstrumentProvider() self.instrument_provider.add(AUDUSD_SIM) self.instrument_provider.add(GBPUSD_SIM) self.client = MockLiveExecutionClient( name=SIM.value, account_id=self.account_id, engine=self.engine, instrument_provider=self.instrument_provider, clock=self.clock, logger=self.logger, ) self.engine.register_client(self.client)
def setUp(self): # Fixture Setup self.clock = TestClock() self.uuid_factory = UUIDFactory() self.logger = TestLogger(self.clock) self.trader_id = TraderId("TESTER", "000") self.account_id = AccountId("BINANCE", "000") self.portfolio = Portfolio( clock=self.clock, logger=self.logger, ) self.portfolio.register_cache(DataCache(self.logger)) self.analyzer = PerformanceAnalyzer() database = BypassExecutionDatabase( trader_id=self.trader_id, logger=self.logger, ) self.exec_engine = ExecutionEngine( database=database, portfolio=self.portfolio, clock=self.clock, logger=self.logger, ) self.exchange = SimulatedExchange( venue=Venue("BINANCE"), oms_type=OMSType.NETTING, generate_position_ids=True, is_frozen_account=False, starting_balances=[Money(1_000_000, USD)], instruments=[ETHUSDT_BINANCE], modules=[], exec_cache=self.exec_engine.cache, fill_model=FillModel(), clock=self.clock, logger=self.logger, ) self.exec_client = BacktestExecClient( exchange=self.exchange, account_id=self.account_id, engine=self.exec_engine, clock=self.clock, logger=self.logger, ) self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=StrategyId("SCALPER", "000"), clock=self.clock, )
def setUp(self): # Fixture Setup self.usdjpy = TestStubs.instrument_usdjpy() self.bid_data_1min = TestDataProvider.usdjpy_1min_bid()[:2000] self.ask_data_1min = TestDataProvider.usdjpy_1min_ask()[:2000] self.data_ticks = {self.usdjpy.symbol: pd.DataFrame()} self.data_bars_bid = {self.usdjpy.symbol: self.bid_data_1min} self.data_bars_ask = {self.usdjpy.symbol: self.ask_data_1min} self.strategies = [TestStrategy1(TestStubs.bartype_usdjpy_1min_bid())] self.clock = TestClock() self.guid_factory = TestGuidFactory() self.logger = TestLogger() self.data_client = DataClient( tick_capacity=100, clock=self.clock, guid_factory=self.guid_factory, logger=self.logger) self.portfolio = Portfolio( currency=Currency.USD, clock=self.clock, guid_factory=self.guid_factory, logger=self.logger) self.analyzer = PerformanceAnalyzer() trader_id = TraderId('TESTER', '000') account_id = TestStubs.account_id() self.exec_db = InMemoryExecutionDatabase( trader_id=trader_id, logger=self.logger) self.exec_engine = ExecutionEngine( trader_id=trader_id, account_id=account_id, database=self.exec_db, portfolio=self.portfolio, clock=self.clock, guid_factory=self.guid_factory, logger=self.logger) self.exec_client = BacktestExecClient( exec_engine=self.exec_engine, instruments={self.usdjpy.symbol: self.usdjpy}, config=BacktestConfig(), fill_model=FillModel(), clock=TestClock(), guid_factory=TestGuidFactory(), logger=TestLogger()) self.exec_engine.register_client(self.exec_client)
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 setUp(self): # Fixture Setup # Fresh isolated loop testing pattern self.loop = asyncio.new_event_loop() asyncio.set_event_loop(self.loop) self.clock = LiveClock() self.uuid_factory = UUIDFactory() self.logger = TestLogger(self.clock) self.trader_id = TraderId("TESTER", "000") self.account_id = TestStubs.account_id() self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=StrategyId("S", "001"), clock=self.clock, ) 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.engine = LiveExecutionEngine( loop=self.loop, database=database, portfolio=self.portfolio, clock=self.clock, logger=self.logger, ) instrument_provider = InstrumentProvider(venue=SIM, load_all=False) self.client = LiveExecutionClient( venue=SIM, account_id=self.account_id, engine=self.engine, instrument_provider=instrument_provider, clock=self.clock, logger=self.logger, )
def setUp(self): # Fixture Setup self.clock = TestClock() self.guid_factory = TestGuidFactory() self.logger = TestLogger() self.data_client = DataClient(tick_capacity=100, clock=self.clock, guid_factory=self.guid_factory, logger=self.logger) self.portfolio = Portfolio(currency=Currency.USD, clock=self.clock, guid_factory=self.guid_factory, logger=self.logger) self.analyzer = PerformanceAnalyzer() trader_id = TraderId('TESTER', '000') account_id = TestStubs.account_id() self.exec_db = InMemoryExecutionDatabase(trader_id=trader_id, logger=self.logger) self.exec_engine = ExecutionEngine(trader_id=trader_id, account_id=account_id, database=self.exec_db, portfolio=self.portfolio, clock=self.clock, guid_factory=self.guid_factory, logger=self.logger) # noinspection PyPep8Naming # USDJPY is clear USDJPY = TestStubs.instrument_usdjpy() self.exec_client = BacktestExecClient( exec_engine=self.exec_engine, instruments={USDJPY.symbol: USDJPY}, config=BacktestConfig(), fill_model=FillModel(), clock=self.clock, guid_factory=self.guid_factory, logger=self.logger) self.exec_engine.register_client(self.exec_client) self.exec_engine.handle_event(TestStubs.account_event()) self.exec_client.process_tick(TestStubs.tick_3decimal( USDJPY.symbol)) # Prepare market print('\n')
def setUp(self): # Fixture Setup self.clock = TestClock() self.uuid_factory = TestUUIDFactory() self.logger = TestLogger(self.clock) self.trader_id = TraderId("TESTER", "000") self.account_id = TestStubs.account_id() self.order_factory = OrderFactory( strategy_id=StrategyId("S", "001"), id_tag_trader=self.trader_id.tag, id_tag_strategy=IdTag("001"), clock=self.clock, ) self.portfolio = Portfolio( clock=self.clock, uuid_factory=self.uuid_factory, logger=self.logger, ) self.analyzer = PerformanceAnalyzer() database = BypassExecutionDatabase(trader_id=self.trader_id, logger=self.logger) self.exec_engine = ExecutionEngine( database=database, portfolio=self.portfolio, clock=self.clock, uuid_factory=self.uuid_factory, logger=self.logger, ) self.cache = self.exec_engine.cache self.exec_engine.process(TestStubs.event_account_state()) self.venue = Venue("FXCM") self.exec_client = MockExecutionClient( self.venue, self.account_id, self.exec_engine, self.logger, ) self.exec_engine.register_client(self.exec_client)
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 setUp(self): # Fixture Setup self.clock = TestClock() self.uuid_factory = UUIDFactory() self.logger = TestLogger(self.clock) self.portfolio = Portfolio( clock=self.clock, logger=self.logger, ) self.data_engine = DataEngine( portfolio=self.portfolio, clock=self.clock, logger=self.logger, config={'use_previous_close': False}, # To correctly reproduce historical data bars ) self.data_engine.cache.add_instrument(AUDUSD_SIM) self.data_engine.cache.add_instrument(USDJPY_SIM) self.portfolio.register_cache(self.data_engine.cache) self.analyzer = PerformanceAnalyzer() self.trader_id = TraderId("TESTER", "000") self.account_id = AccountId("SIM", "001") exec_db = BypassExecutionDatabase( trader_id=self.trader_id, logger=self.logger, ) self.exec_engine = ExecutionEngine( database=exec_db, portfolio=self.portfolio, clock=self.clock, logger=self.logger, ) self.exchange = SimulatedExchange( venue=SIM, oms_type=OMSType.HEDGING, generate_position_ids=False, # Will force execution engine to generate ids is_frozen_account=False, starting_balances=[Money(1_000_000, USD)], instruments=[AUDUSD_SIM, USDJPY_SIM], modules=[], fill_model=FillModel(), exec_cache=self.exec_engine.cache, clock=self.clock, logger=self.logger, ) self.exec_client = BacktestExecClient( exchange=self.exchange, account_id=self.account_id, engine=self.exec_engine, clock=self.clock, logger=self.logger, ) self.exec_engine.register_client(self.exec_client) self.exchange.register_client(self.exec_client) self.strategy = MockStrategy(bar_type=TestStubs.bartype_usdjpy_1min_bid()) self.strategy.register_trader( self.trader_id, self.clock, self.logger, ) self.data_engine.register_strategy(self.strategy) self.exec_engine.register_strategy(self.strategy) self.data_engine.start() self.exec_engine.start() self.strategy.start()
def setup(self): # Fixture Setup self.clock = LiveClock() self.uuid_factory = UUIDFactory() self.logger = Logger(self.clock) self.trader_id = TraderId("TESTER", "000") self.account_id = TestStubs.account_id() self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=StrategyId("S", "001"), clock=self.clock, ) self.random_order_factory = OrderFactory( trader_id=TraderId("RANDOM", "042"), strategy_id=StrategyId("S", "042"), clock=self.clock, ) 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) self.database = BypassExecutionDatabase(trader_id=self.trader_id, logger=self.logger) self.exec_engine = LiveExecutionEngine( loop=self.loop, database=self.database, portfolio=self.portfolio, clock=self.clock, logger=self.logger, ) self.venue = Venue("SIM") self.exec_client = MockExecutionClient( self.venue.value, self.account_id, self.exec_engine, self.clock, self.logger, ) self.risk_engine = LiveRiskEngine( loop=self.loop, exec_engine=self.exec_engine, portfolio=self.portfolio, clock=self.clock, logger=self.logger, config={}, ) self.exec_engine.register_client(self.exec_client) self.exec_engine.register_risk_engine(self.risk_engine)
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 TestAnalyzer: def setup(self): # Fixture Setup self.analyzer = PerformanceAnalyzer() self.order_factory = OrderFactory( trader_id=TraderId("TESTER-000"), strategy_id=StrategyId("S-001"), clock=TestClock(), ) def test_get_realized_pnls_when_no_data_returns_none(self): # Arrange, Act result = self.analyzer.realized_pnls() # Assert assert result is None def test_get_realized_pnls_with_currency_when_no_data_returns_none(self): # Arrange, Act result = self.analyzer.realized_pnls(AUD) # Assert assert result is None def test_analyzer_tracks_returns(self): # Arrange t1 = datetime(year=2010, month=1, day=1) t2 = datetime(year=2010, month=1, day=2) t3 = datetime(year=2010, month=1, day=3) t4 = datetime(year=2010, month=1, day=4) t5 = datetime(year=2010, month=1, day=5) t6 = datetime(year=2010, month=1, day=6) t7 = datetime(year=2010, month=1, day=7) t8 = datetime(year=2010, month=1, day=8) t9 = datetime(year=2010, month=1, day=9) t10 = datetime(year=2010, month=1, day=10) # Act self.analyzer.add_return(t1, 0.05) self.analyzer.add_return(t2, -0.10) self.analyzer.add_return(t3, 0.10) self.analyzer.add_return(t4, -0.21) self.analyzer.add_return(t5, 0.22) self.analyzer.add_return(t6, -0.23) self.analyzer.add_return(t7, 0.24) self.analyzer.add_return(t8, -0.25) self.analyzer.add_return(t9, 0.26) self.analyzer.add_return(t10, -0.10) self.analyzer.add_return(t10, -0.10) result = self.analyzer.returns() # Assert assert len(result) == 10 def test_get_realized_pnls_when_all_flat_positions_returns_expected_series( self): # Arrange order1 = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) order2 = self.order_factory.market( AUDUSD_SIM.id, OrderSide.SELL, Quantity.from_int(100000), ) order3 = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) order4 = self.order_factory.market( AUDUSD_SIM.id, OrderSide.SELL, Quantity.from_int(100000), ) fill1 = TestStubs.event_order_filled( order1, instrument=AUDUSD_SIM, position_id=PositionId("P-1"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00000"), ) fill2 = TestStubs.event_order_filled( order2, instrument=AUDUSD_SIM, position_id=PositionId("P-1"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00010"), ) fill3 = TestStubs.event_order_filled( order3, instrument=AUDUSD_SIM, position_id=PositionId("P-2"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00000"), ) fill4 = TestStubs.event_order_filled( order4, instrument=AUDUSD_SIM, position_id=PositionId("P-2"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00020"), ) position1 = Position(instrument=AUDUSD_SIM, fill=fill1) position1.apply(fill2) position2 = Position(instrument=AUDUSD_SIM, fill=fill3) position2.apply(fill4) self.analyzer.add_positions([position1, position2]) # Act result = self.analyzer.realized_pnls(USD) # Assert assert len(result) == 2 assert result["P-1"] == 6.0 assert result["P-2"] == 16.0
class AnalyzerTests(unittest.TestCase): def setUp(self): # Fixture Setup self.analyzer = PerformanceAnalyzer() def test_add_return(self): # Arrange t1 = datetime(year=2010, month=1, day=1) t2 = datetime(year=2010, month=1, day=2) t3 = datetime(year=2010, month=1, day=3) t4 = datetime(year=2010, month=1, day=4) t5 = datetime(year=2010, month=1, day=5) t6 = datetime(year=2010, month=1, day=6) t7 = datetime(year=2010, month=1, day=7) t8 = datetime(year=2010, month=1, day=8) t9 = datetime(year=2010, month=1, day=9) t10 = datetime(year=2010, month=1, day=10) # Act self.analyzer.add_return(t1, 0.05) self.analyzer.add_return(t2, -0.10) self.analyzer.add_return(t3, 0.10) self.analyzer.add_return(t4, -0.21) self.analyzer.add_return(t5, 0.22) self.analyzer.add_return(t6, -0.23) self.analyzer.add_return(t7, 0.24) self.analyzer.add_return(t8, -0.25) self.analyzer.add_return(t9, 0.26) self.analyzer.add_return(t10, -0.10) result = self.analyzer.get_returns() # Assert self.assertEqual(10, len(result)) def test_add_positions(self): # Arrange position1 = TestStubs.position() position2 = TestStubs.position() positions = [position1, position2] # Act self.analyzer.add_positions(UNIX_EPOCH, positions, Money(100000, USD)) # Assert print(self.analyzer.get_positions())
def setUp(self): # Fixture Setup clock = TestClock() logger = Logger(clock) trader_id = TraderId("TESTER", "000") account_id = TestStubs.account_id() self.portfolio = Portfolio( clock=clock, logger=logger, ) self.data_engine = DataEngine( portfolio=self.portfolio, clock=clock, logger=logger, config={"use_previous_close": False}, ) self.portfolio.register_cache(self.data_engine.cache) self.analyzer = PerformanceAnalyzer() self.exec_db = BypassExecutionDatabase( trader_id=trader_id, logger=logger, ) self.exec_engine = ExecutionEngine( database=self.exec_db, portfolio=self.portfolio, clock=clock, logger=logger, ) self.exchange = SimulatedExchange( venue=Venue("SIM"), oms_type=OMSType.HEDGING, is_frozen_account=False, starting_balances=[Money(1_000_000, USD)], exec_cache=self.exec_engine.cache, instruments=[USDJPY_SIM], modules=[], fill_model=FillModel(), clock=clock, logger=logger, ) self.data_client = BacktestMarketDataClient( instruments=[USDJPY_SIM], client_id=ClientId("SIM"), engine=self.data_engine, clock=clock, logger=logger, ) self.data_engine.register_client(self.data_client) self.exec_client = BacktestExecClient( exchange=self.exchange, account_id=account_id, engine=self.exec_engine, clock=clock, logger=logger, ) self.risk_engine = RiskEngine( exec_engine=self.exec_engine, portfolio=self.portfolio, clock=clock, logger=logger, ) self.exec_engine.register_risk_engine(self.risk_engine) self.exec_engine.register_client(self.exec_client) strategies = [ TradingStrategy("001"), TradingStrategy("002"), ] self.trader = Trader( trader_id=trader_id, strategies=strategies, portfolio=self.portfolio, data_engine=self.data_engine, exec_engine=self.exec_engine, risk_engine=self.risk_engine, clock=clock, logger=logger, )
def setUp(self): # Fixture Setup self.analyzer = PerformanceAnalyzer()
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 AnalyzerTests(unittest.TestCase): def setUp(self): # Fixture Setup self.analyzer = PerformanceAnalyzer() self.order_factory = OrderFactory( trader_id=TraderId("TESTER", "000"), strategy_id=StrategyId("S", "001"), clock=TestClock(), ) def test_get_daily_returns_when_no_data_returns_empty_series(self): # Arrange # Act result = self.analyzer.get_daily_returns() # Assert self.assertTrue(result.empty) def test_get_realized_pnls_when_no_data_returns_empty_series(self): # Arrange # Act result = self.analyzer.get_realized_pnls() # Assert self.assertTrue(result.empty) def test_analyzer_tracks_daily_returns(self): # Arrange t1 = datetime(year=2010, month=1, day=1) t2 = datetime(year=2010, month=1, day=2) t3 = datetime(year=2010, month=1, day=3) t4 = datetime(year=2010, month=1, day=4) t5 = datetime(year=2010, month=1, day=5) t6 = datetime(year=2010, month=1, day=6) t7 = datetime(year=2010, month=1, day=7) t8 = datetime(year=2010, month=1, day=8) t9 = datetime(year=2010, month=1, day=9) t10 = datetime(year=2010, month=1, day=10) # Act self.analyzer.add_return(t1, 0.05) self.analyzer.add_return(t2, -0.10) self.analyzer.add_return(t3, 0.10) self.analyzer.add_return(t4, -0.21) self.analyzer.add_return(t5, 0.22) self.analyzer.add_return(t6, -0.23) self.analyzer.add_return(t7, 0.24) self.analyzer.add_return(t8, -0.25) self.analyzer.add_return(t9, 0.26) self.analyzer.add_return(t10, -0.10) self.analyzer.add_return(t10, -0.10) result = self.analyzer.get_daily_returns() # Assert self.assertEqual(10, len(result)) self.assertEqual(-0.12, sum(result)) self.assertEqual(-0.20, result.iloc[9]) def test_get_realized_pnls_when_all_flat_positions_returns_expected_series( self): # Arrange order1 = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) order2 = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.SELL, Quantity(100000), ) order3 = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) order4 = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.SELL, Quantity(100000), ) fill1 = TestStubs.event_order_filled( order1, instrument=AUDUSD_SIM, position_id=PositionId("P-1"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00000"), ) fill2 = TestStubs.event_order_filled( order2, instrument=AUDUSD_SIM, position_id=PositionId("P-1"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00010"), ) fill3 = TestStubs.event_order_filled( order3, instrument=AUDUSD_SIM, position_id=PositionId("P-2"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00000"), ) fill4 = TestStubs.event_order_filled( order4, instrument=AUDUSD_SIM, position_id=PositionId("P-2"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00020"), ) position1 = Position(fill1) position1.apply(fill2) position2 = Position(fill3) position2.apply(fill4) self.analyzer.add_positions([position1, position2]) # Act result = self.analyzer.get_realized_pnls() # Assert self.assertEqual(2, len(result)) self.assertEqual(6.0, result['P-1']) self.assertEqual(16.0, result['P-2'])
def setUp(self): # Fixture Setup self.clock = TestClock() self.uuid_factory = TestUUIDFactory() self.logger = TestLogger(self.clock) self.portfolio = Portfolio( clock=self.clock, uuid_factory=self.uuid_factory, logger=self.logger, ) self.data_engine = DataEngine( tick_capacity=1000, bar_capacity=1000, portfolio=self.portfolio, clock=self.clock, uuid_factory=self.uuid_factory, logger=self.logger, ) self.data_engine.set_use_previous_close(False) self.analyzer = PerformanceAnalyzer() trader_id = TraderId('TESTER', '000') account_id = TestStubs.account_id() self.exec_db = BypassExecutionDatabase( trader_id=trader_id, logger=self.logger, ) self.exec_engine = ExecutionEngine( database=self.exec_db, portfolio=self.portfolio, clock=self.clock, uuid_factory=self.uuid_factory, logger=self.logger, ) usdjpy = InstrumentLoader.default_fx_ccy(TestStubs.symbol_usdjpy_fxcm()) self.market = SimulatedMarket( venue=Venue("FXCM"), oms_type=OMSType.HEDGING, generate_position_ids=True, exec_cache=self.exec_engine.cache, instruments={usdjpy.symbol: usdjpy}, config=BacktestConfig(), fill_model=FillModel(), commission_model=GenericCommissionModel(), clock=self.clock, uuid_factory=TestUUIDFactory(), logger=self.logger, ) self.exec_client = BacktestExecClient( market=self.market, account_id=account_id, engine=self.exec_engine, logger=self.logger, ) self.exec_engine.register_client(self.exec_client) self.market.register_client(self.exec_client) self.exec_engine.process(TestStubs.event_account_state()) self.market.process_tick(TestStubs.quote_tick_3decimal(usdjpy.symbol)) # Prepare market self.strategy = TradingStrategy(order_id_tag="001") self.strategy.register_trader( trader_id=TraderId("TESTER", "000"), clock=self.clock, uuid_factory=self.uuid_factory, logger=self.logger, ) self.strategy.register_data_engine(self.data_engine) self.strategy.register_execution_engine(self.exec_engine) print("\n")
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 setUp(self): # Fixture Setup usdjpy = InstrumentLoader.default_fx_ccy( TestStubs.symbol_usdjpy_fxcm()) data = BacktestDataContainer() data.add_instrument(usdjpy) data.add_bars(usdjpy.symbol, BarAggregation.MINUTE, PriceType.BID, TestDataProvider.usdjpy_1min_bid()[:2000]) data.add_bars(usdjpy.symbol, BarAggregation.MINUTE, PriceType.ASK, TestDataProvider.usdjpy_1min_ask()[:2000]) clock = TestClock() uuid_factory = TestUUIDFactory() logger = TestLogger(clock) trader_id = TraderId("TESTER", "000") account_id = TestStubs.account_id() self.portfolio = Portfolio( clock=clock, uuid_factory=uuid_factory, logger=logger, ) data_engine = BacktestDataEngine( data=data, tick_capacity=1000, bar_capacity=1000, portfolio=self.portfolio, clock=clock, logger=logger, ) self.analyzer = PerformanceAnalyzer() self.exec_db = BypassExecutionDatabase( trader_id=trader_id, logger=logger, ) self.exec_engine = ExecutionEngine( database=self.exec_db, portfolio=self.portfolio, clock=clock, uuid_factory=uuid_factory, logger=logger, ) self.market = SimulatedMarket( venue=Venue("FXCM"), oms_type=OMSType.HEDGING, generate_position_ids=True, exec_cache=self.exec_engine.cache, instruments={usdjpy.symbol: usdjpy}, config=BacktestConfig(), fill_model=FillModel(), commission_model=GenericCommissionModel(), clock=clock, uuid_factory=TestUUIDFactory(), logger=logger, ) self.exec_client = BacktestExecClient( market=self.market, account_id=account_id, engine=self.exec_engine, logger=logger, ) self.exec_engine.register_client(self.exec_client) strategies = [ EmptyStrategy("001"), EmptyStrategy("002"), ] self.trader = Trader( trader_id=trader_id, strategies=strategies, data_engine=data_engine, exec_engine=self.exec_engine, clock=clock, uuid_factory=uuid_factory, logger=logger, )