Files
tick-stock-panel/docs/factor-platform-plan.md
shy3130 b3e492d890 feat(factor-editor): 算子/字段面板与模板库 UX 迭代
- 算子区去重: 移除裸 chips 行, 速查表升级为唯一算子面板(默认展开, 挂载时置 open 避免与折叠态打架)
- 速查表重设计: 时序(13)/截面(3)/工具(9)三张分组卡片, 每行=完整签名+中文说明+参数约束, 点击整行插入公式光标处; 与 chips 共用 OPERATOR_GROUPS 单一数据源
- 折叠标题突出: 白色前景色+medium 字重+accent 箭头(展开旋转), 悬停变色
- 可用字段: 展开高度 160→256px; 分组名提亮加粗; 字段英文 id 蓝色(与算子签名同色), 中文保持灰色
- 模板库 5→12: 新增 低波动/量比回落/RSI超卖/低振幅/隔夜反转/距高点回落/换手稳定, 全部经 /api/factors/validate 预校验
- 校验/试算按钮居右(ml-auto)
- factor-platform-plan.md §5.2 模板计数同步
2026-09-05 18:19:34 +08:00

32 KiB
Raw Permalink Blame History

因子平台总体方案(研究线产品与架构设计 v1)

状态标记约定与 factor-system-design.md 一致: 【现状】= 当前仓库已存在、已核对代码;【设计】= 本方案提出、尚未实现。 所有阶段代号 P0–P4 见 §10 路线图。

