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.

71 lines
2.3 KiB
Python

"""Screener Oracle service methods."""
from __future__ import annotations
from libs.oracle_client.client import OracleClient
from libs.oracle_client.models import ScreenerResponse, ScreenerStock
_SCREENER_PATH = "/api/v1/screener/stocks"
_DEFAULT_PAGE_SIZE = 250
class ScreenerService:
def __init__(self, client: OracleClient) -> None:
self._client = client
async def search_stocks(
self,
market_cap_min: float | None = None,
market_cap_max: float | None = None,
min_avg_volume: int | None = None,
exchange: str | None = None,
exclude_types: str | None = None,
price_min: float | None = None,
page: int = 1,
page_size: int = _DEFAULT_PAGE_SIZE,
) -> ScreenerResponse:
"""GET /api/v1/screener/stocks — single page."""
params: dict[str, str | int | float] = {
"page": page,
"page_size": page_size,
}
if market_cap_min is not None:
params["market_cap_min"] = market_cap_min
if market_cap_max is not None:
params["market_cap_max"] = market_cap_max
if min_avg_volume is not None:
params["min_avg_volume"] = min_avg_volume
if exchange is not None:
params["exchange"] = exchange
if exclude_types is not None:
params["exclude_types"] = exclude_types
if price_min is not None:
params["price_min"] = price_min
data = await self._client.get(_SCREENER_PATH, params=params)
stocks = [ScreenerStock.model_validate(s) for s in data.get("stocks", [])]
return ScreenerResponse(
stocks=stocks,
total=data.get("total", len(stocks)),
page=page,
page_size=page_size,
)
async def search_all_stocks(self, **kwargs) -> list[ScreenerStock]:
"""Auto-paginate and return all matching stocks."""
all_stocks: list[ScreenerStock] = []
page = 1
page_size = kwargs.pop("page_size", _DEFAULT_PAGE_SIZE)
while True:
resp = await self.search_stocks(**kwargs, page=page, page_size=page_size)
if not resp.stocks:
break
all_stocks.extend(resp.stocks)
if len(resp.stocks) < page_size:
break
page += 1
return all_stocks