- 因子平台: /factors 一级页(检验/因子库/编辑器/组合/挖掘), DSL 公式因子(25 算子点选、双语字段、我的因子模板、脏公式守卫), 版本与生命周期, 自动挖掘 L1 统计筛选 - 因子↔策略四条桥: 触发器 Zap 快建因子条件信号、因子一键生成排名策略、自定义信号 AI 提示词接入因子分组、策略回测因子归因(胜/败单入场信号日因子均值, 独立 tab, 双语因子名) - 回测: 统计卡新增盈亏比(≥1 红/<1 绿), 蒙卡回撤合并为中位/95% 双值卡(自适应字号), 高级设置基础过滤与策略编辑器参数对齐(5 组区间) - 信号库独立页 /signals(原设置 tab 迁出), 持仓提醒入导航; 挖掘并入因子页第 5 tab, /mining 旧链接重定向 - 研究线配套: 因子目录 61→77(评分/矩阵双内核), stats_v2(Newey-West/BH-FDR/DSR), enriched 管道与异动/报价服务配套调整 - 文档: README 导航与特性表、features.md 因子平台章节、操作说明书 9.2、factor-platform-plan 执行状态与 §5、二开文档桥接说明; 交流与支持节改版 - 版本 0.2.2 → 0.2.3; 后端全量 1625 passed(1 例环境性跳过), 前端 build 通过
32 KiB
因子平台总体方案(研究线产品与架构设计 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-05,P3 后续):检验页新增「自动挖掘」入口(
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.py(Newey-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 |
后端技术 spec:FactorSpec 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:13VIRTUAL_SCORING_DEPENDENCIES(35 个虚拟因子依赖声明)、scoring_value_expr(按名取值表达式)、mining.py:342挖掘候选产物本身就是scoring = dict(zip(factor_names, weights))。 - 【现状】研究线已分裂在两处:因子检验是
/backtest?tab=factor,挖掘是独立页/mining(frontend/src/router.tsx:126-127)。本方案将研究线收拢。
1.2 各能力现状对照
| 能力 | 现状 | 本方案落点 |
|---|---|---|
| 因子检验(批量/单因子) | 【现状】backtest/factor.py 61 因子、Rank IC/分年/衰减/分环境;前端 FactorDiscovery |
§3(搬迁 + UX 重设计) |
| 因子注册 | 【现状】硬编码 FACTOR_COLUMNS(factor.py:36),加因子=改代码 |
§4 + 旧文 §2 L-REG 注册表 |
| 公式配置 | 【现状】无(公式即代码) | §5 + 旧文 §3 DSL |
| 自动挖掘 | 【现状】mining.py beam search + 嵌套验证 + 晋升门槛,/mining 页 |
§7(协同设计,不搬家) |
| 因子→策略 | 【现状】scoring 机制可用;复合因子需改代码 | §6 + 旧文 §8 FactorCompositeSpec |
| 生命周期管理 | 【现状】无 | §8(P4) |
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 | 财务组 | 关心基本面(需财务数据源能力) |
交互规则:
- 点预设 = 替换当前选择集(不是叠加),按钮立即显示"当前预设 ✓"。
- 用户手动改勾选后,状态变为「自定义」,所有预设按钮取消高亮。
- 预设是纯前端选择集,不新增后端概念;构成规则在代码里以"组名 + 组内规则/显式 id 列表"声明,实现时从
columns.data按组过滤生成(不硬编码 61 个 id 的第二份清单)。 - 「快速体检」的代表因子实现时从 FACTOR_COLUMNS 按"窗口中位"解析;解析失败的组整组纳入(fail-open 但数量标注会变)。
3.3 三句话引导条
- 位置:页面标题下方,结果区上方;
<details>式可折叠,默认展开,关闭状态记localStorage(key 纳入现有 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 / error(FactorDiscovery.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(旧文 §6,
t_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 路径闭环
- 保存候选后 toast:
已保存到候选方案(右上角查看);因子页头部有「候选方案」按钮(§2.2 共享抽屉)。 - 单因子检验页(FactorDiscovery 内部 mode=single)顶部加返回链:
← 返回批量结果,保留现有列表参数不丢。 - 因子库 → 检验联动(P1):
/factors?tab=inspect&focus={factor_id}打开检验页并只勾选该因子。 - 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.tsx、pages/Factors.tsx |
新增 |
| 2 | FactorDiscovery 连同其 queryKeys 原样迁入 | pages/backtest/FactorDiscovery.tsx → 组件复用 |
搬移 |
| 3 | tab=factor 重定向 /factors(保参,对齐 mining 先例) |
pages/Backtest.tsx |
修改 |
| 4 | Backtest 移除因子 tab,MODES 剩 策略/验证 | pages/Backtest.tsx |
修改 |
| 5 | 候选抽屉提取共享组件,两页挂入口 | Backtest.tsx → components/CandidateDrawer.tsx |
提取 |
| 6 | UX 六项(§3.2–§3.7) | FactorDiscovery.tsx(或其子组件拆分) |
新增 |
| 7 | 导航项「因子」 | Layout.tsx |
修改 |
不做的:不改 queryKeys.ts 键结构、不改任何 API、不动 factor.py。
4. 因子库 tab(P1,依赖 L-REG 注册表)
4.1 列表
- 数据源:
GET /api/factors(旧文 §10 已定义),P1 前无此接口时本 tab 不上线(不放假数据)。 - 列:
id / 中文名 / 分组 / 类型(base|virtual|composite|custom)/ 公式(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 交互流
- 输入公式 → 调
POST /api/factors/validate(旧文 §10;错误码 E001–E016 见旧文 §3.5,含负 shift 即未来函数的 E005)。 - 校验通过 → 展示编译产物:依赖列集合、warmup_bars(旧文 §3 规则 4)。
- 试算:选近 40 交易日 + 当前资产,跑一次 Rank IC 快照(复用检验引擎计算路径,不另写计算逻辑);展示 IC 序列 sparkline 与均值。
- 注册:状态
draft,写入注册表;后续在检验 tab 跑完整检验后转active(§8 状态机)。编辑已有因子时公式变化保存为新版本并回草稿态。 - 模板起点:「从模板开始 / 我的因子」下拉——经典模板(5 个范式)+ 我的因子(已保存自定义因子公式导入);替换非初始公式前弹确认。
- 点选插入:全部 25 个 DSL 算子按「时序(13)/截面(3)/工具(9)」分组,点击插入光标处(与后端
dsl.OPERATORS同步维护),悬停显示签名与参数约束;79 个可用字段 chip 双语显示(英文 id 等宽 + 中文标签),点击插入。
5.3 约束(红线)
- 编辑器产物只经 DSL 编译到 Polars 表达式这一条计算路径(旧文 §3),禁止出现第二套求值器(CONTRIBUTING 禁止平行实现)。
- 注册因子 id 冲突拒绝,不自增后缀静默改名。
- 每一步的服务端校验 fail-closed:校验不过,注册按钮禁用且展示原因。
6. 组合 tab(P3,依赖 FactorCompositeSpec)
6.1 组合构建器
- 成分:从因子库多选(上限 8 个,对齐挖掘 max_factors 习惯),每行显示该因子最近 IC/IR。
- 权重三模式:
- 手动:逐项权重滑杆,实时归一显示;
- ICIR 自动:
w_i ∝ max(ICIR_i, 0),窗口 504 交易日,只用 (t−window, t−1] 数据(旧文 §8 点时规则,严禁 t 日数据参与 t 日权重); - 均等:1/N。
- 预览:选定回看区间内,组合 IC/IR 曲线 vs 各成分——证明"组合优于单因子"或及时劝退。
6.2 注册与桥接
- 「注册为复合因子」→ FactorCompositeSpec 入注册表,类型
composite。 - 桥接机制零引擎改动(旧文 §8 已论证):注册时自动写入
VIRTUAL_SCORING_DEPENDENCIES对应条目 → 立即出现在策略评分可选列表。 - 「一键创建策略」:打开策略新建表单并预填
scoring = {组合id: 1.0},用户补战法参数——完成研究线→交易线的最后一步。
7. 与挖掘页协同【设计】
裁定:挖掘保持独立页(已有用户习惯 + 任务型界面本就该独立),做研究线互链而非合并。
- 因子页头部「AI 挖掘 →」链到
/mining。 - 挖掘候选详情加「查看因子检验」:跳
/factors?tab=inspect&focus=...预选该候选的成分因子。 - P4 可选:挖掘晋升的候选自动以
watch状态写入因子库(人工确认后转 active)——默认不自动转正,晋升门槛(mining.pyGATE_*)只证明样本外可行,不过不代表可持续。
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_v2(t_newey_west 等) | §6 | factor.py _calc_ic 扩展(现状 factor.py:738-750) |
| 组合(§6) | FactorCompositeSpec + scoring 桥 | §8 | scoring.py VIRTUAL_SCORING_DEPENDENCIES(现状 scoring.py:13,写路径自动化) |
| 生命周期(§8) | 衰减重算任务 + 状态字段 | §6(IC 口径复用) | 【设计】注册表状态字段 + 低频任务 |
10. 路线图(PR 切分)
与旧文 §14 的十个 PR 合并视图:数据线四个 PR(st_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 注册表(旧文 §2,FACTOR_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)
- 后端 a:metrics_v2(NW 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)
- 因子市场/分享/导入第三方因子包——无真实需求前不做。
- 因子自动再训练/自动调参流水线——自动权重窗口已是点时滚动,更细即过拟合。
- 实时因子流(盘中逐 tick 因子值)——研究线是日频截面,实时因子属于监控线的事。
- 跨市场(港美股)因子——数据源与交易规则均不支持。
- 因子血缘图谱可视化——注册表依赖列字段已可追溯,图形化为炫技。
- 把挖掘页合并进因子页——任务型界面独立存在(§7 裁定)。
14. 完成标准
本方案"完成"= 路线图 P0–P3 全部合入且:
/factors四 tab(检验/库/编辑器/组合)可用,旧链接可达;- 一个不懂量化的用户按 §3.1 引导能独立跑出一次检验并读懂结论句(可用性自测标准);
- 一个自定义公式因子走完 编辑→校验→试算→注册→检验→进策略评分 全链路无断点;
- 全程未产生第二套计算逻辑(注册/编辑器/组合均编译到同一条 Polars/检验路径);
- P0–P3 各 PR 验收标准逐项通过,界面证据与测试结果真实可查。