37 KiB
因子体系总设计(唯一活文档)
建档: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 |
- 年化超额:有——Top100 ~6.8pt/年,top200 ~9.4pt/年(分散化全面占优:收益↑夏普↑回撤↓换手↓)。
- 夏普:0.16~0.24,偏低,超额靠波动扛。
- 成本侵蚀(生死题):每 +10bps 单边滑点 ≈ 总收益 -7.7pt;月调 11x 换手下实盘小盘冲击 30-50bps → 年拖累 3.3~5.5pt,超额基本被吃光——当前形态不可实盘化。调仓频率单调恶化(月 20.5%>双周 10.5%>周 -29.2%)。
- 逐年稳定性:top200 四正二负(2021 +23.8 / 2022 -12.5 / 2023 +4.2 / 2024 -3.7 vs 基准 +14.7(微盘雪崩年) / 2025 +35.2 / 2026 -8.1)。
- 超额来源:风格证据=与小盘风格高度绑定(2024 超额 -18~-29pt / 2025 +17pt);top200>base>top50 单调=非头部选股 α,是因子粗粒度排序 β+小盘暴露。行业归因定量分解待 sw_industry 首落后增强(持仓行业分布)。
7. 改造方向(留档待拍板,优先级序)
- 调仓缓冲带(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 对照(同批同快照)。
- 实现:
- 基准配置改 top200:矩阵内各维度全面最优。零代码(top_n 参数现成),跑批矩阵默认即改。
- 行业/市值中性化——✅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 数据验收后同式扩展。
- 实现:
- 分数加权替代硬切换——✅参数已落地(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 是风格对价。
五条结论:
- 频率单调律(最强发现):reb5(-29%) < reb10(10%) < reb21(34%) < reb63(70%)——月度以内调仓越频越死(换手×摩擦),季调直接命中实盘换手目标 3.8x 且收益翻倍;因子信息在季度尺度上依然有效。
- 带宽单调律: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 起才有实质留仓。
- 中性化:raw 版(敲巨头)头条最好 46.8% 但机制糙;log 版精准命中设计靶——2024 微盘崩年转正 +3.6%(超额 -18.4→-11.1pt)+ 回撤全场最优;szneul_band5 组合 60.9%/回撤 -33.9% 证明与宽带正交叠加成立。
- ④ 证负:γ=1 集中持股 -8.3pt、2024 最差——不采用。
- 实盘化路径: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(当日非空数+进出股票)。CLIpython -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(建档,pydanticge=0422 + 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」。