放量上涨选股器
只做选股与买卖节点提示:无虚拟资金、无模拟持仓、无模拟成交、无手续费。
一、快速开始
SKILL="C:/Users/admin/.workbuddy/skills/放量上涨选股器"
PY="C:/Users/admin/.workbuddy/binaries/python/versions/3.13.12/python.exe"
"$PY" "$SKILL/scripts/stock_picker.py" check-day # 先确认今天是否交易日
"$PY" "$SKILL/scripts/stock_picker.py" run # 按当前时间跑
"$PY" "$SKILL/scripts/stock_picker.py" run --slot 14:00
"$PY" "$SKILL/scripts/stock_picker.py" run --now "2026-10-20 10:30" # 指定时刻
"$PY" "$SKILL/scripts/stock_picker.py" run --pool-limit 50 # 小样本试跑
"$PY" "$SKILL/scripts/stock_picker.py" run --json # 机器可读摘要
"$PY" "$SKILL/scripts/stock_picker.py" task-plan # 生成四条自动化任务计划
可选:export IWENCAI_API_KEY=<key> 后成分股名单取自 i问财;不配则自动降级到公开全A股名单源。
二、买入信号
- 条件(只用已完成日线,D1 = 最近一个已完成交易日,D2 = D1 前一交易日):
D1 成交量 ≥ D2 成交量 × 2且D1 收盘价 ≥ D2 收盘价 × 1.05,两个条件均含边界。 - 股票池 = 运行当日沪深全A股,同一交易日只取一次快照。
- 同一只股票同一信号只登记一次;多只候选按代码升序处理。
- 参考价取 D1 收盘价;盘中实时价只用于展示与盘中预警,不作收盘价、不参与判定。
- 停牌、数据缺失、行情过期的股票不产生买入信号,报告中注明原因。
三、卖出信号与 T+1
- 维护信号观察名单:曾触发买入信号、尚未触发对应卖出信号的股票,用于确定卖出复核对象。
- 每个交易日首次运行时记录本次槽位;首次运行在下午槽位时,报告注明实际取自哪个槽位。
- 卖出条件:观察名单内
D1 收盘价 < MA5(D1)记一次卖出信号,等于不卖。
MA5 取含 D1 在内的最近五个已完成收盘价,不足五根不触发。 - T+1:当日新买入的股票当日不得卖出;当日已卖出的股票当日不回买。
- 触发卖出后该股当日移出观察名单;同一事件ID 不重复登记。
- 盘中实时价低于 MA5 只作盘中预警,收盘确认前不算正式卖出信号。
- 当日已登记买入信号的股票同日不再登记卖出信号,反之亦然。
- 观察名单内停牌、数据缺失、行情过期的股票保留在名单中,不做卖出判定,报告注明原因。
四、状态文件与去重
- 路径
outputs/volume_up_strategy/state/signal_state.json,含:
成分股快照、快照取自的槽位、已处理槽位列表、signal_history、watchlist、
每只股票最近一次买入信号、最后更新时间。 - 事件ID = 交易日 + 股票代码 + 买卖方向(不含槽位);同一事件ID 只登记一次。
- 先写临时文件,写完再原子替换。
- 损坏或格式不符时禁止登记新信号并报错:不清空、不重置、不擅自初始化。
五、输出报告(每次一份整体报告)
outputs/volume_up_strategy/reports/vol_up_signal_YYYYMMDD.html,同一交易日后续槽位覆盖刷新。- 只收录本次运行触发买入或卖出信号的股票;无信号时正文只显示一行
「今日无符合策略要求的买入或卖出信号」。 - 标题栏:策略名称、报告日期、运行槽位、D1 与 D2 日期、生成时间 + 两个计数徽标。
- 买入信号表(代码升序):代码、简称、信号日期、D1 收盘、D2 收盘、较 D2 涨幅、量比、
MA5、MA5/MA15 排列、盘中实时价、备注。 - 卖出信号表(代码升序):代码、简称、信号日期、D1 收盘、MA5、较 MA5 偏离、D1 量比、
MA5/MA15 排列、盘中实时价、备注。 - 配色:浅底深字,涨与买入红色、跌与卖出绿色。
六、运行顺序(不可颠倒)
交易日 → 读状态(损坏则禁登记)→ 取成分股快照 → 取日线定 D1/D2 → 判定买入
→ 判定卖出与盘中预警 → 原子写状态 → 生成整体报告 → 输出摘要。
D1/D2 确定方式:取该股日线序列,剔除当天尚未完成的K线,剩下最后一根为 D1、
倒数第二根为 D2。禁止用「今天日期减一天」推算 D2。
七、运行摘要
运行时间与槽位、D1/D2 日期、本次新增买入信号、本次卖出信号、盘中预警数、
异常/拦截标的及原因、观察名单只数、报告路径,末尾附重点标的清单。
八、数据源
- 交易日判据与 D1/D2:上证指数
sh000001日线。 - 成分股:i问财「全部A股」→ 降级 东方财富全A股列表 → 新浪行情中心。
- 日线量价与 MA:腾讯自选股公开接口,同一交易日按 D1 缓存,四槽位只全量拉一次。
- 盘中实时价:腾讯批量快照。请求逐只间隔约 0.25 秒。
- 节假日表
scripts/holidays.json每年更新:
python scripts/stock_picker.py sync-holidays --year 2027。
九、自动化部署
四个槽位各建一条独立任务,周一至周五 09:35 / 10:30 / 13:00 / 14:00。
单条定时规则的「小时」与「分钟」是笛卡尔积,无法表达四个不同时点,因此不能合并。
先跑 task-plan 取到四条任务的名称、rrule 与 prompt,再逐条建立。
非交易日由脚本自行 [SKIP] 跳过。
文件结构
放量上涨选股器/
├── SKILL.md
├── scripts/
│ ├── stock_picker.py # 主引擎(check-day / run / task-plan / sync-holidays)
│ ├── make_tasks.py # 生成四条自动化任务的计划 JSON
│ ├── config.json # 阈值、槽位、并发、时限参数
│ └── holidays.json # A股休市日
└── assets/report.html # 整体报告模板
outputs/volume_up_strategy/
├── state/signal_state.json
├── cache/kline_YYYYMMDD.json
└── reports/vol_up_signal_YYYYMMDD.html
实现要点
| 规格 | 关键实现 |
|---|---|
| 三重交易日判定 | 非周末 + 不在节假日表 + 上证指数当日K线存在(check_trading_day) |
| D1/D2 | 剔除 date > D1 的未完成K线后取最后两根,见 metrics() |
| 二.1 买入 | v1 >= v2*2 and c1 >= c2*1.05(含边界),要求 D1/D2 量价齐全且无异常 |
| 三.3 卖出 | 仅对 watchlist,c1 < ma5(严格小于);MA5 不满 5 根不触发 |
| 三.4 T+1 | 当日买入代码不登记卖出;当日卖出代码不登记买入 |
| 四.2 去重 | 事件ID {交易日}_{代码}_{BUY\|SELL},写入前比对 signal_history |
| 四.4 损坏保护 | load_state() 返回 ok=False → 跳过登记与写入,报告只读生成 |
| 五 报告 | assets/report.html + build_body();无信号时正文只有一行提示 |
已知坑
- D1 不能取今天未收盘的K线:盘中跑(09:35~14:00)必须排除当天,否则会把实时量价当 D1。
引擎以「运行时刻 ≥ 15:00」作为当天日线已完成的判据。 - 东方财富接口:纯 urllib 默认 SSL 上下文易
Remote end closed,需显式传
ssl.create_default_context(),并在push2 / 82.push2 / 7.push2之间轮换;
该源对本机 IP 限流时三个域名会同时失效(curl 也不通),属临时封禁,降级到新浪即可。 - i问财配额:当天用尽返回 401,引擎自动降级,摘要打
⚠️ 自动降级。 - task-plan 的 Python 路径:默认取当前解释器,如需固定托管运行时用
--python-exe指定。 - 观察名单会累积:买入后一直不跌破 MA5 的股票会长期留在名单里复核,属策略设计本身。