"""Strategy Engine Service entry point.""" import asyncio from pathlib import Path from shared.broker import RedisBroker from shared.healthcheck import HealthCheckServer from shared.logging import setup_logging from shared.metrics import ServiceMetrics from shared.notifier import TelegramNotifier from strategy_engine.config import StrategyConfig from strategy_engine.engine import StrategyEngine from strategy_engine.plugin_loader import load_strategies # The strategies directory lives alongside the installed package STRATEGIES_DIR = Path(__file__).parent.parent.parent.parent / "strategies" async def run() -> None: config = StrategyConfig() log = setup_logging("strategy-engine", config.log_level, config.log_format) metrics = ServiceMetrics("strategy_engine") notifier = TelegramNotifier( bot_token=config.telegram_bot_token, chat_id=config.telegram_chat_id ) broker = RedisBroker(config.redis_url) strategies_dir = STRATEGIES_DIR strategies = load_strategies(strategies_dir) # Configure each strategy with params from config for strategy in strategies: params = config.strategy_params.get(strategy.name, {}) strategy.configure(params) log.info( "strategies_loaded", count=len(strategies), names=[s.name for s in strategies], ) engine = StrategyEngine(broker=broker, strategies=strategies) health = HealthCheckServer("strategy-engine", port=config.health_port + 1, auth_token=config.metrics_auth_token) health.register_check("redis", broker.ping) await health.start() metrics.service_up.labels(service="strategy-engine").set(1) try: for symbol in config.symbols: stream = f"candles.{symbol.replace('/', '_')}" last_id = "$" log.info("engine_loop_started", stream=stream) while True: last_id = await engine.process_once(stream, last_id) metrics.events_processed.labels( service="strategy-engine", event_type="candle" ).inc() except Exception as exc: log.error("fatal_error", error=str(exc)) await notifier.send_error(str(exc), "strategy-engine") raise finally: metrics.service_up.labels(service="strategy-engine").set(0) await notifier.close() await broker.close() def main() -> None: asyncio.run(run()) if __name__ == "__main__": main()