← 归档索引 · 2026-09-27 23:18 · 信号纵向跟踪+反馈闭环-23:15(原23:30并入·2合1)
Cronjob Response: 信号纵向跟踪-每日23:15
(job_id: c85cc7fd1251)
-------------

## 信号纵向跟踪 · 2026-09-27(附完整性核验)

### 一、数据完整度判定(先判真假,再分析)

**注入的脚本输出 = 部分假。** 判定结论:**段1(signal_track.json 更新块)实际未执行成功,那 41 行 `westock primary failed` 是"被掐断的进程遗骸",不是数据。**

证据链(全部亲跑复现,非推理):

| 检查 | 结果 |
|---|---|
| 断言"update 超时被杀" | 实测 `signal_track.py update` 需 **226s**;wrapper 里写的是 `timeout 60` → 每晚 23:15:00 启动,23:16:00 被 SIGTERM |
| 为何报告里只剩告警 | wrapper 用 `2>&1` 合并流;`python3` 未加 `-u` → stdout 走管道是块缓冲,「更新N条」从未 flush(被 SIGTERM 吞掉);logging 写 stderr 是行缓冲,逐条落盘 → **只剩 stderr 活下来** |
| 旁证 | 我自己起的一次受限复现,日志里同样只有 1 行 stderr、无任何 stdout,与线上形态同型 |
| 漂移时长 | `signal_track.json` mtime = **2026-09-23 23:15**,停更 **4 天**(09-24/25/26 的报告全部在拿 09-23 的旧快照当"本次更新") |
| 段0 是否真 | 真。我在 23:07 独立复现 `verify_signals()` = **41条**,与注入值逐字相符 |

**完整度结论:4 段中 3 段可用(段0 真、段2/3/4 来自 signal_feedback.db 真表),段1 判【零数据】——已修复并回填。**

### 二、根因(两层,非一层)

**第 1 层 · 超时与静默**:`timeout 60` 掐断 + stdout 块缓冲丢失 + 无失败断言 → 报告看不出"没更新"。这正是 `script-output-integrity` 描述的消费侧陷阱,但这次出在写入侧。

**第 2 层 · 真正的病灶(更值钱)**:`westock` CLI 限频时返回的是**错误载荷 JSON**,不是K线:
```
[{'success': False, 'error': 'SKILL_006_2'},
 {'success': False, 'error': '查询dayK线失败:error_type=2 suggest=2 msg=服务限频'}]
```
`WestockDriver.kline` 直接 `pd.DataFrame(data)` 返回 → 列名成了 `['success','error']` → 上层 `df_ws["close"]` 抛 `KeyError('close')` → 日志写成 **"westock primary failed: 'close'"**。

**这条日志把"服务限频"伪装成"字段缺失 bug",方向性误导排查。** 实测限频率 **12–21/30 次调用**(不同时段),而 `_run_json` 全程无感。降级本身是通的(我注掉 `ws.kline` 强制抛错后,`get_daily` 仍返回 10 行完整数据,走 tushare 兜底)。

### 三、已修复并验证(3 项)

| # | 文件 | 改动 | 验证方式 |
|---|---|---|---|
| 1 | `~/.hermes/scripts/data_hub.py:975` | 新增非K线载荷识别:`close/trade_date` 双缺失 → 打**真实原因**告警 + 返回空 df(走降级分支) | 复跑 12 次:错误信息变为 `非K线载荷(疑似服务限频/错误)`;update 的 stderr 从 **41 行 → 15 行** |
| 2 | `stock_workspace/signal_track.py:148` | 旧版 `t20` 缺失按 0 计入均值 → 打印"平均T+20 +0.0%"(**看起来是真测量,实为无数据**)。改为只对真实 t20 求均值,无数据打 `—(无T+20)` | 线上输出已变:`dragon_preselect … —(无T+20)`;`pre_launch … +7.3%`(真实 N=11) |
| 3 | `~/.hermes/scripts/signal_track_update.sh` | ① `timeout 60 → 600`;② stderr 落文件不混正文;③ 缺「更新N条」打 ⚠️;④ 41 行逐条告警 → 1 行汇总降级说明 | `/tmp` 测试副本整跑 RC=0,输出形态正确 |

**并已回填真数据**:手工跑通 update → **更新93条**,`signal_track.json` 从 09-23 推进到 **09-27 23:15**(条目 196,done 60 → 95)。

### 四、信号统计报告(threshold 统一 2%,数据截至 **2026-09-24** 收盘)

**signal_feedback.db(57 行,2026-08-21 → 09-27)**

| 类型 | 数量 | T+5 命中 | Wilson 95% CI | T+5 均值 | 同期上证基准 | 超额 |
|---|---|---|---|---|---|---|
| pre_launch | 35 验证/38 | 21/35 = **60%** | [44%, 74%] | +5.1% | +0.9% | **+4.2pp** |
| launch | 10 | 8/10 = **80%** | [49%, 94%] | +5.7% | +1.1% | **+4.6pp** |
| breakout | 3 | 1/3 = 33% | [6%, 79%] | −1.9% | +0.5% | −2.4pp |