执行状态(2026-09-04

P0–P3 已全部实现并通过验证(后端 98 项因子相关测试 + 全量套件 + 前端 build + 真实数据 E2E):

  • P0 已实现/factors 一级页(检验/因子库/编辑器/组合 四 tab)、检验页 UX 六项、回测页 tab 移除与跳转、候选方案注入策略页。
  • 跟进整合(2026-09-04:侧边栏「挖掘」菜单移除,AI 挖掘并入 /factors?tab=mining(第 5 个 tab);/mining/backtest?tab=mining 旧链接保留参数重定向。
  • 自动挖掘(2026-09-05P3 后续):检验页新增「自动挖掘」入口(POST /api/backtest/mining/auto)——L1 全量统计筛选(app/services/auto_mining.py,门槛按探索/均衡/严格三档)自动生成达标因子池,随请求持久化筛选摘要(达标清单 + 未达标原因分布),L2 相关性剪枝 / L3 束搜索组合 / L4 嵌套样本外验证与达标门槛全部复用现有挖掘引擎;worker 子进程启动时加载因子注册表(自定义/复合因子可入池)。组合搜索本身不依赖 LLM;AI 的位置留给后续"从失败模式生成新 DSL 因子假设"。
  • 因子 ↔ 策略结合(2026-09-05,四条桥全部已实现):① 策略触发器编辑内 Zap 快捷建因子条件信号(SignalTriggerActions + AddFactorSignalDialog,阈值给建议值,csg_f_* 自动挂接当前策略入场/卖出触发器);② 因子库「生成策略」一键产出单因子排名策略(GenerateFactorStrategyDialog 渲染 FactorRankResearchMatrixStrategy 模板,matrix_native,保存为 custom_factor_*);③ 自定义信号 AI 提示词注入全部因子分组(custom_signals_ai.py::_format_fields,行前缀「因子·」,白名单 allowed_fields() 收口);④ 策略回测因子归因(strategy.py 入场候选因子快照 → 胜/败单入场信号日因子均值,结果区第 4 个 tab,meta.scoring 非空即产出;矩阵单因子排名类策略因 META.scoring 设计为空,暂不产出归因,为已知边界)。
  • 编辑器交互重构(2026-09-05:算子区合并为单一可点面板(全部 25 个 DSL 算子按「时序/截面/工具」分组,点击插入光标处,悬停显示签名与参数约束,替代"16 高频 chips + 静态速查表"双列表);可用字段 chip 双语(英文 id 等宽 + 中文标签浅色);「从模板开始」下拉新增「我的因子」分组(导入已保存自定义因子公式),非初始公式替换前弹确认防误覆盖。
  • 因子库扩充(2026-09-05:目录 61 → 77(新增 16 个虚拟因子,追加于目录尾部,挖掘调度前 48 项顺序不变):规模(流通市值对数,由换手率反推流通股本)、收益分解(隔夜/日内 20 日累计)、120 日动量与动量加速度、RSI 边际变化、下行波动、波动率状态(5/60)、振幅趋势、量能潮 OBV、20 日均成交额、均换手/换手波动(低换手溢价)、一年价格位置与距一年高点、KDJ K-D 差。双内核同步实现(strategy/scoring.py 评分路径 + backtest/matrix.py 矩阵内核,ddof 口径对齐存量约定);批量检验上限 64 → 96。
  • P1 已实现backend/app/factors/registry.py 注册表(61 内置因子单一事实源)、快照/契约测试、GET /api/factors
  • P2 已实现backend/app/factors/dsl.py 公式编译器(词法→EBNF 语法→语义校验 E001–E016→Polars 表达式,两阶段求值解决跨截面套时序窗口)、POST /api/factors/validate|trial、编辑器 tab。
  • P3 已实现stats_v2.pyNewey-West t / BH-FDR q / DSR,纯 numpy)、批量检验接线与前端服务端判读;store.py 自定义/复合因子持久化 + 评分桥(与策略共用同一条物化路径)+ CRUD API + 启动多轮加载;组合 tab;生命周期状态(草稿/激活/观察/退役)与状态流转 API。
  • P4 部分实现:生命周期状态已落地;巡检 tab 与后台衰减定时任务延后(见 §10),复合因子权重 ICIR 自动配置模式延后。
  • 验证环境备注:因子批量检验对 custom/composite 的底层依赖先经内置补算路径物化(factor.py::_compute_missing_factors),已按 fail-closed 语义处理缺失列。

0. 文档定位与阅读顺序

文档 角色 生效裁定
本文(factor-platform-plan.md 产品与架构总体方案:两线架构、导航与页面、交互设计、功能全集、路线图 本文 §2–§8 生效后,factor-system-design.md §11 的"不新增顶层页面"结论由本文取代
factor-system-design.md 后端技术 specFactorSpec schema、DSL 文法与算子表、统计口径(NW/BH-FDR/DSR)、API 契约、缓存键、测试矩阵 除 §11 外全部继续有效;本文引用不复制

两文冲突时:产品/前端/导航以本文为准;后端 schema、统计公式、API 字段以旧文为准。

1. 架构总览:两线模型

1.1 模型

研究线(发现问题)                     交易线(执行战法)
┌─────────────────────────┐          ┌─────────────────────────┐
│ 因子库(注册表)            │          │ 策略引擎(战法)            │
│   ↑ 检验(IC/IR/多空)      │          │   时机/买卖规则/仓位/风控   │
│   ↑ 公式DSL(自定义因子)    │          │   ↑ 评分选股               │
│   ↑ 组合因子(加权合成)     │          │   ↑ 验证(鲁棒性/步进)       │
│ 挖掘(自动搜索因子组合)     │          │ 回测(策略绩效)             │
└───────────┬─────────────┘          └───────────↑─────────────┘
            │        唯一桥梁:策略 scoring 配置          │
            └────────── 因子(组合)权重 ──────────────────┘
  • 因子层回答"此刻全市场谁排前面"(截面排序);战法层回答"何时进、买几只、多重仓、何时出、怎么止损"。
  • 两线只通过评分配置结合:{"scoring": {"cf_hotmom": 0.6, ...}}。因子不会"变成"策略,因子给策略供货。
  • 【现状】桥已存在:backend/app/strategy/scoring.py:13 VIRTUAL_SCORING_DEPENDENCIES35 个虚拟因子依赖声明)、scoring_value_expr(按名取值表达式)、mining.py:342 挖掘候选产物本身就是 scoring = dict(zip(factor_names, weights))
  • 【现状】研究线已分裂在两处:因子检验是 /backtest?tab=factor,挖掘是独立页 /miningfrontend/src/router.tsx:126-127)。本方案将研究线收拢。

1.2 各能力现状对照

能力 现状 本方案落点
因子检验(批量/单因子) 【现状】backtest/factor.py 61 因子、Rank IC/分年/衰减/分环境;前端 FactorDiscovery §3(搬迁 + UX 重设计)
因子注册 【现状】硬编码 FACTOR_COLUMNSfactor.py:36),加因子=改代码 §4 + 旧文 §2 L-REG 注册表
公式配置 【现状】无(公式即代码) §5 + 旧文 §3 DSL
自动挖掘 【现状】mining.py beam search + 嵌套验证 + 晋升门槛,/mining §7(协同设计,不搬家)
因子→策略 【现状】scoring 机制可用;复合因子需改代码 §6 + 旧文 §8 FactorCompositeSpec
生命周期管理 【现状】无 §8P4

2. 信息架构与导航【设计】

2.1 导航变化

现状:  回测(/backtest: 因子|策略|验证)   挖掘(/mining)   …
目标:  回测(/backtest: 策略|验证)   因子(/factors)   挖掘(/mining)   …
                     ↑ 导航顺序:回测 → 因子 → 挖掘 相邻
  • 新增一级路由 /factors,导航标签「因子」,插入在回测与挖掘之间(router.tsx + Layout.tsx,两者为二开文档 §5.2 高冲突热点,diff 必须最小)。
  • /backtest 瘦身为「策略」「验证」两个 tab。
  • 旧链接兼容/backtest?tab=factor<Navigate to="/factors" replace>,沿用现有先例——Backtest.tsx:38-43 已用同一模式把 tab=mining 重定向到 /mining 并保留 query 参数。tab=factor 的重定向须保留 run/candidate 类参数的传递习惯(对齐 mining 先例)。

2.2 候选方案抽屉的归属

【现状】候选方案抽屉内联在 Backtest.tsx:114,头部门按钮打开;因子候选(FactorDiscovery「保存候选」)与策略候选共用该存储,且已有"载入复测"流转(Backtest.tsx:35)。

【设计】P0 将抽屉提取为共享组件 CandidateDrawer回测页与因子页都放入口。裁定理由:候选是研究线的产物、交易线的原料,两边都要能开;提取是搬移不是复制(CONTRIBUTING §7 共享组件原则)。

2.3 因子页骨架

/factors
├─ tab=inspect(检验)    P0:现有 FactorDiscovery 整体迁入 + UX 六项改造(§3
├─ tab=library(因子库)  P1:注册表浏览器(§4)
├─ tab=editor(编辑器)   P2:自定义公式因子(§5)
├─ tab=composite(组合)  P3:组合因子构建器(§6)
└─ tab=lifecycle(巡检)  P4:衰减监控看板(§8)
  • tab 状态走 URL query?tab=),与回测页习惯一致,保证可收藏、可跳转。
  • P0 只落地 inspect,其余 tab 以"规划中"占位不渲染入口(YAGNI:不提前放空壳 tab)。

3. 检验 tab 详细设计(P0,纯前端)

3.1 页面线框

┌──────────────────────────────────────────────────────────────────────┐
│ 因子检验                                        [候选方案] [AI 挖掘→] │
│ ┌ 三句话说清楚(可折叠,默认展开,关后记忆到 localStorage)─────────┐ │
│ │ ① 因子 = 用来给股票打分排序的特征(如 20日涨幅、换手率变化)。      │ │
│ │ ② 这里检验:过去一段日子里,哪些特征真的能预测次日涨跌。            │ │
│ │ ③ IC = 预测准确度(绝对值越大越准),IR = 稳定度(越大越稳)。      │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ ┌ 筛选配置 ────────────────────────────────────────────────────────┐ │
│ │ 想好要测什么了吗?没有的话从预设开始:                              │ │
│ │ [全面体检 61] [快速体检 10] [趋势动量 14] [超跌反转 9]             │ │
│ │ [量价资金 11] [财务价值 7]      当前: 全面体检 ✓(点预设=替换选择)  │ │
│ │ 已选 61/61  全选 清空   [🔍 搜索因子 (名称/公式)]                  │ │
│ │ ┌─ 限高 45vh 内部滚动列表(现状保留)────────────────────────┐    │ │
│ │ │ ▾ 动量 (6)   本组测:过去 N 日涨了多少 …                    │    │ │
│ │ │   ☑ 5日动量  5个交易日累计收益率                             │    │ │
│ │ └────────────────────────────────────────────────────────────┘    │ │
│ │ 资产与范围 / 日期 / 调仓 / 分组 / 佣金(现状保留)                  │ │
│ │ [ 筛选 61 个因子 ]                                                 │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ ┌ 筛选结果 ─────────────────────────────────────────────────────────┐ │
│ │ 结论句:61 个因子中 7 个有效*。最强:5日反转(IC −0.041)。          │ │
│ │ 表格: 排名 | 因子(含方向箭头) | 预测力IC | 稳定度IR | IC胜率 |      │ │
│ │       多空收益 | 最大回撤 | [结论徽章] | 操作                       │ │
│ └──────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────┘

3.2 预设场景入口

设计动机:现状默认全选 61 个,用户第一个动作是"做选择题";预设把第一个动作变成"按一下"。

预设清单(数量已按 factor.py FACTOR_COLUMNS 实际分组核对:动量 6、趋势 8、均线偏离 10、量价 9、价格位置 6、超买超卖 3、收益形态 3、波动率 5、流动性 2、涨停基因 2、财务 7,共 61):

预设 数量 构成规则 适合谁
全面体检(默认) 61 全部因子 不知道从哪开始的人;标注"耗时最长"
快速体检 10 除财务组外每组取窗口中位代表因子(如动量组取 20日动量) 想快速看一圈的人
趋势动量 14 动量组 + 趋势组 关心趋势行情下什么有效
超跌反转 9 超买超卖组 + 价格位置组 关心抄底反转逻辑
量价资金 11 量价组 + 流动性组 关心资金与量能信号
财务价值 7 财务组 关心基本面(需财务数据源能力)

交互规则:

  1. 点预设 = 替换当前选择集(不是叠加),按钮立即显示"当前预设 ✓"。
  2. 用户手动改勾选后,状态变为「自定义」,所有预设按钮取消高亮。
  3. 预设是纯前端选择集,不新增后端概念;构成规则在代码里以"组名 + 组内规则/显式 id 列表"声明,实现时从 columns.data 按组过滤生成(不硬编码 61 个 id 的第二份清单)。
  4. 「快速体检」的代表因子实现时从 FACTOR_COLUMNS 按"窗口中位"解析;解析失败的组整组纳入(fail-open 但数量标注会变)。

3.3 三句话引导条

  • 位置:页面标题下方,结果区上方;<details> 式可折叠,默认展开,关闭状态记 localStoragekey 纳入现有 preferences 机制则更好,实现时择一,不新增后端字段)。
  • 文案即 §3.1 线框中三句,不许加第四句——解释超过三句就没人读。
  • 每句中的术语(IC/IR)与表头 tooltip(§3.4)文案保持一致。

