Files
sanguo_vnpy_v2/docs/factor_research/factor-system-design.md
T

37 KiB
Raw Blame History

因子体系总设计(唯一活文档)

建档:2026-09-14 | 维护:因子调研 session 定位:因子线全貌设计回溯——数据底座 → 因子库 → 评估管线 → 合成层 → 选股组合回测 → 判定结论 → 改造方向。后续因子线的任何设计变更更新到本文档(日期节追加),不再按日期开新档。

已收编的历史文档(细节存档,本文档为总览唯一入口):

  • docs/factor_research/2026-08-20-factor-library-survey.md — 因子库全景调查(四批路径源头)
  • docs/superpowers/specs/2026-08-24-factor-batch1-alpha101-158.md(同名 plans 已归档 docs/archive/plans/2026-08-24-factor-batch1-alpha101-158.md,4ebbd43) — 第一批 Alpha101/158 评估管线设计与实施
  • docs/archive/reports/fundamental_factor_survey_20260907.md / docs/archive/reports/dsa_fundamental_factors_20260907.md — 财务 136 调查与落地
  • docs/archive/reports/factor_fundamental_morning_report_20260908.md / docs/archive/reports/factor_p1_morning_report_20260909.md — 批次进展晨报
  • docs/superpowers/specs/2026-07-21-data-source-fusion-design.md — 数据侧活文档(§20 因子相关新域)

1. 目标与总路线

用户拍板「C 起步」:先建评估能力和因子库,研究目的后定。演进路线(2026-08-24 起):

第一批 Alpha101/158 全量挂载重验(08-25)
    → 因子评估管线 + 前端三页(08-26 收官)
    → 财务 136 批(09-08 P0 闭环 → P1 并行)
    → 族分析 + 合成层 quant12_v2a 生产冠军(09-11 收官)
    → ③ 选股组合回测 IC→净值转化(09-12~09-14 判定收官)   ← 当前位置
    → 改造方向(缓冲带/top200/中性化,待拍板) + ④ L2 覆盖前端 UI 化

四批因子路径(survey §5):①Alpha101+158(已完)②聚宽公式本地化质量/成长类=财务 136(已完)③GTJA Alpha191(用户拍板冷冻——因子已够多)④Barra 风格 CNE5(长线,缺数据时再启)。


2. 数据底座

层 内容 状态
行情 dbbardata 唯一行情表(全A 日线 1990+ 含退市;15m 5.5 年) ✅
成份 constituent_unified 并集模型(治偏差) ✅
估值/换手 valuation parquet 拆分域 ✅
财务 财务 136 域(akshare 三表+每股+dupont,NOTICE_DATE<=date 防前视) ✅
事件面板 get_event_panel 白名单(dragon_tiger/block_trade/margin/zt_pool/hot_rank 等 15 域) ✅
因子新四域(09-12 拍板「本地数据越全越好」当日落地) margin 两融 16 年全史 / sw_industry 申万一级映射(快照域,09-14 周一首落)/ dragon_tiger_seats 席位 / nb_daily+nb_hold 北向(HKEX 季快照) ✅(sw 09-14 首落)
语料 corpus 新闻+公告(NAS 权威) ✅ 采集运行中

宇宙口径:全 A 主板+创业板、剔 ST/次新(new_stock_days)、退市股保留(评估防幸存者偏差);实盘可交易宇宙剔 68/4/8/92(factor_topn 自写 _filter_kcbj_keep_chinext,不得用 filters.filter_kcbj_stock——照聚宽原版连创业板 300/301 也误杀)。


3. 因子库

批 内容 数量 状态
内置 ma/return 等基础 7 占位
第一批 vnpy Alpha101(实挂 82,18 个 add_feature 是注释行,grep 假数)+ Alpha158 240 注册/227 可算 ✅
财务批 聚宽财务 136 公式本地化(P0 32 个 TDD → P1 扩展) 96 候选→32+37+6 ✅
P2 批(09-22) 七项目指标调研增量:D16 PEG/D17 PS + E14-16 股息族(dividend 域除息日锚:div_12m 365 天滚动/派息率/连续分红年数断年重计);PEG 分母走守卫列 peg_denom(np_ttm≤0 或 g≤1% → NaN 宁缺毋假);S 族情绪 4 因子(sentiment_lexicon 词表短语优先+计数多数决,news_meta 打分 PIT=次日可见,覆盖门窗内<5 条 NaN;前向积累型——corpus 2026-09-06 起采集,历史窗全 NaN 诚实透出,IC 随语料攒厚度,首个有意义窗=10 月下旬 Q3 披露潮) 9 ✅ TDD
P1-C 批(09-22) spec §20.13 三新域消费面:R 研报共识 5(res_rating_pos 买入+增持占比门窗≥3 / res_coverage 180 天窗研报数 / res_fwd_ep 窗内 mean 预测 EPS 空值不算分母 / res_target_upside 最新带价条目+180 天新鲜度门 null 目标价不进流不遮蔽 / res_rating_chg 窗内净上调——ratingChange=EM 数值编码 0=上调/1=下调/2=首次/3=维持(NAS 真数据 61 变化对自证);PIT=publishDate,180 天窗两端 cum 口径同 E11 手法)+ Q 质押 4(pledge_ratio 周五快照 asof——消失股修复:全解押股退出快照名单后在下一实际期插 0 行(join_asof 永久 stale 旧值与 detail 族解押归零语义矛盾,infra 09-22 核查派单);节假日空周=0 行 0 列文件 loader 列检查跳过 asof 回退节前真期 / pledge_ctrl 实控人在押 max 占所持——detail 区间重建,生效=max(质押开始,公告日),IS_CONTROL_SHAREHOLDER=='1' 直标免 F10 join / pledge_margin_dist=−pledge_warn_line/close 在押最高预估平仓线 / pledge_net_180 窗内解押−新增笔数两事件 cum;无质押=0 真实零 fill 语义与缺域 NaN 严格区分;1997 全史区间重建全窗可回测非前向积累) 9 ✅ TDD
GTJA191 — — ❄️ 冷冻(用户 09-12 拍板)
Barra CNE5 风格因子 — 长线

