异动哨兵 + Telegram 播报 · 设计文档
日期:2026-08-06 · 状态:已上线(GitHub Actions 报警版,2026-08-07 实测推送成功) 不进发布网站(build.py 白名单外),纯内部工程文档。
当前生效的部署(2026-08-07)
- 跑在哪:GitHub Actions(私有仓库,免费额度内),
.github/workflows/yidong.yml。
不依赖用户任何设备,Mac 关机照跑。
- 何时跑:每交易日 UTC 17:35(盘中,发心跳)与 21:15(收盘,静默除非异动);
GitHub 定时可能晚 10-30 分钟,属正常。
- 推什么:±8% 报警(哪只、动多少、从多少到多少)+ 心跳 + 故障告警。无分析——
分析层待用户注册 DeepSeek API 后加(key 走 Secrets,同 TG_TOKEN 的注入方式)。
- 凭据在哪:GitHub 仓库 Secrets(TG_TOKEN/TG_CHAT),由
注入github.py从
~/.异动哨兵.env 写入,加密存储。
- 两个已知坑:定时不准点(见上);仓库连续 60 天无提交定时会被暂停(本库碰不到)。
- 首次实测:run 31166437231,推送成功(措辞已修:未开盘≠休市)。
⚠️ 先读这段:云端方案已验证死亡(带证据)
最终定位(2026-08-06 深夜,探针 B 的沙箱日志原话):
curl到 api.telegram.org → exit 56,CONNECT tunnel failed, response 403 from proxy
——沙箱的网络代理策略性封锁对外部服务的直连,不是故障,是设计,无法从内部绕开。
pwd && ls→ 私有仓库根本没被 clone 进沙箱,脚本文件都不存在。
排查过程中还撞出第三个独立障碍,记下来防止后人再踩:
- 云端 agent 会对"带凭据往外发消息"的指令做安全审查。第一版指令没写授权背景
(谁的 bot、谁的群、谁授权),被当成数据外传直接拒绝,且拒绝得无声无息—— 从外面看与网络故障一模一样。第二版补了授权说明后 agent 愿意执行了,才撞到上面的 代理 403。教训:给云端 agent 的指令要自带授权上下文;但就算过了这关,网络也不通。
排除项:token 经 getMe 验证有效(@reaichainbot),同一 token 本地推送成功。
结论:Claude 云端 routine 推 Telegram 此路不通,别再试。 三个 routine 全部停用, token 已从云端配置中抹除。
剩下的可选路(未决)
- Mac + launchd:
工具/异动哨兵/播报.py已写好可用,含 Claude 分析。代价是 Mac 得醒着。 - GitHub Actions:跑在 GitHub 云上、免费、网络通,能稳定送出"哪只动了多少",
但分析那段做不了(需要付费 API key)。适合"报警秒到、分析等 Mac"的拆分。
一句话
观察名单里的股票单日涨跌超过 8% 时,自动分析原因推送到 Telegram 群;群里还能 @bot 拿知识库内容问答。
拍板记录(2026-08-06 与用户逐项确认)
| 决策点 | 结论 | 备选与否决原因 |
|---|---|---|
| 通道 | Telegram 群 | WhatsApp 官方 API 不支持发群,群 bot 只能走非官方途径,有封号风险 |
| 范围 | 推送 + 问答 bot 一步到位 | — |
| 频率 | 开盘后每 4 小时一次(实际=盘中一次+收盘后一次) | 原提议 15 分钟一次,用户降频 |
| 部署 | 推送跑云端定时任务,问答 bot 跑 Mac | 全 VPS(月费+需单独 API key)、全 Mac(睡眠即停摆)均否决 |
| 前提 | 知识库推私有 GitHub 仓库 | 云端 agent 要读公司卡/台账;顺带解决"正本只有 Mac 一份、无备份"的风险 |
架构:两个独立的半边
半边 A:云端定时推送(不依赖 Mac)
Claude 云端定时任务(scheduled cloud agent),每个交易日跑两次:
- 美东 13:30(开盘后 4 小时):拉观察名单全部标的当日涨跌(yfinance,复用 报价.py 的名单解析逻辑)。|涨跌| ≥ 8% 的标的逐只分析:当日新闻 + 证监会公告 + 对照该公司的公司卡/论点台账/核心篮子备忘,按宪法语言纪律写一段新闻式中文分析(动了多少、市场在定价什么、台账论点受不受影响),推送 Telegram 群。无异动也发一条心跳("盯 N 只,无异动")——群里哪天 13:30 没心跳,就知道是任务死了,不是市场安静。防静默失效,这是本库反复踩过的坑。
- 美东 16:10(收盘后):再扫一遍,只对新出现的异动发声,无新异动则静默。
去重状态存在仓库里:异动写入根目录 异动台账.md(带日期+触发价),下次跑先读它,同一标的同一天不重复报;从 8% 恶化到 15% 这类算"加剧",再报一次。台账由云端 agent 直接 commit 回 GitHub——符合"判断留痕"的宪法要求。
半边 B:Mac 常驻问答 bot
Python 进程(python-telegram-bot 库),launchd 开机自启、崩溃自动拉起:
- 长轮询收群消息——不需要公网 IP、不开端口,家庭网络即可。
- 群里 @bot 或
/ask 问题触发:调本机已登录的 Claude Code 无头模式(claude -p,工作目录=知识库,只读工具+可搜网),用知识库内容回答,走现有订阅额度,不需要单独 API key。 - 串行队列,一次答一个,防止并发烧额度。
- 每小时
git pull --ff-only一次,保证回答用的知识库不落后于云端 commit 的异动台账。 - Mac 睡眠/关机时 bot 不应答(推送不受影响)。
新增纪律(GitHub 化带来的)
仓库有远程之后:本地 commit 完要 push;云端会 commit 异动台账,本地下次干活前 pull。冲突概率极低(云端只碰 异动台账.md),但交接说明里要写这条。
2026-08-06 决策变更:砍掉留痕
原设计要求异动分析追加进 异动台账.md 并提交进版本库。已取消,用户拍板: 「群里需要的是当日异动,知识库里是基本面」。
这是一条职责边界,不是妥协:群回答"今天发生了什么",知识库回答"我们怎么判断这家公司"。 把每日异动往台账里灌,只会用噪音撑坏一个本来该沉淀判断的地方。
连带影响:云沙箱推不回仓库这个已知缺陷,不再是缺陷——本来就不需要它写回。 routine 的工具白名单已去掉 Write/Edit,想写也写不了。
实际部署记录(边做边补)
| 项 | 值 |
|---|---|
| 私有仓库 | jiabinzeit-lab/ai-chain-research(2026-08-06 建,已验证 isPrivate) |
| bot | @reaichainbot |
| 群 id | -5583599280(负数=群;正数是私聊,填错会变成只发给自己且看着完全正常) |
| 本地凭据 | ~/.异动哨兵.env,权限 600,在仓库外,不进 git |
| 盘中 routine | trig_01Tq9hpRyECSuXWjYTgZi9GV — https://claude.ai/code/routines/trig_01Tq9hpRyECSuXWjYTgZi9GV |
| 收盘 routine | 待盘中那只验通后再建 |
| 探针 routine | trig_01HKVAxjPQQzNJnd6f3z9xmU,已停用(跑一个多小时未回报,结论不明) |
云端 token 的存放:云沙箱读不到家目录的凭据文件,所以 token 写在 routine 提示词里(存于用户自己的 Anthropic 账号,不进 GitHub)。由用户本人粘贴——助手被权限分类器拦住读取凭据,这个拦截是对的,没有绕过。 真泄漏时 BotFather 发 /revoke 十秒作废。
用户要亲手做的(无法代办)
- GitHub 账号 + 授权(建私有仓库、让 Claude 云端能访问)。
- Telegram 找 @BotFather 发
/newbot建 bot,拿 token(约 2 分钟)。 - 建群、把 bot 拉进群。
- (可选)Mac 插电 + 设置防睡眠,只影响问答 bot 在线时长。
已知限制,明说
- yfinance 报价延迟约 15 分钟,"8%"以拉取时点为准,不是真·实时。
- 阈值只看常规时段涨跌幅(previousClose 对比),盘前盘后异动不触发。
- 一天只扫两次:开盘头 4 小时内的闪崩闪涨,最早 13:30 才会被看到。这是用户主动选的频率,要更快随时可加密。
- 分析与问答消耗 Claude 订阅用量。
- 问答 bot 在线时段 = Mac 醒着的时段。
测试方案
- 阈值临时调到 1% 干跑一遍,验证"触发→分析→推送→留档"全链路。
- Telegram 推送先发到只有用户一人的测试群,内容格式认可后再进正式群。
- 云端任务先手动触发一次成功,再挂上时刻表。
分期施工
- GitHub 化:建私有仓库、推送现有历史、写进交接说明。(半小时,当天可完)
- 云端推送:哨兵脚本 + 定时任务 + 测试群跑通。(半天)
- Mac 问答 bot:bot 进程 + launchd + 测试。(半天)
每期独立可用:只做完第 1 期也白赚一个异地备份;只做完第 2 期推送就已上线。