def setUp(self):
        # Fixture Setup
        clock = TestClock()
        logger = Logger(clock)
        trader_id = TraderId("TESTER-000")
        self.order_factory = OrderFactory(
            trader_id=trader_id,
            strategy_id=StrategyId("S-001"),
            clock=TestClock(),
        )

        cache_db = BypassCacheDatabase(
            trader_id=trader_id,
            logger=logger,
        )

        cache = Cache(
            database=cache_db,
            logger=logger,
        )

        self.portfolio = Portfolio(
            cache=cache,
            clock=clock,
            logger=logger,
        )

        self.exec_engine = ExecutionEngine(
            portfolio=self.portfolio,
            cache=cache,
            clock=clock,
            logger=logger,
        )
    def setup(self):
        # Fixture Setup
        self.clock = TestClock()
        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=TestClock(),
        )

        self.database = BypassCacheDatabase(
            trader_id=self.trader_id, logger=self.logger
        )
Exemplo n.º 3
0
    def setUp(self):
        # Fixture Setup
        clock = TestClock()
        logger = Logger(clock, level_stdout=LogLevel.DEBUG)
        trader_id = TraderId("TESTER-000")

        self.order_factory = OrderFactory(
            trader_id=trader_id,
            strategy_id=StrategyId("S-001"),
            clock=TestClock(),
        )

        cache_db = BypassCacheDatabase(
            trader_id=trader_id,
            logger=logger,
        )

        self.cache = Cache(
            database=cache_db,
            logger=logger,
        )

        self.portfolio = Portfolio(
            cache=self.cache,
            clock=clock,
            logger=logger,
        )

        self.exec_engine = ExecutionEngine(
            portfolio=self.portfolio,
            cache=self.cache,
            clock=clock,
            logger=logger,
        )

        self.risk_engine = RiskEngine(
            exec_engine=self.exec_engine,
            portfolio=self.portfolio,
            cache=self.cache,
            clock=clock,
            logger=logger,
        )

        # Wire up components
        self.exec_engine.register_risk_engine(self.risk_engine)

        # Prepare components
        self.cache.add_instrument(AUDUSD_SIM)
        self.cache.add_instrument(GBPUSD_SIM)
        self.cache.add_instrument(BTCUSDT_BINANCE)
        self.cache.add_instrument(BTCUSD_BITMEX)
        self.cache.add_instrument(ETHUSD_BITMEX)
class TestBypassCacheDatabase:
    def setup(self):
        # Fixture Setup
        self.clock = TestClock()
        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=TestClock(),
        )

        self.database = BypassCacheDatabase(
            trader_id=self.trader_id, logger=self.logger
        )

    def teardown(self):
        self.database.flush()

    def test_load_currency_returns_none(self):
        assert self.database.load_currency(None) is None

    def test_load_instrument_returns_none(self):
        assert self.database.load_instrument(None) is None

    def test_load_account_returns_none(self):
        assert self.database.load_account(None) is None

    def test_load_order_returns_none(self):
        assert self.database.load_order(None) is None

    def test_load_position_returns_none(self):
        assert self.database.load_position(None) is None

    def test_load_strategy_returns_empty_dict(self):
        assert self.database.load_strategy(None) == {}
Exemplo n.º 5
0
def cache_db(trader_id, live_logger):
    return BypassCacheDatabase(
        trader_id=trader_id,
        logger=live_logger,
    )
Exemplo n.º 6
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")

        self._config = config

        # Extract configs
        config_trader = config.get("trader", {})
        config_system = config.get("system", {})
        config_log = config.get("logging", {})
        config_cache_db = config.get("cache_database", {})
        config_cache = config.get("cache", {})
        config_data = config.get("data_engine", {})
        config_risk = config.get("risk_engine", {})
        config_exec = config.get("exec_engine", {})
        config_strategy = config.get("strategy", {})

        # System config
        self._timeout_connection = config_system.get("timeout_connection", 5.0)
        self._timeout_reconciliation = config_system.get(
            "timeout_reconciliation", 10.0)
        self._timeout_portfolio = config_system.get("timeout_portfolio", 10.0)
        self._timeout_disconnection = config_system.get(
            "timeout_disconnection", 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(
            f"{config_trader['name']}-{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
        # ----------------------------------------------------------------------

        if config_cache_db["type"] == "redis":
            cache_db = RedisCacheDatabase(
                trader_id=self.trader_id,
                logger=self._logger,
                instrument_serializer=MsgPackInstrumentSerializer(),
                command_serializer=MsgPackCommandSerializer(),
                event_serializer=MsgPackEventSerializer(),
                config={
                    "host": config_cache_db["host"],
                    "port": config_cache_db["port"],
                },
            )
        else:
            cache_db = BypassCacheDatabase(
                trader_id=self.trader_id,
                logger=self._logger,
            )

        cache = Cache(
            database=cache_db,
            logger=self._logger,
            config=config_cache,
        )

        self.portfolio = Portfolio(
            cache=cache,
            clock=self._clock,
            logger=self._logger,
        )

        self._data_engine = LiveDataEngine(
            loop=self._loop,
            portfolio=self.portfolio,
            cache=cache,
            clock=self._clock,
            logger=self._logger,
            config=config_data,
        )

        self._exec_engine = LiveExecutionEngine(
            loop=self._loop,
            portfolio=self.portfolio,
            cache=cache,
            clock=self._clock,
            logger=self._logger,
            config=config_exec,
        )

        self._risk_engine = LiveRiskEngine(
            loop=self._loop,
            exec_engine=self._exec_engine,
            portfolio=self.portfolio,
            cache=cache,
            clock=self._clock,
            logger=self._logger,
            config=config_risk,
        )

        # Wire up components
        self._exec_engine.register_risk_engine(self._risk_engine)
        self._exec_engine.load_cache()

        self.trader = Trader(
            trader_id=self.trader_id,
            strategies=strategies,
            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 self._load_strategy_state:
            self.trader.load()

        self._builder = TradingNodeBuilder(
            data_engine=self._data_engine,
            exec_engine=self._exec_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
Exemplo n.º 7
0
 def cache_db():
     return BypassCacheDatabase(
         trader_id=TestStubs.trader_id(),
         logger=TestStubs.logger(),
     )