"""Pydantic 请求/响应 Schema 定义""" from typing import Any from pydantic import BaseModel, Field # ==================== 数据采集 ==================== class BatchFetchRequest(BaseModel): """批量数据获取请求。""" symbols: list[str] = Field(..., description="品种合约代码列表") periods: list[str] = Field(default=["5min", "15min", "30min", "60min", "daily"], description="K线周期列表") data_type: str = Field(default="futures", description="数据类型: futures/stock") class CandleItem(BaseModel): """单根K线数据。""" datetime: str = Field(..., description="K线时间") open: float = Field(..., description="开盘价") close: float = Field(..., description="收盘价") high: float = Field(..., description="最高价") low: float = Field(..., description="最低价") volume: float = Field(default=0, description="成交量") class TimeframeData(BaseModel): """单个周期的K线数据集合。""" period: str = Field(..., description="周期") candles: list[CandleItem] = Field(default_factory=list, description="K线列表") candle_count: int = Field(default=0, description="K线数量") fetched_at: str = Field(default="", description="获取时间") class SymbolDataResponse(BaseModel): """单个品种数据响应。""" symbol: str data_type: str current_price: float | None = None timeframes: list[TimeframeData] = Field(default_factory=list) source: str = Field(default="cache", description="数据来源: cache/live/live+cache") class BatchFetchResponse(BaseModel): """批量获取响应。""" success: list[str] = Field(default_factory=list) failed: list[str] = Field(default_factory=list) details: dict[str, Any] = Field(default_factory=dict) class LatestDataResponse(BaseModel): """最新数据响应。""" symbol: str data_type: str current_price: float | None = None timeframes: list[TimeframeData] = Field(default_factory=list) source: str = "cache" # ==================== 定时任务 ==================== class CreateTaskRequest(BaseModel): """创建定时任务请求。""" symbol: str = Field(..., description="品种合约代码") data_type: str = Field(default="futures", description="数据类型") periods: list[str] = Field(default=["5min", "15min", "30min", "60min", "daily"], description="周期列表") interval_seconds: int = Field(default=300, description="轮询间隔(秒)") task_type: str = Field(default="interval", description="任务类型: interval/daily/once") run_time: str | None = Field(default=None, description="执行时间 HH:MM") class TaskInfo(BaseModel): """任务信息。""" id: int symbol: str data_type: str periods: list[str] interval_seconds: int task_type: str = "interval" enabled: bool = True running: bool = False last_run: str | None = None last_status: str | None = None next_run: str | None = None created_at: str updated_at: str class TaskListResponse(BaseModel): """任务列表响应。""" tasks: list[TaskInfo] total: int # ==================== 用户认证 ==================== class LoginRequest(BaseModel): """登录请求。""" username: str password: str class LoginResponse(BaseModel): """登录响应。""" success: bool token: str | None = None user: dict[str, Any] | None = None message: str | None = None class UserInfo(BaseModel): """用户信息。""" id: int username: str role: str email: str | None = None # ==================== AI 分析 ==================== class AIAnalysisRequest(BaseModel): """AI分析请求。""" symbol: str = Field(..., description="品种合约代码") force_refresh: bool = Field(default=False, description="是否强制刷新") class AIAnalysisResponse(BaseModel): """AI分析响应。""" success: bool data: dict[str, Any] | None = None is_cached: bool = False error: str | None = None warning: str | None = None # ==================== 复盘计划 ==================== class ReviewPlanRequest(BaseModel): """复盘计划生成请求。""" review_date: str = Field(..., description="复盘日期 YYYY-MM-DD") class ReviewPlanResponse(BaseModel): """复盘计划响应。""" success: bool data: dict[str, Any] | None = None message: str | None = None