Back to skills
extension
Category: OtherAPI key required

A Stock Report

A股数据驱动型报告自动生成与推送系统,支持晨报 / 收盘小结 / 晚报 / 盘中预警 / IPO周报 / 财经周末要闻。内置投资者情绪打分(6维度,满分100)与AI后市展望。

personAuthor: cookfish1979hubclawhub

A股报告系统

A股数据驱动型报告自动生成与推送系统,支持晨报 / 收盘小结 / 晚报 / 盘中预警 / IPO周报 / 财经周末要闻


版本历史(Changelog)

v2.0.8 — IPO 周报"排队情况"段补回 queue_detail 字段(2026-06-06)

问题现象: 6/6 10:02 cron 跑出的 IPO 周报(IPO周报_20260605.md)第一段「排队情况」显示「数据获取失败 ⚠️ 数据暂缺」,但同一份报告的二/三/四/五/六段都正常。其他 7 份历史报告(5/29、5/22、5/15、5/8、5/4、5/1、4/24)的"排队情况"段都正常(合计 248-378 家)。

问题根因: _collect_ipo_data() 函数(send_ipo_report.py)的 return dict 缺少 queue_detailqueue_status_detailsource_date 这 3 个 key,但 build_report_lines() 期望这 3 个 key 来填"排队情况"段:

# build_report_lines 行 288-290
qd = data.get('queue_detail', {})        # ← 期望的 key
sd = data.get('queue_status_detail', {}) # ← 期望的 key
source_date = data.get('source_date', 'N/A')
# 走到 if qd: 分支才输出"排队情况",否则走 else 分支 → "数据获取失败"

data.get('queue_detail', {}) 永远返回 {}(因为 _collect_ipo_data 没 return 这个 key),所以 qd 为空 → 走 else 分支 → "数据获取失败"。

次因: _fetch_queue_from_web() 函数(行 190-282)是已实现的正确逻辑(5 板块拉取 + pivot + 状态细项),但 main 调的是 _collect_ipo_data() 而不是 _fetch_queue_from_web(),且 _fetch_queue_from_web() 的 docstring 写「不返回值」但函数末尾实际没 return 语句——典型"重构一半"的死代码

修复:

  1. _collect_ipo_data() 末尾补 5 板块拉取ak.stock_register_kcb/cyb/bj/sh/sz 5 个接口的合并 + 180 天 cutoff + pivot 算 queue_detail + value_counts 算 queue_status_detail + max 日期算 source_date
  2. 修时区 bug:东方财富返回的"更新日期"是 tz-aware(带 +08:00),但 period_end_dt 是 tz-naive,PASSED_CUTOFF 比较时报 Invalid comparison between dtype=datetime64[s] and Timestamp —— 两边都加 .dt.tz_localize(None) 归一为 naive
  3. build_report_lines() 不动(最小修复,build_report_lines 是历史稳定代码)

验证:

  • 6/6 10:51 重跑:排队段正常输出「全市场共379家:问询145家 | 已过会待发行11家 | 提交注册31家」+ 5 板块明细
  • 文件大小:1524 字节 → 1946 字节(+422 字节正好是排队段差异)
  • 推送 + 状态记录正常:✅ 已推送 + [去重] 已记录 20260606|20260605

mtime 异常说明: 脚本和周报的 inode Birth 时间都是 6/6 10:02 左右,但 send_ipo_report.py/.gitignore 第 43 行被排除(# Skills (managed separately via ClawHub) + skills/),根本不在 git 跟踪范围内。所以 mtime 异常是沙箱文件系统事件(快照恢复/容器重挂载/镜像重建),不是有人改了代码没 commit没有 git 提交记录进一步佐证这点(git log 找不到任何 send_ipo_report.py 的痕迹)。

教训沉淀(未来避免):

  • 任何"重构接口"(改 return dict 的字段)必须同步改所有调用方(grep 搜 key 名找 caller)
  • "死代码"(写了但没接入的函数)是高危信号——要么删,要么接入
  • data.get(key, {}) 这种"缺失则跳过"模式在用户场景下静默失败——应加 assert 或显式 raise

下次跑: 6/13(周六)10:00 cron 正常 schedule

v2.0.7 — 晚报 ai.txt 写入指令 + 完整 bug 链条修复(2026-06-05)

问题根因: v2.0.5 修复(send 脚本加 ai.txt 日期头校验)的副作用——send 脚本只读 ai.txt但 dispatcher prompt 只让 LLM 写 content.txt。LLM 不知道要写 ai.txt,于是 ai.txt 永远是 6/4 22:36 的 v2.0.4 旧版(v2.0.5 加的日期头校验意外保护了旧文件不被覆盖)。结果:v2.0.6 patch("绝对禁止要闻列指数")其实生效了,但被旧 ai.txt 截胡推送用户收到的还是 v2.0.4 旧版6/7 违反 v2.0.6 约束)。

症状链:

  1. v2.0.6 patch 加了 "⚠️ 财经要闻约束:绝对禁止..." 到 dispatcher prompt
  2. v2.0.5 send 脚本只读 ai.txtv2.0.5 修复逻辑
  3. dispatcher prompt 没让 LLM 写 ai.txt只让写 content.txt
  4. LLM 跑了 N 次,每次都更新 content.txtv2.0.6 约束生效),ai.txt 永远是 6/4 22:36 旧版
  5. send 脚本读 ai.txt 旧版 → 推送旧版 → 用户收到 6/7 违反版本

修复内容:

  1. dispatcher prompt 晚报第 3 步后新增指令:明确要求 LLM 同步将 [财经要闻] 和 [操作建议] 两段精简写入 /tmp/evening_report_ai.txt,第一行 ## 日期:YYYYMMDD,格式与 send 脚本解析严格对齐
  2. frontmatter version2.0.42.0.7跳过 v2.0.5/v2.0.6——那两版当时没改 frontmatter,本版次补登记)
  3. 验证:手动 cron run(2026-06-05 23:47),LLM 主动写了 ai.txt2640 字节7 条要闻全合规),send 脚本推送完整版(3803 字节),微信收到 7/7 合规晚报

