Files
signal-platform/app/providers/protocol.py
T
dennisthiessen f0b92a9718
Deploy / lint (push) Successful in 5s
Deploy / test (push) Successful in 36s
Deploy / deploy (push) Successful in 25s
add earnings-date guard — warn when a report falls in the target horizon
Finnhub's earnings calendar now supplies next_earnings_date through the
fundamentals chain; persisted on fundamental_data (migration 006) and exposed in
the fundamentals API. The recommendation panel warns when earnings fall within
the ~30-day target horizon (a report can gap price through stop/target) and
otherwise shows the next date. Informational only.

Deploy: run alembic upgrade (new fundamental_data.next_earnings_date column).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 12:44:08 +02:00

89 lines
2.5 KiB
Python

"""Provider protocols and lightweight data transfer objects.
Protocols define the interface for external data providers.
DTOs are simple dataclasses — NOT SQLAlchemy models — used to
transfer data between providers and the service layer.
"""
from __future__ import annotations
from dataclasses import dataclass, field
from datetime import date, datetime
from typing import Protocol
# ---------------------------------------------------------------------------
# Data Transfer Objects
# ---------------------------------------------------------------------------
@dataclass(frozen=True, slots=True)
class OHLCVData:
"""Lightweight OHLCV record returned by market data providers."""
ticker: str
date: date
open: float
high: float
low: float
close: float
volume: int
@dataclass(frozen=True, slots=True)
class SentimentData:
"""Sentiment analysis result returned by sentiment providers."""
ticker: str
classification: str # "bullish" | "bearish" | "neutral"
confidence: int # 0-100
source: str
timestamp: datetime
reasoning: str = ""
citations: list[dict[str, str]] = field(default_factory=list) # [{"url": ..., "title": ...}]
@dataclass(frozen=True, slots=True)
class FundamentalData:
"""Fundamental metrics returned by fundamental providers."""
ticker: str
pe_ratio: float | None
revenue_growth: float | None
earnings_surprise: float | None
market_cap: float | None
fetched_at: datetime
next_earnings_date: date | None = None
unavailable_fields: dict[str, str] = field(default_factory=dict)
# ---------------------------------------------------------------------------
# Provider Protocols
# ---------------------------------------------------------------------------
class MarketDataProvider(Protocol):
"""Protocol for OHLCV market data providers."""
async def fetch_ohlcv(
self, ticker: str, start_date: date, end_date: date
) -> list[OHLCVData]:
"""Fetch OHLCV data for a ticker in a date range."""
...
class SentimentProvider(Protocol):
"""Protocol for sentiment analysis providers."""
async def fetch_sentiment(self, ticker: str) -> SentimentData:
"""Fetch current sentiment analysis for a ticker."""
...
class FundamentalProvider(Protocol):
"""Protocol for fundamental data providers."""
async def fetch_fundamentals(self, ticker: str) -> FundamentalData:
"""Fetch fundamental data for a ticker."""
...