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>
This commit is contained in:
2026-03-23 17:45:39 +08:00
parent 0f1bc2bb39
commit 3448667b79
54 changed files with 5440 additions and 2947 deletions

View File

@@ -5,8 +5,7 @@ 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
from shared.schema.market import InsiderTradeResponse
class TradingServiceClient:
@@ -107,6 +106,8 @@ class TradingServiceClient:
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.
@@ -119,45 +120,16 @@ class TradingServiceClient:
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_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.
@@ -168,40 +140,32 @@ class TradingServiceClient:
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")
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 CompanyFactsResponse.model_validate(response.json())
return response.json()
async def get_line_items(
self,
ticker: str,
statement_type: str | None = None,
period: str | None = None,
line_items: list[str],
end_date: str,
period: str = "ttm",
limit: int = 10,
) -> 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
"""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())