Sequoia-X 项目研究站 · 飞书播报
Sequoia-X 飞书播报:按策略分群推送的 webhook 路由
推送模块把选股结果组装成飞书交互卡片,再按策略的 webhook_key 决定发到哪个群:环境变量里配了 STRATEGY_WEBHOOK_<KEY> 就推给对应机器人,没配就回落到默认 Webhook。这类设计的实际价值是——海龟突破和定增公告可以进不同的群,不用在代码里改收件人。
Sequoia-X 的飞书播报卡片长什么样
源码构造的是飞书 interactive 卡片,字段固定。
| 卡片部分 | 源码内容 | 适用场景 | 注意点 |
|---|---|---|---|
| 消息类型 | msg_type = "interactive" | 需要结构化排版的播报 | 不是纯文本消息,网关或中转层需要支持卡片格式 |
| 标题 | 📈 Sequoia-X 选股播报 | {策略名},模板蓝色 | 一眼分辨是哪个策略的结果 | 策略名取的是类名(如 MaVolumeStrategy),不是中文别名 |
| 摘要行 | 日期 / 策略 / 选股数量三项 | 快速确认当天是否跑过 | 日期取的是执行当天(date.today()),不是数据源的最后一个交易日 |
| 分隔线 | hr 元素 | 视觉分层 | 纯展示,不影响数据 |
| 选股列表 | 每个标的一段 lark_md 链接:[名称](https://xueqiu.com/S/<代码>) | 点进去直接看个股页 | 名称要先查库外的股票基础信息,查不到就用代码兜底 |
| 链接前缀 | 6 开头 → SH;4 / 8 开头 → BJ;其余 → SZ | 生成雪球代码 | 与数据层入库时的 sh./sz. 规则不同,别混淆 |
| 空结果 | 列表为空时不会走到推送(main.py 先判断命中数) | 避免空卡片刷屏 | 推送器内部虽有「(无选股结果)」兜底文案,正常流程不会用到 |
Sequoia-X 七个策略的 webhook 标识
标识定义在各策略类里,环境变量名由配置模块扫描前缀得到。
| 策略类 | webhook_key | 环境变量名 | 适用场景 |
|---|---|---|---|
| MaVolumeStrategy | ma_volume | STRATEGY_WEBHOOK_MA_VOLUME | 均线放量信号单独建群 |
| TurtleTradeStrategy | turtle | STRATEGY_WEBHOOK_TURTLE | 突破类信号单独建群 |
| HighTightFlagStrategy | flag | STRATEGY_WEBHOOK_FLAG | 旗形整理信号单独建群 |
| LimitUpShakeoutStrategy | shakeout | STRATEGY_WEBHOOK_SHAKEOUT | 洗盘信号单独建群 |
| UptrendLimitDownStrategy | limit_down | STRATEGY_WEBHOOK_LIMIT_DOWN | 错杀信号单独建群 |
| RpsBreakoutStrategy | rps | STRATEGY_WEBHOOK_RPS | 强势股信号单独建群 |
| PrivatePlacementStrategy | private_placement | STRATEGY_WEBHOOK_PRIVATE_PLACEMENT | 公告事件单独建群 |
| 基类默认值 | default | 回落到 FEISHU_WEBHOOK_URL | 必填项,缺失则配置校验直接失败 |
STRATEGY_WEBHOOK_ 开头的键收集进一个映射(键名去掉前缀并转小写);推送时用策略的 webhook_key 去查这个映射,查不到就用默认 Webhook。所以键名的大小写与拼写必须与策略类里的标识一致。Sequoia-X 飞书配置:从建机器人到验证
按顺序做完这五步,推送链路才算打通。
在飞书群里添加自定义机器人
在目标群设置里添加「自定义机器人」,拿到该机器人的 Webhook 地址。开源项目不包含机器人创建能力,这一步在飞书侧完成。
先配一个默认 Webhook
把地址写进项目根目录
.env的FEISHU_WEBHOOK_URL。它是必填项——不填的话程序在读取配置阶段就会失败退出,连数据同步都不会开始。按策略补充专属 Webhook
想让某个策略单独进群,就在
.env里加对应的STRATEGY_WEBHOOK_<KEY>,例如STRATEGY_WEBHOOK_TURTLE。没配的键自动回落到默认地址。跑一次日常模式观察日志
执行
python main.py,每条命中的策略都会打印一行推送结果:成功是「飞书推送成功 [key],共 N 只股票」,失败会带上 HTTP 状态与飞书响应体。到群里核对卡片内容
确认标题里的策略名、日期、数量与标的一一对应。若同一只股票出现在多条卡片里,那是因为它同时满足多个策略——这是预期行为。
飞书推送成功 [turtle],共 8 只股票 / 飞书推送失败 [turtle] HTTP状态=400 飞书响应=...。真实的运行记录本站没有采集,页面只描述源码会打印什么。Sequoia-X 推送失败怎么判定与排查
最容易踩的坑:HTTP 200 不等于推送成功。
| 现象 | 源码判定 | 适用场景 | 处理方向 |
|---|---|---|---|
| HTTP 200 但没收到消息 | 响应体 code != 0 仍记为失败 | 地址失效、机器人被移除、内容被风控 | 看日志里的飞书响应体,按返回码定位 |
| 日志出现请求异常 | 捕获 requests.RequestException 后记 ERROR | DNS / 网络 / 代理问题 | 换网络环境或用能访问飞书的机器执行 |
| 单次推送耗时 10 秒 | 请求超时设为 10 秒 | 网络拥塞或服务端响应慢 | 超时只影响这一条推送,不会中断后续策略 |
| 进了错误的群 | 用 webhook_key 查映射,查不到回落默认 | 环境变量名拼错、大小写不一致 | 对照上表逐个核对键名 |
| 推送失败但数据已更新 | 推送异常被吞掉,不抛出、不影响主流程 | 数据入库与推送解耦 | 推送失败不会让当天数据白拉,修复后可重跑(当天重写是安全的) |
| 完全没有推送日志 | 命中为空时 main.py 直接跳过推送 | 阈值严或当天行情不匹配 | 先看策略是否命中,再看推送 |
Sequoia-X 卡片里的股票名称从哪里来
卡片上显示中文名而不是代码,这一步是推送前额外做的查询。
| 环节 | 实现 | 适用场景 | 注意点 |
|---|---|---|---|
| 查询方式 | 推送前逐只调用 baostock 基础信息接口取名称 | 命中数量不多时成本可接受 | 这是一次额外登录与逐只查询,命中多时推送阶段会变慢 |
| 失败兜底 | 查不到名称时用雪球代码(如 SZ000001)当显示名 | 数据源临时不可用 | 不会因为取名称失败而放弃整条推送 |
| 名称缓存 | 源码未做持久化缓存 | 每日一次推送场景够用 | 频繁手动重跑会重复查询,注意上游接口负担 |
| 链接格式 | lark_md 的 [名称](url) 语法 | 点击直达个股页 | 卡片需以 lark_md 渲染,纯文本模式看不到链接 |
| 与库内代码的关系 | 库内存纯数字代码,推送时再转带前缀格式 | 保持存储与展示解耦 | 两条转换规则不一致(sh./sz. 与 SH/SZ/BJ),改代码时别互相替换 |
| 去重 | 同一策略内部返回的清单已是去重结果 | 定增策略尤其需要(同一标的可能多次定增) | 跨策略之间不做合并去重 |
.env 等本地配置里,不要提交到版本库、不要贴进截图或公开文档。本站示例中出现的地址均为占位符。飞书播报常见问题
不配飞书 Webhook,Sequoia-X 能用吗?
不能。默认 Webhook 是配置模型的必填字段,缺失时初始化配置就会抛校验错误,程序在启动阶段退出。如果你只想要数据不想要推送,需要自行改造代码,这超出本站整理范围。
Sequoia-X 一个群能收到所有策略结果吗?
可以。只配 FEISHU_WEBHOOK_URL 不配任何 STRATEGY_WEBHOOK_* 时,所有策略都回落到这个默认地址,结果都会进同一个群。想分组就补对应的环境变量。
Sequoia-X 推送成功但群里看不到?
先确认消息类型:源码发的是 interactive 卡片,如果接收端或中转层只支持纯文本,可能被丢弃。其次确认机器人仍在群里且有发送权限,再核对日志里是否真的打印了「飞书推送成功 [key]」。
Sequoia-X 推送失败要重跑整个流程吗?
通常不必。推送与数据入库是解耦的:推送异常只记日志,不影响已经写入的数据。修好 Webhook 后手工重跑当天是安全的,因为日常模式写入前会先删除当日记录。
Sequoia-X 卡片日期为什么是执行日?
源码里卡片日期取的是程序执行当天的日期,而不是数据源中最后一个交易日的日期。节假日补跑时两者可能不一致,判断数据新鲜度应结合策略命中情况与日志里的同步条数。
能改成钉钉、企业微信或邮件吗?
仓库里的通知模块只实现了飞书,没有其他渠道的代码。要接别的渠道需要自己按 notify/ 目录的结构新增模块并在 main.py 中调用。以上以仓库当前源码为准。