diff --git a/docs/factor_p1_morning_report_20260909.md b/docs/factor_p1_morning_report_20260909.md new file mode 100644 index 0000000..452c639 --- /dev/null +++ b/docs/factor_p1_morning_report_20260909.md @@ -0,0 +1,88 @@ +# P1 因子批+合成层·晨报(2026-09-09) + +> 范围:P1 批 43 因子(35 现有域+2 变体+6 新域)IC 两段验证 + 族分析跨批暗相关 + 合成层 v1(八环第④环) +> 代码:factor-fundamental 分支(8 commit,待互评通过合 master) +> 评估库:`/volume1/stock/factor_eval_fundamental.db`(P0/P1/合成层同库池化) + +--- + +## 一、总览 + +| 项 | 结果 | +|---|---| +| P1 注册因子 | 43 个(P1-A 35 + 变体 2 + P1-B 新域 6),特征列 32→68 | +| IC 两段跑批 | 5 组 × h1/h2 = 10 趟,3h12m 零错误(h1 4175 只/h2 4809 只) | +| effective | 0 个(最高 ICIR 0.251 未过 0.3 阈值;P1 价值在补族谱+合成原料,非新晋单因子王) | +| 族分析 | 209 因子(P0 32+P1 43+量价 62 参照+composite)32 族冗余 84.7% | +| 跨批暗相关 | 真跨批 29 对(alpha42 交叉之王 14 对;估值族×high_low_5 −0.71~−0.74) | +| 合成层 | composite_quant12 ICIR h1 **0.885** / h2 **0.735**,超最强单源 alpha16(0.66)=合成增益实证 | +| 互评备注 | 4 条中 3 条随批完成(SUE 严窗/北交所白名单/600519 锚点),F 族 eff+1 敏感性未做 | + +## 二、P1 IC 结果(RankIC 1D,两段) + +### h1 段头部(2016-01~2021-06) + +| 因子 | IC | ICIR | 说明 | +|---|---|---|---| +| fund_np_accel 净利加速度 | +0.011 | **+0.251** | 加速度族 h1 头名 | +| fund_ep_vb 长史EP | +0.020 | +0.218 | baostock 1990 树(D14) | +| fund_vsig 盈利波动 | +0.010 | +0.213 | CNE6 Earnings Variability | +| fund_sue_eps | +0.012 | +0.210 | | +| fund_sue_np_strict | +0.013 | +0.203 | 严窗变体≈0.999 主版(备注②结论:σ 含当期影响极小) | +| fund_gp_over_m 毛利/市值 | +0.018 | +0.197 | Novy-Marx | +| fund_vsig_acc / ebitda_over_ev / bp_vb / ebit_over_ev / rev_accel / vsig_cfo | | 0.17~0.195 | | + +### h2 段头部(2021-07~2026-09) + +| 因子 | IC | ICIR | 说明 | +|---|---|---|---| +| fund_bp_vb 长史BP | +0.034 | **+0.225** | 与 P0 fund_bp(0.319) 互证=估值 h2 主线 | +| fund_gp_over_m | +0.021 | +0.157 | 两段稳(0.197/0.157) | +| fund_gdhs_chg 户数变化 | +0.008 | +0.154 | 新域,筹码集中逻辑 h2 有效 | +| fund_vsig | +0.011 | +0.128 | | +| fund_np_accel | +0.007 | +0.127 | 加速度族 h2 仍在前 5=两段最稳 | +| fund_topholder_chg | +0.005 | +0.123 | 覆盖 2022+ 仍有效 | +| fund_ln_mv | −0.023 | −0.117 | 负=小市值效应 h2 加强(与微盘风格延续一致) | + +### 核心洞察 + +1. **加速度族是 P1 最重要发现**:np_accel(h1 0.251 头名 / h2 0.127)+ rev_accel(0.173/0.107)两段稳定——比 P0 水平增长族(h1 强→h2 大滑坡 18 eliminated)耐用,成长叙事的「二阶导」比「一阶导」活过了 2021 分水岭。 +2. **估值轴双源互证**:bp_vb(baostock 1990 长史树)h2 0.225 头名,与 P0 fund_bp(东财口径)h2 0.319 同向同量级(族分析 r=0.999)——D14 交叉验证过,两套原料一个结论。 +3. **VSIG 三件套 h1 齐发**(0.213/0.195/0.169)h2 只剩主版 0.128——盈利波动在 h1 是独立信息,h2 被估值/筹码盖过。 +4. **盈利能力递进族 h2 弱负**:roe_avg −0.022/roic −0.023——ROE 叙事 2021 后失效反号,与 P0 分水岭结论一致(这些本就是共线对照件,族分析 r 0.997-0.998 印证)。 +5. **弱尾**:debt_issue/goodwill_growth/nwc_growth/interest_cover 等 ICIR |x|<0.03 无信息;gm_nm_scissors/da_intensity 弱于预期。 + +## 三、族分析+跨批暗相关(209 因子×129 月,32 族冗余 84.7%) + +- 真跨批 29 对(财务×量价):**alpha42 交叉之王 14 对**(资产增长 +0.81 / NSI +0.80 / ROA −0.80 / ...);**high_low_5 第二引力源 7 对**——估值族(bp/cp/ep_vb)全灭 −0.71~−0.74 = 调研§6 预警第 5 条「低波×低估值」二连命中。 +- 设计验证命中:asset_growth_neg r=−1.000(精确镜像)、sue_np_strict 0.999、bp_vb/ep_vb 0.999/0.995(D14 交叉验证)、P1 口径递进族与 P0 高共线(roa_pretax 0.998 / roe_avg 0.997 / roic 0.989 / ebit_over_ev 0.991)。 +- **含义**:后续上线组合时 alpha42/high_low_5 与财务估值因子需做正交或二选一,防同源暴露叠加。 + +## 四、合成层 v1(八环第④环 Combiner 首落地) + +| 因子 | h1 ICIR | h2 ICIR | 结论 | +|---|---|---|---| +| composite_quant12(12 量价独立源) | **0.885** | **0.735** | 两窗 effective,超最强单源 alpha16(0.66) | +| composite_fund6(6 财务源,v1.1) | {{FUND6_H1}} | {{FUND6_H2}} | v1.0 剔 topholder 源后重跑 | +| composite_all18(量价+财务) | {{ALL18_H1}} | {{ALL18_H2}} | v1.0 参考 all19 h2=0.630 | + +- **合成增益实证**:quant12 两窗 ICIR 均超任一单源(最强 alpha16 0.66)——等权 rank 合成 12 独立源的分散收益 > 单源质量,八环战法第④环假设成立。 +- **v1.0→v1.1 修复**:fund7/all19 在 h1 整窗空(months=0)——根因链=topholder 源数据 2021Q3 起(契约说 2020Q1,实测不符)+首期无差分→2022 年中才生效+polars null 传染+引擎无 fill_null 算子 → 剔除该源改 fund6/all18(h2 也重跑保持口径一致;quant12 不受影响不重跑)。 +- topholder_chg 单因子保留注册(h2 0.123 有效),仅合成层 v1 剔除,v2 数据补全或特征层合成时回填。 + +## 五、top_holders 契约 discrepancy(已知会 data session) + +- §19.10 契约口径 2020Q1 起 vs NAS 镜像实测 108,610 文件全在 **2021Q3 起**——契约需修订,避免后续引用再踩。 +- 09-09 二轮回评复核(只读探针):`static/top_holders/` 文件名期分布首期=**20210930**(5431 文件/期整齐步进),边界 2021Q3 实锤。§19.10 修订文本(master 侧一行改,本分支无该节无法直接提交): + `2020Q1→2026Q2` → `2021Q3→2026Q2(09-09 修订:原 2020Q1 契约口径与 NAS 镜像实测不符——108,610 文件首期 20210930;后果=fund_topholder_chg 首期无差分 2022 年中才生效,合成层 v1 已剔该源)` + +## 六、待你动作(30 秒级) + +- 无阻塞项。前端「因子评估」选批次 p1-g1~g5 / composite-v11 可看全部结果(合流 master 后会导入主库默认批次)。 + +## 七、遗留与后续 + +- 合流 master:待 data session 第二轮回评(已邀请,对象=factor-fundamental 8 commit)。 +- F 族 eff+1 敏感性对照:唯一未做的互评备注,需 adapter 加 PIT 偏移开关两段对照,排 P2。 +- composite full 窗:砍(YAGNI,两段已够用)。 +- 僵尸 run 行:composite-full / 重复 composite-h1/h2(容器重启冗余重跑残留)待清。 diff --git a/sanguo_factor/composite_library.py b/sanguo_factor/composite_library.py index f7e1a76..3d2b0b3 100644 --- a/sanguo_factor/composite_library.py +++ b/sanguo_factor/composite_library.py @@ -1,7 +1,7 @@ -"""合成层 v1(Combiner): 量价 12 独立源 + 财务 7 源 → 等权 rank 合成总分因子. +"""合成层 v1(Combiner): 量价 12 独立源 + 财务 6 源 → 等权 rank 合成总分因子. 「因子战法八环」第④环首个落地. 因子 = 表达式字符串注册(category="composite"), -表达式由 build 函数从源清单常量表循环拼接(19 源数千字符,引擎 eval 解析无碍; +表达式由 build 函数从源清单常量表循环拼接(18 源数千字符,引擎 eval 解析无碍; 可读性/可维护性由源常量表承载,不手写长表达式). cs_rank 语义(vnpy_v4.4.0/vnpy/alpha/dataset/cs_function.py:15): @@ -16,10 +16,10 @@ cs_rank 语义(vnpy_v4.4.0/vnpy/alpha/dataset/cs_function.py:15): 弃用,全文统一 rank 外. - 财务源: 注册表达式本身已是 `cs_rank(指标)`(负 IC 已在表达式内取负定向, 高=好) → 直接内嵌、不再套 cs_rank;源表方向列 = 内嵌后净方向,登记 "-" - 时才前置 `(-1) * `(当前 7 源全为已定向正向,不触发). + 时才前置 `(-1) * `(当前 6 源全为已定向正向,不触发). -Null 传播: polars 算术 null 传染 → 合成值任一源 null 即 null(覆盖 = 19 源 -交集;gdhs/topholder 等事件流源在上市早期覆盖受限,合成因子覆盖期短于 +Null 传播: polars 算术 null 传染 → 合成值任一源 null 即 null(覆盖 = 18 源 +交集;gdhs 等事件流源在上市早期覆盖受限,合成因子覆盖期短于 单源,属已知限制非缺陷). warmup: 量价源最大窗 vma_60=60 bar / alpha83 内层 ts_sum(ts_mean(volume,10),50) diff --git a/sanguo_factor/fundamental_adapter.py b/sanguo_factor/fundamental_adapter.py index 078caf8..4bd7f27 100644 --- a/sanguo_factor/fundamental_adapter.py +++ b/sanguo_factor/fundamental_adapter.py @@ -649,7 +649,7 @@ def _load_forecast_events(codes: list[str], data_dir: str) -> tuple[pl.DataFrame pl.lit(report_date, dtype=pl.Date).alias("REPORT_DATE"), pl.lit(_ANNUALIZE_FACTOR.get(report_date.month), dtype=pl.Float64).alias("_annf"), pl.col("公告日期").cast(pl.Date, strict=False).alias("eff"), - pl.col("预告类型").cast(pl.Utf8).replace( + pl.col("预告类型").cast(pl.Utf8).replace_strict( FORECAST_TYPE_SCORE, default=None, return_dtype=pl.Float64 ).alias("_score"), ).filter(pl.col("vt_symbol").is_in(code_set) & pl.col("eff").is_not_null()) diff --git a/scripts/factor_research/import_runs_to_main_db.py b/scripts/factor_research/import_runs_to_main_db.py index bab62e0..9bbc836 100644 --- a/scripts/factor_research/import_runs_to_main_db.py +++ b/scripts/factor_research/import_runs_to_main_db.py @@ -8,8 +8,10 @@ Leaderboard 只读主库(默认 factor_eval.db),导入后即可与量价类别 用法: python scripts/factor_research/import_runs_to_main_db.py \ --src /volume1/stock/factor_eval_fundamental.db \ - --dst /volume1/stock/sanguo_vnpy_v2/data_backup/factor_eval.db \ + --dst /volume1/stock/sanguo_vnpy_v2/data/factor_eval.db \ --run-ids fund-p0-h1,fund-p0-h2,quant62_ref + ⚠️ dst 必须是 data/factor_eval.db(容器主库默认位);09-08 曾误写 + data_backup/ 导致前端不可见,勿再踩. (--dst 省略时用 default_eval_db_path(),容器内即主库默认位) 语义: diff --git a/tests/factor/test_composite_library.py b/tests/factor/test_composite_library.py index dd879aa..0462dbc 100644 --- a/tests/factor/test_composite_library.py +++ b/tests/factor/test_composite_library.py @@ -255,6 +255,6 @@ def test_composite_end_to_end(db, synthetic_static, tmp_path): m = eval_store.get_detail(eval_db, out["run_id"], name)["metrics"] assert "error" not in m, f"{name}: {m.get('error')}" # 量价源全天候覆盖 → quant12 截面 IC 样本点非零; - # fund7/all19 在合成静态域 topholder_chg 仅 1/3 股覆盖 → count 可为 0(非错误) + # fund6/all18 在合成静态域 gdhs_chg 等事件流源覆盖受限 → count 可为 0(非错误) m = eval_store.get_detail(eval_db, out["run_id"], "composite_quant12")["metrics"] assert m["1"]["count"] > 0