akg-factor-bridge/量化因子导出与合成设计.md

608 lines
39 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 量化因子导出与合成设计v2.02026-07-26
> **一句话**:把 astock-kg 知识图谱的产业理解,做成一个**自洽的、有经济含义的**
> 景气度选股因子 `akg_score`,托管在通用因子管理平台 `quant_factor_service`
> 里(本文只用其**注册 / 存储 / 调度 / 评价**能力,**不用其合成能力**,理由见 §2
> 因子的合法性来自**产业逻辑**,不来自历史 IC 拟合。
>
> **本版是对 v1.1 的方向性修订,不是增补。** v1.1 的核心方案(四路子因子对称注册
> → 平台 ElasticNet/贝叶斯/GRU 拟合出复合因子)已被推翻,理由见 §2。v1.1 中的
> **数据契约、视图定义、子因子构造口径、平台接口细节**仍然有效本版继承并更新§5、§6
>
> **版本号约定(避免歧义)**`v1.1 / v2.0` 指**本设计文档**的版本;因子自身的演进阶段
> 一律用 **S1 / S2 / S3** 表示S1 = 首个上线版本)。
---
## 0. 版本变更与决策基线
### 0.1 v1.1 → v2.0 的三处推翻
| 项 | v1.1 | v2.0 | 触发原因 |
|---|---|---|---|
| 复合方式 | 平台**拟合合成**ElasticNet/贝叶斯基线GRU 三头为目标) | **桥内自洽公式**(漏斗),平台不参与合成 | 拟合要求全部输入可回填、且历史上与收益共变;传导两者都不满足 |
| 四路地位 | 四路**对称**,权重由拟合决定 | **两道硬门槛 + 三项加权**,权重由投资逻辑指定 | 「c 应该是硬门槛……传导第一、还没热第二、便宜第三」 |
| 回测角色 | **生死闸**(神经 IC-IR 超线性基线才判收) | **仪表盘**(持续观测,不做 go/no-go | 「核心是这个值有其合理性和经济含义在,那么大方向肯定不会是错的」 |
### 0.2 v2.0 决策基线
| 议题 | 决定 | 理由摘要 |
|---|---|---|
| 承载形态 | **独立 `akg-factor-bridge` 工程**Docker可单独部署 | 基座只暴露只读视图,桥消费视图+热度、写平台;三方镜像都保持纯净 |
| Universe | **astock-kg 覆盖池**`industry_pools` 全主题成员并集),实测 **1675 只** | 池内信号厚;实测规模足够做截面统计 |
| 复合因子 | **`akg_score` = 景气度漏斗**,桥内计算,注册为 `single`(平台视角它就是一个普通因子) | 自洽公式的产物不是"平台合成结果",不占 `multiple` 语义 |
| 赛道范围 C | **十五五规划前沿赛道产业链**(核聚变、商业航空航天、通信、算力、人工智能、低空经济等;材料 → 设备/零部件 → 制造/系统集成 → 应用/服务,全链) | **划定范围,不做计算**——范围本身就是确定性来源 |
| 传导 | **只 live 使用,不回填、不进拟合** | 传导是推断不是观察回填必然引入前视§2.2 |
| 评价 | 复用平台 `ic_calculator` + 分层回测,**当仪表盘看** | 复用平台的目的就在评价与调度,但不让它当判官 |
| 开发规范 | **全流程 Docker**(构建/运行/连库/psql 一律走容器) | 团队铁律 |
---
## 1. 投资论题:为什么是"景气度漏斗"
这一节是全文的地基。因子的每一项都能追回到这里的某一句话;若论题变了,因子该重做。
**主线判断。** A 股乃至全球股市未来三五年的主线是科技。这条主线会在 AI 渗透率接近
2015 年移动互联网渗透率、AI 变成某种公用服务或基础设施之后终结——那时它才会像新能源
或制造业那样"可研究"(业绩稳定、能做确定性高的预测)。在此之前,它不可研究。
**不可研究意味着什么。** 具体到方法论,处在这个阶段的赛道有三个特征:
1. **大方向向上**——产业趋势本身没有分歧,政策与产业资本都在推;
2. **无法准确估值**——收入曲线还没定型DCF/PE 给不出可信中枢;
3. **没有另类领先数据**——不像制造业有订单、排产、开工率可以先行跟踪。
三条同时成立时,自下而上的基本面精算是无效的(算不准),量价动量是滞后的(等确认
就已经在右侧了)。**剩下唯一可行的办法是景气度投资**:不追求算准,只追求
**方向对 + 位置早 + 价格不离谱**
**落到选股上,就是找两类特征的交集:**
- **确定性高**——确定性不来自盈利预测,来自**产业逻辑**:它在不在国家级主线上、
在产业链上占什么位置、这个位置有没有壁垒。
- **相对较便宜**——不是绝对估值便宜,是**相对于预测的空间还在**。因为系统赌的是
大方向正确,必须给自己留容错度;贵了就没有容错度了。
**热度在这里的真实作用。** 单一股票的热度本身没有太大意义。它的价值在于
**辅助验证产业传导逻辑是否已经启动**——用来缩短左侧建仓的时间和风险。所以热度
不是一个独立的 alpha 来源,它是传导逻辑的**确认器**与**位置指示器**
板块层面已启动(传导给出),个股层面还没热(热度给出)= 左侧位置还在。
> S1 的实现把"还没热"落成了一个**独立加性项**而非条件项,这是一处有意的简化,
> 代价与备选方案见 §3.4 与 §9-9。
**研报滞后的再解释。** 硬科技赛道的特征是壁垒高、投入大、业绩分化、生态站位分工
明确。券商研报覆盖这类标的天然滞后。在一个看预期的市场里,**滞后本身反而是确定性的
体现**——研报开始密集覆盖时,产业逻辑已经被验证到了能写进报告的程度。所以我们不把
"研报少"当成信息缺失来惩罚,而是把"研报所指的赛道"当成一个已经通过验证的范围来使用。
---
## 2. 方法论转向:从"拟合合成"到"自洽公式"
### 2.1 原方案为何走不通
v1.1 的设想是把四路信号当成对称的特征喂给平台的合成引擎ElasticNet 滚动 /
BayesianRidge / GRU 三头),让模型学权重。三条独立的理由否决了它:
**(一)实证否决。** 单纯的 heat 与其他因子的合成结果此前并不理想。这不是调参问题,
是"把热度当 alpha 源"这个前提本身站不住——热度既可能是动量也可能是拥挤反转,符号不
稳定,模型学到的权重会随窗口反复翻转。
**(二)数据本身有系统性偏差。** 上升空间本质上是**券商报喜不报忧**的预测。它作为
一个"还有多少空间"的相对标尺是可用的(这也是为什么它留在漏斗里当门槛),但作为一个
待拟合的自变量,它携带的偏差是结构性的、不随样本增加而消失的。
**(三)传导根本进不了拟合模型。** 这是决定性的,展开在 §2.2。
### 2.2 观察 vs 推断:一个必须区分的类型学
四路信号看起来同构(都是"每股每日一个数"),但它们的**认识论地位**不同:
| 维度 | **观察observation** | **推断inference** |
|---|---|---|
| 定义 | 世界上发生了某件事,被带时间戳地记录下来 | 系统在某一天,用当天的状态推出的一个判断 |
| 本例 | 事件(`disclosure_date`)、热度(上游历史留存)、预期空间(研报 `asof_date` | **板块传导**`scan_date` |
| 历史 | 有耐久历史,重放可复现 | **无耐久历史**,过期即不可复原 |
| 回填 | 可回填,点时正确 | **回填 = 前视** |
**传导为什么是推断。** 传导候选 = 当日异动集movers× 当时的产业链图谱。两个输入
都没有耐久历史:历史每日的 hotspot 异动集没有留存;产业链图谱是**随研报持续生长的
当前态**`industry_pools` 只存最新快照、没有时点版本。
于是若要重建 2024 年某日的传导,只能用**今天的图谱**去套 2024 年的行情——而今天的
图谱里,有大量关系是 2025、2026 年的研报才写进去的。**这是教科书式的前视偏差**
回填出来的历史传导会"提前知道"后来才被发现的产业链关系,其历史 IC 必然虚高,而这个
虚高恰恰无法在样本外复现。
**推论。** 任何需要"历史上该特征与收益共变"的方法——线性回归、贝叶斯、GRU无一例
外——都无法把传导纳入。不是因为传导没用,恰恰相反,是因为**传导是我们唯一真正原创
的信号,而它天生不可回测**。
> **神经网络能否豁免?** 不能。常被误解的一点是"神经网络不要求因子为正、有信息即可"
> ——这句话本身对A 股利好往往是大跌的开始,符号确实无所谓,模型可以学到负向使用)。
> 但它要求的是**该特征在样本内相对结果有过变化**。传导没有可信的样本内历史,
> 模型面对的是一列几乎全空、仅最近三天有值的特征,只会把它的权重压到零。
### 2.3 转向:自洽公式
既然最有价值的信号无法进拟合,就不要为了迁就方法而丢掉信号——**换方法**。
因子化仍然是必须的,也必须通过现有因子管理平台托管;但**未必要通过平台的合成方案**。
如果系统自己能用自洽的方案算出这个值,那么:
- **合法性来源改变**:从"历史 IC 显著"改成"**这个值有其合理性和经济含义**"。
- **回测不再是前置条件**:甚至不需要马上回测。核心是这个值经济含义成立,
**那么大方向肯定不会是错的**——这是我们追求的。
- **回测降为仪表盘**:仍然做、仍然看、仍然复用平台的 `ic_calculator` 和分层回测,
但它输出的是"当前市场是否在奖励这套逻辑"的读数,不是"这个因子该不该活"的判决。
这个转向还有一个附带好处:公式的每一项都能被人读懂、被人质疑、被人调整。拟合出来的
权重做不到这一点,而在一个我们明确承认"无法准确估值"的领域里,**可解释性比精度更重要**。
---
## 3. 复合因子 `akg_score`:景气度漏斗
### 3.1 结构
```
KG 覆盖池 Uindustry_pools 全主题并集,实测 1675 只)
┌─────────────────▼─────────────────┐
│ 硬门槛 ① 赛道 C │ 十五五前沿赛道产业链成员
│ 材料→设备/零部件→制造/系统集成→应用 │ —— 划定范围,不计算
└─────────────────┬─────────────────┘
┌─────────────────▼─────────────────┐
│ 硬门槛 ② 估值 V │ upside ≥ θ_v贵了不买
│ (留容错度) │ —— 一票否决
└─────────────────┬─────────────────┘
候选池 P_t
┌─────────────────▼─────────────────┐
│ 池内加权排序(截面标准化后加权) │
│ w_T · z(传导) ← 第一,最重 │
│ w_H · z(−热度) ← 第二,还没热 │
│ w_V · z(便宜) ← 第三,再加权 │
└─────────────────┬─────────────────┘
akg_score写平台因子表
```
**为什么是漏斗而不是加权和。** 加权和允许"某一项极好补偿另一项极差"——在这套逻辑里
这恰恰是灾难:一个不在赛道上的股票传导分再高也不该买(传导的经济含义依附于产业链
的真实性),一个贵到没有容错度的股票赛道再正也不该买。**硬门槛表达的是"不可交易"
权重表达的是"更值得先买"**,两者不能混为一谈。
### 3.2 硬门槛 ① 赛道 C定义域非计算量
**定义**C(i) = 股票 i 属于十五五规划前沿赛道产业链的任一环节。
赛道清单以十五五规划确定的前沿领域为准,已明确的包括:**核聚变、商业航空航天、通信、
算力、人工智能、低空经济**等(完整清单待补,见 §9-2。每个赛道按**上下游全链**取,
`layer` 统一四层枚举:**材料 → 设备/零部件 → 制造/系统集成 → 应用/服务**。
**这是本设计最重要的一步C 是一个被划定的范围,不是一个被计算的分数。**
理由(用户裁定):所谓硬科技赛道本身就是**壁垒高、投入大、业绩分化、生态站位分工
明确**。这些属性一旦成立,赛道内标的的"确定性"就已经由产业结构提供了,不需要再用
数据去打分——**打分反而会把结构性的确定性稀释成一个可被其他项补偿的连续量**。
这也与 astock-kg 的"不打分"铁律一致:系统负责把范围划清楚,不负责给股票评级。
**实现路径(桥内新增模块 `tracks.py` + 配置 `config/frontier_tracks.yml`**
```yaml
# 示意结构,实际清单待 §9-2 确认
tracks:
- name: 商业航空航天 # 正式名唯一,别名进 aliases
aliases: [商业航天, 航天科技]
kg_themes: [...] # 映射到 industry_pools 主题名
kg_segments: [...] # 映射到环节(材料/设备/制造/应用)
kg_concepts: [...] # 映射到概念标签
- name: 低空经济
...
```
**成员表落在哪里(归属)**yml 是**唯一事实源**,随桥仓库版本控制;映射产物物化为
`track_members`(列:`ts_code, track, layer, source_rule, updated_at`**落在桥工程
自身的 `data/` 目录下的版本化快照文件**CSV/Parquet`git diff`**不落基座、
不落平台**——这样既不破坏 §4 的三层边界,又满足"必须能被人逐条 review、能被 diff、
能追溯某只股票凭什么进来"的审计要求。若日后下游需要 SQL 查询,再另议是否落库。
**关键前置风险**C 是一次图谱成员性测试,它成立的前提是 astock-kg 的图谱**真的覆盖
了这些赛道**。通信 / 算力 / 半导体大概率已覆盖;**核聚变、低空经济、商业航空航天的
覆盖情况未知**。因此 **G1 里程碑的第一件事是赛道覆盖体检**§8体检结果决定 S1 先
上哪几个赛道——覆盖为空的赛道宁可先不放进来,也不要放一个空集合进公式。
### 3.3 硬门槛 ② 估值 V贵了不买
**定义**V(i,t) = `akg_upside(i,t) ≥ θ_v`
**θ_v 的口径**`θ_v = max(0, 池内 upside 的 q 分位)`,默认 q = 0即退化为
`θ_v = 0`:一致预期目标价中枢不低于现价)。**绝对下限 0 不可让渡**——它是"容错度是否
真的存在"的物理判据;分位数只用于**在此之上进一步收紧**,绝不用于放行 upside 为负的
标的。q 的取值见 §9-3。
**为什么必须是硬门槛而不是扣分项**:系统的算法本质是"大方向正确",精度有限,
**必须给自己留下容错度**。容错度的物理载体就是价格与预期中枢之间的空间。空间为负时,
即便产业逻辑完全正确,也已经没有犯错的余地了——这时不是少买一点的问题,是不该买的问题。
**已知偏差**upside 来自券商一致预期,天然报喜不报忧,绝对水平偏乐观。作为**截面
相对标尺**它仍可用(乐观偏差在覆盖股之间大体同向);若实测发现 θ_v = 0 几乎筛不掉
任何股,就靠上调 q 来收紧,而不是放弃这道门槛。
**缺失处理**upside 为 NaN无券商覆盖= **不通过门槛**。这是保守选择:
没有覆盖就没有容错度的度量,宁可漏不可错。代价是牺牲一部分真正冷门的早期标的
——这个代价与"研报滞后是确定性体现"的论题有张力,列为 §9-4 待议。
### 3.4 门槛内的三项加权
在候选池 P_t **之内**(标准化只在池内做,池外样本不参与统计量估计):
| 项 | 构造 | 默认权重 | 语义 |
|---|---|---|---|
| **传导** z_T | `(log1p(akg_transmission) mean) / std` | **0.50** | 产业逻辑正在向该环节传导——最硬的买入理由 |
| **还没热** z_H | `1 × robust_z(akg_heat)`(中位数/MAD | **0.30** | 个股尚冷 = 左侧位置还在(见下方"退化说明" |
| **便宜** z_V | `robust_z(akg_upside)`(中位数/MAD | **0.20** | 过了门槛之后,空间越大越优先 |
$$\text{akg\_score}_t(i) = w_T \cdot z_T + w_H \cdot z_H + w_V \cdot z_V,\quad
i \in P_t$$
**权重次序由投资逻辑指定**(传导第一、还没热第二、便宜第三),不由拟合决定。
0.5/0.3/0.2 是满足该次序的一组默认值,是**旋钮不是结论**;调整它需要的是逻辑上的
理由,不是回测上的理由。
**"还没热"的退化说明(必须写明的一处妥协)**§1 里热度的定位是**条件性**的——
只有在传导已确认板块启动的前提下,"个股尚冷"才等于"左侧位置还在"。但 S1 把它实现
成了**无条件加性项**,后果是:传导为 0 的股票只要够冷,仍然能拿到 0.30 权重的正分,
此时该项退化成一个**独立的反拥挤/低关注度因子**,与 §1 的"确认器"定位脱钩。
接受这个妥协的理由是:赛道硬门槛已经保证了标的的产业地位,在**已经确定是好赛道**的
池子里,"冷"更可能意味着"还没被发现"而非"基本面差",所以退化后的语义仍然可辩护。
备选实现(条件项 `z_H · 1[z_T>0]`、或交互项 `z_T · z_H`)列为 §9-9S2 再评估。
**几个必要的技术处置:**
- **截面标准化是自洽性的前提,不是可选项**。三项量纲完全不同(传导是"路径数 × 空间
比例"的乘积量、热度是 0~1 分、upside 是收益率),不标准化则权重毫无意义。
**热度项与便宜项**采用池内**稳健标准化**(中位数 / MAD对齐平台
`MathKernel.winsorize_mad` 的处置口径),避免少数极值主导。
- **传导项例外:不能用 MAD**。传导在池内约 **95% 为 0**(覆盖池内单日仅 83 行有值),
此时 `median = 0`**`MAD = 0` → 除零**。传导项改用非稳健口径
`z_T = (log1p(x) mean) / std``std = 0`(当日池内无任何传导)时整列置 0。
`log1p` 是为压长尾,避免单只票的极端路径数吃掉整个排序。
- **传导缺失 = 0即"取基准值",不是剔除**。标准化后 0 会落在池内均值**之下**
等价于对有传导者的相对加分——这正是想要的:传导项实质是**稀疏加分**而非连续排序,
少数被产业逻辑点名的票被显著抬升。若把传导设为必需项,候选池会塌缩到每日几十只
以下,既失去组合意义也无法做任何截面统计。
- **热度缺失 = 池内中位数**(视为"信息未知"而非"很冷"upside 已在门槛处保证非空。
- **门槛外的股票不出行(不写入),而不是写 0**。写 0 会被平台的分层/IC 计算当成
"中位水平",从而污染排序语义;不出行则由平台 Gen-2 的 Polars 外连接自然容忍。
- **时点对齐**:热度是 **T+1 到达**的日频数据,因此 `akg_score(T)` 的热度项实际使用
**T1 日热度**(当日可得的最新一期)。这不是缺陷而是点时正确的必然结果,
必须在因子描述与调度设计里写明§6.4、§8-G5
### 3.5 事件因子在 S1 的位置
用户给定的权重次序里没有事件项,因此 **`akg_event` 在 S1 不进主公式**。
保留它的理由和未来用法A 股"利好往往是股票大跌的开始"**正向事件不可靠**
但**负向事件(诉讼仲裁、行政处罚、股权质押)作为排除条件是稳健的**——它们不预测
上涨,但确实标记不该碰的标的。因此规划 **S2 把事件做成第三道软否决闸**
`akg_event < θ_e` 时剔除或大幅降权。这条不在 S1 上,先观察事件因子自身的分布与
覆盖(实测每日仅 195 行,稀疏)再定 θ_e。
---
## 4. 系统边界:基座 / 桥 / 平台
**三层职责切分(已锁定,不再讨论):**
- **astock-kg 基座**:只**暴露数据**,不算因子。对外只给一组**只读视图**(插槽接口);
基座内部随便重构、接口不变。**不新增任何因子计算**,守住"不打分"铁律。
- **`akg-factor-bridge`(独立工程 / 插槽)**:承载全部因子建模——读基座视图 + 直连 153
读热度 + 读平台行情,做子因子变换与**漏斗合成**,转前缀码,写平台因子表 + 注册。
所有建模决策(赛道清单、门槛阈值、权重、半衰期、极性表)集中在桥里,归属清晰;
赛道成员快照等桥自有中间产物落桥工程 `data/`不外溢到基座或平台§3.2)。
- **因子平台 `quant_factor_service`**:保持通用、不感知 astock-kg。只把桥写进来的因子
当普通因子,承担存储、注册、调度、**评价(仪表盘)**、下游服务。
> **为什么不合并进 astock-kg**:基座定位是"数据分析基座微内核",其他应用围绕它形成
> **插槽架构**。因子导出理论上只需要拿到数据库连接方式,不需要动基座。独立工程还带来
> 部署自由——桥落在哪台服务器只由"能否同时连通三处"决定。
```
astock-kg 基座PostgreSQL── 只读视图(插槽接口,零新增计算)
├ v_factor_universe 覆盖池1675
├ v_factor_consensus (一致预期 → upside
├ v_factor_events EVENT 断言,已解析 ts_code → event
└ v_factor_transmission (传导未动成员 → transmission
│ 热度不经基座:桥直连 153 代理 stock_fund_heat_scores
│ 现价不经基座:桥直连平台 gp_day_data
akg-factor-bridge独立 Docker 工程,可部署于任意能连通三库的服务器)
四路子因子变换 + 赛道成员快照data/ + 【漏斗合成 akg_score】
因子平台 quant_factor_service通用、不感知 astock-kg
t_factor_akg_{upside,heat,event,transmission,score} + factor_metadata
→ 评价RankIC / IC-IR / 分层回测)= 仪表盘
→ 每日调度 / 下游策略消费
```
**因子表契约**(平台侧,不可改):
`t_factor_{code}(trade_date DATE, stock_code VARCHAR(15), factor_value DOUBLE)`
主键 `(trade_date, stock_code)``stock_code` 为**前缀式** `SH600000`
`600000.SH → SH600000`)。注册表 `factor_metadata(factor_code, display_name,
target_ds_name, target_table_name, category JSON, factor_type, frequency, status,
author, description)`
---
## 5. 子因子口径(继承 v1.1 文档,按 v2.0 语义更新)
四路子因子**继续独立注册与落库**——它们是漏斗的原料,也是各自可独立观察的仪表。
### 5.1 `akg_upside` 预期空间 → **门槛② + 权重③**
- **源**:基座 `v_factor_consensus.target_mid_avg` ÷ 平台 `gp_day_data.close` 1。
- **as-of 口径**:现价日取 `asof_date <= 当日`的最新一致预期(`merge_asof` backward
杜绝前视。
- **实测**2026-07-23 单日 **795 行**;一致预期在基座内只有 2026-07-11 起 7 天历史。
- **注意**`gp_day_data` 的代码列是 **`symbol`**(前缀式,如 `SH688280`
`ts_code`;桥内 `_read_gp_price()` 按候选列自动探测。
### 5.2 `akg_heat` 热度 → **权重②(语义取负)**
- **源**153 代理 `stock_fund_heat_scores.score`0~1**T+1 日频**,已是前缀码),
取每日最新 batch。
- **v2.0 语义变更****不再当动量/alpha 源用,改为"还没热"取负号使用**。
子因子表 `t_factor_akg_heat` **仍存原始 score 不变**,取负只发生在漏斗内部
(保持子因子表语义中立、可被其他消费方复用)。**该语义翻转待用户确认**§9-1
- **实测**2026-07-23 单日 **1674 行**(覆盖最广);历史 2025-03-26 起 322 天。
### 5.3 `akg_event` 事件 → **S1 不入公式S2 负面否决闸**
- **源**:基座 `v_factor_events``predicate='EVENT'`ts_code 取**文档锚**
`documents.meta->>'company_ts_code'`(公告是单公司文档,锚定 100% 可靠),
**不用**未解析的 `claims.subject_id`
- **构造**:Σ 窗口内事件极性 × 时间衰减 `exp(交易日龄·ln2/半衰期)`
半衰期 10 交易日、窗口 60 交易日(草案,见 §9-5
- **实测**2026-07-23 单日 **195 行**(稀疏);历史 2014-01-04 起 843 天(最深)。
### 5.4 `akg_transmission` 板块传导 → **权重①(最重)**
- **源**:基座 `v_factor_transmission``transmission_candidates` 的 `quiet` 成员摊平)。
时点戳字段为 **`scan_date`**(传导扫描日,每日 18:15 后产出)。
- **构造**`路径数 × (1 已动比例)`,同股同日多候选取最大。
对齐传导模块"多源汇聚=逻辑更硬、已动比例低=空间更大"的语义。
- **实测**2026-07-23 单日 **83 行**;历史仅 2026-07-11 起 **3 天**
- **使用约束****只 live 累积,不回填,不进任何拟合模型**§2.2)。
---
## 6. 实现现状(截至 2026-07-24 实机验证)
### 6.1 已完成
- 基座四视图已建(`sql/astock_kg_slot_views.sql`,容器内 `psql` 应用)。
- 桥工程 `akg-factor-bridge` 全量落地Docker + compose + CLI
三库连通性全部打通:基座 PG ✅ / 153 热度 ✅ / 平台因子库 ✅
**平台因子库亦可经 153 同一 ShardingSphere 访问** —— v1.1 文档 §8.1 已回答)。
- 四子因子**全部注册成功**`factor_metadata` 含 `factor_type` 列)。
- 四子因子**全部落库成功**2026-07-23upside 795 / heat 1674 / event 195 /
transmission 83 行。
- **未完成**:赛道成员表、漏斗合成 `akg_score`、`factor_coverage_probe.py` 实跑。
### 6.2 实测数据历史深度(回填范围据此定)
天数列 = 该源 `COUNT(DISTINCT 时点列)`,为**有数据的日期数**(非交易日历天数)。
| 源 | 时点列 | 起 | 止 | 天数 |
|---|---|---|---|---|
| 行情 `gp_day_data` | `timestamp` | 1997-08-29 | 2026-07-23 | 5584 ⚠️ |
| 事件 events | `disclosure_date` | 2014-01-04 | 2026-07-20 | 843 |
| 热度 heat | `trade_date` | 2025-03-26 | 2026-07-23 | 322 |
| 一致预期 consensus | `asof_date` | 2026-07-11 | 2026-07-23 | 7 |
| 传导 transmission | `scan_date` | 2026-07-11 | 2026-07-23 | **3** |
覆盖池 universe**1675 只**。
> ⚠️ **待实机复核**`gp_day_data` 区间跨约 28.9 年,按 A 股年均 ~242 交易日应在 7000
> 上下,实测 5584 相当于年均 193 天——怀疑真实起始日晚于 1997约在 2003~2006 之间,
> 早期只有零星记录)。**§7 中 upside "理论可回填到 2006"依赖这一行,需先复核**。
> 复核方式:按年统计 `COUNT(DISTINCT timestamp)`,看从哪一年起接近 242。
>
> 另注consensus/transmission 的起始日 2026-07-11、事件起始日 2014-01-04 均为周六,
> 因这三者的时点列是**披露日/扫描日等自然日**而非交易日,属正常。
### 6.3 已解决的实现陷阱(记录以免重踩)
| 现象 | 根因 | 处置 |
|---|---|---|
| `factor_metadata 无 factor_code 列` | **ShardingSphere 代理不支持 `information_schema` 内省** | 改用 `SELECT * FROM factor_metadata LIMIT 0``cur.description` 取列名,附硬编码兜底 |
| `Unknown column 'ts_code'` on `gp_day_data` | 平台该表代码列实为 `symbol` | `_read_gp_price()` 按候选列 `symbol/ts_code` 逐个探测 |
| upside `MergeError: incompatible merge keys dtype` | pandas 2.x 两侧 datetime 分辨率不一致us vs ns | 两侧强制 `astype("datetime64[ns]")` 后单次 `merge_asof(by="k")` |
| event `'float' object has no attribute 'strip'` | SQL NULL direction → NaN 撞 `.strip()` | `event_type`/`direction` 先 `.fillna("")` |
| `build akg_heat --date 2026-07-24` 无数据 | 热度 T+1当日尚无 | `views` 子命令增加**数据前沿/历史深度**报告,构建日期据实选 |
### 6.4 运维口径Docker 铁律)
```bash
# 起容器
docker compose up -d --build
# 连通性 + 历史深度自检
docker compose exec akg-factor-bridge python run.py views
# 注册
docker compose exec akg-factor-bridge python run.py register
# 日更 / 回填
docker compose exec akg-factor-bridge python run.py build all --mode daily
docker compose exec akg-factor-bridge python run.py build akg_event \
--mode history --start 2024-01-01 --end 2026-07-24
# 基座建视图
docker exec -i akg-postgres psql -U akg -d akg < sql/astock_kg_slot_views.sql
```
所有写入**幂等**(删涉及日期区间 → 批插),可安全重跑。
**调度时点的已知约束**:传导 18:15 后落库,故 `akg_score(T)` 最早 T 日 18:40 可算;
但热度 T+1 到达,该次计算的热度项用的是 **T1 日热度**§3.4 末)。若要让热度项对齐
到 T 日,须改为 **T+1 早间补算 `akg_score(T)`**——两种方案的取舍见 §9-10。
---
## 7. 回填策略(分层,不追求全量对齐)
自洽公式路线**不再需要为了训练而凑齐历史**,回填的目的降为两条:
让评价仪表盘有足够样本、让子因子各自的分布可被观察。因此按可行性分层推进即可。
| 子因子 | 可回填性 | 路径 | 深度 |
|---|---|---|---|
| `akg_heat` | ✅ 直接 | 取 `stock_fund_heat_scores` 历史区间 | 2025-03-26 起 |
| `akg_event` | ✅ 直接 | EVENT claims 带真实 `disclosure_date` | 2014 起(依公告抽取进度) |
| `akg_upside` | ⚠️ 需重建 | 由 `gp_report_rc` 按披露日重建一致预期聚合 + 历史收盘 | 待 §6.2 复核后定 |
| `akg_transmission` | ❌ **不回填** | 回填=前视§2.2 | 只 live 累积 |
| `akg_score` | 随最短板 | 门槛②依赖 upside权重①依赖传导 | 见下 |
**`akg_upside` 重建的两条路待定§9-6**
- **甲案(基座侧)**:在 astock-kg 内回填 `consensus_daily` 历史,桥不动。
优点是基座产出一致、其他消费方同样受益;缺点是动基座、工作量在基座侧。
- **乙案(桥侧)**:桥直连 `gp_report_rc` 自行聚合。优点是不动基座、迭代快;
缺点是聚合逻辑在两处存在(基座有 live 版、桥有历史版),有漂移风险。
**已知陷阱(数据源盘点已记)**`gp_report_rc.tp` 是**利润总额不是目标价**
目标价走 `max_price/min_price`;点时一律用披露日。另需注意行情为**前复权**
历史目标价(当时的名义价)除以前复权价会在除权点产生系统性偏移,重建时需做基准一致化。
**`akg_score` 的历史怎么办。** 因为传导不可回填,历史 `akg_score` 必然缺失第一权重项。
两种诚实的做法,二选一并在因子描述里写明:
- **A. 只从传导有值的交易日起算(推荐)**。注意一个易被忽略的坑live 区间内部
也有空洞——2026-07-11~07-23 里 consensus 有 7 天而 transmission 只有 3 天,
按 §3.4 的 `std=0 → 整列置 0` 规则,那 4 天的 `akg_score` 会**静默退化成没有传导项
的版本**,却和真 live 值混在同一张表里,下游无从区分。
**因此 S1 的落库规则是:`akg_score` 只在当日传导表有数据的交易日出行**
(另在运行日志里记录被跳过的日期),保证表内每一行都真正包含了第一权重项。
- **B. 出一个明确标注的历史近似版** `akg_score_hist`:传导项置 0即历史上只有
门槛+热度+便宜三项),**单独注册、单独命名**,绝不与 live 版混在一张表里。
它的用途仅限于观察门槛与另外两项的历史分布,**不得用于宣称因子有效性**。
**可选外溢代理spillover proxy。** 若确实需要一个可回填的传导替身,可用
`A@R R`(邻接矩阵 × 收益的一阶外溢减自身收益)构造。它可回填,但**携带成员性前视**
(用今天的产业链图谱定义邻接),故其历史 IC 只能作为**乐观上界**读取,不能当作
传导的历史业绩。列为 S3 可选,非必需。
---
## 8. 里程碑G 系列,替代 v1.1 文档的 F 系列)
- **G0 · 文档评审**:本文评审通过。同步确认 **§9-1热度语义、§9-2赛道清单**。
- **G1 · 赛道覆盖体检****当前阻塞项**):拿到完整赛道清单后,逐赛道统计图谱内
可映射到的主题/环节/成员数,产出"哪些赛道有料、哪些是空的"的体检表。
**覆盖为空的赛道不进 S1 公式。** 同期完成三件事:
①补跑 `factor_coverage_probe.py`v1.1 文档遗留的 F0 覆盖面诊断,只读,尚未执行);
②统计池内 upside 分布以定 **§9-3 的 q**;③复核 **§6.2 的 `gp_day_data` 起始日**。
- **G2 · 赛道成员表落地**`config/frontier_tracks.yml` + `tracks.py` +
`data/track_members.csv` 快照;人工 review 一遍成员,确认没有明显错配。
- **G3 · 漏斗实现 + 注册 `akg_score`**:桥内实现两道门槛与三项加权,落
`t_factor_akg_score`,注册。**开工前确认 §9-8权重量值**。
同时输出**每日候选池规模**日志——若日均候选数长期低于 30说明**组合层面无法分散
成篮**(这是组合可行性约束,**不是 IC 可算性约束**),需回头看是赛道覆盖太窄
§9-2、估值门槛太紧§9-3、还是券商覆盖率不足§9-4
- **G4 · 回填与仪表盘****开工前确认 §9-6upside 重建路径、§9-7score 历史处理)**。
按 §7 分层回填;挂上平台评价,产出第一版 RankIC / IC-IR / 分层读数。
**读数不作为判收条件**,作为观察记录。
- **G5 · 每日调度上线**:按 §9-10 定下的时点方案配置桥容器 cron 或平台 XXL-JOB
`akg_score` 进入下游消费。
---
## 9. 开放问题(待拍板)
1. **热度语义翻转确认**v2.0 把热度从"越热越好"改成"**还没热更好**"(漏斗内取负)。
这与"热度用于辅助验证传导是否启动、缩短左侧建仓时间"一致,但需要明确确认。
2. **完整赛道清单**:已明确核聚变、商业航空航天、通信、算力、人工智能、低空经济;
**需要补全"等领域"具体还包括哪些**(如生物制造、量子科技、脑机接口、
氢能与新型储能、6G、先进材料……。清单直接决定 C 门槛的范围。
3. **估值门槛的 q 分位**`θ_v = max(0, 池内 q 分位)`q 默认 0。若实测池内 upside
普遍为正券商乐观q 应上调到多少0.30.5——G1 统计分布后定。
4. **无券商覆盖股的处置**:当前设计是 upside 缺失 → 不过门槛(保守)。
但这与"研报滞后反而是确定性体现"的论题有张力——最早期、最冷门、最符合论题的
标的可能恰恰没有覆盖。是否要为"赛道内 + 无覆盖"的股票开一条单独通道?
5. **事件极性表与半衰期**(继承 v1.1 文档 §8.3`发行上市 / 并购交割 / 股权质押` 的
符号,以及半衰期 10 日 / 窗口 60 日是否合适。S1 事件不入公式,此题可延后到 S2。
6. **upside 历史重建走甲案还是乙案**§7
7. **`akg_score` 历史处理走 A 还是 B**§7 末)。建议 A。
8. **权重旋钮的默认值** 0.5/0.3/0.2 是否认可(次序已定,量值待认)。
9. **"还没热"是否要改成条件项**S1 用无条件加性项§3.4 退化说明)。
备选:`z_H · 1[z_T>0]`(仅对有传导的股生效)或 `z_T · z_H`交互。S2 评估。
10. **调度时点**T 日 18:40 算(热度用 T1vs T+1 早间补算 `akg_score(T)`
(热度对齐 T但因子延迟一天可用。取决于下游策略的下单时点。
---
## 10. 判收标准v2.0 重写)
**明确取消**"神经 IC-IR 需优于线性基线"这条 v1.1 判收项——它属于被推翻的路线。
**必须满足(工程正确性):**
- 四子因子 + `akg_score` 建表/注册成功,每日调度幂等,重跑不产生重复或漂移。
- **点时正确,全链无未来函数**:各源分别以 `disclosure_date` / `asof_date` /
`scan_date` / T+1 热度盖章;`akg_score` 在 T 日算出、用于 T+1 买入;
热度项使用 T1 日值这一事实在因子描述中显式声明。
- **传导不出现在任何历史区间**(除非走 §7 末 B 方案且单独命名),杜绝前视污染;
`akg_score` 表内不含"传导项被静默置零"的行§7 末 A 方案)。
- 赛道成员快照可审计:每只股票能追溯到"因哪个赛道、哪个环节、哪条映射规则"入选。
**必须满足(逻辑自洽性):**
- 公式的每一项都能用 §1 的论题解释;出现无法解释的项,删掉而不是保留
(已知的一处妥协——"还没热"退化为无条件项——已在 §3.4 显式记录并列入 §9-9
- 门槛与权重的角色不混淆:门槛不可被权重补偿。
- 截面标准化只在候选池内做,池外不出行。
**观察但不判死(仪表盘):**
- RankIC / IC-IR / 分层单调性 / 换手率 / 候选池规模。
- 这些读数用于回答"当前市场是否在奖励这套逻辑",以及"哪一项在拖后腿"。
**读数差不构成下线因子的理由**;构成的理由只有一个——**产业逻辑被证伪**。
**神经 GRU 的复活条件**(降级为"未来挑战者"):当且仅当
a传导积累出足够长的 live 历史(≥ 1 年,且期间图谱结构相对稳定),
b自洽公式已上线并有可对比的基准读数——此时才有必要让 GRU 去挑战公式,
并且必须是**严格 OOS、只用 live 区间**。在此之前不开这条线。
---
## 附录 A · 术语
| 词 | 含义 |
|---|---|
| 基座 | astock-kg数据分析基座微内核只暴露数据不算 alpha |
| 桥 | `akg-factor-bridge`,独立 Docker 工程,全部因子建模在此 |
| 平台 | `quant_factor_service`,通用因子管理平台;本文只用其注册/存储/调度/评价能力 |
| 覆盖池 U | `industry_pools` 全主题成员并集,实测 1675 只 |
| 候选池 P | U 中同时通过赛道门槛 C 与估值门槛 V 的子集 |
| 观察 / 推断 | 有耐久时间戳记录 / 依赖当时系统状态的当日判断§2.2 |
| 漏斗 | 两道硬门槛 + 池内三项加权的复合结构 |
| `scan_date` | 传导扫描日,`transmission_candidates` 的时点戳(每日 18:15 后产出) |
| S1 / S2 / S3 | 因子自身的演进阶段(区别于文档版本 v1.1 / v2.0 |
## 附录 B · 关联文档
- astock-kg`涌现式应用层重构设计.md`(四路信号即四条用户主线的数据面产物)、
`数据源盘点.md`(热度/一致预期/资金语义、`gp_report_rc.tp` 陷阱)、
`项目全景盘点_2026-07.md`
- 桥工程:`akg-factor-bridge/README.md`Docker 用法、待实机核实项)、
`sql/astock_kg_slot_views.sql`(四视图定义)。
- 平台:`quant_factor_service/readme.md`(多因子合成引擎技术文档)与运维手册
——本文只引用其**契约与评价能力**,不再引用其合成能力。
---
> **提交提醒**:本文档、`backend/scripts/factor_coverage_probe.py`,以及
> `akg-factor-bridge` 整个工程,均为未提交状态,请在开发机 `git commit` 后同步到服务器。