慢算子坑:vnpy 原版 ts_corr/ts_rank/ts_decay/ts_quantile/slope 族 rolling_map 10M 行小时级,sanguo_factor/fast_ops.py 13 算子原生覆盖(EXPRESSION_FUNCTIONS 官方扩展点;ts_mean/std/sum/min/max/corr/cov/rank/decay_linear/slope/rsquare/resi/quantile——含 ts_corr_v2/cov_v2 大窗原生路等后续增量,以 register_fast_ops 返回清单为准);ts_argmax/argmin 并列场景原生恒等式不成立留原版(20 因子另批)。

年化基数双轨(09-27 审计 F-9 终审=只注明不统一):评估线 metrics.py 年化=(1+日均)^244,归因线 attribution.rolling_ir 年化 IR=mean/std×√252——两线各自内部一致,跨线直比 IR/年化存在 ~1.6% 系统性口径差;统一常量会平移评估线已沉淀的 h2 考场/排行榜历史基线,且改动归因线会破坏已产 63 月件与月度增量件 rolling_ir 的跨件可比性,故两线均不动。


4. 评估管线

链路:universe(dbbardata 松散 CTE 枚举+逐 symbol 四列全等前缀)→ run_batch_eval(进程内 calculate_by_expression + pivot 切窗 cutoff 掩码;factor_values_out 可导截面宽表 parquet=datetime 索引×vt_symbol 列,供组合回测消费)→ 向量化 RankIC → factor_eval.db → 4 API 端点 → 前端三页。

考场纪律(h2 盲考):因子评估窗与组合回测窗严格同窗(2021-07-01~2026-09-11),截面导出起点早于回测起点半年(2021-01-01)留预热——首日调仓必有 T-1 截面可用。

  • IC 口径:日频 RankIC 前瞻 1/5/10 日;族分析按相关性分组选代表。
  • 跑批纪律:parquet 缓存+逐因子落库+断点续跑;NAS 侧宿主守望 host_watch.sh(exec 会话收割器 ~20min 处决 DSM 行为的根治)。

5. 合成层(生产冠军 composite_quant12_v2a)

quant12 源清单(族分析独立性选定,composite_library.py,方向包裹 cs_rank 定向):