3.4 表头判读 tooltip(文案定稿)

悬停表头即出,内容一句话 + 判读标准。列名同步通俗化(括号内保留原术语供专业用户):

通俗列名 tooltip 文案
IC 均值 预测力 IC 每天用因子给股票打分、与次日真实涨跌算相关性(Rank IC)的均值。|IC|≥0.02 且稳定,即有预测力;负值同样有效(反向使用)。
IR 稳定度 IR IC 均值 ÷ IC 波动。≥0.3 值得关注,≥0.5 相当稳定。
IC 胜率 预测日占比 IC 与预测方向一致的天数占比。50% 是抛硬币,55%+ 不错。
多空收益 多空收益 每期买因子最高组、(模拟)卖最低组的累计收益差。注意 A 股做空受限,此列为理论口径。
最大回撤 最大回撤 上述多空组合最痛的一段亏损幅度,衡量拿得住不住。
排名 排名 按当前排序键排序的名次,默认按 |IC|。

3.5 结果判读(徽章 + 结论句)

  • 【现状】结果行字段:ic_mean / ir / ic_win_rate / long_short_return / long_short_max_drawdown / errorFactorDiscovery.tsx:372-376);当前 API 无 t 值
  • 【设计·P0】客户端经验阈值判读(须在 UI 上明示"经验规则"):
    • 有效|ic_mean| ≥ 0.02 且 |ir| ≥ 0.3
    • 边缘|ic_mean| ≥ 0.02 或 |ir| ≥ 0.3(其一成立)
    • 无效:其余
    • 计算失败error 非空(现状已有 error 显示)
  • 【设计·P3 起】后端 metrics_v2(旧文 §6t_newey_west)落地后,判读切换为服务端显著性与阈值双条件,前端仅渲染服务端 verdict;P0 的客户端阈值作为降级路径保留。
  • 结论句模板:{N} 个因子中 {M} 个有效。最强:{label}IC {值})。N=参与计算的因子数(排除 error),M=有效徽章数。结论句挂在表头右侧,字号小、颜色 muted。

