trading/shared/fundamentals/base.py

47 lines
1.6 KiB
Python

"""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."""
...