源 方向 族
vma_60 / alpha16(全池最强单源)/ alpha83 / alpha12 / alpha2 / alpha42 + alpha158 量能收缩族代表 + alpha101 量价背离族
wvma_20 / klow / kup / cord_5 / vol_ma5 / alpha81 − 波动/反转族(alpha158+内置)+ alpha81
  • 权重:composite_weighting.py,ICIR 拟合 profile(weight_profiles/quant12_icirfit_v1.json);v2a=quant12 源+ICIR 权重,方向/包裹口径完全复用 v1.1(等权式零改动测试锁死)。
  • L1/L2 双层语义(④ UI 的机制基础):L1=拟合权重档案(sources.weight);L2=overrides 覆盖层,每项 {source, weight, reason}(reason 硬字段),resolve_weights 从 L1 出发逐项替换后全组重归一化——UI 编辑的正是这层,机制上天然不触碰 L1 原文件。
  • 扫描注册(09-14 ④ 落地):register_scanned_profiles 启动扫 weight_profiles/*.json,ui 建档注册成 composite_<stem>;跳过显式注册档案(防 v2a 双名)/_roll_ 滚动档案(composite_rolling 域)/坏档案(stderr 留痕不炸注册链)。
  • 滚动版本 composite_rolling.py:weight_profiles/{scope}roll{year}.json 按年拟合。
  • 财务 6 源合成(fund6)v1.1 剔 fund_topholder_chg(源数据 2021Q3 起,首期无差分 null 传染)。
  • fund8 扩展(09-22,P1-C 晋级双源入合成):composite_fund8 = fund6 六源 + FUND_P1C_SOURCES 两源(pledge_net_chg / res_target_upside,均已 cs_rank 定向内嵌)等权 8 项;v1.1 三因子与 FUND_SOURCES 常量零改动(测试锁死),fund6/fund8 并存各用各的可评窗。覆盖限制:研报/质押源 2021 起(h1 窗 2021-07 全程有值 n=609),fund8 覆盖 = 8 源 null 传染交集 → 2021 前为空;fund6 保留 2016+ 全窗。v2a 档案校验白名单扩为四源表(+fund6+P1-C 拼接 8 源),fund8 的 ICIR 拟合档案路线已打通。
  • 档案铁律(④ L2 UI 的前置约束):权重档案 UI 编辑走新档案新名字(如 quant12_v2a_ui_日期),绝不改生产冠军定义;reason 必填。

6. ③ 选股组合回测(IC→净值转化,09-14 判定收官)

6.1 链路与组件

因子截面宽表(batch_eval factor_values_out)
    → FactorTopNStrategy(sanguo_portfolio/strategies/factor_topn.py)
        · 截面 asof 严格早于调仓日(searchsorted side=left −1,防前视)
        · run_daily 9:30 + 交易日计数器 %rebalance_days 触发调仓
        · 过滤链(ST/次新/涨跌停/停牌) + TopN 等权
        · vt_symbol SSE/SZSE → 聚宽 XSHG/XSHE 双格式转换(撮合层查行情的关键)
    → BulletTrade 撮合回测(runner_backtest --json,CLI 双入口见 §9 坑1)
    → 判定(五问)

入口:sanguo_portfolio/runner_backtest.py --strategy factor_topn --factor-name composite_quant12_v2a --factor-dir <截面目录> --top-n N --rebalance-days K;跑批容器模式见 §9 坑 6。

6.2 口径铁律

  • 复权:use_real_price=True → 撮合基准价 fq='pre'(engine.py:1877);持仓日终估值引擎传 fq='none' 必须映射 pre(_FQ_ALIASES)——映射 raw 会「前复权价买入多拿股数×不复权价计市值」口径撕裂(首日 equity 凭空 +15% 实锤)。
  • 滑点三态(76523f0):--slippage 不传=引擎默认 24.6bps(_BASE_MARKET_SLIPPAGE,并非零);显式 0=真零(PriceRelatedSlippage ratio=0 阻断默认回退);正值=比率滑点(聚宽语义 price×(1±ratio/2),ratio 为全幅、单边半幅)。勿用 FixedSlippage(每股固定元数语义)。
  • 成本参数:佣金万 3 双边+印花税千 1 卖出+最低 5 元。
  • 同批同快照:组间对比必须同一跑批(或验证数据冻结窗口);跨批微扰(复权因子增量、参数微差)经 5 年复利路径混沌放大可达 ±12pt(第五跑实锤)——单组数字看量级、组间差异看同批。
  • 回测确定性:同输入同输出(base2 复刻与 base 逐日净值比 1.0000、总收益差 0.00pt)——分叉必来自配置或数据变化,可作变更检测器使用。

6.3 判定矩阵设计

主轴 TopN 等权月调(21 交易日),单维敏感性:集中度(top50/100/200)、频率(5/10/21 日)、成本(5/10/12.3bps)。基准=沪深300。

6.4 判定五问终态(2026-09-14,窗口 2021-07~2026-09 共 5.17 年)

组 总收益 年化 夏普 最大回撤 累计超额 年换手
top200 33.87% 5.94% 0.24 -39.5% +48.8pt 10.9x
slip1(5bps) 31.74% 5.61% 0.23 -42.8% +46.2pt 11.2x
slip2(10bps) 23.89% 4.33% 0.18 -43.5% +38.3pt 11.2x
base=Top100(12.3bps) 20.52% 3.76% 0.16 -43.9% +35.0pt 11.2x
top50 12.58% 2.37% 0.11 -44.8% +27.2pt 11.5x
reb10(双周调) 10.47% 1.99% 0.08 -49.6% +24.9pt 23.1x
reb5(周调) -29.17% -6.60% -0.29 -59.9% -15.0pt 44.8x
  1. 年化超额:有——Top100 ~6.8pt/年,top200 ~9.4pt/年(分散化全面占优:收益↑夏普↑回撤↓换手↓)。
  2. 夏普:0.16~0.24,偏低,超额靠波动扛。
  3. 成本侵蚀(生死题):每 +10bps 单边滑点 ≈ 总收益 -7.7pt;月调 11x 换手下实盘小盘冲击 30-50bps → 年拖累 3.3~5.5pt,超额基本被吃光——当前形态不可实盘化。调仓频率单调恶化(月 20.5%>双周 10.5%>周 -29.2%)。
  4. 逐年稳定性:top200 四正二负(2021 +23.8 / 2022 -12.5 / 2023 +4.2 / 2024 -3.7 vs 基准 +14.7(微盘雪崩年) / 2025 +35.2 / 2026 -8.1)。
  5. 超额来源:风格证据=与小盘风格高度绑定(2024 超额 -18~-29pt / 2025 +17pt);top200>base>top50 单调=非头部选股 α,是因子粗粒度排序 β+小盘暴露。行业归因定量分解待 sw_industry 首落后增强(持仓行业分布)。

7. 改造方向(留档待拍板,优先级序)

  1. 调仓缓冲带(no-trade band)——✅机制已落地(09-14 夜,TDD):只换出跌出前 X% 的持仓(如 top200 持有、跌出 top400 才卖),预期砍换手 11x→3-5x,成本拖累降一个量级——实盘化的第一前提。
    • 实现:FactorTopNConfig.band_ratio(缺省 1.0=硬切,与原行为逐字节等价的回归锚);rebalance 3b 步——持仓截面 rank ≤ top_n×band_ratio 则不卖,跌出带才让位,TopN 照常补买;被过滤链剔出的持仓不在 rank 内不受带保护(照卖,与原行为一致)。透传四处:argparse --band-ratio + _build_strategy/run_backtest_json/结果回显(坑 1 纪律,json 测试扩五参钉死)。矩阵待跑:top200 × band{1.5, 2.0} vs base 对照(同批同快照)。
  2. 基准配置改 top200:矩阵内各维度全面最优。零代码(top_n 参数现成),跑批矩阵默认即改。
  3. 行业/市值中性化——✅size 变体已落地(09-14 夜,TDD):治 2024 微盘雪崩失血;四域数据已备(sw_industry 09-14 落位、市值 valuation 域)。
    • 实现:composite_weighting.register_szneu_variant——生产冠军自动挂双变体:_szneu = cs_neutralize((v2a原式), close*share_capital)(原始市值线性,v2b 同式)与 _szneul = log(·)(Barra CNE5 同款对数市值),category=composite(评估批自动 join 财务域,share_capital 走 fund_*_neu 已验证链路)。残差算子线性 ⇒ 包裹式中性化 ≡ 各源中性化再加权(引擎端到端测试双变体逐点实证)。
    • ⚠️09-15 晨关键发现:原始市值线性中性化≈无效——szneu 截面与 v2a 的 top200 重叠 194/200(97%)、整体 spearman 0.9999:OLS 被市值右尾(万亿巨头)绑架,对主体股票 b·x≈0,只敲掉极端巨头的头寸。真正移除秩倾斜须回归 log(size)(_szneul)。行业中性化(x=行业哑元组)待 sw_industry 数据验收后同式扩展。
  4. 分数加权替代硬切换——✅参数已落地(09-14 夜,TDD)+ 矩阵证负(09-16):FactorTopNConfig.weight_gamma(缺省 0=等权回归锚):目标市值 ∝ (N+1−rank)^γ(rank∈1..N 为 TopN 内名次),γ>0 头重脚轻——硬切换「进出/留任」二元决策的连续版本。透传四处同 band_ratio(json 测试扩六参钉死)。矩阵判定:γ=1 = 25.53%(-8.34pt vs base3)/夏普 0.19/2024 -9.8%(超额 -24.5pt 最差)——集中持股放大单一年的风格暴露,方向性负贡献,④判定=不采用。

7.1 改造四条矩阵终态(2026-09-16 凌晨,同批九组+组合)

标定:base3 ≡ 昨夜 band_base 逐位全同(33.87/0.24/-39.5/10.9x)——隔夜两批数据零漂移,全表同批可比。窗口/成本/截面快照与 §6.4 同口径(2021-07~2026-09,引擎默认 24.6bps,09-12 v2a 截面)。

组 配置 总收益 夏普 最大回撤 年换手
base3 v2a top200 月调硬切 33.87% 0.24 -39.5% 10.9x
band15/20/5 带宽 1.5/2.0/5.0× 36.5/38.7/45.5% 0.26/0.27/0.31 ~-39.5% 10.7/10.4/8.6x
reb63 v2a top200 季调硬切 69.78% 0.44 -34.9% 3.8x
szneu raw 市值中性化 46.81% 0.32 -37.9% 10.9x
szneul log 市值中性化 42.94% 0.30 -34.7% 10.8x
szneul_band5 ③×宽带 60.93% 0.40 -33.9% 8.6x
gamma1 ④ γ=1 25.53% 0.19 -41.5% 10.8x
szneul_reb63 ③log×季调 80.10% 0.50 -33.1% 3.8x
szneu_reb63 ③raw×季调 88.33% 0.52 -33.0% 3.8x

终局两组合(09-16 晨出数):正交叠加全部成立——szneul_reb63=80.10%/0.50/2024 超额 -8.6pt(全家族最优);szneu_reb63=88.33%/0.52(头条最高)。生产推荐=szneul_reb63:log 中性化机制有原则(Barra 同款、跨期稳定),2024/2022 超额与回撤全面最优,牺牲 8pt 头条换风格鲁棒性值得;szneu_reb63 为性能备选。⚠️诚实框定:11 组挑优存在选择偏差,两条单调律(频率↓摩擦死、log 中性化治 2024)是机制性结构发现可期外推,具体点位数勿当真;季调 5 年仅 20 个决策点路径依赖偏高;2021 小牛年中性化让渡 ~5pt 是风格对价。

五条结论:

  1. 频率单调律(最强发现):reb5(-29%) < reb10(10%) < reb21(34%) < reb63(70%)——月度以内调仓越频越死(换手×摩擦),季调直接命中实盘换手目标 3.8x 且收益翻倍;因子信息在季度尺度上依然有效。
  2. 带宽单调律:1.0→5.0× 收益 33.9→45.5% 换手 10.9→8.6x 单调改善;温和带(1.5/2.0)换手几乎无感(10.7/10.4x)——持仓 21 天 rank 持续性近零(6% 留 top200、74% 爆千名外,trades 重建解剖),带宽罩不住 rank 爆炸,band5 起才有实质留仓。
  3. 中性化:raw 版(敲巨头)头条最好 46.8% 但机制糙;log 版精准命中设计靶——2024 微盘崩年转正 +3.6%(超额 -18.4→-11.1pt)+ 回撤全场最优;szneul_band5 组合 60.9%/回撤 -33.9% 证明与宽带正交叠加成立。
  4. ④ 证负:γ=1 集中持股 -8.3pt、2024 最差——不采用。
  5. 实盘化路径:reb63 家族(3.8x 换手下回测已含 24.6bps 摩擦;实盘小盘冲击 30-50bps 增量拖累 ≈1.1-1.9pt/年,年化 11% 可承受)——候选生产配置 = 中性化因子 × 季调,szneul_reb63/szneu_reb63 两组合 09-16 晨出数定稿。

7.2 szneul_reb63 影子盘接线(09-22 深夜,件①②落地)

生产配置实盘化的数据/接线两件,TDD 落地(1678 绿):

  • 件② sanguo_factor/daily_section.py——每日截面增量生产器(影子盘数据契约):收盘后对目标因子跑短窗批(run_batch_eval(factor_values_out=) 临时目录整窗导出,窗=end−220 历史日覆盖 WARMUP_BARS=120 交易日预热)→ merge_section 幂等 merge 进主截面 parquet(同 index 日替换/新日追加/sort/tmp+os.replace 原子写)→ section_sanity(当日非空数+进出股票)。CLI python -m sanguo_factor.daily_section。短窗批顺带落 IC metrics 日度记录=未来 IC 衰减告警线免费原料。消费端 factor_topn 读「严格早于调仓日的最近截面日」,本工具保证任意调仓日有新鲜截面。
  • 件① live 接线:live_strategy.py 工厂加 factor_topn(SANGUO_LIVE_STRATEGY=factor_topn),五 env 逐项可覆盖(SANGUO_LIVE_FACTOR_NAME/DIR/TOP_N/REB_DAYS/BAND),默认=生产配置 szneul_reb63(szneul/top200/reb63/band1.0);factor_dir 空=策略守卫不动作。
  • 件③④待拍板(VPS 生产动作,等口令):③VPS 每日截面 schtask(收盘数据后,VPS=生产因子计算的架构口径);④影子 instance 起跑(新 instance 非动 live_21/shadow_62,paper 模式不接 QMT 起法待定)。
  • 决议 K(09-24 用户裁决,issue #69)影子 A/B 挑战者:等权基线 composite_quant12(v1.1)同挂 _szneul 变体(composite_weighting._register_all 注册名表扩一项)——挑战者 composite_quant12_szneul 与在位者 composite_quant12_v2a_szneul 只差权重(源表/中性化包裹/策略参数全同构);起跑挂 szneul_reb63 同参影子(top200/reb63/band1.0),4 周+数据判:ICIR 赢=生产不动,等权赢=走换版本口令流程。裁决全档=流水线 spec §2/§4.4/§10(8147224);辩论全程=infra 立论四点→factor rebuttal(生产在位+fund8 实证+护栏已锁)→infra 认负两条事实错误→用户拍板。
  • 顺带修两存量测试卫生:channel_test 探针用例注入钟(盘后时段跑必红的时间条件缺陷,09-01 盘后防护遗留);composite routes fixture 幂等重挂 _REGISTRY(test_library/test_registry clear 后不还原,factor+api 组合首跑暴露建档 400)。

7.5 P1 流水线化(2026-09-22 计划落档,实现见 docs/superpowers/plans/2026-09-22-p1-factor-factory.md)

因子工厂四件套,全部新增不动既有模块(补中间不重建):

件 模块 职责
版本注册表 sanguo_factor/version_registry.py + config/factor_registry.yaml 状态机(incubating→assessable→promoted→decaying→retired→graveyard)+版本快照点时解析+墓园死因留档(流水线 spec 决议 D/E);CLI 转移即事件(决议 J1:事件 JSONL+晋级 issue 模板与可选 API)
衰减判定 sanguo_factor/decay.py 相对降幅 50%+绝对地板 t<2.0+连续 3 月才告警(1~2 月标黄);只对已晋级;集体水位中位数(决议 C/F,起步默认首年校准)
观察报告 sanguo_factor/observe.py 未晋级因子三色(记录新鲜度 90 天+覆盖 300 只),只观察不告警不判死
月度批评 sanguo_factor/monthly_review.py + review_compare.py 双机(NAS DSM+VPS schtask)各跑,读 factor_eval.db 判定出报告;JSON 对拍件 append-only,跨月续算;对拍分歧只开排查不开告警(决议 H);报告含 pre-gate 硬指标+无血统警告(决议 J2/J3)
因子贡献分解 sanguo_factor/attribution.py 日度 Fama-MacBeth 回归式归因(P3 第三刀, 流水线 spec §4.7 五条): 0.7 族代表+控制集(市场/log市值/行业哑变量)+sqrt(市值) WLS; 恒等式可加和+size 泄漏锚点+ridge 对照(λ=1 固定档, 惩罚随列方差缩放 A+λ·diag(A)≡相关形阵+λI——尺度不变, 等权/√市值两通道同效; 09-27 审计 F-2 修订: 旧 λI 加在权重放大的原始阵上, √市值量级相对收缩 ~1e-9=no-op; 系数统一收缩 1/(1+λ), 仅 VIF>10 触发, 当前 quant12 vif≈1.4 不进通道故历史产物不受影响); 行业表 join 不中→industry_code=0 独立桶(显式 ind_0 哑变量, 0 桶最大时自适应基线), unknown_industry_share 披露——不静默丢样本(2026-09-26 data 契约; 表交付 .SH/.SZ 通用形态, 消费端 norm_symbol 归一到 vt 形); 产物 attribution.json 供 /pipeline/attribution factorContribution 消费
归因批(月度 stage4) sanguo_factor/attribution_batch.py 09-27 落地、10-04 首班起挂月度批评链第四段(runner=scripts/nas_sync/run_factor_monthly_standalone.sh): ①15 截面增量前置(12 quant 源+size_log+在位者 composite_quant12_v2a_szneul+挑战者 composite_quant12_szneul, daily_section 220 历日短窗幂等 merge——NAS 截面无每日班, 批前必然新鲜; as_of 撞周末先归一 ≤as_of 最近 bar 日, latest_bar_date 库内权威防 sanity raise) ②归因双跑同窗同参(全窗锚 2021-07-01, 挑战者受其截面自然窗限制; 挑战者落工作区 challenger/ 子目录=端点 glob 非递归防顶掉) ③cp 双投递生效位(在位者件→data/attribution/ 根 glob 取最新; 挑战者件→challenger/attribution_<end>_<因子名>.json 带因子名)——#69 影子 A/B 四周对照的归因侧供给; 工作区 /volume1/stock/factor_cross_section/attribution/ 留全历史、生效位只持最新; fail loud=截面断供/归因挂/投递缺任一→容器非零→班次 final=1(静默旧件=红线)
研判卡回放 sanguo_factor/verdict_replay.py 月度批评同班车:monthly_points 触发点普查(已晋级逐月 t 中位数<集体地板)+七档事后近似成绩(基准回测曲线等权混合,档3/4=需精确验证);产物 verdict_replay.json 供 /pipeline/research-card 拼卡(设计=流水线 spec §4.7 P3 第一刀,2026-09-25)
先批后评·第一段 sanguo_factor/monthly_batch.py 月度批评日全量重评批薄 CLI(注册表全量→12M 窗→复用 run_batch_eval),跑批从「人点」变「日历」(决议 J)
数据缺口比对 sanguo_factor/data_gap_check.py + config/data_manifest.yaml 注册表 params.source vs 底座 manifest,缺口 exit 2 开 issue 转 data session(决议 J/§11.3-②)

数据链: eval_store 的 metrics["1"]["t_stat"] 即衰减判定输入(daily_section 日度落库已在产原料)。部署接线(NAS DSM 任务/VPS schtask/对拍汇集)等用户在场执行,步骤在计划档尾节。

7.6 P4-2 分解器刀(2026-10-02,#84;调研=reports/2026-10-02-p4-2-decomposer-survey.md,spec §4.8 D1-D5)

卡片→候选因子表达式一次成型:LLM 只写表达式(数字全由评估管线算),确定性护栏全代码硬门,通过者自动挂血统进 registry(零特权:与手写因子同注册表同求值器同月度考场)。

件 模块 职责与要点
确定性护栏 sanguo_factor/factor_guard.py 白名单三源预校验(ast.parse+Name:算子干净子集 35 ∪ 列名三族 101=bars 7+fund 90+sent 4 与 adapter 常量同源 ∪ 数字常量;func 位 Name 排除防算子名误报)+复杂度五条件(符号长≤300/引用列≤6 只数数据列/节点≤50/字面量≤10/深度≤12)+AST 防换皮(整树同构=严格序键∪≥8 节点公共子树=交换律规范键;ctx 与 Expression 根剔成退化公共子树)+derive_source(列族→source 确定性推导,跨 fund+sent 拒)
反馈循环 sanguo_api/hypothesis_decompose.py C3:max_rounds=3 上限+只重生成失败者(违规结构化渲染回 prompt)+通过者跨轮保有(原样复述=跳过不重验);prompt 白名单与校验同源渲染
decompose 端点 sanguo_api/routes_pipeline.py POST /pipeline/hypotheses/{id}/decompose:四层错误(404/409/503/502);通过者 upsert_factor(incubating)+add_version(params={expression,source,origin:decomposer,justification})→卡片转 building;502 零落库(save_registry 原子写+全成才落盘)
动态注册链 monthly_batch.py resolve_with_yaml D2 必修:内存静态库 miss→读 yaml 最新版 params.expression→register_factor(category=category_for_source);--registry 补 env SANGUO_FACTOR_REGISTRY 默认——分解产物进月度批评必经
IC 正交闸 sanguo_factor/ic_gate.py D4:逐日截面 Pearson→mean→对在库 max→≥0.99 置疑;月度批带 factor_values_out 导出({report_dir}/values/{label}/)后跑,报告件 ic_gate_{label}.json(不自动转移——裁决权在判定五问/人);新因子判定=params.origin==decomposer
死亡回写 version_registry.py writeback_card_death D5:CLI graveyard 转移同步回写假设卡片(死因+因子名;hyp- 卡 id 才回写,旧 H- 静默跳过;失败只 stderr 不阻断转移)

配套:卡片状态转移矩阵(pipeline_store.py,D3:queued→data_check→building→evaluating→promoted,任态→graveyard,两终态禁复活——重推假设=开新卡,对齐因子墓园决议 D;矩阵禁复活后 COALESCE 清空语义无需实现)。

已知偏差与 follow-up(终审台账):批内异名同表达式不查重(IC 闸值级兜底);decompose 端点无并发互斥(单用户低概率);save 后卡片转移失败重试=add_version 重复快照(无害);畸形反馈轮整单 502(重试语义);ic_gate json 缺席或 checked=0=闸未实质运行(无新因子或值文件缺失),非闸故障。

7.7 P70 收尾批(2026-10-03,#70 三件+决议 M 半环;计划=plans/2026-10-03-p70-factor-monitoring-batch.md)

流水线主体(P0-P4)收官后的边角四件一次清账,SDD 四任务+终审+修复波全双裁定:

件 commit 内容
① 合成层入册 d15653d composite_quant12(assessable 等权基线)+composite_quant12_v2a(promoted,promotion_t=26.32 锚 composite-v2a-h2 1d t=26.3192、promoted_at=2026-09-11)入 config/factor_registry.yaml——月度批评自此盯合成层衰减(此前生产在用的 v2a 衰了无人盯=最大监控盲区),等权/ICIR 两形态当月 IC 自动并排。szneul 变体不入册(无批评 t 锚,归 #69 影子 A/B+daily_section 盯)
② 月报门边 f9914ca monthly_review 新增 edge_cases(assessable 且当月 t∈[1.8,2.0),晋级 bar 2.0 的 10% 边带=起步默认首年校准):摘要行加门边计数+🟠清单节,人审第一屏直达「下次可能过门」
③ 考场一键 367b4cf python -m sanguo_factor.exam_gate --candidate <已注册名> [--baseline composite_quant12_v2a]:候选+基准同一 run 同批快照跑 h2 考场(默认 2021-07-01→今),1/5/10d ICIR 全不输且至少一胜=SUGGEST_PROMOTE(人裁);报告落 reports/factor_exam/exam_{cand}_{end}.md;promotion 永不自动化
④ 缺口开单 dbe6623 决议 M 半环闭合:data_gap_check 指纹自动开单(缺口集合 sha1 前 8 位=指纹入 title;同指纹 open 单在册→跳过,缺口自愈后复发=新指纹开新单;复用 J1 open_gitea_issue,env SANGUO_GITEA_TOKEN/SANGUO_GITEA_BASE_URL)+monthly_batch --manifest/--gap-issue 批前告警(fail-soft:缺口不阻批不换 exit 码;manifest 缺路径守卫=1b27226)

配套:测试 fixture 补 composite 链幂等重挂(b582b70——T1 真注册表入册后全套序依赖红的根治,守门测试 test_checked_in_registry_yaml_names_all_resolve 尽职抓到)。全域 tests/factor 485 绿(终审亲跑复核)。

已知偏差与 defer 台账(终审 triage 全缓):exam_gate NaN 周期计入 compared 不判胜负(方向安全不误晋级,首年校准加 isnan);candidate==baseline 静默自比→NO_PROMOTE;render count=0 显示 n/a;pre_gate_table 硬编码 2.0 未收编 _PROMOTION_BAR(实功能点仅 1 处,首年校准波收编);find_open_issue 单页 50(仓库 issue 量级内够用)。

首月观察点(10-04 首班起):composite_quant12 应走 observations「新鲜且覆盖足」、v2a 走 verdicts(promotion_t=26.32 生效;衰减线=双条件 AND:t<13.16 且 t<2.0,地板主导误报极低);exam_gate 生产首跑=NAS 真跑一次验收(搭首班窗顺车)。

审计杂项收敛批(2026-10-05,P3-15/16/17/18/19+T6-N1;上段 defer 台账「pre_gate_table 硬编码 2.0」就此收编):exam_gate 缺周期语义改 fail-closed——1/5/10d 任一周期任一侧缺 ICIR→INSUFFICIENT_PERIODS 不建议晋级(原「缺周期跳过不计」可退化单周期对比出 SUGGEST_PROMOTE,已废);考场报告文件名带 HHMMSS(同日重跑不覆盖,eval run label 不变);pre_gate REVIEW 阈值收编 _PROMOTION_BAR 常量(负 t 侧无镜像门边带=负向晋级不存在,维持现状);v2a 条目补 evidence_run: ev_20260911_021832_2f68(=promotion_t 26.32 锚批,NAS factor_eval.db label=composite-v2a-h2,1d t=26.3192 实查核验;惯例:promoted 条目 promotion_t 必须可溯源到 evidence_run);composite_library.build_composite_expression docstring 明示等权交集语义(任一源缺→null,分母恒 N 不重归一);data_gap_check 台账坏行(合法 JSON 非 dict)降级跳过+stderr(T6-N1)。

8. 前端与任务态

  • 投研三页(IC 排行榜/因子详情/批量评估):终端风 tokens(深空黑/荧光青),路由挂侧边栏「投研」组;mockup 三份在 docs/factor_research/*mockup.html。先读 frontend/src/styles/tokens.css 再做前端设计(第一版亮色被打回的教训)。
  • 因子任务落 backtest_stats(type=factor);组合回测走 POST /portfolio/backtest 异步。
  • ④ L2 覆盖 UI 化(#43,09-14 当日三段落地):原型 factor-l2-override-mockup.html(657276b 用户确认)。实施:
    • 机制层 composite_weighting.py:create_override_profile(UI 唯一写路径——只写新文件、命名规约 <基准stem>_ui_<日期>、总说明+每项 reason 必填、非负/非全零、tmp+os.replace 原子写、落档重载复读校验后立即注册)+ register_scanned_profiles 扫描注册(§5)+ list_weight_profiles/get_profile_payload 清单详情。档案格式=L1 verbatim + overrides + ui 溯源块(存 resolved 值会双重应用不幂等,测试钉死)。
    • API routes_factor.py:GET /factor/composites(清单)/ GET /factor/composites/profiles/{key}(详情含 resolved)/ POST /factor/composites/profiles(建档,pydantic ge=0 422 + create 层 400 双防线)。
    • 前端:L2Composite.vue 挂 /factor/l2(投研组「合成层 L2」,原型同款交互:L1 只读 badge/双 bar 联动/cap 警示/理由拦截);保存成功态一键跳批量评估(query 预填 factor/窗口 2021-07-01→2026-09-11 h2 考场,单因子 chip 模式、可移除恢复类目、人工点跑);Leaderboard composite 行加 L2 入口;批量评估 02 卡加指定单因子搜索下拉(按类目分组可搜,L1/L2 档案合成因子免跳转直选——用户验收反馈补)。

9. 工程坑与纪律清单(判定期连环案全录)

# 坑 纪律
1 CLI 双入口陷阱:runner_backtest 进程内 run_backtest(parse_args()) 参数完整 vs --json 走 run_backtest_json 手工拼 Namespace(曾漏 factor 四参数=三跑全空仓) 任何新参数双侧透传+test_run_backtest_json_passes_* 回归;验证必须走生产同款入口
2 引擎默认滑点 24.6bps:未显式 set_slippage 时 _calc_trade_price_with_default_slippage 套 24.6bps,「零滑点对照组」实为最大成本组,成本敏感性表观反向 三态语义(§6.2);对照组设计先查默认值
3 FixedSlippage 元/股语义:value=0.002 → ±0.001 元/股≈零成本,非比率 比率滑点一律 PriceRelatedSlippage
4 微扰混沌放大:同策略微扰(小滑点/数据快照差)5 年复利分叉 ±12pt 单变量对比必须同批;分叉=配置/数据变化信号(确定性回放)
5 trades 提取字段:bullet_trade Trade=security/time/tax/order_id(非 code/date) _extract_trades keys 已补+回归;Trade.amount 带符号(正=买)可分买卖
6 一次性跑批容器:docker run -d --rm -e HOME=/tmp --user 1024:100 --group-add 101 -v /volume1/stock:/volume1/stock -v /app安装目录:/app --entrypoint python 镜像 -X utf8 <runner>;HOME=/tmp 必设(vnpy 建 ~/.vntrider PermissionError);绝不配 --restart;日志落文件(--rm 容器删尸日志蒸发);timeout 给实测 1.4x 余量(贴线=负载稍高全灭);SKIP 断点续跑=json 存在即跳
7 pydantic v2 校验顺序:字段类型校验先于 field_validator,Optional[str] 直接拒 Timestamp 输入 字段放宽 Union[str, datetime]
8 代码格式双轨:截面/vnpy 侧 vt_symbol=SSE/SZSE,BulletTrade/聚宽侧=XSHG/XSHE 跨界必转(_to_jq_symbol)
9 filter_kcbj_stock 误杀创业板 实盘宇宙用 _filter_kcbj_keep_chinext

10. 未决事项

  • 行业归因定量分解:sw_industry 落位后(data session 09-14 夜验收)。
  • 改造方向四条待用户拍板优先级(§7) → 09-16 矩阵终态已答(§7.1):①宽带=band5 有效/温和带证伪、③log 中性化命中 2024 靶、④证负不采用、②top200 已默认;候选生产配置=中性化×季调(szneul_reb63/szneu_reb63 晨间出数),待用户拍板。
  • tests/api channel_test 随启随验断言墙钟依赖(非交易时段跑全量套件必挂,CI 不跑该目录暂无害)——修法=补非交易时段回退 9:35 分支断言,归属 live/工程 session。
  • ④ L2 覆盖前端 UI 化(#43):三段已落地(§8),剩 NAS 环境验收(建档→评估→生产冠军零变化)。
  • 判定期修复合集(47ab325/e2e6fe2/76523f0)在待推 VPS 清单,按口令闸门铁律等用户「推vps」。