Rockyzsu/stock / 监控推送
监控与推送:四类监控机制、四条推送渠道
这是 README 完全没有覆盖的一块能力:monitor/ 目录里有 9 个脚本,覆盖了四类监控——可转债监控(jsl_monitor.py)、自选池实时监控(realtime_monitor_ts.py)、大单监控(big_deal.py)、封板监控(ceiling_break.py),外加一个把快照写进 Redis 的接口(server_api.py)。
四类机制的骨架是同一个:轮询数据源 → 比对阈值 → 历史去重 → 推送。差别在于数据源(集思录 / 新浪行情 / 逐笔成交)、触发条件(溢价率 / 涨跌幅 / 买一量)和推送渠道。本页把参数、阈值、口径与失效场景全部列清——包括两个会导致脚本导入期直接失败的配置问题。
Rockyzsu/stock · 四类机制
Rockyzsu/stock 的 monitor/ 目录有哪些脚本?四类监控机制怎么分工
| 监控脚本 | 监控对象 | 数据源与调用 | 触发条件 | 输出 |
|---|---|---|---|---|
monitor/jsl_monitor.py | 可转债(全市场与自选池) | 集思录:先 login() 拿会话,再取可转债列表 | 溢价率 / 正股涨跌幅超过阈值;FILTER_REDEEM = True 过滤强赎 | 写 Redis 快照 + 调用通知 |
monitor/realtime_monitor_ts.py | 自选池 + 可转债池 | 新浪行情通道:ts.get_apis() 建会话,循环 ts.quotes(codes, conn=api) | 涨跌幅超过阈值(正负双向);也监控买卖一价差 | 控制台 + notify() 推送 |
monitor/big_deal.py | 大单成交 | Tushare 逐笔:ts.get_today_ticks(code) | 成交量超过设定倍数(源码中留有多档阈值注释) | 日志记录命中股票 |
monitor/ceiling_break.py | 封板强度 | 新浪行情:ts.get_realtime_quotes() 读 b1_v(买一量) | 买一量 ≤ 10000(手)判定封单变薄 | 调用 notify() 推送提醒 |
monitor/server_api.py | 可转债快照转发 | 继承 ReachTargetJSL,取数后写 Redis | 无阈值,按需调用 update() | 写入 Redis 键 ptrade |
monitor/alert_me.py | 统一入口 | fire CLI:--monitor_type 选择 jsl 或其他 | 无,由子模块决定 | 转发到对应监控对象 |
monitor/realtime_kzz_price.py | 可转债实时价 | 集思录 /data/cbnew/cb_list/ + pypinyin 处理名称 | 按拼音首字母匹配标的后打印价格 | 控制台输出 |
monitor/crawler_monitor.py | 爬虫存活 | 自身任务状态 | 爬虫未按预期产出 | 企业微信推送 |
monitor/__init__.py | — | — | — | 包声明 |
Rockyzsu/stock 的四类机制共享同一套骨架:轮询 → 阈值 → 去重 → 推送。所以理解其中一个(建议从 ceiling_break.py 开始,因为它最短且不依赖数据库)之后,其余几个的阅读成本会大幅下降。
Rockyzsu/stock · 参数与缺口
Rockyzsu/stock 的监控参数怎么配:五个键在官方样例里不存在
| 参数 | 样例配置里的值 | 代码实际读取 | 作用 | 缺了会怎样 |
|---|---|---|---|---|
ACCESS_INTERVAL | 20 | 是 | 常规轮询间隔(秒) | 导入期 KeyError |
EXPIRE_TIME | 1800 | 是 | 历史去重窗口(秒),由 HistorySet(expire=...) 使用 | 导入期 KeyError |
MONITOR_PERCENT | 8 | 未见读取 | 样例里像是监控百分比阈值 | 配置里有但代码没用,属无效配置 |
JSL_USER / JSL_PASSWORD | 空字符串 | 是 | 集思录账号(登录时再做 JS 加密) | 登录失败并 raise ValueError |
ZZ_PERCENT | 样例中不存在 | 是 | 正股涨跌幅阈值 | 导入期 KeyError |
ZG_PERCENT | 样例中不存在 | 是 | 相关涨跌幅阈值 | 导入期 KeyError |
REMAIN_SIZE | 样例中不存在 | 是 | 剩余规模筛选阈值 | 导入期 KeyError |
ACCESS_INTERVAL_REALTIME | 样例中不存在 | 是 | 实时档轮询间隔(秒) | 导入期 KeyError |
REDIS_KEY | 样例中不存在 | 是 | 写 Redis 用的键名 | 导入期 KeyError |
redis.uc.host/port/password | 样例只有 redis.qq | 是 | Redis 连接信息 | 导入期 KeyError |
这一栏是本页最重要的信息:monitor/jsl_monitor.py 在模块顶层就读取 11 个配置键,其中 ZZ_PERCENT、ZG_PERCENT、REMAIN_SIZE、ACCESS_INTERVAL_REALTIME、REDIS_KEY 五个在官方样例配置里根本不存在,另有 redis.uc 子对象也不存在(样例只给了 redis.qq)。也就是说:照官方样例配置填完,这个监控脚本仍然会在 import 阶段直接崩掉。反过来说,样例里的 MONITOR_PERCENT 在已下载的源码里没有被读取——配置文件与代码已经互相脱节。
Rockyzsu/stock · 推送渠道
Rockyzsu/stock 接的四条推送渠道有哪些:两条完整、两条有坑
| 渠道 | 实现函数 | 目标服务 | 所需凭证 | 当前状态 |
|---|---|---|---|---|
| 企业微信 | configure/util.py 的 send_message_via_wechat() | qyapi.weixin.qq.com:/cgi-bin/gettoken 再 /cgi-bin/message/send | enterprise_wechat 的 corpid / corpsecret / agentid / userid | 链路完整;需企业微信应用权限 |
| 邮箱(阿里云企业邮) | send_from_aliyun() 与 send_from_aliyun_ssl() | smtp.qiye.aliyun.com:25 端口与 465(SSL)两条路径 | aliyun 的账号与密码;收件人默认取 mail.qq.user | 链路完整;端口被拦时 SSL 分支会回退到 25 端口 |
| Server 酱 | notify() | https://sc.ftqq.com/{WECHAT_ID}.send | WECHAT_ID(SendKey) | 源码自己加了提醒:warnings.warn("该接口需要收费了,请使用企业微信") |
| 短信(Twilio) | send_sms() | Twilio Client | twillio.twilio_account_sid / twilio_auth_token | 存在 bug:代码写成 config.twilio_account_sid(把 dict 当对象用),且样例键名拼作 twillio |
| QQ 邮箱(另一条独立实现) | utils/push_msn.py 的 MailSend.send_txt() | smtplib.SMTP_SSL('smtp.qq.com', 465) | data.cfg 里的 from_mail / password / to_mail(被 .gitignore 排除) | 可读;但整个文件是 Python 2 语法,且 type=='wechat' 分支是空的 pass |
四条渠道的成熟度差别很大:企业微信与阿里云邮箱是完整链路;Server 酱已被源码作者标注为需要收费;Twilio 短信有明确的属性访问 bug;utils/push_msn.py 是另一套独立的邮箱实现,但整体是 Python 2 代码(用 email.Utils 与 long()),且有分支未实现。
Rockyzsu/stock · 落地步骤
跑通 Rockyzsu/stock 监控的七个步骤与顺序
把监控跑起来的最小顺序
- 先确认推送渠道可用:单独调用一次企业微信发送函数,确认能收到消息。预期输出:手机/PC 上收到一条测试消息。推送不通的时候调试监控是浪费时间。
- 补齐配置键:在
config.json的jsl_monitor下补ZZ_PERCENT、ZG_PERCENT、REMAIN_SIZE、ACCESS_INTERVAL_REALTIME、REDIS_KEY,并在redis下补一个uc子对象。预期输出:python -c "import monitor.jsl_monitor"不再抛KeyError。 - 启动 Redis 并确认可写:确认
redis.uc的 host/port 指向真实服务。预期输出:手动set一个键成功。 - 处理集思录登录:确认本地有 Node 运行时(
execjs依赖它),并用真实账号跑一次datahub/jsl_login.py。预期输出:打印「登录成功」。 - 先跑最轻的封板监控验证骨架:
monitor/ceiling_break.py只依赖实时行情与推送,不依赖数据库。预期输出:终端按time.sleep间隔持续打印买一量。 - 再跑可转债监控并观察一轮完整循环:确认阈值命中时 Redis 有键、推送有消息。预期输出:Redis 里出现带 60 秒 TTL 的键,同时收到通知。
- 把它挂到计划任务:Windows 用任务计划程序,Linux 用 cron。预期输出:非交易时段不会误触发(脚本本身有交易日判断函数可复用)。
Rockyzsu/stock · 失效场景
Rockyzsu/stock 监控失效有哪些场景:八类问题与排查动作
| 失效场景 | 现象 | 根因 | 排查动作 |
|---|---|---|---|
| 脚本一 import 就崩 | KeyError: 'ZZ_PERCENT' 之类 | 配置键缺失(5 个键 + redis.uc 不在官方样例里) | 对照本页参数表逐键补齐 |
| 集思录登录失败 | 脚本抛 ValueError('登录失败') | 账号密码错、或 execjs 找不到 Node 运行时导致加密失败 | 先修 Node,再核对账号 |
| 推送一条都收不到 | 终端无报错但手机无消息 | WECHAT_ID 为空、或企业微信 corpsecret 无发消息权限 | 打印发送函数的返回值与响应体 |
| 日志文件报路径错误 | loguru 初始化失败 | ReachTargetJSL 用相对路径 ../log/<类名>.log,而 log/ 目录不在仓库中 | 先手工创建 log/ 目录,或在正确的工作目录下运行 |
| 监控在非交易时段乱报警 | 收盘后仍收到通知 | 轮询循环本身不判断交易时段 | 在循环里加交易日与时间段判断 |
| 同一个信号被反复推送 | 同一只标的连发多条 | 去重窗口(EXPIRE_TIME,样例 1800 秒)过短或未生效 | 调大去重窗口,或确认 HistorySet 被正确初始化 |
| 封板监控阈值不贴合实际 | 该报的不报 | 源码把「买一量 ≤ 10000」写成常量,不随标的流通盘调整 | 按标的市值改写阈值逻辑 |
| Redis 键读不到 | 下游拿不到快照 | 键在写入后 expire(key, 60),60 秒即过期 | 下游需在过期前读取,或自行调整 TTL |
排查顺序建议:先看「是不是 import 期就崩」(配置类问题),再看「有没有数据」(登录态与网络问题),最后看「为什么没推送」(渠道与权限问题)。这个顺序对应三类完全不同的原因,混在一起排查会绕远路。
FAQ
关于 Rockyzsu/stock 的常见问题
monitor/ 为什么 README 里完全没提?
monitor/,而该目录有 9 个 Python 脚本、是项目自动化能力的核心。推测层面的原因(重构期间漏更新)不写进页面。这也正是本站做「版本核验」的原因——只看 README 会漏掉整个监控能力。以固定提交 9478dee528cc 的目录树为准。监控是实时的吗?多久轮询一次?
ACCESS_INTERVAL(样例值 20 秒)控制,实时档由 ACCESS_INTERVAL_REALTIME 控制(该键不在样例配置里,需要自己补)。所以实际频率取决于你的配置与上游站点的限频规则。以源码与实际配置为准。监控会自己下单吗?
monitor/ 里任何脚本都不调用下单接口,它的终点是「写 Redis」或「发通知」。下单能力在 trader/auto_trader.py 里,是另一条独立链路,而且依赖被 .gitignore 排除的凭证文件。详见交易边界页。为什么会有五个配置键不存在?
jsl_monitor.py 在模块顶层读取 11 个键,而 sample_config.json 的 jsl_monitor 段只有 5 个键;反过来样例里的 MONITOR_PERCENT 在已下载的源码中没有被读取。这是长期迭代中「配置先行、代码后改」或反之的典型结果。处理方式很简单:按代码读取的键补齐配置,而不是按样例配置去改代码。推送渠道该选哪个?
push_msn.py 的服务器地址也可以。这些监控和 EasyClaw 的监控技能有什么区别?
非交易时段跑监控会不会有问题?
configure/util.py 的 is_weekday_today()、TushareUtil 的交易日历),建议在循环里显式加上判断。