3.6 因子方向标识

  • 位置:结果表因子名旁,非复选框列表(检验前方向未知,不预测)。
  • 推导:ic_mean > 0↑ 值大看多ic_mean < 0↓ 值小看多null/error → 不显示。
  • 这是从数据推导的事实(样本内 IC 符号),非先验声明,因此不进因子库元数据(P1 因子库的方向列同样取最近一次检验的 IC 符号,并标注样本区间)。

3.7 路径闭环

  1. 保存候选后 toast已保存到候选方案(右上角查看);因子页头部有「候选方案」按钮(§2.2 共享抽屉)。
  2. 单因子检验页(FactorDiscovery 内部 mode=single)顶部加返回链:← 返回批量结果,保留现有列表参数不丢。
  3. 因子库 → 检验联动(P1):/factors?tab=inspect&focus={factor_id} 打开检验页并只勾选该因子。
  4. AI 挖掘 →:因子页头部的 /mining 链接(研究线互链,§7)。

3.8 状态设计(CONTRIBUTING §7 强制项)

状态 触发 展示
加载(因子清单) columns.isLoading 列表区骨架/「因子加载中…」(现状已有)
加载(运行中) run.isPending 按钮禁用 + 进度文案(现状已有),期间保留上次结果不闪空(现状行为核对)
空结果 results=[] EmptyState + 引导语「试试更长时间范围或减少因子」
错误 run.isError 错误条 + 重试按钮,保留左侧配置
无权限/无数据 财务预设但无财务数据源能力 预设按钮禁用 + title 说明「需要财务数据能力」(对齐能力矩阵门控习惯)

