投研日报 + 周报项目 · PM 审查报告
审查日:2026-10-14(周三)|方式:只读。只运行过只读的 score_calls.py / score_candidates.py,并用 DuckDB 只读查询了 theme-radar 指数库。没有调用 ima、grok 或任何外部接口,研报正文没有外发。
所有内容都是个人研究,不构成实盘买卖建议;钱的决定由 Henry 拍板。
1. 一页纸总览
1.1 项目目标
从每天约 100+ 篇研报(ima)、Spark 公开晨报和自有数据湖(期货、A 股)里,做三件事:
- 发现变化:超预期、低于预期、边际拐点、基本面与价格背离;
- 沉淀成可检验的判断:产业卡片、前瞻判断、多空候选,每条都写证伪条件;
- 事后记分、自我修正:命中率和超额收益,汰弱留强。
约束:A 股个股规则历史回测没有稳定超额;期货只有基差和期限结构层经回测保留;只做研究和模拟盘(目前已有一笔约 5000 元的小额实盘,见 3.1)。
1.2 模块与数据流(文字版)
【输入】
ima 研报(28篇/日额度) ─┐ Spark 晨报/异动/证伪监控(Gemini) ─┐ 期货通(同花顺本地 MCP) → futures-lake
东财公开研报(回填) ─┤ │ 腾讯/新浪 → stock-lake(a_daily/估值/财务)
│ │ theme-radar 行业指数(⚠ 停在 9/30)
▼ ▼
【加工】
ima-digest 06:45 ──选篇→本地子agent精读→notes.md
├─E 证据账本 industry_evidence/ledger.jsonl (1276 行)
├─E2 card_strength --today-only → 卡片动态
├─F 前瞻判断 calls/ledger.jsonl (7 条)
└─F2 多空候选 calls/candidates.jsonl (7 条)
cycle-weekly 周六:cycle_scan(平台放量) + card_strength(汰弱留强) + card_universe → 8 张卡 / watchlist.json / 个股入账
research-weekly 周日:research-loop 四市场打分 → 候选 → 四项审慎筛选 → candidates_<下周六>.md
morning_cards 07:40(今天新增):标的池 / 期货候选 / 卡片强弱 三张 PNG
aihy-daily 09:30:去出处观点 → aihy.cc 公开发布(自动)
beta-watch 月度:时代贝塔假设账本 → 可新建卡片
【产出】 飞书 cld:日报、早盘卡、早报、模拟盘、周报、告警;aihy.cc 公开文章;期货开盘啦卡片(15:20 launchd)
【反馈记分】
score_calls.py(判断) / score_candidates.py(候选) → 周日周报
exits.jsonl(强制出池,0 行) card_strength history.jsonl(排名) research-loop evaluate(调权,本周"样本不足未调权")
falsifier-watch(Spark 证伪) → falsifier_events.jsonl
1.3 节奏时间轴(cld 机器人,北京时间)
| 时间 | 任务 | 是否推送 |
|---|---|---|
| 00:20 每天 | ima-digest-retry 补读 | 有新下载才推 ≤10 行 |
| 06:45 每天 | ima-digest 投研日报 | ≤35 行 |
| 07:40 交易日 | morning-cards 三张卡 + 早盘解读 | 3 图 + ≤8 行 |
| 08:57 每天 | morning-research 投研早报 | 3–6 行(同一时刻 cdh 机器人还发一条生活早报) |
| 09:00 周一 | cost-radar 原料成本 | ≤8 行 |
| 09:30 每天 | aihy-daily | 失败才推 |
| 09:30 周六 | cycle-weekly 产业周期周报(与 aihy 同一时刻启动) | ≤30 行 |
| 10:30 每月首个周日 | beta-watch | ≤20 行 |
| 14:50 交易日 | finnex-keepalive | 失败才推 |
| 15:10 周五 | real-stop-check 实盘止损检查 | ≤6 行 |
| 15:20 交易日 | 期货开盘啦卡片(launchd) | 自动 1 卡 |
| 15:35 交易日 | publish-watchdog | 失败才推 |
| 16:05 交易日 | paper-combo-a 期货模拟盘 | ≤6 行 |
| 16:35 交易日 | lake-daily 期货湖 | 失败才推 |
| 16:40 / 16:50 | cb-double-low 月末 / cb-watch 周五 | 月末 ≤10 行 / 异常 ≤6 行 |
| 17:30 交易日 | stock-daily 股票湖(约 2.5 小时,跑到约 20:00) | 失败才推 |
| 18:40 每天 | falsifier-watch | 触发才推 |
| 19:30 周日 | research-weekly | 4 图 + 文字 + 两份记分 + 入池名单 |
| 21:00 每天 | health-check | 失败才推 |
一个普通交易日的主动推送约 6–7 条(约 60 行 + 4–5 张图)。周末另有周六约 30 行、周日约 4 图 + 25 行以上。
2. 做得好的 5 点
- 判断能被记账、能被证伪。 判断、候选、出池三本账字段统一(target、horizon、benchmark、falsifier、entry=next_open)。
score_calls.py并排给出 20 日短线口径,exits.jsonl有强制出池机制。这套底子是对的,对个人投研来说少见。 - 对回测结果说实话,而且写进了提示词。 研究周报第一行固定写「A 股等候选模型未通过历史回测」,期货只认基差和期限结构层。bull-genes 两轮的负面结论也记进了记忆,没有被包装成有效。
- 点名前先看价格位置,并且执行到位。 10/5 被 Henry 批评之后,日报里每个点名都附「一年 / 离高点 / 近 3 月」,并标出「下跌趋势中」(例:10/14 生益科技、10/13 巨石)。
- 日报结构对准了 Henry 的诉求。 超预期 / 边际与背离 / 宏观机会与风险三块固定在最前面,内容基本都是带数字的硬数据。日报还会自曝错误:10/14 主动说明「序号错位误下 5 篇」,并写进了 feedback 记忆。
- 运维默认静默,隐私边界守住了。 health、lake、watchdog、aihy、keepalive 只在失败时推送,休市日历统一用 holidays.json;10/9 之后研报正文只给本地子 agent 读,research-loop 调 LLM 时只传分项分,不传正文。ima 额度近 7 天都用满 28 篇,没再撞 220021。
3. 问题清单(按严重度排序)
🔴 P1-2 闭环记分大面积失灵:行业判断 3/3「无数据」,两套口径数字对不上
- 现象:账本在写,但记分没有真正跑起来。
- 证据(今天实跑
score_calls.py --markdown):- 半导体(10/4)、电网设备(10/5)、玻璃玻纤(10/13)三条行业判断都显示「无数据」。原因:theme-radar
indices.duckdb中 sw1/sw2/concept/benchmark 全部停在 2026-09-30。唯一调用fetch_indices.py的地方是旧的 weekly-review,它已经迁到 cdh 机器人,而且新版提示词删掉了这一步。两份 schedules.json 和 LaunchAgents 里都找不到任何指数更新任务。10/10 周报已经发现「基准只更新到 9/30」,但没有修。 - 同一标的两套算法结果不同:早盘卡上东方电气超额 +0.6%、华明 +9.5%;score_calls 是 -0.4%、+8.5%。
morning_cards.py自己又实现了一遍收益计算。 score_candidates.py输出的标题仍是「前瞻判断记分」,周报里两份记分会混淆。- 「玻璃玻纤 看多」10/13 同时进了 ledger 和 candidates,被重复计数。
- 候选写了触发条件(如碳酸锂「连续 2 日站上 5 日线」),但记分是判断日次日无条件入场。测的是「观点」而不是「按条件执行的交易」,候选块里的入场条件没有被检验。
exits.jsonl为 0 行(暂时合理),第一批 20 日口径大约 11/5 前后才到期,目前没有任何「到期」样本。
- 半导体(10/4)、电网设备(10/5)、玻璃玻纤(10/13)三条行业判断都显示「无数据」。原因:theme-radar
- 影响:「自进化」暂时只是名义上的。行业判断永远无数据,个股数字两张表不一致,Henry 看到的胜率不可信。
- 建议:见路线图「本周 1、2」。
🟠 P2-1 证据账本被一次性回填刷屏,卡片排名靠数量而非质量
- 证据(1276 行全量剖析):
- 10/9 单日入账 754 行(占 59%),主要是「内资研报(东财公开)」730 行回填。研报日期滞后入库日 11–26 天的有 300+ 行。
card_strength.py的 28 天窗口按入库日date计,而不是report_date。于是:焦煤卡 97 条证据里 89 条来自 10/9 回填,化工成本卡 77 条里有 41 条。这两张 10/10 新建的 B 级卡直接排到第 1、2 名(history.jsonl)。- 同一时间序列的多期快照被当成独立证据:猪价 9/11 和 9/18、布油周均价 9/11 和 9/18、炼化价差两周,各算一条。
- signal 词表漂移:schema 规定的是「涨价/缺货/订单/扩产/库存/交期/积压/出口单价…」,实际最多的是「需求 270、价格 244、供给 121」,不在词表里。框架核心喂养的「交期」只有 6 条,「积压」只有 2 条。
- direction 出现 schema 之外的「0」,共 58 条;companies 为空 871 条(68%);industry 有 144 个取值,没有规范化(「油气开采」和「油气开采Ⅱ」并存,还有「宏观」「原油」这类非申万名);confidence「高」占 62%,明显偏高;337 行缺 source 字段。
- 完全重复的只有 3 条,跨日数字指纹重复 3 组。去重本身问题不大,问题出在权重。
- 影响:卡片的汰弱留强、新卡提名、日报「卡片动态」都建立在这本账上。数量偏差会直接改变哪张卡「留强、优先挑标的」。
- 建议:用 report_date 加时间衰减;同一 theme + 指标只取最新一期;每份研报贡献封顶;回填数据打
backfill:true并降权;写入前做 schema 校验。
🟠 P2-2 卡片体系和标的池规则互相打架,「需拍板」事项迟迟没有闭环
- 证据:
- 化工成本卡排名第 1、结论「留强(优先挑标的)」,但评级 B 按规则不能挑标的,规则自相矛盾。
- 卫星化学、宝丰能源四项审慎筛选都过了,因为卡片是 B 被挡。10/10 周报「需要你拍板」提出后,10/11 周报和 candidates_2026-10-17.md 里仍然悬着。
- 天山铝业:10/10 周六周报以「研报判断铝转向过剩」排除,10/11 周日研究周报又把它「入池」,两条线结论相反。
- 覆铜板 / 电子布在 10/11、10/13 连续被标为「新卡候选」,10/14 日报又把生益科技列为多空候选。但卡片已到 8 张上限,
card_strength.py里还硬编码了EXCLUDE = ["覆铜板","CCL"]。结果是证据最硬的新主线进不了卡片体系,只能从「多空候选」侧门绕过卡片纪律进入标的。
- 影响:卡片纪律(评级、阶段、证伪)形同虚设。Henry 每周收到「需拍板」,但看不到它被处理。
- 建议:把「需拍板」做成带状态的清单(open / 已决 / 默认处理日期),超过 7 天没回就按默认规则处理;8 卡上限改成「新卡净值高于末位就自动替换」;去掉 EXCLUDE 硬编码,单独建覆铜板 / 电子布卡并接受审计。
🟠 P2-3 推送重复,决策信息被埋在里面
- 证据:
- 早上三连发:06:45 日报里有「卡片动态」和「多空候选」,07:40 卡 2(期货候选)和卡 3(卡片强弱榜)加「早盘解读」③④再讲一遍,08:57 morning-research 再报一次模拟盘状态和当天推送预告。同一时刻 cdh 机器人还发生活早报,08:57 一分钟内到两条。
- 周日 19:30 研究周报是 4 张卡 + ≤10 行摘要 + 判断记分 ≤6 行 + 候选记分 + 入池名单,加上周六周报 ≤30 行,一个周末超过 60 行。
- 日报 ≤35 行里有 40 多个数字,而 Henry 真正要做决定的三件事分散在三条消息里:持仓或候选是否触线、今天哪个候选触发、哪件事等他拍板。
- 提示词之间互相矛盾或已经过时:ima-digest 同时写着「约 10 份额度」和「约 30 次额度 / 最多 28 篇」。
- 影响:注意力被摊薄。Henry 本身有手机和屏幕时间问题(记忆 henry-profile),高频推送和这个目标冲突。
- 建议:见第 5 节精简清单。早上合并为两条,每条最上面放「今日决策 3 行」。
🟠 P2-4 单点故障多,健康检查覆盖不到研究链路
- 证据:
- ima 额度:每天 28/28 用满,零余量。10/14 选篇序号错位浪费 5 篇,事后才发现。
- 数据湖延迟:10/13 日报写「A 股价格截至 10/9」。stock-daily 10/13 才上线,一次跑约 2.5 小时、到 20:00 左右才结束,和周六 cycle-weekly 的
--scope all全量更新共用 writer.lock。 - theme-radar 指数:已停更 14 天,没有任何告警。
- 期货通:本地客户端加 MCP 登录态,同时支撑 15:20 发布、16:05 模拟盘、16:35 数据湖;大商所 412 是已知缺口。
- 网络:channel.log 显示 10/11 研究周报 5 张卡片全部 TLS 断连发送失败(Clash TUN),没有重试或补发记录。
- health_check.py 现有检查项是 launchd / fundpulse / aihy / research / ima / hermes / finnex / cli / disk / schedules,不包括 stock-lake 新鲜度、theme-radar 指数新鲜度、证据账本 schema、记分「无数据」比例、图片发送失败。
- 整体:全部依赖一台 Mac、一块外置盘 /Volumes/future、一个 Claude Pro 额度。日报每天还要起 3–4 个子 agent。
- 建议:扩展 health_check(本月 1);notify_feishu 加重试并记录发送结果;stock-daily 先更新 a_daily(约 30 分钟可用),估值后补。
🟡 P3-1 aihy.cc 公开发布有合规和版权风险(需要 Henry 知情确认)
- 证据:aihy-daily 的提示词是「总编…不需要他过目」,素材来自 ima 研报(日报自己标着「不外传」),只做「去出处」转述后自动部署到公开网站。记忆中 Henry 还决定公开内容保留「偏多/偏空」方向标签。
- 影响:付费研报转述后对外发布有版权风险;公开发布品种方向判断,在国内可能被认定为未经许可的投资咨询。这是对外产品,风险等级比私人日报高一档。
- 建议:请 Henry 明确拍板。可选方案:公开版只写事实和数据,不写方向;或者每周人工抽检 1 次;把禁用词合规检查扩展到方向词。
🟡 P3-2 业务规则写在超长提示词里,且没有提交
- 证据:
- schedules.json 有 33KB,cycle-weekly 提示词 2873 字、ima-digest 4021 字,汰弱留强、出池、入账去重等规则每次都由 LLM 现场执行,结果有不确定性;
- schedules.json、score_calls.py 和 5 个新工具(morning_cards / card_strength / score_candidates / social_cards / extract_text)都还没提交;
- 审查期间 ima-digest 的时间从 08:00 被改成 06:45,说明提示词在频繁修改。
- 影响:规则漂移,事后无法复现「当时为什么这么判」。
- 建议:确定性规则下沉到脚本(例如 card_strength 直接输出汰弱结论、去重逻辑写进账本写入器),提示词只保留「读结果、写解读」;每次改完 schedules.json 就提交一次。
🟡 P3-3 cost-radar 恢复运行与 Henry 之前的意见冲突
4. 改进路线图
本周(≤5 项,低成本高收益)
| # | 事项 | 做法 | 验收标准 |
|---|---|---|---|
| 1 | 修复记分底座 | 把 theme-radar/scripts/fetch_indices.py 增量更新接到 stock-daily 收尾(或周日 18:00 单独跑);score_candidates 标题改为「多空候选记分」;ledger 和 candidates 同一标的同一天只记一处 | score_calls.py --markdown 里 3 条行业判断都有数,「无数据」为 0;指数 max(trade_date) 落后不超过 1 个交易日 |
| 2 | 统一记分口径,并检验入场条件 | morning_cards.py 改为调用 score_calls.score(),不再自算;候选记分增加「按 trigger 触发才入场」口径(未触发记「未入场」) | 早盘卡和 score_calls 对同一标的的超额完全一致;候选表能区分「观点收益」和「触发后收益」 |
| 3 | 证据账本降噪 | card_strength 改按 report_date 计(加衰减),同 theme + 同指标只取最新一期,每篇研报贡献封顶 3 条;10/9 回填行标 backfill:true 并按 0.3 权重计;写入前做 schema 校验(signal 词表、direction ±、industry 申万名) | 重算后焦煤卡证据里回填占比 <30%;新写入的行 100% 通过校验;排名变化在周六周报里说明 |
| 4 | 实盘与研究分开,修正指令措辞 | real-stop-check 改为单独私人消息,措辞改成「已触及你 10/13 自定的止损线」;早盘卡 1 移除 ★实盘行;health_check 增加推送文本禁用词扫描(买入 / 卖出 / 做多 / 做空 / 加仓) | 一周内研究频道推送里禁用词为 0 次;实盘只在周五出现 1 条 |
| 5 | 推送合并,拍板事项闭环 | 取消 08:57 morning-research(内容并入 07:40 早盘解读);日报删掉「卡片动态」行(由卡 3 承担);做一份 decisions.md 拍板清单,本周请 Henry 一次回完 4 件事:卫星/宝丰是否破格、覆铜板是否建卡、cost-radar 留不留、aihy 方向标签 | 交易日早上投研推送 ≤2 条;拍板清单 4 件全部有结论 |
本月
- health_check 覆盖研究链路:新增 stock-lake 新鲜度、theme-radar 新鲜度、证据账本 schema 违规数、记分「无数据」占比、notify_feishu 发送失败(解析 channel.log 的 card failed)。验收:人为让指数过期,当晚 21:00 告警。
- 卡片规则代码化:汰弱留强、8 卡替换、标的池调入调出由 card_strength / card_universe 直接输出结论,周报只负责解读;去掉 EXCLUDE 硬编码,正式审计覆铜板 / 电子布卡。验收:同一份数据连跑两次周报,结论完全相同。
- 数据时效:stock-daily 拆成两段,a_daily + a_daily_ret 先跑(目标 18:00 前完成),估值和财务后补;notify_feishu 失败重试 3 次并补发。验收:日报「A 股价格截至」等于前一交易日的比例 ≥95%。
- ima 选篇防错:
--pick前自动回显「序号 → 标题」做校验,不一致就拒绝下载。验收:月内误下 0 篇。 - 首次记分复盘会(约 11/5,第一批 20 日到期):判断和候选分开出表,列命中率、平均超额、触发率;同时把所有改动提交 git。
季度(截至 2027-01)
- 候选留存门槛(现在就预先登记):样本 n≥30 后,20 日口径命中率 >55% 且平均超额 >0,才保留「个股候选」;否则降级为只到行业层。验收:门槛写进 docs,并按时执行。
- 证据预测力检验:卡片证据净值(降噪后)对未来 60 日相对收益做 rank IC。不显著就把证据账本定位为「叙事档案」,不再用来决定排名。
- 冗余与降本:期货通的公共备份源演练一次自动切换;ima 额度不够时用东财公开研报补位;评估 Claude 订阅与 Grok 优惠到期(12/16)后的子 agent 成本。
- 合规定稿:一页《研究与实盘边界》《对外发布边界》,Henry 签字确认,写进 CLAUDE.md 和记忆。
5. 建议精简后的推送清单
交易日(主动推送 4 条 + 条件告警)
| 时间 | 内容 | 长度 |
|---|---|---|
| 06:45 | 投研日报:顶部「今日决策 3 行」(触线 / 触发 / 待拍板,没有就写「无」)→ 超预期与低于预期 ≤4 → 边际与背离 ≤4 → 宏观机会与风险各 1 + 今日盯盘 → 多空候选 ≤2(只放 A/S 卡片池内标的或品种)→ 新增判断 | ≤25 行 |
| 07:40 | 早盘卡:卡 1 标的池每天发;卡 2、卡 3 只在有变化时发 + ≤5 行解读(只写触线、触发、排名变化) | 1–3 图 + ≤5 行 |
| 15:20 | 期货开盘啦卡(对外产品,自动) | 1 卡 |
| 16:10 | 收盘一条:组合 A ≤4 行;月末加转债月报 ≤6 行;周五加 cb-watch 异常 | ≤6 行(月末 ≤12 行) |
| 条件触发 | 18:40 证伪提醒、21:00 健康异常、数据湖失败(合并成一条「系统异常」) | ≤5 行 |
每周
| 时间 | 内容 | 长度 |
|---|---|---|
| 周五 15:10 | 实盘纪律检查(私人,只陈述事实和 Henry 自定的线) | ≤4 行 |
| 周六 10:00 | 产业周期周报(错开 aihy 的 09:30):卡片排名表 + 证伪触发 + 观察标的 0–5 + 待拍板 ≤3(带默认处理日期) | ≤25 行 |
| 周日 19:30 | 研究周报:宏观状态 + 四市场第 1 名卡 1–2 张 + 一张合并记分表(判断 + 候选,统一口径)+ 入池与排除名单 | ≤2 图 + ≤15 行 |
| 周一 09:00 | cost-radar:待 Henry 确认,建议挪到 cdh 机器人 | ≤6 行 |
每月
- 首个周日 10:30:时代贝塔雷达,≤15 行。
- 月末最后一个交易日:转债月报,并入当天 16:10 收盘消息。
- 记分复盘(新增):当月判断和候选的到期结果,≤10 行,并入周日周报。
调整后,交易日从约 6–7 条、60 多行降到 4 条、约 40 行,周末从 60 多行降到约 40 行,而且每条消息开头都是决策信息。

研究档案