Files
All-in-one-Financial-Analysis/atlas-terminal/server/core/providers/yahooquery.py
T

67 lines
2.6 KiB
Python

"""YahooQuery provider for the ATLAS Data Gateway."""
from __future__ import annotations
from typing import Any
from server.core.data_gateway import Profile, Quote
from server.core.providers.base import BaseProvider, ProviderError
class YahooQueryProvider(BaseProvider):
name = "yahooquery"
def _ticker(self, symbol: str) -> Any:
try:
from yahooquery import Ticker
except Exception as exc: # pragma: no cover - dependency is expected in app runtime
raise ProviderError(f"yahooquery import failed: {exc}") from exc
return Ticker(symbol.strip().upper())
async def quote(self, symbol: str) -> Quote:
def fetch() -> Quote:
normalized = symbol.strip().upper()
data = self._ticker(normalized).price
row = data.get(normalized) if isinstance(data, dict) else None
if not isinstance(row, dict):
raise ProviderError("missing price payload")
price = row.get("regularMarketPrice") or row.get("postMarketPrice")
prev = row.get("regularMarketPreviousClose")
change = (price - prev) if isinstance(price, (int, float)) and isinstance(prev, (int, float)) else None
change_pct = (change / prev * 100) if change is not None and prev else None
return Quote(
symbol=normalized,
price=float(price) if isinstance(price, (int, float)) else None,
currency=row.get("currency"),
change=change,
change_pct=change_pct,
source=self.name,
raw=row,
)
return await self._to_thread(fetch)
async def profile(self, symbol: str) -> Profile:
def fetch() -> Profile:
normalized = symbol.strip().upper()
ticker = self._ticker(normalized)
profiles = ticker.asset_profile
row = profiles.get(normalized) if isinstance(profiles, dict) else None
if not isinstance(row, dict):
raise ProviderError("missing asset_profile payload")
return Profile(
symbol=normalized,
name=row.get("longName") or row.get("shortName"),
description=row.get("longBusinessSummary"),
sector=row.get("sector"),
industry=row.get("industry"),
country=row.get("country"),
exchange=row.get("exchange"),
website=row.get("website"),
employees=row.get("fullTimeEmployees"),
source=self.name,
raw=row,
)
return await self._to_thread(fetch)