feat(selection): 集成 B1 FastDTW 图形评分
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
# 知行 B1 集成原项目评分
|
||||
|
||||
## Goal
|
||||
|
||||
在不改变知行 B1 选股语义的前提下,复用原项目的案例、特征、权重和阈值,并修正曲线距离为真正生效的 FastDTW,为每只 B1 命中股票提供可解释、可持久化、可验证的 0–100 最佳案例匹配结果。
|
||||
|
||||
## Background
|
||||
|
||||
当前系统已具备 `POST /api/v1/selection/runs`、后台批量评估、PostgreSQL 结果持久化、结果查询与前端轮询展示;策略固定为 `zhixing_b1`,按显式目标交易日读取 qfq OHLCV,并独立保留七种子信号(`.trellis/spec/backend/selection.md:12-49,85-152`,`docs/adr/0005-selection-formula-semantics-and-independent-subsignals.md:7-23`)。评分尚未接入。
|
||||
|
||||
用户已明确本任务只迁移 Python 可执行的 0–100 图形相似度评分,不迁移 prompt 中依赖图片和大模型的 1–5 主观视觉评分。
|
||||
|
||||
实施门禁发现原源码的一维 FastDTW 调用实际抛错并回退 `_simple_dtw`;用户进一步确认版本一直接修正为真正生效的 FastDTW,因为允许局部时间对齐更符合评分要求。新分数使用独立版本,不承诺兼容旧 `_simple_dtw` 历史结果。
|
||||
|
||||
原可执行评分在候选信号产生后运行,对候选最近 25 个交易日与十个固定案例比较趋势结构、KDJ、量能和价格形态,实际权重为 `0.10/0.20/0.25/0.45`,总分为加权和乘以 100;每股只保留最高分案例,达到 `60.0` 才 enrichment(`/Users/yuxuanhui/bcc-github/quant-project/zgnb/zgnb-project/src/zgnb/domain/pattern/config.py:8-38`,`/Users/yuxuanhui/bcc-github/quant-project/zgnb/zgnb-project/src/zgnb/domain/pattern/matcher.py:19-128`,`/Users/yuxuanhui/bcc-github/quant-project/zgnb/zgnb-project/src/zgnb/application/pipeline.py:168-220`)。原文档权重与运行代码不一致,YAML 动态权重也未真正注入,迁移以实际运行代码为兼容基线。
|
||||
|
||||
原案例行情与缓存均未被 Git 跟踪,缓存没有版本或失效校验且已与当前行情漂移;原项目也没有评分数值 golden 测试。完整证据记录在 `research/scoring-analysis.md`。
|
||||
|
||||
## Requirements
|
||||
|
||||
- R1:评分必须是 B1 命中后的 enrichment,不参与七个 mask 的判断,不改变股票是否选中、同股多 category、signals 顺序或 `(ts_code, target_trade_date, strategy, category)` 稳定身份。
|
||||
- R2:版本一固定使用原运行代码的十个案例、25 日升序窗口、四维特征、`0.10/0.20/0.25/0.45` 权重、容忍参数、最佳案例规则和 `>= 60.0` 阈值;曲线距离使用真正生效、显式半径的 FastDTW,版本标识为 `zhixing_b1_pattern_fastdtw_v1`。算法、案例、FastDTW 半径或阈值变化必须升级评分版本。
|
||||
- R3:案例定义属于代码中的版本化业务规则;案例特征在每次 run 中从 PostgreSQL 最新 qfq 行情完整构建,严格使用突破日前最后 25 个交易日,不依赖旧项目、本地 CSV、Tushare 或旧磁盘缓存。
|
||||
- R4:每个 run 只加载一次完整案例库,每只 `selected` 股票只评分一次;同股七个 category 共享股票级评分,不能复制成 category 级规则。
|
||||
- R5:评分结果存入 `selection_run_item`,与选股 evaluation status 分离;结果包含状态、有限的 0–100 总分、60 分阈值、评分版本、最佳案例、四个有限分项和安全原因。旧 run 保持可读。
|
||||
- R6:案例库缺失、单股评分异常、低于阈值或关闭评分都不得使选股失败,也不得进入现有选股失败计数;状态必须能区分 `not_executed`、`matched`、`below_threshold` 和 `failed`。
|
||||
- R7:HTTP 在 `stocks[].score` 返回可空的股票级评分,现有 `stocks[].signals[]` 与 `failures[]` 语义不变;后端支持稳定的代码、评分升序和评分降序数据库分页。
|
||||
- R8:前端在股票级区域展示匹配分数、案例、四个分项以及低于阈值/评分失败状态,并提供评分排序;任何评分状态都不能遮挡已命中的 signals。
|
||||
- R9:所有持久化和 HTTP 数值必须有限;原 25 日窗口产生的非有限中间特征必须通过离线兼容 fixture 锁定最终行为,不能把 `NaN` 或 `Infinity` 写入数据库或响应。
|
||||
- R10:提供 `ZHIXING_SELECTION_PATTERN_SCORING_ENABLED` 运行开关;关闭后选股链维持原行为,新结果不产生评分。
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] 离线 fixture 不依赖原项目或网络,数值 golden 覆盖十案例最佳匹配、四分项、总分、阈值边界、稳定同分、窗口不足和非有限中间值,并锁定修正后 FastDTW 版本一的确定结果。
|
||||
- [ ] 对同一固定 B1 run,开启和关闭评分得到完全相同的选中股票、七个 category、signal details 和选股批次状态,差异只在股票级评分字段。
|
||||
- [ ] 一只同时命中多个 category 的股票只调用一次 scorer,只保存和返回一个 `stocks[].score`,全部 signals 仍按既有顺序返回。
|
||||
- [ ] 十个案例均存在时,最高分 `>= 60` 的股票返回完整 matched score、案例、版本和四个分项;低于 60 时返回明确的 below-threshold 状态而不伪装成匹配。
|
||||
- [ ] 任一案例缺失或单股评分抛错时,选股继续并保留 signals;评分返回 failed/不可用状态,现有 `failed_count` 与 `failures[]` 不增加。
|
||||
- [ ] 旧 run 和关闭评分产生的 run 可由新后端与前端安全读取,`score` 为空或 not-executed,不影响原页面功能。
|
||||
- [ ] `code`、`score_desc` 和 `score_asc` 排序在 PostgreSQL 分页前执行,并以 `ts_code` 作为稳定次级键;前端不会只重排当前页。
|
||||
- [ ] 一次 run 只读取一次案例库且不按股票/category 重复查询;验证记录包含评分耗时和查询/调用次数。
|
||||
- [ ] Alembic upgrade/downgrade SQL、后端 Ruff/Pyright/pytest、前端 format/lint/typecheck/test/build 和根目录门禁全部通过;未配置 PostgreSQL 测试库时明确报告跳过项。
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- prompt 中的 1–5 主观视觉评分、图片生成、视觉模型调用和 `PASS/WATCH/FAIL`。
|
||||
- 改写知行 B1 公式、合并七个子信号、让评分反向决定是否入选或用于自动交易。
|
||||
- 评分独立重跑、同股多评分器或多版本并存、通用评分平台。
|
||||
- 评分阈值筛选、只导出高分股票代码和独立排名页面;MVP 只提供结果展示与排序。
|
||||
- 兼容原项目实际回退的 `_simple_dtw` 历史分数;FastDTW v1 是用户明确选择的新评分版本。
|
||||
Reference in New Issue
Block a user