You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

95 lines
3.2 KiB
Python

"""Dividend calendar Oracle service methods."""
from __future__ import annotations
import datetime as dt
from typing import Sequence
from libs.oracle_client.client import OracleClient
from libs.oracle_client.models import (
DividendCalendarEntry,
DividendHistoryResponse,
DividendIngestResponse,
DividendUpcomingResponse,
)
def _date_param(value: dt.date | str | None) -> str | None:
if value is None:
return None
if isinstance(value, dt.date):
return value.isoformat()
return str(value)
class DividendService:
def __init__(self, client: OracleClient) -> None:
self._client = client
async def get_upcoming(
self,
*,
as_of_date: dt.date | str | None = None,
from_ex_date: dt.date | str | None = None,
to_ex_date: dt.date | str | None = None,
symbols: Sequence[str] | None = None,
limit: int = 500,
force_refresh: bool = False,
) -> DividendUpcomingResponse:
params: dict[str, object] = {
"limit": int(limit),
"force_refresh": bool(force_refresh),
}
as_of = _date_param(as_of_date)
from_ex = _date_param(from_ex_date)
to_ex = _date_param(to_ex_date)
if as_of:
params["as_of_date"] = as_of
if from_ex:
params["from_ex_date"] = from_ex
if to_ex:
params["to_ex_date"] = to_ex
if symbols:
params["symbols"] = [str(symbol).strip().upper() for symbol in symbols if str(symbol).strip()]
data = await self._client.get("/api/v1/dividends/upcoming", params=params)
entries = [DividendCalendarEntry.model_validate(item) for item in data.get("dividends", [])]
return DividendUpcomingResponse(
dividends=entries,
total_count=int(data.get("total_count", len(entries))),
metadata=dict(data.get("metadata") or {}),
)
async def get_history(
self,
symbol: str,
*,
limit: int = 1000,
force_refresh: bool = False,
) -> DividendHistoryResponse:
data = await self._client.get(
f"/api/v1/dividends/history/{symbol}",
params={"limit": int(limit), "force_refresh": bool(force_refresh)},
)
entries = [DividendCalendarEntry.model_validate(item) for item in data.get("dividends", [])]
annual_yield_estimate = data.get("annual_yield_estimate")
return DividendHistoryResponse(
symbol=data.get("symbol", symbol),
dividends=entries,
total_count=int(data.get("total_count", len(entries))),
annual_yield_estimate=float(annual_yield_estimate) if annual_yield_estimate is not None else None,
metadata=dict(data.get("metadata") or {}),
)
async def ingest(
self,
symbols: Sequence[str],
*,
force_refresh: bool = False,
) -> DividendIngestResponse:
payload = {
"symbols": [str(symbol).strip().upper() for symbol in symbols if str(symbol).strip()],
"force_refresh": bool(force_refresh),
}
data = await self._client.post("/api/v1/dividends/admin/ingest", json=payload)
return DividendIngestResponse.model_validate(data)