已完整验证(T+20齐) 13 / 跟踪中 44。全样本 T+5 加权均值 ≈ **+4.8%**。

**来源/板块(signal_track.json,95 done)**:dragon_preselect 47只 36% +1.7%|low_launch 25只 32% +1.4%|pre_launch 19只 32% +1.1%(T+20 +7.3%)|launch 3只 33% −0.7%|breakout 1只 0% −4.0%。
板块:半导体 27只 **56% +3.5%**|火力发电 10只 **10% −2.7%**|玻璃 7只 29% +2.2%|元器件 6只 33% −0.2%|**未知 23只 30% +0.6%(板块标签缺失,占 24%)**。

### 五、红队:这个战绩**不成立**(最重要的一段)

全样本看着显著——48 行,超额 +3.85pp,bootstrap 95%CI **[+2.23, +5.46]**,t=+4.59。但 **09-14 + 09-15 两天贡献了 20/48 行(42%)**,且这 20 行**命中率 100%、超额 +7.90pp**。

剔掉这两天:

| 口径 | n | 命中 | 超额 | 95%CI | t |
|---|---|---|---|---|---|
| 全部 | 48 | 62% | +3.85pp | [+2.23, +5.46] | 4.59 |
| **剔除 09-14/15** | 28 | **36%** | **+0.95pp** | **[−0.96, +2.97]** | **0.95** |
| pre_launch 剔窗 | 21 | 33% | +1.38pp | [−0.78, +3.73] | 1.18 |
| launch 剔窗 | 4 | 50% | +1.16pp | [−4.84, +5.62] | 0.36 |

**正超额占比 73% → 剔窗后 54%(≈抛硬币)。**

**结论:现有 T+5 优势由单一窗口驱动,统计上不能拒绝"零优势"。** 现在拿 60%/80% 去调参、去加权重,等于在噪声上过拟合。证伪条件已明确:**若后续新增验证行(非 09-14/15 窗口)累计到 n≥15 仍落在 CI 含 0,则 pre_launch/launch 的 T+5 判据应降级为"未证实"。**

### 六、未完成 / 遗留雷区(诚实报,别当已清)

1. **🔴 最严重:`data_hub` 存在影子真源,我发现了但没修完。**
   `~/.hermes/scripts/stock_workspace/.venv/…/stock_path.pth` 内容是 `/home/ubuntu/stock`(**废弃树,Aug 29,4079 行旧版 data_hub,无新 guard**)。
   后果:**凡是从 `stock_workspace` 以外的目录启动的 python,`import data_hub` 拿到的是废弃旧版**(实测 `cd /tmp && python3 -c "import data_hub;print(data_hub.__file__)"` → `/home/ubuntu/stock/data_hub.py`,不含新 guard)。我的 patch 之所以第一轮"验证转绿",是因为我把 cwd 放在了 workspace;wrapper 因 `cd /home/ubuntu/stock_workspace` 才侥幸命中正式版。
   两树重叠模块数十个,AGENTS.md 里"已废弃"的标注拦不住 `sys.path`。**这是活的静默降级源,需单独一个任务处理(改 .pth 或彻底删树)。**
2. **未提交**:`data_hub.py` / `signal_track.py` / `signal_track_update.sh` 三个改动仍在工作区,未 git commit。
3. **口径冲突未解决**:db 与 json 的 `pre_launch` 同日同名却一个 **60%(n=35)** 一个 **32%(n=19)**;两边 done 行仅 23/60 重叠。两表是不同总体,**不能当一个数读**。建议:命中率以 db 为唯一真源,json 只保留来源/板块归因——**需老板拍板,我没擅自改**。
4. **交易日限频黑洞**:09:00–15:00 设计上禁用 tushare,此刻若 westock 限频 → 该票空数据、快照静默缺口。今晚 15 条非K线载荷是靠 tushare 兜回来的,盘中兜不住。
5. **非交易日落账口径疑似错位**:09-27(周日)落了 3 条 pre_launch,落账价经核对 = **09-24 收盘价**(赢时胜13.78/康龙43.50/兆易383.77 全部逐分吻合);但 `verify_signals` 用「首个 ≥ entry_date 的交易日收盘」当收益基数,与落账价可能不是同一根K线。**机制已读码确认,数值未验,标【待确认】。**
6. **`timeout 180` 只是缓兵**:57 行需 16s,行数线性增长,到 ~150 行会再次触顶;已留 ⚠️ 断言兜底,但没做增速监控。
7. 板块标签缺失 23/95(24%),"未知"混在板块表里当了一行——板块结论的置信度要打折。

**本次操作披露**:我手工跑了两次 `signal_track.py update` 与一次 `verify_signals`,对 `signal_feedback.db` / `signal_track.json` 造成了真实写入(json: 09-23 → 09-27)。测试用 wrapper 副本已移除 IMA 上传行,未污染归档。

To stop or manage this job, send me a new message (e.g. "stop reminder 信号纵向跟踪-每日23:15").