核心教训:

  • 架构对称原则:每个"读取文件"的脚本,都必须有对应的"写入文件"的 prompt 指令(LLM 不会猜
  • 修复副作用审计:v2.0.5 修旧 bug 引入新依赖(ai.txt),但没同步改 dispatcher prompt,应该在 v2.0.5 当天就 patch
  • 版本号管理:v2.0.5/v2.0.6 当时没 bump frontmatter,造成"脚本版本"和"skill 版本"脱节,本版次补登

v2.0.6 — 财经要闻约束加严(2026-06-05 凌晨,未登记于 frontmatter

问题根因: 用户反馈 5/29 晚报要闻含 "沪指失守 4015"、"亚太普跌 1.7%" 等指数数字——晚报要闻本应聚焦宏观政策/公司事件/监管动态,不应重复 A 股收盘段已包含的指数数据。

修复内容: dispatcher prompt 晚报第 2 步加 ⚠️ 约束:"绝对禁止在要闻中列出任何指数/大宗商品/板块的点位或涨跌幅数字"(但本版未 bump frontmatter,v2.0.7 补登

遗留 bug: 修复其实生效了(content.txt 7/7 合规),但 v2.0.5 修复的 ai.txt 中间文件问题导致 send 推送的还是旧版——本以为是修复失败,实际是 v2.0.7 根因。v2.0.7 彻底闭环

v2.0.5 — send_evening_report.py 加 ai.txt 日期头校验(2026-06-04,未登记于 frontmatter

问题根因: ai.txt 是 LLM 写的中间文件,可能残留旧日期的内容(如周末写的 ai.txt 推到周一)。send 脚本无脑读取会推错日期。

修复内容: send_evening_report.py 第 _read_ai_file() 函数加日期校验:第一行必须是 ## 日期:YYYYMMDD,与推送目标日期不匹配则删除该文件,要闻/操作建议为空兜底。

副作用(本版没发现,v2.0.7 暴露): send 脚本只读 ai.txt,但 dispatcher prompt 没让 LLM 写 ai.txt。修复后 send 一直读旧 ai.txt 推送。v2.0.7 同步加 dispatcher prompt 写 ai.txt 指令后修复

v2.0.4 — 大小写统一修复(2026-06-04)

问题根因: hermes 注册表目录与 SKILL.md / cron 配置的 skill 名大小写不一致 —— 4 个层面互相冲突:

| 位置 | 名字 | 大小写 | |------|------|--------| | hermes 注册表目录 | a-stock-report | 小写 ❌ | | SKILL.md frontmatter name | A-stock-report | 大写 ❌ | | 3 个 cron 任务的 skills 字段 | ['A-stock-report'] | 大写 ❌ | | 3 个 cron 任务的 prompt 指令 | 加载 A-stock-report skill | 大写 ❌ |

症状: hermes 加载 skill 时按目录名匹配,目录小写与配置大写不一致 → hermes 自动加载失败;prompt 中"加载 X skill"指令本应兜底,但因同样大小写问题,LLM 调 skill_view("A-stock-report") 也会失败(找不到大小写不匹配的资源)→ 任务以"无 skill 状态"运行。

修复内容:

  1. 目录重命名/root/.hermes/skills/a-stock-report//root/.hermes/skills/A-stock-report/
  2. SKILL.md version 字段2.0.32.0.4(patch 版本,bug 修复)
  3. 删除 v1.10.2 旧备份目录 a-stock-report-v1.10.2.bak/(完整内容保留在 /workspace/archive/a-stock-report-v1.10.2.bak_pre_delete_20260604_182313,可恢复)
  4. cron 任务的 3 个 skills 字段保持 ['A-stock-report'](无需改,原本就大写)
  5. cron 任务的 3 个 prompt 指令保持 加载 A-stock-report skill(无需改,原本就大写;双重保险保留)

修复后 4 层完全统一为 A-stock-report(首字母大写) —— hermes 自动加载和 LLM 兜底加载都指向同一目标。

安全措施:

  • 重命名前已完整备份 v2.0.3 到 /workspace/archive/a-stock-report-v2.0.3_pre_rename_20260604_182754(16 文件,239,162 bytes)
  • 删除 v1.10.2 前已备份到 /workspace/archive/a-stock-report-v1.10.2.bak_pre_delete_20260604_182313(17 文件,332,491 bytes)

影响范围: 3 个 cron 任务(早报 / 晚报 / 周末要闻)将于下次运行时生效。盘中预警 / IPO / 收盘小结未改动(其 skills 字段未配置或已正确)。

v2.0.3 — 锁机制系统化升级(2026-06-01)

问题根因: 6 个脚本(close_summary / evening / intraday / ipo / weekend / collect_evening)的锁实现不一致,且都缺关键能力:

  • 5 个脚本用 open(f, 'w').close() 创空锁,只比 mtime 跨日——同一天内残留就锁死
  • 1 个脚本(ipo)用 O_CREAT|O_EXCL 原子创建,但没有 stale 检测——死了或被 kill -9 后锁永远留着
  • 全部无 PID —— 无法判断持有者是否还活着
  • 全部无 TTL —— 进程死了锁不过期

解决方案: 新增 scripts/_lock.py 统一锁模块(85 行),6 个脚本全改用:

import sys as _sys
_sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from _lock import lock as _smart_lock, unlock as _smart_unlock

def _acquire_lock():
    if not _smart_lock(_LOCK_FILE, owner=__file__):
        _sys.exit(0)
def _unlock():
    _smart_unlock(_LOCK_FILE)

_lock.py 智能锁三大能力:

  1. PID 检测os.kill(pid, 0) 判断持有者是否还活着
  2. TTL 过期:默认 3600s(1 小时)后自动视为 stale
  3. stale 抢占:锁住的人死了 / 锁超时 → 自动清理并抢占

锁文件格式{pid}\n{owner}\n{created_at_timestamp}(3 行结构化)

行为矩阵:

| 锁状态 | 持有者 PID | TTL | 行为 | |--------|------------|-----|------| | 无锁 | - | - | 创建并占用 ✅ | | 有锁 | 存活 | 未超 | 拒绝,返回 False ❌ | | 有锁 | 死亡 | - | 清理 + 抢占 ✅ | | 有锁 | 存活 | 已超 | 清理 + 抢占 ✅ |

验证(6 项单测全过):

  • 无锁 → True
  • 活锁(PID 在)→ False
  • 死锁(PID 99999)→ 自动清理并抢占
  • 超时锁(2h 前 TTL=1h)→ 自动清理并抢占
  • unlock 幂等
  • 锁文件格式正确(pid/owner/timestamp 三行)

未改:send_morning_report.pyread_lock/write_lock 是业务级"当日是否已推送"去重,不是进程锁,保留原状。

测试结果: 集成测试模拟 cron 重启后死锁场景,新进程自动清理 + 抢占成功:

[LOCK] 持有者已退出 (pid=88888),自动清理并抢占。
✅ 锁内容: pid=257001 (当前进程)

v2.0.2 — 6/1 报告修复补完(2026-06-01)

在 v2.0.1 基础上,补全两个小问题:

  • 单行无"全A股"前缀直接采纳send_close_summary.py 144-170 行,单行数据不再误报"降级"提示
  • 主力净流入日期比较归一化send_close_summary.py 261-267 行,比较前把 20260601 归一为 2026-06-01,消除多余"日期不匹配" warning

6/1 重跑验证:涨停 166 跌停 23 炸板 48 炸板率 22.4%,主力 -609.56 亿,零 warning。

v2.0.1 — 收盘小结问财字段名兼容 + 残留锁自愈(2026-06-01)

问题现象:

  • 5/1 收盘报告生成后,复盘发现 炸板率=0 分 异常分支被命中
  • 6/1 重跑时,相同 query 问财 API 在不同时刻返回不同字段名炸板家数(旧)/ 涨停开板家数(新,同义词)
  • 根因:问财 OpenAPI 在 query 包含 炸板家数 时,nlp 翻译结果不稳,命中不同 cache 段

修复:

  • send_close_summary.py 167 行兼容两个字段名:
    zb_key = next((k for k in item if '炸板家数' in k or '涨停开板家数' in k), None)
    
  • 6/1 报告验证:涨停=166 跌停=23 炸板=48 炸板率=22.4%,炸板率得分 59 分 ✅

锁残留:

  • 5/1 脚本跑通后,锁文件 /tmp/a_stock_close_summary.lock 残留(推测:推送阶段异常退出导致 finally: _unlock() 未跑到)
  • 6/1 重跑时仍能正常释放(正常退出路径)
  • 锁已自愈,下次出现时优先排查推送阶段异常日志

v2.0.0 — 架构重构

重大变化:脚本角色重新划分为「采集」与「发送」两层

| 变化 | 说明 | |------|------| | 晚报双脚本拆分为采集+推送 | collect_evening_data.py(采集+写JSON/MD) + send_evening_report.py(读文件+推送),原来晚报PE等数据在send里直接调问财,现改为采集脚本统一用akshare获取 | | 晨报/周末要闻数据采集独立 | collect_morning_data.py 独立采集外围市场数据,不再依赖 send 脚本内部逻辑 | | 问财接口权限精确化 | 白名单原则落地:仅实际调用的脚本才加载 IWENCAI_API_KEY;无需问财的脚本(如 send_morning_report.pycollect_evening_data.py)不加载 | | 数据源更新 | 全市场成交额/流通市值来源从「同花顺问财」改为 akshare stock_zh_a_spot_em() 实时行情 | | 白名单表去重修正 | 原 SKILL.md 有重复行+错误脚本名(TUSHARE_API_KEY 应为 TUSHARE_TOKEN),已全部对齐实际脚本 |

v1.x 历史版本功能未变,仅文档同步。


安全配置(必读)

所有外部密钥均通过环境变量注入,禁止硬编码。密钥文件 /workspace/.env 由脚本自动加载(环境变量优先)。

密钥白名单原则

每个脚本仅加载本任务实际需要的变量,不得全量注入 .env 所有密钥。

| 脚本 | 必需密钥 | |------|---------| | collect_morning_data.py | TUSHARE_TOKEN, IWENCAI_API_KEY | | send_close_summary.py | WECOM_WEBHOOK_KEY, IWENCAI_API_KEY, TUSHARE_TOKEN | | collect_evening_data.py | WECOM_WEBHOOK_KEY(数据采集通过 akshare,无需问财)| | send_evening_report.py | WECOM_WEBHOOK_KEY, IWENCAI_API_KEY(PE/分位数查询)| | send_morning_report.py | WECOM_WEBHOOK_KEY(仅推送,无需问财)| | send_intraday_alert.py | WECOM_WEBHOOK_KEY | | send_ipo_report.py | WECOM_WEBHOOK_KEY | | send_weekend_news.py | WECOM_WEBHOOK_KEY, IWENCAI_API_KEY |

问财 API

问财查询(涨停家数、A50期货、VIX等)统一在进程内通过 _iwencai_query() 函数直连 OpenAPI,不使用 subprocess 外部调用,避免通过 IENV 泄露环境变量给子进程。

字段名兼容写法(重要): 问财 OpenAPI 在 query 包含同义词时,nlp 翻译可能返回不同字段名(如 炸板家数涨停开板家数)。消费侧必须兼容多字段名,避免单一字段名失效导致数据缺失。已修复 send_close_summary.py:167(兼容 炸板家数 / 涨停开板家数)。

自动推送说明

配置 WECOM_WEBHOOK_KEY 即表示授权自动推送报告至企业微信。推送是自动化报告系统的组成部分,非人工干预。

| 密钥 | 环境变量 | 最小权限 | 来源 | |------|---------|---------|------| | 企业微信 Webhook | WECOM_WEBHOOK_KEY | 仅发送(只写) | 微信企业版 → 应用 → Webhook | | 同花顺问财 API Key | IWENCAI_API_KEY | 只读查询 | 同花顺 i问财 SkillHub | | 妙想 API Key | MX_APIKEY | 只读查询 | 同花顺 i问财 | | Tushare Token | TUSHARE_TOKEN | 只读查询 | Tushare Pro |

.env 文件格式示例:

WECOM_WEBHOOK_KEY=c4a1cd60-254e-4612-b365-c701482ae98c
IWENCAI_API_KEY=***
MX_APIKEY=***
TUSHARE_TOKEN=***

##快速开始

#收盘小结(独立脚本,直接推送,无需LLM生成内容)
source /workspace/.env && python3 /workspace/skills/A-stock-report/scripts/send_close_summary.py
source /workspace/.env && python3 /workspace/skills/A-stock-report/scripts/send_close_summary.py --date2026-04-13

#晚报(统一采集脚本,直接采集 +推送)
source /workspace/.env && python3 /workspace/skills/A-stock-report/scripts/collect_evening_data.py
source /workspace/.env && python3 /workspace/skills/A-stock-report/scripts/collect_evening_data.py --date2026-04-13
source /workspace/.env && python3 /workspace/skills/A-stock-report/scripts/collect_evening_data.py --dry-run

#晚报(兼容旧脚本,独立推送)
source /workspace/.env && python3 /workspace/skills/A-stock-report/scripts/send_evening_report.py

#晨报(需LLM先生成内容,写入 /tmp/morning_report_content.txt)
source /workspace/.env && python3 /workspace/skills/A-stock-report/scripts/send_morning_report.py

#财经周末要闻(需LLM先生成内容,写入 /tmp/weekend_news_content.txt)
source /workspace/.env && python3 /workspace/skills/A-stock-report/scripts/send_weekend_news.py
source /workspace/.env && python3 /workspace/skills/A-stock-report/scripts/send_weekend_news.py --extract-only # 仅提取情绪数据

# IPO周报
source /workspace/.env && python3 /workspace/skills/A-stock-report/scripts/send_ipo_report.py

#盘中预警
source /workspace/.env && python3 /workspace/skills/A-stock-report/scripts/send_intraday_alert.py

执行模式

收盘小结、晚报、晨报 采用不同模式:

  • 收盘小结:单一 Python 脚本,内置全部逻辑(取数 → 打分 → 生成报告 → 推送),cron 直接触发,无需 LLM 生成内容。 晨报、晚报、周末要闻 采用两段式
  • 第一段(cron prompt):调用 dispatcher 生成带真实日期的 prompt,写入约定路径
  • 第二段(同一 session):读取 prompt 文件 → LLM 执行 → 写入内容文件 → 调用推送脚本

这样 SKILL.md 中的 prompt 模板只含通用占位符,日期在运行时由 dispatcher 动态注入。


数据来源

| 数据 | 来源 | 接口 | |------|------|------| | 六大指数(点位/涨跌幅) | 腾讯实时 API | qt.gtimg.cn | | 全市场成交额 | akshare | stock_zh_a_spot_em() 全量实时行情 | | 全市场流通市值 | akshare | stock_zh_a_spot_em() 全量实时行情 | | 涨跌停家数/炸板率 | 同花顺问财 | 今日涨停家数 跌停家数 炸板家数(1次查询) | | 全市场主力净流入 | 东方财富 RPT_MARKET_CAPITALFLOW | INDEX_CODE="800000.EI",SORT BY TRADE_DATE DESC 取第1行,BONDTYPE="A股" | | 行业板块涨跌(前5/后5) | hithink-sector-selector | 今日行业板块涨幅前10 / 今日行业板块跌幅前10 | | 行业主力资金流 Top | hithink-sector-selector | 近5日主力净流入前10行业板块 | | 两融余额/两融交易额 | AKShare | macro_china_market_margin_sh/sz(仅晚报使用) | | IF期货基差 | 新浪 nf_IF0 实时接口(今日优先)+ AKShare 兜底 | hq.sinajs.cn / akshare futures_main_sina |


文件名日期规则

| 报告 | 文件名日期取值 | |------|--------------| | 收盘小结 | --date 参数值;无参数则取当天 | | 晚报 | --date 参数值;无参数则取当天 | | 晨报 | 生成当天 | | 财经周末要闻 | 生成当天 |

注意:晚报内容里的两融余额标注日期(如"两融余额(04月13日)")是数据对应的上一交易日,与文件名日期可能差1天。


周末要闻情绪轨迹数据来源

一周情绪轨迹从历史报告MD文件中提取,合并规则:

| 指标 | 来源 | key取法 | |------|------|--------| | 涨停家数/情绪打分 | 收盘小结 收盘小结_YYYYMMDD.md | 从文件名提取 YYYYMMDD | | 两融余额/两融比例 | 晚报 晚报_YYYYMMDD.md | 从报告内容里两融余额行提取日期作为 key |

两套数据以交易日 key 对齐合并,保证周一到周五趋势线一致。


防并发锁

各脚本使用独立的锁文件,同时运行互不干扰:

| 脚本 | 锁文件 | |------|--------| | send_close_summary.py | /tmp/a_stock_close_summary.lock | | send_evening_report.py | /tmp/a_stock_evening.lock | | send_morning_report.py | /tmp/a_stock_morning.lock | | send_weekend_news.py | /tmp/a_stock_weekend.lock | | send_ipo_report.py | /tmp/a_stock_ipo.lock | | send_intraday_alert.py | /tmp/a_stock_intraday.lock |

锁残留检测(v2.0.1 起): 脚本有 finally: _unlock() 兜底,正常退出一定会释放。若锁文件残留

  1. 排查推送阶段异常日志(wx() 返回非 0 / 信号中断 / 网络超时)
  2. 确认无进程在跑(ps -ef | grep send_close)后,手动 rm /tmp/a_stock_close_summary.lock
  3. 残留超过 1 小时不重跑需要介入,避免重复推送

报告模板

晨报

📰 【股市晨报】YYYY年MM月DD日(周X)

━━━ 隔夜全球市场 ━━━
【美股收盘】
▪ 道琼斯:XXXXX.XX点,+X.XX%(精确数字,不得用"约")
▪ 标普500:XXXXX.XX点,+X.XX%
▪ 纳斯达克:XXXXX.XX点,+X.XX%(可附"X连涨/连跌X日")
▪ VIX恐慌指数:XX.XX(+X.XX%),恐慌等级:【低位(<20)/中位(20-30)/高位(>30)】

【港股及A50】
▪ 恒生指数:XXXXX.XX点,+X.XX%(附简要背景)
▪ 富时A50期货:XXXXX点,+X.XX%,偏强/偏弱运行【预判A股明日开盘】

【大宗商品】
▪ WTI原油:XXX.XX美元/桶,+X.XX%(精确数字,不得用"约")
▪ 现货黄金:XXXX.XX美元/盎司,+X.XX%(精确数字)

━━━ 财经要闻 ━━━
【1】(标题)|✅利好/❌利空/⚠️中性 对A股影响
  点评:(简洁分析,≤50字)
【2】(标题)|✅利好/❌利空/⚠️中性 对A股影响
  点评:(≤50字)
(**≤7条**,顺序编号,每条格式固定:
  【编号】(标题)|✅/❌/⚠️标签 对A股影响
  点评:(事件+分析,≤50字))

━━━ 今日操作建议 ━━━
【大盘研判】
(综合外围市场、宏观政策、量能等因素,给出2-3句综合判断)

【操作建议】
1. 【板块/策略】(期限):具体建议+附标的
2. 【板块/策略】(期限):...

【风险提示】
⚠️ (1-3条,最重要的风险)

⚠️ 仅供参考,不构成投资建议。股市有风险,投资需谨慎。

收盘小结

📊 【A股收盘小结】YYYY年MM月DD日

━━━ 一,主要股指表现 ━━━
• 上证指数:XXXX.XX,↑/↓X.XX%
• 深证成指:XXXX.XX,↑/↓X.XX%
• 创业板指:XXXX.XX,↑/↓X.XX%
• 科创50:XXXX.XX,↑/↓X.XX%
• 沪深300:XXXX.XX,↑/↓X.XX%
• 中证500:XXXX.XX,↑/↓X.XX%
全市场成交额:XXXXX亿
IF期货信号:IF=XXXX.X,基差+/-XX.X点(升水/贴水)

━━━ 二,板块行情 ━━━
  🔺 涨幅前5:
    · 板块名+X.XX%
    · ...
  🟢 跌幅前5:
    · 板块名-X.XX%
    · ...

━━━ 三,全市场主力资金 ━━━
  🔴/🟢 全市场主力资金:+/-XXX.XX亿元(净流入/净流出)

━━━ 四,行业主力资金流 ━━━
  近5日净流入板块 TOP5:
    · 板块名 +/-XXX.XX亿(+/-X.XX%)
    · ...
  近5日净流出板块 TOP3:
    · 板块名 +/-XXX.XX亿

━━━ 五,量化情绪打分 ━━━(满分100,6因子等权平均)
· 涨停家数 → X分(区间10~100家映射)
· 涨跌停比:XX倍 → X分(对数插值)
· 炸板率 → X分(区间40%~10%映射,越低越好)
• 主力净流入占比:X.XX% → X分(区间-5%~+5%映射)
• 全市场换手率:X.XX% → X分(区间1%~4%映射)
• IF基差:+/-XX.XX点 → X分(区间-300~+150点映射)
━━━━━━━━━━━
综合评分:XX/100  🟢做多|🟡偏多|⚪分歧|🟠偏空谨慎|🔴冰点

━━━ 六,后市展望 ━━━
市场震荡调整,风格偏向题材与成长,建议控制仓位、关注轮动节奏。

━━━ 数据来源:腾讯财经·东方财富·同花顺 ━━━
⚠️ 仅供参考,不构成投资建议。股市有风险,投资需谨慎。

晚报

📋 【A股晚报】YYYY年MM月DD日

━━━ A股收盘 ━━━
• 上证指数:XXXX.X,↑/↓X.XX%
• 深证成指:XXXX.X,↑/↓X.XX%
• 创业板指:XXXX.X,↑/↓X.XX%
• 科创50:XXXX.X,↑/↓X.XX%
• 沪深300:XXXX.X,↑/↓X.XX%
• 中证500:XXXX.X,↑/↓X.XX%
• 成交额:X.XX万亿元

━━━ 亚太股市 ━━━
• 恒生指数:XXXX,↑/↓X.XX%
• 日经225:XXXXX,↑/↓X.XX%
• 韩国综合:XXXX,↑/↓X.XX%

━━━ 市场风险偏好 ━━━
• 两融余额(MM月DD日):XXXXX亿,较前日+/-XXXX亿
• 两融余额/A股流通市值(MM月DD日)= X.XX%
  阈值:<3%安全 | 3-3.5%预警 | ≥3.5%高危
• 两融交易额/A股成交额(MM月DD日)= X.X%
  阈值:<7%保守 | 7-11%中性 | >11%过热
• 股市风险溢价(MM月DD日)= X.XX%
  阈值:<3%高估 | 3-6%中性 |>6%低估
• 沪深300 PE = XX.XX,近5年分位点 XX.X%

━━━ 财经要闻 ━━━
【1】(标题)|✅利好/❌利空/⚠️中性 对A股影响
  点评:(≤50字)
【2】...(**≤7条**,每条格式固定,点评≤50字)

━━━ 今日操作建议 ━━━
【大盘研判】(2-3句)
【操作建议】
1. 【板块/策略】(期限):具体建议
2. 【板块/策略】(期限):...
【风险提示】(1-3条)

⚠️ 仅供参考,不构成投资建议。股市有风险,投资需谨慎。

财经周末要闻(cron 触发后 LLM 生成)

📰 【财经周末要闻】过去48小时

━━━ 六条重要财经要闻 ━━━
【1】(标题)→ ✅利好/❌利空
  逻辑:...  交易风险提示:...

━━━ 一周情绪轨迹 ━━━
• 涨停家数趋势:周一X家 → 周二X家 → ... → 周五X家
• 两融余额/A股流通市值:周一X.XX% → ... → 周五X.XX%
• 两融交易额占比:周一X.X% → ... → 周五X.X%
• 量化情绪打分:周一XX分 → ... → 周五XX分
• 整体趋势:[升温/降温/震荡]

━━━ 整体市场情绪研判 ━━━
情绪指标总结 | 核心驱动因素 | 当前风险点 | 下周操作参考

⚠️ 仅供参考,不构成投资建议。

定时任务(cron)

| 任务 | cron 表达式 | 触发时间(北京时间) | 说明 | |------|-----------|-------------------|------| | A股晨报生成并推送 | 0 8 * * 1-5 | 周一至五 08:00 | AI内容生成 → 推送(单cron) | | A股晚报生成并推送 | 0 20 * * 1-5 | 周一至五 20:00 | AI内容生成 → 推送(单cron) | | A股收盘小结 | 30 15 * * 1-5 | 周一至五 15:30 | 数据采集 → 推送 | | A股盘中预警 | */5 9,10,11,13,14 * * 1-5 | 周一至五 09:00-11:55 / 13:00-14:55 | 实时监控 → 推送 | | A股周末要闻生成并推送 | 0 20 * * 0 | 周日 20:00 | AI内容生成 → 推送(单cron) | | 每周 Skill 复盘 | 0 18 * * 0 | 周日 18:00 | skill 自审 | | A股IPO周报 | 0 10 * * 6 | 周六 10:00 | 数据采集 → 推送 |


安装与验证

配置完 cron 后,按以下顺序逐一检查:

Step 1:密钥检查

| 报告类型 | 必需密钥 | 最低权限 | 检查命令 | |---------|---------|---------|---------| | 收盘小结 | WECOM_WEBHOOK_KEY | 仅发送 | grep WECOM_WEBHOOK_KEY /workspace/.env | | 晚报 | WECOM_WEBHOOK_KEY | 发送 | grep WECOM_WEBHOOK_KEY /workspace/.env | | 晨报 | 同晚报 | 同上 | 同上 | | 财经周末要闻 | 同晚报 | 同上 | 同上 | | IPO周报 | TUSHARE_TOKEN + WECOM_WEBHOOK_KEY | 查询+发送 | grep TUSHARE_TOKEN /workspace/.env | | 盘中预警 | 无外部依赖 | — | 无需检查 |

注意send_evening_report.py 的"财经要闻"和"明日操作建议"两个区块依赖 cron 中的 LLM 步骤生成,不是脚本自己能产出的。若未配置对应 cron task,这两个区块永远为空,这是设计预期,不是 bug。

Step 2:依赖检查

# 检查 akshare
python3 -c "import akshare; print('akshare', akshare.__version__)"

# 检查 tushare(IPO周报需要)
python3 -c "import tushare; print('tushare OK')"

# 检查 hithink-sector-selector CLI
python3 /workspace/skills/hithink-sector-selector/scripts/cli.py --help | head -3

Step 3:Cron 任务检查

运行 mcp_cronjob list 确认已配置的 cron 与计划运行的任务一致:

| 应存在 | 当前状态 | |--------|---------| | A股晨报生成并推送(08:00) | ✅ | | A股晚报生成并推送(20:00) | ✅ | | A股收盘小结(15:30) | ✅ | | A股盘中预警(交易时段) | ✅ | | A股周末要闻生成并推送(周日 20:00) | ✅ | | 每周 Skill 复盘(周日 10:00) | ✅ | | A股IPO周报(周六 10:00) | ✅ |


Cron 任务配置指引

所有 LLM 驱动型报告采用单 cron 模式:prompt 中先由 LLM 生成内容写入文件,再在同一 session 内调用脚本落地推送。

为什么用文件中转? cron prompt 在独立 session 运行,无法直接将变量传给后续脚本。通过写入约定路径的文件,脚本读取后注入报告模板,实现解耦。

1. 晨报(周一至五 08:00 北京时间)

{
  "name": "A股晨报生成并推送",
  "schedule": "0 8 * * 1-5",
  "repeat": "forever",
  "deliver": "local",
  "skills": [
    "a-stock-report"
  ],
  "prompt": "请加载 a-stock-report skill,然后执行以下任务:\n\n1. 调用晨报数据采集脚本获取结构化数据:\n   source /workspace/.env && python3 /workspace/skills/A-stock-report/scripts/collect_morning_data.py\n   \n   采集内容:道琼斯/标普500/纳斯达克/VIX点位涨跌幅、恒生指数/A50期货、WTI原油/现货黄金价格\n\n2. 读取采集结果 /tmp/morning_data.json,结合今日财经要闻,用 batch_web_search 搜索(6-10条):\n   - \"A股重要财经要闻 宏观政策 [今日日期]\"\n   - \"A股板块异动 热点题材 [今日日期]\"\n   \n   ⚠️ 关键要求:所有数据必须为精确数字,不得出现\"约\"、\"约XX\"、\"约XX%\"等模糊表述\n   ⚠️ **字数限制:全文不超过2000字,每条要闻点评控制在50字以内,不超过7条。**\n   ⚠️ **财经要闻约束:绝对禁止在要闻中列出任何指数/大宗商品/板块的点位或涨跌幅数字(包括 \"隔夜美股普涨X%\"、\"大宗商品走强X%\" 等定性带数字的表述)。如需引用市场反应只做定性描述(\"美股普涨\"、\"大宗走强\"),不写具体数字。聚焦宏观政策、公司事件、监管动态、板块题材、海外重大事件等。**\n\n3. 将结构化数据 + 财经要闻 合并渲染为完整晨报,写入 /tmp/morning_report_content.txt\n   格式严格遵循 SKILL.md 中晨报模板(含隔夜全球市场、财经要闻、操作建议三部分)\n4. 调用晨报推送脚本完成推送:\n   source /workspace/.env && python3 /workspace/skills/A-stock-report/scripts/send_morning_report.py\n\n5. 完成后打印\"✅ 晨报已完成:数据采集、内容生成并推送微信\""
}

3. 晚报(周一至五 20:00 北京时间,12:00 UTC)

{
  "name": "A股晚报生成并推送",
  "schedule": "0 12 * * 1-5",
  "repeat": "forever",
  "deliver": "local",
  "skills": [
    "a-stock-report"
  ],
  "prompt": "请加载 a-stock-report skill,然后执行以下任务:\n\n1. 调用晚报数据采集脚本,将结果写入约定路径:\n   source /workspace/.env && python3 /workspace/skills/A-stock-report/scripts/collect_evening_data.py\n   \n   采集内容:六大指数、亚太股市、两融余额、两融比例、沪深300 PE分位数、股市风险溢价(ERP)等结构化数据,输出 JSON + 晚报 Markdown。\n\n2. 读取采集结果文件 /tmp/evening_data.json,结合采集的晚报 Markdown,用 batch_web_search 搜索今日收盘相关财经要闻(6-8条):\n   - \"A股重要财经要闻 宏观政策 [今日日期]\"\n   - \"A股板块异动 热点题材 [今日日期]\"\n\n   **⚠️ 关键要求:搜索结果必须包含具体数字,所有数据不得出现\"约\"、\"约XX\"、\"约XX%\"等模糊表述,必须填入精确值。**\n   ⚠️ **字数限制:全文不超过2000字,每条要闻点评控制在50字以内,不超过7条。**\n   ⚠️ **财经要闻约束:绝对禁止在要闻中列出任何指数/大宗商品/板块的点位或涨跌幅数字(包括 \"亚太普跌X%\"、\"科技股集体杀跌X%\" 等定性带数字的表述)。如需引用市场反应只做定性描述(\"亚太普跌\"、\"板块杀跌\"),不写具体数字。聚焦宏观政策、公司事件、监管动态、板块题材、海外重大事件等。**\n\n3. 将结构化数据 + 财经要闻 合并渲染为完整晚报,写入 /tmp/evening_report_content.txt。\n   格式应严格遵循 SKILL.md 中晚报模板:\n   - 六大指数/亚太股市/两融数据 等结构化数据直接复用采集脚本输出\n   - [财经要闻] 区块由 LLM 搜索生成(≤7条)\n   - [今日操作建议] 区块由 LLM 综合分析生成\n\n   ⚠️ **同时**将 [财经要闻] 和 [操作建议] 两段单独精简写入 /tmp/evening_report_ai.txt:\n      - 第一行必须是 `## 日期:YYYYMMDD`(YYYYMMDD = 当天日期,北京时间)\n      - 紧接一行 `[财经要闻]` 标记,后跟要闻列表(每条含【N】标题|标签 + 缩进 2 格的 点评:)\n      - 紧接一行 `[操作建议]` 标记,后跟大盘研判 + 3 条操作建议 + 风险提示\n      - 此文件供 send 脚本读取并推送微信,不写会导致推送内容缺要闻和操作建议!\n\n4. 调用晚报推送脚本完成推送:\n   source /workspace/.env && python3 /workspace/skills/A-stock-report/scripts/send_evening_report.py\n5. 完成后打印\"✅ 晚报已完成:数据采集、内容生成并推送微信\""
}

4. 盘中预警(周一至五 09:30-11:35 / 13:00-14:55,每5分钟)

{
  "name": "A股盘中预警",
  "schedule": "*/5 1,2,3,5,6,7 * * 1-5",
  "repeat": "forever",
  "deliver": "local",
  "skills": [
    "A-stock-report"
  ],
  "prompt": "请加载 A-stock-report skill,然后执行以下任务:\n\n1. 采集最新行情数据(盘中行情每隔约5分钟检查一次):\n   - 上证指数、创业板指 实时点位和涨跌幅(via hithink)\n   - 沪深300主力净流入(via datacenter.eastmoney)\n   - IF沪深300期货当月连续 实时数据(via baostock)\n   - 炸板率(via东方财富涨停板数据)\n\n2. 判断是否触发预警条件,**符合以下任一条件即推送预警消息**:\n\n   【预警触发条件】\n   a) IF当月连续涨幅 > 1.5%(期货大幅升水,可能预示指数大幅高开)\n   b) 主力净流入 > 200亿元(今日已流入规模,via东方财富)\n   c) 上证或创业板指 涨幅 > 2%(情绪过热预警)\n   d) 炸板率 > 40%(涨停炸板率异常高,短线情绪极度不稳定)\n\n3. 若触发预警,调用推送脚本发送预警消息:\n   source /workspace/.env && python3 /workspace/skills/A-stock-report/scripts/send_intraday_alert.py [预警类型] [当前涨跌幅]\n   同时打印\"✅ 盘中预警已推送:[预警类型] [数值]\"\n\n4. 若未触发预警,打印\"✅ 盘中预警检查完成,当前无异常\"(不推送消息)"
}

5. 财经周末要闻(周日 20:00 北京时间)

{
  "name": "A股周末要闻生成并推送",
  "schedule": "0 12 * * 0",
  "repeat": "forever",
  "deliver": "local",
  "skills": [
    "a-stock-report"
  ],
  "prompt": "请加载 a-stock-report skill,然后执行以下任务:\\n\\n1. 用 batch_web_search 搜索以下内容:\\n   - \\\"A股周末要闻 政策动态 [本周末日期范围]\\\"(至少8条,来源权威媒体)\\n   - \\\"美股收盘 本周回顾 道琼斯 纳斯达克 标普500 [本周]\\\"(复盘本周美股走势)\\n   - \\\"A股本周回顾 上证指数 创业板指 本周涨幅\\\"(复盘本周A股行情)\\n   - \\\"下周A股预期 下周展望 下周策略 [YYYY年MM月]\\\"(如有券商展望)\\n   - \\\"美股期货盘前 纳斯达克期货 A50期货 [今日]\\\"(为下周一定调)\\n\\n   ⚠️ 关键要求:搜索结果必须包含精确数字,所有数据不得出现\"约\"、\"约XX\"、\"约XX%\"等模糊表述,必须填入精确值。\\n   ⚠️ **字数限制:全文不超过2000字,逻辑分析从简,每条要闻控制在2-3句以内。**\n   ⚠️ **财经要闻约束:绝对禁止在要闻中列出任何指数/大宗商品/板块的点位或涨跌幅数字(包括 \"美股本周累涨X%\"、\"黄金大涨X%\" 等定性带数字的表述)。如需引用市场反应只做定性描述(\"美股走强\"、\"大宗分化\"),不写具体数字。聚焦宏观政策、公司事件、监管动态、板块题材、海外重大事件等。**\\n\\n2. 按以下模板严格格式化内容,写入 /tmp/weekend_news_content.txt:\\n📰 【财经周末要闻】[YYYY年MM月DD日(周X)]\\n\\n━━━ 周末要闻摘要 ━━━\\n【1】(标题)|✅利好/❌利空/⚠️中性 对A股影响\\n  摘要:(2-3句,概括事件并分析影响)\\n  来源:XX媒体\\n【2】(标题)|...\\n(8-12条,顺序编号,每条格式固定)\\n\\n━━━ 本周复盘 ━━━\\n【美股本周】(道琼斯:XXXXX点,本周+X.XX%;纳斯达克:XXXXX点,本周+X.XX%;标普500:XXXXX点,本周+X.XX%)\\n【A股本周】(上证:XXXX.XX点,本周+X.XX%;创业板:XXXX.XX点,本周+X.XX%)\\n【大宗商品】(黄金:XXXX美元/盎司,本周+X.XX%;原油:XXX美元/桶,本周+X.XX%)\\n\\n━━━ 下周展望 ━━━\\n【外围市场】美股期货(A50/纳指期货)当前表现预判下周基调\\n【A股预判】综合周末消息面,展望下周A股可能走势\\n【关注板块】(2-3个板块+逻辑简述)\\n\\n⚠️ 仅供参考,不构成投资建议。股市有风险,投资需谨慎。\\n\\n3. 调用周末要闻推送脚本:source /workspace/.env && python3 /workspace/skills/A-stock-report/scripts/send_weekend_news.py\\n4. 完成后打印\"✅ 周末要闻已完成:内容生成并推送微信\""
}

应严格遵循 SKILL.md 中对应模板的 [财经要闻] / [操作建议] 分段标记。

6. 收盘小结(周一至五 15:30 北京时间)

收盘小结为独立脚本模式,无需 skill 和 LLM 生成内容,直接调用脚本即可。

{
  "name": "A股收盘小结",
  "schedule": "30 7 * * 1-5",
  "repeat": "forever",
  "deliver": "local",
  "prompt": "source /workspace/.env && python3 /workspace/skills/A-stock-report/scripts/send_close_summary.py"
}

7. IPO周报(周六 10:00 北京时间)

IPO周报为独立脚本模式,无需 skill 和 LLM 生成内容,直接调用脚本即可。

{
  "name": "A股IPO周报",
  "schedule": "0 2 * * 6",
  "repeat": "forever",
  "deliver": "local",
  "prompt": "source /workspace/.env && python3 /workspace/skills/A-stock-report/scripts/send_ipo_report.py"
}

验证 3:端到端 cron 验证

实际 cron 跑过后,检查:

  1. 推送消息中"财经要闻"和"明日操作建议"区块是否有内容
  2. 内容日期是否与当天日期一致
  3. 报告文件名是否为当天日期

若发现为空,回到"验证 2"确认内容文件是否成功写入。

IPO周报数据来源

| 报告模块 | 接口 | 来源 | 用途 | |---------|------|------|------| | 一、排队情况 | ak.stock_register_kcb/cyb/bj/sh/sz | 东方财富注册制审核公示 | 各板块在审排队数+状态分布 | | 二、本周期上会 | ak.stock_ipo_review_em | 东方财富 IPO审核动态 | 上会企业列表 | | 三、本周期获批 | ak.stock_ipo_declare_em | 证监会公示 | 获发行批文(注册/核准) | | 四、终止撤回 | ak.stock_ipo_declare_em | 证监会公示 | 本周终止企业 | | 五、下周期上会 | ak.stock_ipo_review_em | 东方财富 IPO审核动态 | 下周期上会计划 | | 六、新股上市 | ak.stock_xgsr_ths | 同花顺 | 上市日期+发行价+首日涨跌幅 |

注:六、新股上市仅用同花顺 stock_xgsr_ths,一次调用同时获取上市信息+发行价+首日涨跌幅,无需额外调用证监会 CNINFO 接口。


常见问题

Q1:生成后如何做质量检查? A:生成报告后必须检查以下四项:

  1. 日期检查:报告第一行日期 == 文件名日期 == 当天实际日期(三者必须一致)
  2. 星期检查:报告中的日期字符串(YYYY年MM月DD日(周X))与文件名中的日期 weekday() 对应周一~周五正确
  3. 数据完整性
    • 收盘小结:指数行情、情绪打分、板块资金流、风险偏好、操作建议五段落齐全
    • 晨报/晚报:涨跌停统计、风险偏好、操作建议三段落齐全
  4. 时效性:数据陈旧(>2个交易日)时在报告内注明

Q2:如何判断涨停情绪? A:涨停情绪由第4节打分函数统一评分(满仓风险系数 × 涨停家数权重 + 涨跌停比 × 炸板率综合得出 0-100 分),不再单独使用 emoji 分级。报告生成后通过"质量检查第3项"确认段落齐全即可。

  • 参考:情绪总分 ≥ 70 → 🟢做多;≥ 55 → 🟡偏多;≥ 40 → ⚪分歧;≥ 25 → 🟠偏空;< 25 → 🔴冰点

Q3:炸板率如何评分? A:炸板率由第4节打分函数中的 _sc(exp_rate, 40, 10) 公式映射到 0-100 分,阈值区间 [40%, 10%],炸板率越低得分越高。

  • 参考:情绪总分 ≥ 70 → 🟢做多;≥ 55 → 🟡偏多;≥ 40 → ⚪分歧;≥ 25 → 🟠偏空;< 25 → 🔴冰点

Q4:两融数据比当天少一天? A:正常现象。两融数据在当天收盘后约 1~2 小时后更新,晚报/收盘小结取到的是上一交易日数据。

Q5:主力净流入 > 500亿时显示什么? A:打印预警信息 ⚠️ 主力净流出-XXX亿,超大单+大单砸盘XXX亿,异常大额出逃,注意风险,但保留真实数值(不重置为0)。

Q6:定时任务重复推送? A:已内置文件锁机制的脚本会拒绝并发执行。当前各脚本锁机制如下:

  • 晚报:send_evening_report.py/tmp/a_stock_evening.lock(exists 检测 + sys.exit(0),finally 解锁)
  • 盘中预警:send_intraday_alert.py/tmp/a_stock_intraday.lock(同上)
  • 周末要闻:send_weekend_news.py/tmp/a_stock_weekend.lock(同上)
  • IPO周报:send_ipo_report.py/tmp/a_stock_ipo.lock(原子 os.O_EXCL 创建,更严格,finally 解锁)
  • 晨报:send_morning_report.py/workspace/skills/A-stock-report/scripts/.morning_report_lock.json(JSON 文件,内容含 datestatus,检查当日是否已成功推送后才允许重复执行)

Q7:报告内容日期和文件名不对应? A:收盘小结文件名=报告日期;晚报文件名=生成当天日期,内容日期=上一交易日;周末要闻以内容里两融余额标注的日期为 key,与收盘小结文件名日期对齐合并。

Q8:如何使用 --date 指定历史日期? A:收盘小结和晚报均支持 --date YYYY-MM-DD,如 python3 send_close_summary.py --date 2026-04-13。晨报不支持指定历史日期。

Q9:IPO 周报显示"排队情况(数据获取失败)"怎么排查? A:先确认是数据源问题还是脚本问题(v2.0.8 修复了脚本问题)。 第一步:手动测试 5 个数据源接口

import akshare as ak
for fn_name in ['stock_register_kcb', 'stock_register_cyb', 'stock_register_bj', 'stock_register_sh', 'stock_register_sz']:
    fn = getattr(ak, fn_name, None)
    if fn is None:
        print(f'❌ {fn_name}: 接口不存在(akshare 版本问题)')
    else:
        df = fn()
        print(f'✅ {fn_name}: {len(df)}行')
  • 如果任何接口返回空或抛异常 → 数据源问题(东方财富接口临时不可用),等会儿再跑或查 akshare 更新
  • 如果 5 个接口都正常 → 脚本问题(v2.0.8 已修复,见 Changelog)

第二步:如果接口都正常但报告仍说"数据获取失败"

  • 检查 _collect_ipo_data() 的 return dict 是否包含 queue_detailqueue_status_detailsource_date 这 3 个 key(v2.0.7 之前的版本可能漏掉)
  • 这 3 个 key 是 build_report_lines() 期望的(data.get('queue_detail', {}) 取值),缺失会走 "数据获取失败" 分支
  • 数据返回但 key 名为 queue(IPO 获批数据)也是常见 bug

第三步:看脚本输出日志(重跑时加 2>&1 | grep 排队):

[排队] 数据更新日期: 2026年06月05日     ← 5 板块拉取成功
[排队] queue_detail: {...}              ← pivot 计算成功
[排队] queue_status_detail: {...}       ← 状态细项计算成功
  • 如果 3 行都在但报告仍坏 → build_report_lines() 读到错的 key
  • 如果报错 Invalid comparison between dtype=datetime64[s] and Timestamp → 时区 bug(v2.0.8 已修)