def test_config_with_inmemory_execution_database(self): # Arrange config = TradingNodeConfig(cache_database=CacheDatabaseConfig( type="in-memory")) # Act node = TradingNode(config=config) # Assert assert node is not None
config_node = TradingNodeConfig( trader_id="TESTER-001", log_level="INFO", exec_engine={ "reconciliation_lookback_mins": 1440, }, # cache_database=CacheDatabaseConfig(), data_clients={ "BINANCE": BinanceDataClientConfig( api_key=None, # "YOUR_BINANCE_API_KEY" api_secret=None, # "YOUR_BINANCE_API_SECRET" account_type=BinanceAccountType.SPOT, base_url_http=None, # Override with custom endpoint base_url_ws=None, # Override with custom endpoint us=False, # If client is for Binance US testnet=False, # If client uses the testnet instrument_provider=InstrumentProviderConfig(load_all=True), ), }, exec_clients={ "BINANCE": BinanceExecClientConfig( api_key=None, # "YOUR_BINANCE_API_KEY" api_secret=None, # "YOUR_BINANCE_API_SECRET" account_type=BinanceAccountType.SPOT, base_url_http=None, # Override with custom endpoint base_url_ws=None, # Override with custom endpoint us=False, # If client is for Binance US testnet=False, # If client uses the testnet load_all_instruments=True, # If load all instruments on start load_instrument_ids=[], # Optionally pass a list of instrument IDs instrument_provider=InstrumentProviderConfig(load_all=True), ), }, timeout_connection=5.0, timeout_reconciliation=5.0, timeout_portfolio=5.0, timeout_disconnection=5.0, check_residuals_delay=2.0, )
config_node = TradingNodeConfig( trader_id="TESTER-001", log_level="INFO", exec_engine={ "reconciliation_lookback_mins": 1440, }, # cache_database=CacheDatabaseConfig(), data_clients={ "FTX": FTXDataClientConfig( api_key=None, # "YOUR_FTX_API_KEY" api_secret=None, # "YOUR_FTX_API_SECRET" subaccount=None, # "YOUR_FTX_SUBACCOUNT" us=False, # If client is for FTX US instrument_provider=InstrumentProviderConfig(load_all=True), ), }, exec_clients={ "FTX": FTXExecClientConfig( api_key=None, # "YOUR_FTX_API_KEY" api_secret=None, # "YOUR_FTX_API_SECRET" subaccount=None, # "YOUR_FTX_SUBACCOUNT" us=False, # If client is for FTX US instrument_provider=InstrumentProviderConfig(load_all=True), ), }, timeout_connection=5.0, timeout_reconciliation=5.0, timeout_portfolio=5.0, timeout_disconnection=5.0, check_residuals_delay=2.0, )
config_node = TradingNodeConfig( trader_id="TESTER-001", log_level="INFO", exec_engine={ "reconciliation_lookback_mins": 1440, }, # cache_database=CacheDatabaseConfig(), data_clients={ "BINANCE": BinanceDataClientConfig( # api_key=os.getenv("BINANCE_FUTURES_API_KEY"), # api_secret=os.getenv("BINANCE_FUTURES_API_SECRET"), account_type=BinanceAccountType.FUTURES_USDT, instrument_provider=InstrumentProviderConfig(load_all=True), ), }, exec_clients={ "BINANCE": BinanceExecClientConfig( # api_key=os.getenv("BINANCE_FUTURES_API_KEY"), # api_secret=os.getenv("BINANCE_FUTURES_API_SECRET"), account_type=BinanceAccountType.FUTURES_USDT, instrument_provider=InstrumentProviderConfig(load_all=True), ), }, timeout_connection=5.0, timeout_reconciliation=5.0, timeout_portfolio=5.0, timeout_disconnection=5.0, check_residuals_delay=2.0, )
async def main(market_id: str): # Connect to Betfair client early to load instruments and account currency loop = asyncio.get_event_loop() logger = LiveLogger(loop=loop, clock=LiveClock()) client = get_cached_betfair_client( username= None, # Pass here or will source from the `BETFAIR_USERNAME` env var password= None, # Pass here or will source from the `BETFAIR_PASSWORD` env var app_key= None, # Pass here or will source from the `BETFAIR_APP_KEY` env var cert_dir= None, # Pass here or will source from the `BETFAIR_CERT_DIR` env var logger=logger, loop=loop, ) await client.connect() # Find instruments for a particular market_id market_filter = {"market_id": (market_id, )} provider = get_cached_betfair_instrument_provider( client=client, logger=logger, market_filter=tuple(market_filter.items()), ) await provider.load_all_async() instruments = provider.list_all() print(f"Found instruments:\n{instruments}") # Determine account currency account = await client.get_account_details() # Configure trading node config = TradingNodeConfig( timeout_connection=30.0, log_level="DEBUG", cache_database=CacheDatabaseConfig(type="in-memory"), exec_engine={"allow_cash_positions": True}, # Retain original behaviour for now data_clients={ "BETFAIR": { # "username": "******", # "password": "******", # "app_key": "YOUR_BETFAIR_APP_KEY", # "cert_dir": "YOUR_BETFAIR_CERT_DIR", "market_filter": market_filter, }, }, exec_clients={ "BETFAIR": { "base_currency": account["currencyCode"], # "username": "******", # "password": "******", # "app_key": "YOUR_BETFAIR_APP_KEY", # "cert_dir": "YOUR_BETFAIR_CERT_DIR", "market_filter": market_filter, }, }, ) strategies = [ OrderBookImbalance(config=OrderBookImbalanceConfig( instrument_id=instrument.id.value, max_trade_size=10, order_id_tag=instrument.selection_id, )) for instrument in instruments ] # Setup TradingNode node = TradingNode(config=config) node.trader.add_strategies(strategies) # Register your client factories with the node (can take user defined factories) node.add_data_client_factory("BETFAIR", BetfairLiveDataClientFactory) node.add_exec_client_factory("BETFAIR", BetfairLiveExecClientFactory) node.build() try: await node.start() except Exception as ex: print(ex) print(traceback.format_exc()) finally: node.dispose()
def __init__(self, config: Optional[TradingNodeConfig] = None): if config is None: config = TradingNodeConfig() PyCondition.not_none(config, "config") PyCondition.type(config, TradingNodeConfig, "config") # Configuration self._config = config # 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.loop_debug) # Components self._clock = LiveClock(loop=self._loop) self._uuid_factory = UUIDFactory() self.created_time = self._clock.utc_now() self._is_running = False # Identifiers self.trader_id = TraderId(config.trader_id) self.machine_id = socket.gethostname() self.instance_id = self._uuid_factory.generate() # Setup logging self._logger = LiveLogger( loop=self._loop, clock=self._clock, trader_id=self.trader_id, machine_id=self.machine_id, instance_id=self.instance_id, level_stdout=LogLevelParser.from_str_py(config.log_level.upper()), ) self._log = LoggerAdapter( component_name=type(self).__name__, logger=self._logger, ) self._log_header() self._log.info("Building...") if platform.system() != "Windows": # Windows does not support signal handling # https://stackoverflow.com/questions/45987985/asyncio-loops-add-signal-handler-in-windows self._setup_loop() ######################################################################## # Build platform ######################################################################## if config.cache_database is None or config.cache_database.type == "in-memory": cache_db = None elif config.cache_database.type == "redis": cache_db = RedisCacheDatabase( trader_id=self.trader_id, logger=self._logger, serializer=MsgPackSerializer(timestamps_as_str=True), config=config.cache_database, ) else: # pragma: no cover (design-time error) raise ValueError( "The cache_db_type in the configuration is unrecognized, " "can one of {{'in-memory', 'redis'}}.", ) self._msgbus = MessageBus( trader_id=self.trader_id, clock=self._clock, logger=self._logger, ) self._cache = Cache( database=cache_db, logger=self._logger, config=config.cache, ) self.portfolio = Portfolio( msgbus=self._msgbus, cache=self._cache, clock=self._clock, logger=self._logger, ) self._data_engine = LiveDataEngine( loop=self._loop, msgbus=self._msgbus, cache=self._cache, clock=self._clock, logger=self._logger, config=config.data_engine, ) self._exec_engine = LiveExecutionEngine( loop=self._loop, msgbus=self._msgbus, cache=self._cache, clock=self._clock, logger=self._logger, config=config.exec_engine, ) self._exec_engine.load_cache() self._risk_engine = LiveRiskEngine( loop=self._loop, portfolio=self.portfolio, msgbus=self._msgbus, cache=self._cache, clock=self._clock, logger=self._logger, config=config.risk_engine, ) self.trader = Trader( trader_id=self.trader_id, msgbus=self._msgbus, cache=self._cache, portfolio=self.portfolio, data_engine=self._data_engine, risk_engine=self._risk_engine, exec_engine=self._exec_engine, clock=self._clock, logger=self._logger, ) if config.load_strategy_state: self.trader.load() # Setup persistence (requires trader) self.persistence_writers: List[Any] = [] if config.persistence: self._setup_persistence(config=config.persistence) self._builder = TradingNodeBuilder( loop=self._loop, data_engine=self._data_engine, exec_engine=self._exec_engine, msgbus=self._msgbus, cache=self._cache, clock=self._clock, logger=self._logger, log=self._log, ) self._log.info("INITIALIZED.") self.time_to_initialize = self._clock.delta(self.created_time) self._log.info(f"Initialized in {int(self.time_to_initialize.total_seconds() * 1000)}ms.") self._is_built = False
config_node = TradingNodeConfig( trader_id="TESTER-001", log_level="INFO", data_clients={ "IB": InteractiveBrokersDataClientConfig( gateway_host="127.0.0.1", instrument_provider=InstrumentProviderConfig( load_all=True, filters=tuple({ "secType": "CASH", "pair": "EURUSD" }.items()), # filters=tuple( # { # "secType": "STK", # "symbol": "9988", # "exchange": "SEHK", # "currency": "HKD", # "build_options_chain": True, # "option_kwargs": json.dumps( # { # "min_expiry": "20220601", # "max_expiry": "20220701", # "min_strike": 90, # "max_strike": 110, # "exchange": "SEHK" # } # ), # }.items() # ), ), routing=RoutingConfig(venues={"IDEALPRO"}), ), }, # exec_clients={ # "IB": InteractiveBrokersExecClientConfig(), # }, timeout_connection=90.0, timeout_reconciliation=5.0, timeout_portfolio=5.0, timeout_disconnection=5.0, check_residuals_delay=2.0, )