Files
evotraders/shared/client/trading_client.py
cillin 3448667b79 feat: 微服务架构拆分和前后端优化
后端:
- 拆分出 agent_service, runtime_service, trading_service, news_service
- Gateway 模块化拆分 (gateway_*.py)
- 添加 domains/ 领域层
- 新增 control_client, runtime_client
- 更新 start-dev.sh 支持 split 服务模式

前端:
- 完善 API 服务层 (newsApi, tradingApi)
- 更新 vite.config.js
- Explain 组件优化

测试:
- 添加多个服务 app 测试

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 17:45:39 +08:00

172 lines
5.3 KiB
Python

# -*- 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
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,
end_date: str | None = None,
start_date: str | None = None,
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 start_date:
params["start_date"] = start_date
if end_date:
params["end_date"] = end_date
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_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_market_cap(self, ticker: str, end_date: str) -> dict:
"""Get market cap for a ticker/date."""
response = await self._client.get(
"/api/market-cap",
params={"ticker": ticker, "end_date": end_date},
)
response.raise_for_status()
return response.json()
async def get_line_items(
self,
ticker: str,
line_items: list[str],
end_date: str,
period: str = "ttm",
limit: int = 10,
) -> LineItemResponse:
"""Get line-item search results for a ticker/date."""
params: list[tuple[str, str | int]] = [
("ticker", ticker),
("end_date", end_date),
("period", period),
("limit", limit),
]
for item in line_items:
params.append(("line_items", item))
response = await self._client.get("/api/line-items", params=params)
response.raise_for_status()
return LineItemResponse.model_validate(response.json())