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
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
|