"""Abstract base class for fundamental data providers.""" from __future__ import annotations from abc import ABC, abstractmethod from datetime import UTC, datetime from pydantic import BaseModel, Field # --------------------------------------------------------------------------- # FundamentalsSnapshot — canonical schema # # NOTE: This is the authoritative definition until it is moved into # ``shared.schemas.trading``. Once the parallel schema task lands, delete # this class and update all imports to point at the schemas module. # --------------------------------------------------------------------------- class FundamentalsSnapshot(BaseModel): """Point-in-time snapshot of a stock's fundamental financial metrics.""" ticker: str eps: float | None = None pe_ratio: float | None = None peg_ratio: float | None = None revenue_growth: float | None = None profit_margin: float | None = None debt_to_equity: float | None = None market_cap: float | None = None fetched_at: datetime = Field(default_factory=lambda: datetime.now(UTC)) model_config = {"from_attributes": True} # --------------------------------------------------------------------------- # Abstract provider # --------------------------------------------------------------------------- class FundamentalsProvider(ABC): """Abstract base class for fundamental data providers.""" @abstractmethod async def fetch(self, ticker: str) -> FundamentalsSnapshot | None: """Fetch fundamental data for *ticker*. Returns None on failure/rate limit.""" ...