def test_apply_order_filled_event_to_market_order(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) filled = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), last_px=Price("1.00001"), ) # Act order.apply(filled) # Assert self.assertEqual(OrderState.FILLED, order.state) self.assertEqual(Quantity(100000), order.filled_qty) self.assertEqual(Decimal("1.00001"), order.avg_px) self.assertEqual(1, len(order.execution_ids)) self.assertFalse(order.is_working) self.assertTrue(order.is_completed) self.assertEqual(0, order.execution_ns)
def setUp(self): # Fixture Setup self.clock = TestClock() uuid_factor = TestUUIDFactory() logger = TestLogger(self.clock) self.order_factory = OrderFactory( strategy_id=StrategyId("S", "001"), id_tag_trader=IdTag("001"), id_tag_strategy=IdTag("001"), clock=TestClock(), ) state = AccountState( AccountId.from_string("BITMEX-1513111-SIMULATED"), BTC, Money(10., BTC), Money(0., BTC), Money(0., BTC), uuid4(), UNIX_EPOCH ) self.account = Account(state) self.portfolio = Portfolio(self.clock, uuid_factor, logger) self.portfolio.register_account(self.account)
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, 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 self.assertEqual(command, deserialized) self.assertEqual(order, deserialized.order) print(command) print(len(serialized)) print(serialized) print(b64encode(serialized))
def setup(self): # Fixture Setup self.order_factory = OrderFactory( trader_id=TraderId("TESTER-000"), strategy_id=StrategyId("S-001"), clock=TestClock(), )
def test_apply_order_filled_event_to_market_order(self): # Arrange order = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) submitted = TestStubs.event_order_submitted(order) accepted = TestStubs.event_order_accepted(order) filled = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00001"), ) order.apply(submitted) order.apply(accepted) # Act order.apply(filled) # Assert self.assertEqual(OrderState.FILLED, order.state) self.assertEqual(Quantity(100000), order.filled_qty) self.assertEqual(Decimal("1.00001"), order.avg_price) self.assertEqual(1, len(order.execution_ids)) self.assertTrue(order.is_completed) self.assertEqual(UNIX_EPOCH, order.filled_timestamp)
def test_serialize_and_deserialize_order_filled_events(self): # Arrange event = OrderFilled( self.account_id, ClientOrderId("O-123456"), OrderId("1"), ExecutionId("E123456"), PositionId("T123456"), StrategyId("S", "001"), AUDUSD_SIM.symbol, OrderSide.SELL, Quantity(100000), Quantity(100000), Quantity(), Price("1.00000"), AUDUSD_SIM.quote_currency, AUDUSD_SIM.is_inverse, Money(0, USD), LiquiditySide.TAKER, UNIX_EPOCH, uuid4(), UNIX_EPOCH, ) # Act serialized = self.serializer.serialize(event) deserialized = self.serializer.deserialize(serialized) # Assert self.assertEqual(deserialized, event)
def test_serialize_and_deserialize_stop_limit_orders_with_expire_time( self): # Arrange order = StopLimitOrder( ClientOrderId("O-123456"), StrategyId("S", "001"), AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), price=Price("1.00000"), trigger=Price("1.00010"), time_in_force=TimeInForce.GTD, expire_time=UNIX_EPOCH, init_id=uuid4(), timestamp_ns=0, ) # Act serialized = self.serializer.serialize(order) deserialized = self.serializer.deserialize(serialized) # Assert self.assertEqual(order, deserialized) print(b64encode(serialized)) print(order)
def setUp(self): # Fixture Setup clock = TestClock() logger = TestLogger(clock) self.order_factory = OrderFactory( trader_id=TraderId("TESTER", "000"), strategy_id=StrategyId("S", "001"), clock=TestClock(), ) state = AccountState( account_id=AccountId("BINANCE", "1513111"), balances=[Money("10.00000000", BTC)], balances_free=[Money("0.00000000", BTC)], balances_locked=[Money("0.00000000", BTC)], info={}, event_id=uuid4(), event_timestamp=UNIX_EPOCH, ) self.data_cache = DataCache(logger) self.account = Account(state) self.portfolio = Portfolio(clock, logger) self.portfolio.register_account(self.account) self.portfolio.register_cache(self.data_cache) self.data_cache.add_instrument(AUDUSD_SIM) self.data_cache.add_instrument(GBPUSD_SIM) self.data_cache.add_instrument(BTCUSDT_BINANCE) self.data_cache.add_instrument(BTCUSD_BITMEX) self.data_cache.add_instrument(ETHUSD_BITMEX)
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_submit_bracket_order_command_to_from_dict_and_str_repr(self): # Arrange uuid = self.uuid_factory.generate() bracket = self.order_factory.bracket_market( instrument_id=AUDUSD_SIM.id, order_side=OrderSide.BUY, quantity=Quantity.from_int(100000), stop_loss=Price.from_str("1.00000"), take_profit=Price.from_str("1.00100"), ) command = SubmitOrderList( trader_id=TraderId("TRADER-001"), strategy_id=StrategyId("S-001"), order_list=bracket, command_id=uuid, ts_init=self.clock.timestamp_ns(), ) # Act, Assert assert SubmitOrderList.from_dict( SubmitOrderList.to_dict(command)) == command assert ( str(command) == "SubmitOrderList(instrument_id=AUD/USD.SIM, order_list=OrderList(id=1, instrument_id=AUD/USD.SIM, orders=[MarketOrder(BUY 100_000 AUD/USD.SIM MARKET GTC, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-1, venue_order_id=None, tags=ENTRY), StopMarketOrder(SELL 100_000 AUD/USD.SIM STOP_MARKET @ 1.00000 GTC, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-2, venue_order_id=None, tags=STOP_LOSS), LimitOrder(SELL 100_000 AUD/USD.SIM LIMIT @ 1.00100 GTC, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-3, venue_order_id=None, tags=TAKE_PROFIT)]))" # noqa ) assert ( repr(command) == f"SubmitOrderList(trader_id=TRADER-001, strategy_id=S-001, instrument_id=AUD/USD.SIM, order_list=OrderList(id=1, instrument_id=AUD/USD.SIM, orders=[MarketOrder(BUY 100_000 AUD/USD.SIM MARKET GTC, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-1, venue_order_id=None, tags=ENTRY), StopMarketOrder(SELL 100_000 AUD/USD.SIM STOP_MARKET @ 1.00000 GTC, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-2, venue_order_id=None, tags=STOP_LOSS), LimitOrder(SELL 100_000 AUD/USD.SIM LIMIT @ 1.00100 GTC, status=INITIALIZED, client_order_id=O-19700101-000000-000-001-3, venue_order_id=None, tags=TAKE_PROFIT)]), command_id={uuid}, ts_init=0)" # noqa )
def test_submit_bracket_order_raises_not_implemented_error(self): entry_order = self.order_factory.stop_market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), Price("0.99995"), ) # Act bracket_order = self.order_factory.bracket( entry_order, Price("0.99990"), Price("1.00010"), ) command = SubmitBracketOrder( entry_order.instrument_id, self.trader_id, self.account_id, StrategyId("SCALPER", "001"), bracket_order, self.uuid_factory.generate(), self.clock.timestamp_ns(), ) self.assertRaises(NotImplementedError, self.client.submit_bracket_order, command)
def test_submit_order_command_to_from_dict_and_str_repr(self): # Arrange uuid = self.uuid_factory.generate() order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) command = SubmitOrder( trader_id=TraderId("TRADER-001"), strategy_id=StrategyId("S-001"), position_id=PositionId("P-001"), order=order, command_id=uuid, ts_init=self.clock.timestamp_ns(), ) # Act, Assert assert SubmitOrder.from_dict(SubmitOrder.to_dict(command)) == command assert ( str(command) == "SubmitOrder(instrument_id=AUD/USD.SIM, client_order_id=O-19700101-000000-000-001-1, position_id=P-001, order=BUY 100_000 AUD/USD.SIM MARKET GTC)" # noqa ) assert ( repr(command) == f"SubmitOrder(trader_id=TRADER-001, strategy_id=S-001, instrument_id=AUD/USD.SIM, client_order_id=O-19700101-000000-000-001-1, position_id=P-001, order=BUY 100_000 AUD/USD.SIM MARKET GTC, command_id={uuid}, ts_init=0)" # noqa )
def test_cancel_order_command_with_none_venue_order_id_to_from_dict_and_str_repr( self): # Arrange uuid = self.uuid_factory.generate() command = CancelOrder( trader_id=TraderId("TRADER-001"), strategy_id=StrategyId("S-001"), instrument_id=AUDUSD_SIM.id, client_order_id=ClientOrderId("O-123456"), venue_order_id=None, command_id=uuid, ts_init=self.clock.timestamp_ns(), ) # Act, Assert assert CancelOrder.from_dict(CancelOrder.to_dict(command)) == command assert ( str(command) == "CancelOrder(instrument_id=AUD/USD.SIM, client_order_id=O-123456, venue_order_id=None)" # noqa ) assert ( repr(command) == f"CancelOrder(trader_id=TRADER-001, strategy_id=S-001, instrument_id=AUD/USD.SIM, client_order_id=O-123456, venue_order_id=None, command_id={uuid}, ts_init=0)" # noqa )
def test_modify_order_command_with_none_venue_order_id_to_from_dict_and_str_repr( self): # Arrange uuid = self.uuid_factory.generate() command = ModifyOrder( trader_id=TraderId("TRADER-001"), strategy_id=StrategyId("S-001"), instrument_id=AUDUSD_SIM.id, client_order_id=ClientOrderId("O-123456"), venue_order_id=None, price=Price.from_str("1.00000"), trigger=Price.from_str("1.00010"), quantity=Quantity.from_int(100000), command_id=uuid, ts_init=self.clock.timestamp_ns(), ) # Act, Assert assert ModifyOrder.from_dict(ModifyOrder.to_dict(command)) == command assert ( str(command) == "ModifyOrder(instrument_id=AUD/USD.SIM, client_order_id=O-123456, venue_order_id=None, quantity=100_000, price=1.00000, trigger=1.00010)" # noqa ) assert ( repr(command) == f"ModifyOrder(trader_id=TRADER-001, strategy_id=S-001, instrument_id=AUD/USD.SIM, client_order_id=O-123456, venue_order_id=None, quantity=100_000, price=1.00000, trigger=1.00010, command_id={uuid}, ts_init=0)" # noqa )
def test_position_changed_event_to_from_dict_and_str_repr(self): # Arrange order1 = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) fill1 = TestStubs.event_order_filled( order1, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00001"), ) order2 = self.order_factory.market( AUDUSD_SIM.id, OrderSide.SELL, Quantity.from_int(50000), ) fill2 = TestStubs.event_order_filled( order2, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00011"), ) position = Position(instrument=AUDUSD_SIM, fill=fill1) position.apply(fill2) uuid = UUID4() event = PositionChanged.create(position, fill2, uuid, 0) # Act, Assert assert PositionChanged.from_dict( PositionChanged.to_dict(event)) == event assert ( str(event) == "PositionChanged(instrument_id=AUD/USD.SIM, position_id=P-123456, account_id=SIM-000, from_order=O-19700101-000000-000-001-1, strategy_id=S-001, entry=BUY, side=LONG, net_qty=50_000, quantity=50_000, peak_qty=100_000, currency=USD, avg_px_open=1.00001, avg_px_close=1.00011, realized_points=0.00010, realized_return=0.00010, realized_pnl=2.00 USD, unrealized_pnl=5.00 USD, ts_opened=0, ts_last=0, ts_closed=0, duration_ns=0)" # noqa ) assert ( repr(event) == f"PositionChanged(trader_id=TESTER-000, strategy_id=S-001, instrument_id=AUD/USD.SIM, position_id=P-123456, account_id=SIM-000, from_order=O-19700101-000000-000-001-1, strategy_id=S-001, entry=BUY, side=LONG, net_qty=50_000, quantity=50_000, peak_qty=100_000, currency=USD, avg_px_open=1.00001, avg_px_close=1.00011, realized_points=0.00010, realized_return=0.00010, realized_pnl=2.00 USD, unrealized_pnl=5.00 USD, ts_opened=0, ts_last=0, ts_closed=0, duration_ns=0, event_id={uuid})" # noqa )
def test_apply_partial_fill_events_to_market_order_results_in_partially_filled( self, ): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity.from_int(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) fill1 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("1"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00001"), last_qty=Quantity.from_int(20000), ) fill2 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("2"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S-001"), last_px=Price.from_str("1.00002"), last_qty=Quantity.from_int(40000), ) # Act order.apply(fill1) order.apply(fill2) # Assert assert order.status == OrderStatus.PARTIALLY_FILLED assert order.filled_qty == Quantity.from_int(60000) assert order.leaves_qty == Quantity.from_int(40000) assert order.avg_px == Decimal("1.000014") assert len(order.execution_ids) == 2 assert order.is_active assert not order.is_inflight assert order.is_working assert not order.is_completed assert order.ts_last == 0
def test_market_value_when_insufficient_data_for_xrate_returns_none(self): # Arrange state = AccountState( account_id=AccountId("BITMEX", "01234"), balances=[Money("10.00000000", BTC), Money("10.00000000", ETH)], balances_free=[ Money("10.00000000", BTC), Money("10.00000000", ETH) ], balances_locked=[ Money("0.00000000", BTC), Money("0.00000000", ETH) ], info={}, event_id=uuid4(), event_timestamp=UNIX_EPOCH, ) account = Account(state) self.portfolio.register_account(account) order = self.order_factory.market( ETHUSD_BITMEX.symbol, OrderSide.BUY, Quantity(100), ) fill = TestStubs.event_order_filled( order=order, instrument=ETHUSD_BITMEX, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("376.05"), ) last_ethusd = QuoteTick( ETHUSD_BITMEX.symbol, Price("376.05"), Price("377.10"), Quantity("16"), Quantity("25"), UNIX_EPOCH, ) position = Position(fill) self.portfolio.update_position( TestStubs.event_position_opened(position)) self.data_cache.add_quote_tick(last_ethusd) self.portfolio.update_tick(last_ethusd) # Act result = self.portfolio.market_values(BITMEX) # Assert # TODO: Currently no Quanto thus no xrate required self.assertEqual({ETH: Money('0.02659221', ETH)}, result)
def test_stop_a_running_trader(self): # Arrange self.trader.start() # Act self.trader.stop() strategy_states = self.trader.strategy_states() # Assert self.assertEqual(ComponentState.STOPPED, self.trader.state) self.assertEqual( "STOPPED", strategy_states[StrategyId("TradingStrategy", "001")] ) self.assertEqual( "STOPPED", strategy_states[StrategyId("TradingStrategy", "002")] )
def setUp(self): # Fixture Setup self.account_id = TestStubs.account_id() self.order_factory = OrderFactory( strategy_id=StrategyId("S", "001"), id_tag_trader=IdTag("001"), id_tag_strategy=IdTag("001"), clock=TestClock())
def setUp(self): # Fixture Setup self.account_id = TestStubs.account_id() self.order_factory = OrderFactory( trader_id=TraderId("TESTER", "000"), strategy_id=StrategyId("S", "001"), clock=TestClock(), )
def setUp(self): # Fixture Setup self.serializer = MsgPackOrderSerializer() self.order_factory = OrderFactory( trader_id=TraderId("TESTER", "000"), strategy_id=StrategyId("S", "001"), clock=TestClock(), )
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_start_a_trader(self): # Arrange strategies = [ TradingStrategy(TradingStrategyConfig(order_id_tag="001")), TradingStrategy(TradingStrategyConfig(order_id_tag="002")), ] self.trader.add_strategies(strategies) # Act self.trader.start() strategy_states = self.trader.strategy_states() # Assert assert self.trader.is_running assert strategy_states[StrategyId("TradingStrategy-001")] == "RUNNING" assert strategy_states[StrategyId("TradingStrategy-002")] == "RUNNING"
def test_get_strategy_states(self): # Arrange strategies = [ TradingStrategy(TradingStrategyConfig(order_id_tag="001")), TradingStrategy(TradingStrategyConfig(order_id_tag="002")), ] self.trader.add_strategies(strategies) # Act status = self.trader.strategy_states() # Assert assert StrategyId("TradingStrategy-001") in status assert StrategyId("TradingStrategy-002") in status assert status[StrategyId("TradingStrategy-001")] == "INITIALIZED" assert status[StrategyId("TradingStrategy-002")] == "INITIALIZED" assert len(status) == 2
def test_add_strategy(self): # Arrange, Act self.trader.add_strategy(TradingStrategy()) # Assert assert self.trader.strategy_states() == { StrategyId("TradingStrategy-000"): "INITIALIZED" }
def test_position_filled_with_no_change_returns_expected_attributes(self): # Arrange order1 = self.order_factory.market( AUDUSD_FXCM, OrderSide.BUY, Quantity(100000)) order2 = self.order_factory.market( AUDUSD_FXCM, OrderSide.SELL, Quantity(100000)) fill1 = TestStubs.event_order_filled(order1) position = Position(fill1) fill2 = TestStubs.event_order_filled( order2, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("1.00000"), ) last = QuoteTick( AUDUSD_FXCM, Price("1.00050"), Price("1.00048"), Quantity(1), Quantity(1), UNIX_EPOCH, ) # Act position.apply(fill2) # Assert self.assertEqual(Quantity(), position.quantity) self.assertEqual(PositionSide.FLAT, position.side) self.assertEqual(UNIX_EPOCH, position.opened_time) self.assertEqual(1.0, position.avg_open_price) self.assertEqual(2, position.event_count()) self.assertEqual({order1.cl_ord_id, order2.cl_ord_id}, position.cl_ord_ids()) self.assertEqual({ ExecutionId("E-19700101-000000-001-001-1"), ExecutionId("E-19700101-000000-001-001-2") }, position.execution_ids(), ) self.assertEqual(UNIX_EPOCH, position.closed_time) self.assertEqual(1.0, position.avg_close_price) self.assertFalse(position.is_long()) self.assertFalse(position.is_short()) self.assertTrue(position.is_closed()) self.assertEqual(0.0, position.realized_points) self.assertEqual(0.0, position.realized_return) self.assertEqual(Money(0, USD), position.realized_pnl) self.assertEqual(Money(0, USD), position.unrealized_pnl(last)) self.assertEqual(Money(0, USD), position.total_pnl(last))
def test_apply_partial_fill_events_to_market_order_results_in_partially_filled( self, ): # Arrange order = self.order_factory.market( AUDUSD_SIM.id, OrderSide.BUY, Quantity(100000), ) order.apply(TestStubs.event_order_submitted(order)) order.apply(TestStubs.event_order_accepted(order)) fill1 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("1"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), last_px=Price("1.00001"), last_qty=Quantity(20000), ) fill2 = TestStubs.event_order_filled( order, instrument=AUDUSD_SIM, execution_id=ExecutionId("2"), position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), last_px=Price("1.00002"), last_qty=Quantity(40000), ) # Act order.apply(fill1) order.apply(fill2) # Assert self.assertEqual(OrderState.PARTIALLY_FILLED, order.state) self.assertEqual(Quantity(60000), order.filled_qty) self.assertEqual(Decimal("1.000014"), order.avg_px) self.assertEqual(2, len(order.execution_ids)) self.assertTrue(order.is_working) self.assertFalse(order.is_completed) self.assertEqual(0, order.execution_ns)
def test_calculate_given_one_long_one_short_returns_expected(self): # Arrange stat = LongRatio() order1 = self.order_factory.market( ETHUSD_FTX.id, OrderSide.BUY, Quantity.from_int(1), ) order2 = self.order_factory.market( ETHUSD_FTX.id, OrderSide.SELL, Quantity.from_int(1), ) fill1 = TestEventStubs.order_filled( order1, instrument=ETHUSD_FTX, position_id=PositionId("P-1"), strategy_id=StrategyId("S-001"), last_px=Price.from_int(10_000), ) fill2 = TestEventStubs.order_filled( order2, instrument=ETHUSD_FTX, position_id=PositionId("P-2"), strategy_id=StrategyId("S-001"), last_px=Price.from_int(10_000), ) position1 = Position(instrument=ETHUSD_FTX, fill=fill1) position1.apply(fill2) position2 = Position(instrument=ETHUSD_FTX, fill=fill2) position2.apply(fill1) data = [position1, position2] # Act result = stat.calculate_from_positions(data) # Assert assert result == "0.50"
def setup(self): # Fixture Setup self.trader_id = TestStubs.trader_id() self.instrument = BetfairTestStubs.betting_instrument() self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=StrategyId("S-001"), clock=TestClock(), )
def setUp(self): # Fixture Setup self.generator = ClientOrderIdGenerator(IdTag("001"), IdTag("001"), LiveClock()) self.order_factory = OrderFactory( trader_id=TraderId("TESTER", "000"), strategy_id=StrategyId("S", "001"), clock=TestClock(), )