""" Market data provider interface and registry. To add a new provider: 1. Create providers/your_provider.py 2. Subclass MarketDataProvider 3. Register in PROVIDER_REGISTRY below """ from __future__ import annotations from abc import ABC, abstractmethod from typing import AsyncIterator from app.domain.events import Event class MarketDataProvider(ABC): """ Base class for all market-data feed adapters. Lifecycle: connect() → subscribe() → stream() → close() """ name: str = "unknown" @abstractmethod async def connect(self) -> None: """Establish connection to the data source.""" @abstractmethod async def subscribe(self, symbols: list[str]) -> None: """Subscribe to symbols. May be called after reconnect.""" @abstractmethod async def stream(self) -> AsyncIterator[Event]: """Yield normalized domain events. Must handle reconnect internally.""" yield # type: ignore @abstractmethod async def close(self) -> None: """Graceful shutdown.""" def get_provider(name: str) -> MarketDataProvider: """Factory: instantiate provider by name.""" from app.providers.binance import BinanceProvider from app.providers.alpaca import AlpacaProvider from app.providers.bybit import BybitProvider registry: dict[str, type[MarketDataProvider]] = { "binance": BinanceProvider, "alpaca": AlpacaProvider, "bybit": BybitProvider, } cls = registry.get(name.lower()) if cls is None: available = ", ".join(registry.keys()) raise ValueError(f"Unknown provider '{name}'. Available: {available}") return cls()