feat(web): M6.5 股票筛选页(/selection)—— 评分/条件双模式 + 当前/历史选股

- app/selection/page.tsx:因子评分(多因子+权重+TopN)与条件模式(结构化条件行
  编辑:static.*/因子/close>ma60/ROE 等,AND 语义);as_of 留空=最近交易日;
  结果表(rank/symbol/score/因子值/入选理由)+ 最近选股记录点击回看
- lib/types.ts:SelectionQuery/Condition/Candidate/Result/Meta/Run DTO
- app-shell 导航加入「股票筛选」;rail 脚注与 Dashboard 文案 SQLite→MySQL(M-DB 收尾)
- 端到端验证:真实 MySQL 上 POST /api/selections 返回候选并落库可读回;
  /selection 页面 200;后端全量 pytest + 前端 tsc --noEmit 通过
This commit is contained in:
Simon
2026-09-09 00:25:27 +08:00
parent 0d3e123de3
commit 0ab9038570
4 changed files with 443 additions and 2 deletions
+53
View File
@@ -73,3 +73,56 @@ export interface FactorTestReport {
sample_days: number;
unimplemented: string[];
}
/* ---- 选股系统(v2 §14/§21.1,与 domain/entities/selection.py 对应) ---- */
export interface SelectionCondition {
field: string;
op: "gt" | "gte" | "lt" | "lte" | "eq" | "ne" | "in" | "not_in";
value?: number | string | (number | string)[] | null;
ref?: string | null;
}
export interface SelectionQuery {
universe: { exclude_st?: boolean; min_listing_days?: number };
as_of?: string | null; // null/省略 = 最近交易日
method: "score" | "condition";
factors: { name: string; weight: number }[];
conditions: SelectionCondition[];
top_n?: number | null;
top_pct?: number | null;
min_score?: number | null;
}
export interface SelectionCandidate {
symbol: string;
rank: number;
score: number;
factor_values: Record<string, number>;
filter_status: string[];
selection_reason: string[];
}
export interface SelectionResult {
as_of_date: string;
method: string;
statistics: { universe_size: number; evaluated: number; selected: number };
candidates: SelectionCandidate[];
unimplemented: string[];
config_snapshot: Record<string, unknown>;
}
export interface SelectionMeta {
id: string;
as_of: string;
method: string;
universe_size: number;
selected: number;
created_at?: string | null;
}
export interface SelectionRun {
selection_id: string;
result: SelectionResult;
}