# -*- coding: utf-8 -*- """Trading service client for market data operations.""" import httpx from shared.schema.price import PriceResponse from shared.schema.financial import FinancialMetricsResponse, LineItemResponse from shared.schema.market import InsiderTradeResponse, CompanyFactsResponse from shared.schema.portfolio import Portfolio class TradingServiceClient: """Async client for the Trading Service API.""" def __init__(self, base_url: str = "http://localhost:8001"): """Initialize the client with a base URL. Args: base_url: Base URL for the trading service API. """ self.base_url = base_url.rstrip("/") self._client: httpx.AsyncClient | None = None async def __aenter__(self) -> "TradingServiceClient": self._client = httpx.AsyncClient(base_url=self.base_url, timeout=30.0) return self async def __aexit__(self, exc_type, exc_val, exc_tb) -> None: if self._client: await self._client.aclose() async def get_prices( self, ticker: str, start_date: str | None = None, end_date: str | None = None, ) -> PriceResponse: """Get price data for a ticker. Args: ticker: Stock ticker symbol. start_date: Start date (YYYY-MM-DD). end_date: End date (YYYY-MM-DD). Returns: PriceResponse with price data. """ params = {"ticker": ticker} if start_date: params["start_date"] = start_date if end_date: params["end_date"] = end_date response = await self._client.get("/api/prices", params=params) response.raise_for_status() return PriceResponse.model_validate(response.json()) async def get_news( self, ticker: str, start_date: str | None = None, end_date: str | None = None, ) -> dict: """Get news for a ticker. Args: ticker: Stock ticker symbol. start_date: Start date (YYYY-MM-DD). end_date: End date (YYYY-MM-DD). Returns: Dictionary with news data. """ params = {"ticker": ticker} if start_date: params["start_date"] = start_date if end_date: params["end_date"] = end_date response = await self._client.get("/api/news", params=params) response.raise_for_status() return response.json() async def get_financials( self, ticker: str, period: str | None = None, limit: int | None = None, ) -> FinancialMetricsResponse: """Get financial metrics for a ticker. Args: ticker: Stock ticker symbol. period: Reporting period (e.g., "annual", "quarterly"). limit: Maximum number of records to return. Returns: FinancialMetricsResponse with financial data. """ params = {"ticker": ticker} if period: params["period"] = period if limit: params["limit"] = limit response = await self._client.get("/api/financials", params=params) response.raise_for_status() return FinancialMetricsResponse.model_validate(response.json()) async def get_insider_trades( self, ticker: str, limit: int | None = None, ) -> InsiderTradeResponse: """Get insider trades for a ticker. Args: ticker: Stock ticker symbol. limit: Maximum number of records to return. Returns: InsiderTradeResponse with insider trade data. """ params = {"ticker": ticker} if limit: params["limit"] = limit response = await self._client.get("/api/insider-trades", params=params) response.raise_for_status() return InsiderTradeResponse.model_validate(response.json()) async def get_portfolio(self) -> Portfolio: """Get the current portfolio. Returns: Portfolio with current positions and cash. """ response = await self._client.get("/api/portfolio") response.raise_for_status() return Portfolio.model_validate(response.json()) async def post_trades(self, trades: list[dict]) -> dict: """Submit trades for execution. Args: trades: List of trade orders. Returns: Dictionary with trade execution results. """ response = await self._client.post("/api/trades", json=trades) response.raise_for_status() return response.json() async def post_settle(self) -> dict: """Settle all pending trades. Returns: Dictionary with settlement results. """ response = await self._client.post("/api/settle") response.raise_for_status() return response.json() async def get_market_status(self) -> dict: """Get current market status. Returns: Dictionary with market status information. """ response = await self._client.get("/api/market/status") response.raise_for_status() return response.json() async def get_company_facts(self, ticker: str) -> CompanyFactsResponse: """Get company facts for a ticker. Args: ticker: Stock ticker symbol. Returns: CompanyFactsResponse with company information. """ response = await self._client.get(f"/api/company/{ticker}/facts") response.raise_for_status() return CompanyFactsResponse.model_validate(response.json()) async def get_line_items( self, ticker: str, statement_type: str | None = None, period: str | None = None, ) -> LineItemResponse: """Get line items (financial statement data) for a ticker. Args: ticker: Stock ticker symbol. statement_type: Type of statement (income, balance, cash_flow). period: Reporting period. Returns: LineItemResponse with financial statement data. """ params = {"ticker": ticker} if statement_type: params["statement_type"] = statement_type if period: params["period"] = period response = await self._client.get("/api/line-items", params=params) response.raise_for_status() return LineItemResponse.model_validate(response.json())