3.9 迁移清单(P0 范围内的代码动作,供实施 PR 参考)

# 动作 文件 性质
1 新建 /factors 路由 + Factors.tsx 页壳(tab=inspect router.tsxpages/Factors.tsx 新增
2 FactorDiscovery 连同其 queryKeys 原样迁入 pages/backtest/FactorDiscovery.tsx → 组件复用 搬移
3 tab=factor 重定向 /factors(保参,对齐 mining 先例) pages/Backtest.tsx 修改
4 Backtest 移除因子 tabMODES 剩 策略/验证 pages/Backtest.tsx 修改
5 候选抽屉提取共享组件,两页挂入口 Backtest.tsxcomponents/CandidateDrawer.tsx 提取
6 UX 六项(§3.2–§3.7 FactorDiscovery.tsx(或其子组件拆分) 新增
7 导航项「因子」 Layout.tsx 修改

不做的:不改 queryKeys.ts 键结构、不改任何 API、不动 factor.py。

4. 因子库 tabP1,依赖 L-REG 注册表)

4.1 列表

  • 数据源:GET /api/factors(旧文 §10 已定义),P1 前无此接口时本 tab 不上线(不放假数据)。
  • 列:id / 中文名 / 分组 / 类型(basevirtualcompositecustom/ 公式(desc 或 DSL)/ 最近 IC(含样本区间)/ 状态徽章 / 资产类型 / warmup 天数
  • 筛选:搜索框(id/名称/公式,复用检验 tab 同款逻辑)+ 类型、分组、状态下拉。
  • 行点击 → 详情抽屉。

4.2 详情抽屉

  • FactorSpec 全字段(旧文 §2.2 的 17 字段)按人话展示:公式、方向(最近检验 IC 符号 + 样本区间)、warmup"需要 X 日历史预热")、依赖列、适用资产。
  • 操作:「去检验」(§3.7 联动)、「克隆到编辑器」(P2 后可用)、custom/composite 显示「编辑」「停用」。
  • 底部:最近一次检验报告摘要(IC/IR/多空/回撤)+「查看完整报告」跳检验 tab。

4.3 状态徽章

与 §8 状态机一致:active / watch / retired / draft。P1 只有 active(全部内置因子)与 draft(编辑器产物),watch/retired 在 P4 激活。

5. 因子编辑器 tab(P2,依赖 DSL 编译器)

5.1 布局

┌────────────────────────┬──────────────────────────┐
│ 公式编辑区              │ 校验与预览区               │
│ textarea (等宽字体)     │ ✓/✗ 语法校验(错误码+定位) │
│ 算子面板 (25 个, 三组)   │ 依赖列集合                │
│   时序/截面/工具, 点击插入│ warmup = max(窗口) 提示    │
│ 可用字段 ▾ (双语 chip)   │ [试算最近 40 日 IC]        │
│ 从模板开始/我的因子 ▾    │ 试算结果: IC 走势 sparkline │
│ [校验] [试算 40 日]     │ 注册/更新表单               │
└────────────────────────┴──────────────────────────┘

5.2 交互流

  1. 输入公式 → 调 POST /api/factors/validate(旧文 §10;错误码 E001–E016 见旧文 §3.5,含负 shift 即未来函数的 E005)。
  2. 校验通过 → 展示编译产物:依赖列集合、warmup_bars(旧文 §3 规则 4)。
  3. 试算:选近 40 交易日 + 当前资产,跑一次 Rank IC 快照(复用检验引擎计算路径,不另写计算逻辑);展示 IC 序列 sparkline 与均值。
  4. 注册:状态 draft,写入注册表;后续在检验 tab 跑完整检验后转 active(§8 状态机)。编辑已有因子时公式变化保存为新版本并回草稿态。
  5. 模板起点:「从模板开始 / 我的因子」下拉——经典模板(12 个范式, 覆盖反转/动量/波动/量价/换手/超卖/位置)+ 我的因子(已保存自定义因子公式导入);替换非初始公式前弹确认。
  6. 点选插入:全部 25 个 DSL 算子按「时序(13)/截面(3)/工具(9)」分组,点击插入光标处(与后端 dsl.OPERATORS 同步维护),悬停显示签名与参数约束;79 个可用字段 chip 双语显示(英文 id 等宽 + 中文标签),点击插入。

5.3 约束(红线)

  • 编辑器产物只经 DSL 编译到 Polars 表达式这一条计算路径(旧文 §3),禁止出现第二套求值器(CONTRIBUTING 禁止平行实现)。
  • 注册因子 id 冲突拒绝,不自增后缀静默改名。
  • 每一步的服务端校验 fail-closed:校验不过,注册按钮禁用且展示原因。

6. 组合 tabP3,依赖 FactorCompositeSpec

6.1 组合构建器

  • 成分:从因子库多选(上限 8 个,对齐挖掘 max_factors 习惯),每行显示该因子最近 IC/IR。
  • 权重三模式:
    1. 手动:逐项权重滑杆,实时归一显示;
    2. ICIR 自动w_i ∝ max(ICIR_i, 0),窗口 504 交易日,只用 (twindow, t1] 数据(旧文 §8 点时规则,严禁 t 日数据参与 t 日权重);
    3. 均等1/N。
  • 预览:选定回看区间内,组合 IC/IR 曲线 vs 各成分——证明"组合优于单因子"或及时劝退。

6.2 注册与桥接

  • 「注册为复合因子」→ FactorCompositeSpec 入注册表,类型 composite
  • 桥接机制零引擎改动(旧文 §8 已论证):注册时自动写入 VIRTUAL_SCORING_DEPENDENCIES 对应条目 → 立即出现在策略评分可选列表。
  • 「一键创建策略」:打开策略新建表单并预填 scoring = {组合id: 1.0},用户补战法参数——完成研究线→交易线的最后一步。

7. 与挖掘页协同【设计】

裁定:挖掘保持独立页(已有用户习惯 + 任务型界面本就该独立),做研究线互链而非合并。

  1. 因子页头部「AI 挖掘 →」链到 /mining
  2. 挖掘候选详情加「查看因子检验」:跳 /factors?tab=inspect&focus=... 预选该候选的成分因子。
  3. P4 可选:挖掘晋升的候选自动以 watch 状态写入因子库(人工确认后转 active)——默认不自动转正,晋升门槛(mining.py GATE_*)只证明样本外可行,不过不代表可持续。

8. 因子生命周期(P4

8.1 状态机

draft ──(完整检验通过)──▶ active ──(衰减告警/人工)──▶ watch ──(持续衰减/人工)──▶ retired
  ▲                                                        │
  └──────────────(重新编辑公式, 重新走检验)──────────────────┘
迁移 触发条件 动作
draft→active 检验报告满足:|IC|≥0.02 且 |IR|≥0.3(或 metrics_v2 后 t 显著) 进策略可选列表
active→watch 滚动 63 日 IR < 0,或滚动 63 日 |IC| 较全样本减半 因子库标黄,不影响策略运行
watch→retired 连续两个观察窗(126 日)仍衰减,或人工 从策略可选列表隐藏(已引用它的策略配置不破坏,仅新建不可选)
retired→draft 人工重新编辑 重走检验

8.2 衰减监控

  • 计算:后台低频任务(日线收盘后),对 active/watch 因子重算滚动 63 日 Rank IC/IR——复用检验引擎同一条 IC 计算路径。
  • 展示:因子库 tab 状态列 + P4 的 lifecycle 看板(衰减榜:谁最近不行了)。
  • 通知:首版只做页面内徽章;接通知服务(NotificationFormatter 继承点)为可选后续,防打扰。

9. 后端支撑映射

本方案功能 后端依赖 旧文章节 代码落点
检验 tab(§3 无新依赖(P0 纯前端)
因子库(§4 L-REG 注册表 + GET /api/factors §2、§10 【设计】app/factors/registry.py(三处合一:factor.py:36 + scoring.py 虚拟因子 + pipeline ENRICHED_COLUMNS
编辑器(§5 DSL 编译器 + POST /api/factors/validate §3、§10 【设计】app/factors/dsl.py
判读升级(§3.5 metrics_v2t_newey_west 等) §6 factor.py _calc_ic 扩展(现状 factor.py:738-750
组合(§6 FactorCompositeSpec + scoring 桥 §8 scoring.py VIRTUAL_SCORING_DEPENDENCIES(现状 scoring.py:13,写路径自动化)
生命周期(§8 衰减重算任务 + 状态字段 §6IC 口径复用) 【设计】注册表状态字段 + 低频任务

10. 路线图(PR 切分)

与旧文 §14 的十个 PR 合并视图:数据线四个 PRst_history / delisted_kline / industry_pit / index_ext)独立并行,不受本路线图阻塞。

P0 — 因子页拆分 + 检验 UX(1 个 PR,纯前端)

  • 范围:§2 导航/路由/重定向 + §3.9 迁移清单 7 项 + §3.2–§3.7 UX 六项。
  • 依赖:无。
  • 验收:/factors 可用;旧链接 301 语义跳转;候选抽屉两页可用;六项 UX 逐项截图;窄屏检查;pnpm build 过;queryKeys 无变更。
  • 回滚:revert 单 PR 即回到现状,无数据迁移。

P1 — 注册表 + 因子库(2 个 PR:后端 / 前端)

  • 后端:L-REG 注册表(旧文 §2FACTOR_COLUMNS 由注册表生成、对外常量保留兼容别名;scoring.py 改读注册表、函数签名不变)+ GET /api/factors
  • 前端:因子库 tab 上线(§4)。
  • 验收:注册表生成结果与现 61 因子逐项一致(快照测试);旧候选方案引用的历史 id 全部可读。

P2 — DSL + 编辑器(2 个 PR

  • 后端:DSL 编译器 + validate/试算端点(旧文 §3,含 E001–E016)。
  • 前端:编辑器 tab(§5)。
  • 验收:错误因子公式全路径测试;试算与检验引擎同源计算对拍一致。

P3 — metrics_v2 + 组合 + 判读升级(2 个 PR)

  • 后端 ametrics_v2NW t 值等,旧文 §6;测试=黄金参考向量 + 可选 dev 组 statsmodels 对拍)。
  • 后端 b+前端:FactorCompositeSpec + scoring 桥自动化 + 组合 tab(§6)+ 结果判读切服务端(§3.5)。
  • 验收:组合因子在策略评分中可选且数值路径唯一;DSR/BH-FDR 数值测试过。

P4 — 生命周期(1 个 PR,可延后)

  • §8 状态机 + 衰减任务 + 巡检看板。
  • 验收:衰减告警可复现(构造样本);retired 因子不破坏存量策略配置(兼容测试)。

11. 验证矩阵(对齐 CONTRIBUTING §9

改动 最低验证
P0 前端 pnpm build;手工检查:加载/空/错/禁用/无权限五态、预设切换与自定义态、搜索不丢选择(回归本轮已验证的行为)、旧链接重定向、候选抽屉双页、窄屏
P1 注册表 后端 pytest:注册表快照=现 61 因子、历史 id 兼容、scoring 行为不变(对拍测试);API 契约测试
P2 DSL 编译器单测(合法/非法公式全错误码)、防未来函数(E005 用例)、试算与检验同源对拍
P3 统计 NW/BH-FDR/DSR 数值断言(黄金向量);组合因子端到端:注册→策略评分可选→回测出数
P4 生命周期 衰减触发用例、retired 兼容用例、低频任务不阻塞启动
全阶段 git diff --check;每 PR 附界面证据(截图覆盖改动前后)

12. 兼容性与风险

影响 对策
旧链接 /backtest?tab=factor 收藏/外链失效 Navigate 重定向保参(mining 先例)
候选方案存储 无 schema 变化 仅抽屉组件提取,存储与"载入复测"链路不动
因子 id 不变 P0 不碰 factor.py;P1 注册表生成需逐项快照对齐
router.tsx/Layout.tsx 高冲突热点 上游合并冲突面 diff 最小化:只加一条路由/一个导航项,不动既有结构
P0 判读阈值是经验值 可能误判"有效" UI 明示"经验规则";P3 换服务端显著性后降级为兜底
方向箭头取自样本内 IC 符号 过拟合误读 tooltip 注明"样本内方向,历史不代表未来"
编辑器产生大量低质因子 注册表膨胀 draft 不进策略可选列表;必须过完整检验才 active

13. 不做什么(YAGNI,续旧文 §16)

  1. 因子市场/分享/导入第三方因子包——无真实需求前不做。
  2. 因子自动再训练/自动调参流水线——自动权重窗口已是点时滚动,更细即过拟合。
  3. 实时因子流(盘中逐 tick 因子值)——研究线是日频截面,实时因子属于监控线的事。
  4. 跨市场(港美股)因子——数据源与交易规则均不支持。
  5. 因子血缘图谱可视化——注册表依赖列字段已可追溯,图形化为炫技。
  6. 把挖掘页合并进因子页——任务型界面独立存在(§7 裁定)。

14. 完成标准

本方案"完成"= 路线图 P0P3 全部合入且:

  1. /factors 四 tab(检验/库/编辑器/组合)可用,旧链接可达;
  2. 一个不懂量化的用户按 §3.1 引导能独立跑出一次检验并读懂结论句(可用性自测标准);
  3. 一个自定义公式因子走完 编辑→校验→试算→注册→检验→进策略评分 全链路无断点;
  4. 全程未产生第二套计算逻辑(注册/编辑器/组合均编译到同一条 Polars/检验路径);
  5. P0–P3 各 PR 验收标准逐项通过,界面证据与测试结果真实可查。