功能更新

This commit is contained in:
2026-08-15 08:57:15 +08:00
parent 50fd032b45
commit c1c43d2ff7
30 changed files with 1908 additions and 888 deletions

View File

@@ -24,7 +24,7 @@ class CandleOut(BaseModel):
# ---------- Backtest ----------
class BacktestRequest(BaseModel):
symbol: str = "DEMO"
symbol: str = "000001"
timeframe: str = "1d"
strategy: str = "macd_cross" # macd_cross | ma_cross | single_ma
params: dict[str, float] = Field(default_factory=dict) # 各策略参数
@@ -82,6 +82,68 @@ class SyncRequest(BaseModel):
force: bool = False # True => 忽略缓存重新拉取
# ---------- Event Backtest自然语言事件回测 ----------
class EventBacktestSpec(BaseModel):
"""事件回测参数entry 条件在信号日 D 收盘确认 -> D+1 买入 -> 持有 N 日卖出。"""
entry: ScreenConditions
entry_timing: Literal["next_open", "next_close"] = "next_open" # 次日开盘/收盘买入
holding_days: int = Field(default=3, ge=1, le=250) # 买入后再持有 N 个交易日
exit_timing: Literal["close", "open"] = "close" # 到期按收盘/开盘卖出
class EventBacktestRequest(BaseModel):
text: str = Field(min_length=2, max_length=500)
spec: EventBacktestSpec | None = None # 直传则跳过 LLM 解析(调参重跑)
ts_code: str | None = None # 指定则只回测该股;空则全市场
start: datetime | None = None
end: datetime | None = None
class EventTradeOut(BaseModel):
ts_code: str
name: str | None = None
entry_date: datetime
entry_price: float
exit_date: datetime
exit_price: float
ret_pct: float # 区间收益率 %(复权校正)
class EventYearStatOut(BaseModel):
year: int
samples: int
mean_pct: float
median_pct: float
win_rate: float
class EventStatsOut(BaseModel):
samples: int
stocks: int
mean_pct: float
median_pct: float
win_rate: float # %
std_pct: float = 0.0
p10_pct: float = 0.0
p25_pct: float = 0.0
p75_pct: float = 0.0
p90_pct: float = 0.0
max_pct: float = 0.0
min_pct: float = 0.0
by_year: list[EventYearStatOut] = Field(default_factory=list)
class EventBacktestResponse(BaseModel):
text: str
spec: EventBacktestSpec
universe: str # "all" 或 ts_code
start: datetime
end: datetime
stats: EventStatsOut
trades: list[EventTradeOut] = Field(default_factory=list) # 最好+最差样本(各 100
total: int
class SyncResponse(BaseModel):
symbol: str
bars: int
@@ -197,7 +259,7 @@ class PreviewInfoOut(BaseModel):
class PreviewResponse(BaseModel):
ts_code: str
symbol: str
source: str # qfq=回测缓存全量前复权 | market=近段未复权兜底
source: str # bfq|qfq|hfq=实际复权口径(本地 adj_factor 换算) | market=近段未复权兜底
info: PreviewInfoOut
candles: list[CandleOut]
indicators: dict[str, dict[str, list[float | None]]] = Field(default_factory=dict)
@@ -220,3 +282,61 @@ class CurrentUserOut(BaseModel):
class LoginResponse(BaseModel):
user: CurrentUserOut
expires_at: datetime
# ---------- 股票列表(全市场浏览) ----------
class StockListItemOut(BaseModel):
ts_code: str
symbol: str
name: str
industry: str | None = None
market: str | None = None
close: float | None = None # 最新收盘candles 未复权)
prev_close: float | None = None
pct_chg: float | None = None # 最新两根日线计算
last_ts: datetime | None = None
bar_count: int | None = None # 本地缓存日线条数
watched: bool = False # 是否自选(当前用户)
class StockListResponse(BaseModel):
total: int
items: list[StockListItemOut]
# ---------- 看股页筛选项 ----------
class FacetItemOut(BaseModel):
name: str
count: int
class StockFacetsResponse(BaseModel):
industries: list[FacetItemOut] = Field(default_factory=list)
areas: list[FacetItemOut] = Field(default_factory=list)
# ---------- 用户偏好 / 自选股 / 提问历史 ----------
class PreferencesOut(BaseModel):
prefs: dict[str, object] = Field(default_factory=dict) # key -> JSON 值
class PreferencesUpdate(BaseModel):
prefs: dict[str, object] # 部分更新:只覆盖出现的 key值为 null 表示删除)
class WatchlistOp(BaseModel):
ts_code: str = Field(min_length=6, max_length=12)
class ScreenerQueryOut(BaseModel):
id: int
text: str
conditions: ScreenConditions | None = None
hit_count: int | None = None
created_at: datetime
model_config = {"from_attributes": True}
class ScreenerQueryListResponse(BaseModel):
items: list[ScreenerQueryOut]