47 lines
1.6 KiB
Python
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."""
|
|
...
|