"""Pydantic DTO —— 这就是 OpenAPI 契约(前端据此生成类型化客户端)。 契约先于业务锁定:字段一旦定下,前端可并行开发,后端实现改动不影响前端。 """ from __future__ import annotations from datetime import datetime from pydantic import BaseModel, Field # ---------- Candle ---------- class CandleOut(BaseModel): ts: datetime open: float high: float low: float close: float volume: float model_config = {"from_attributes": True} # ---------- Backtest ---------- class BacktestRequest(BaseModel): symbol: str = "DEMO" timeframe: str = "1d" strategy: str = "macd_cross" # macd_cross | ma_cross | single_ma params: dict[str, float] = Field(default_factory=dict) # 各策略参数 initial_cash: float = 1000000.0 fast_mode: bool = False # True => 关闭 T+1/费用,交互试探 start: datetime | None = None end: datetime | None = None class SignalOut(BaseModel): ts: datetime side: str # "buy" | "sell" price: float qty: float class EquityPoint(BaseModel): ts: datetime value: float class IndicatorOut(BaseModel): strategy: str data: dict[str, list[float | None]] = {} # 列名 -> 序列(MACD: macd/signal/hist;均线: fast/slow 或 ma) class MetricsOut(BaseModel): total_return: float max_drawdown: float sharpe: float volatility: float num_trades: int = 0 win_rate: float = 0.0 class BacktestResponse(BaseModel): symbol: str timeframe: str strategy: str candles: list[CandleOut] indicators: IndicatorOut signals: list[SignalOut] equity: list[EquityPoint] metrics: MetricsOut final_cash: float final_position: float initial_cash: float class SyncRequest(BaseModel): symbol: str start: str | None = None # YYYYMMDD end: str | None = None source: str = "auto" # auto | tushare | akshare force: bool = False # True => 忽略缓存重新拉取 class SyncResponse(BaseModel): symbol: str bars: int source: str