第 7 章 · 01 定增公告监控:基于事件而非行情 本节摘要:本节讲 Sequoia-X 第 7 套策略——定增公告监控。这是七套策略里唯一的事件驱动策略:它不读行情数据,而是从 akshare 拉取东方财富的「全部增发」数据,筛出最近 7 天内发布过定向增发(区别于公开增发)公告的股票。本节会先讲 A 股定增的基础知识(什么是定增、为什么值得关注、定向 vs 公开的区别);再讲 akshare 数据源——它与 baostock 完全独立,两条链路并行不悖;然后讲 Sequoia-X 实现的三个细节——只保留定向增发、按时间窗口筛选、代码去重;最后用一段可运行的教学示例(用合成数据模拟公告表)演示完整流程。 内容来源:原项目定增公告策略模块精读。
本节摘要:本节讲 Sequoia-X 第 7 套策略——定增公告监控。这是七套策略里唯一的事件驱动策略:它不读行情数据,而是从 akshare 拉取东方财富的「全部增发」数据,筛出最近 7 天内发布过定向增发(区别于公开增发)公告的股票。本节会先讲 A 股定增的基础知识(什么是定增、为什么值得关注、定向 vs 公开的区别);再讲 akshare 数据源——它与 baostock 完全独立,两条链路并行不悖;然后讲 Sequoia-X 实现的三个细节——只保留定向增发、按时间窗口筛选、代码去重;最后用一段可运行的教学示例(用合成数据模拟公告表)演示完整流程。
内容来源:原项目定增公告策略模块精读。
⚠️ 风险提示:本策略是「信息触达」的辅助——定增公告常被「内幕资金」先一步买入,公告日追入容易接盘。请把本策略结果视为「信息提示」而非「买入信号」。
阅读完本节,你应当能够:
定向增发(简称「定增」)是 A 股上市公司常用的再融资方式:
上市公司向特定的少数投资者(机构、关联方、战略伙伴等)发行新股,筹集资金。
与「公开增发」(向全市场发行)的关键区别:
| 维度 | 定向增发 | 公开增发 |
|---|---|---|
| 发行对象 | 特定(机构、关联方) | 不特定(全市场) |
| 发行价 | 协商(常低于市价) | 询价 |
| 监管要求 | 较宽松 | 严格 |
| 信息披露 | 定增方案 / 进度公告 | 招股书 |
| 市场关注度 | 高(暗示投资逻辑) | 中 |
为什么值得关注:
为什么 Sequoia-X 用 akshare 拉定增公告?
| 维度 | akshare | baostock |
|---|---|---|
| 数据类型 | 事件型(公告、资金流、新闻) | 行情型(K 线、财务) |
| 实时性 | 较好(聚合多源) | 一般(隔日) |
| 接口 | 简单(ak.xxx_em()) |
简单(bs.query_xxx) |
| 在 Sequoia-X 中 | 定增公告策略 | 数据引擎 / 海龟策略 |
Sequoia-X 的策略层两条数据链路完全独立:
这是 Sequoia-X 架构的精妙之处——技术面策略和事件策略完全不共享数据——可以独立优化、独立替换、独立失败。
Sequoia-X 的定增策略核心实现是**「拉 → 筛 → 去重」**三步:
def run(self) -> list[str]: # 1. 拉:akshare 拉全市场增发数据 df = ak.stock_qbzf_em() # 东方财富 - 全部增发 # 2. 筛:只保留「定向增发」(排除公开增发) df = df[df["发行方式"] == "定向增发"] # 3. 时间窗:只保留最近 7 天内的公告 cutoff = today - timedelta(days=7) df = df[df["发行日期"].dt.date >= cutoff] # 4. 去重:同一只票可能有多次定增 symbols = df["股票代码"].unique().tolist() return symbols
df = df[df["发行方式"] == "定向增发"]
为什么排除「公开增发」?
「定向增发」过滤后留下的标的质量更高。
cutoff = today - timedelta(days=7) df = df[df["发行日期"].dt.date >= cutoff]
为什么是 7 天?
7 天是「覆盖最新一周」的经验值。
# 同一只票可能有多次定增(一年内多次发行) symbols = df["股票代码"].unique().tolist()
A 股允许上市公司一年内多次定增——同一只票可能有多行数据。Sequoia-X 用 unique() 自然去重——避免「同一只票在飞书消息里出现多次」。
这是一个小但重要的细节——去重让推送更清爽。
akshare 的真实接口在沙箱中可能受限,下面用合成数据完整演示策略的三步筛选逻辑:
# private_placement_demo.py # 可运行:定增公告策略模拟 import random from datetime import date, timedelta def fake_stock_qbzf_em() -> list[dict]: """模拟 akshare.stock_qbzf_em() 的返回数据。""" today = date.today() return [ # 近期定向增发(应保留) {"股票代码": "000001.SZ", "股票名称": "平安银行", "发行方式": "定向增发", "发行日期": today - timedelta(days=1)}, {"股票代码": "600519.SH", "股票名称": "贵州茅台", "发行方式": "定向增发", "发行日期": today - timedelta(days=3)}, {"股票代码": "300750.SZ", "股票名称": "宁德时代", "发行方式": "定向增发", "发行日期": today - timedelta(days=6)}, # 同一只票 1 年内多次定增(应去重) {"股票代码": "000001.SZ", "股票名称": "平安银行", "发行方式": "定向增发", "发行日期": today - timedelta(days=2)}, # 公开增发(应排除) {"股票代码": "601318.SH", "股票名称": "中国平安", "发行方式": "公开增发", "发行日期": today - timedelta(days=1)}, # 超过 7 天的旧公告(应排除) {"股票代码": "002594.SZ", "股票名称": "比亚迪", "发行方式": "定向增发", "发行日期": today - timedelta(days=15)}, {"股票代码": "600036.SH", "股票名称": "招商银行", "发行方式": "定向增发", "发行日期": today - timedelta(days=30)}, ] def detect_private_placement(rows: list[dict], lookback_days: int = 7) -> list[str]: """Sequoia-X 定增策略的核心筛选逻辑。""" today = date.today() cutoff = today - timedelta(days=lookback_days) # 1. 发行方式 = 定向增发 rows = [r for r in rows if r["发行方式"] == "定向增发"] # 2. 时间窗口 rows = [r for r in rows if r["发行日期"] >= cutoff] # 3. 提取代码(去掉交易所后缀,纯 6 位数字) symbols_with_suffix = [r["股票代码"] for r in rows] symbols = list(set(s.split(".")[0] for s in symbols_with_suffix)) # 自动去重 return sorted(symbols) if __name__ == "__main__": raw = fake_stock_qbzf_em() selected = detect_private_placement(raw) print(f"近 {7} 天内定向增发(去重后)共 {len(selected)} 只:") for s in selected: print(f" {s}")
预期输出:
近 7 天内定向增发(去重后)共 3 只: 000001 300750 600519
这段代码清晰展示:三个筛选步骤(定向增发 + 7 天窗口 + 去重)协同工作,把 7 条原始数据筛成 3 只入选标的。
如果你的环境有 akshare 且能访问东方财富,真实接口长这样:
import akshare as ak # 拉全市场增发数据(东方财富) df = ak.stock_qbzf_em() # 字段包括:股票代码、股票名称、发行方式、发行日期、增发价格、增发数量等 print(df.columns.tolist()) # ['股票代码', '股票名称', '发行方式', '发行日期', '增发价格', '增发数量', ...] # 筛选 + 提取代码的逻辑与上面 mock 数据完全相同
ak.stock_qbzf_em()的返回字段可能随 akshare 版本变化——Sequoia-X 用的是稳定的字段名(股票代码、股票名称、发行方式、发行日期),但新增字段可能影响列名解析。生产环境建议用 try/except 包装,字段变化时优雅降级。
定增公告常被「内幕资金」先一步买入:
定增方案敲定 │ ├── 内幕资金(定增对象)→ 提前建仓 │ ▼ 公告发布日 ← 你看到的 │ ▼ 公告次日 ← 股价常高开(**你追入的位置**)
所以 Sequoia-X 不把定增当买入信号,而是当**「信息触达」**——告诉用户「这家公司最近有定增」,让你自己判断要不要研究、要怎么操作。
这是「工程师的克制」——给信息,不给结论。
| 策略 | 信号类型 | 数据源 | 适配市况 | 触发频率 |
|---|---|---|---|---|
| 海龟突破 | 价格趋势 | baostock | 强趋势 | 日 |
| 均线金叉放量 | 价格趋势 | baostock | 趋势启动 | 日 |
| 高窄旗形 | 形态结构 | baostock | 趋势中继 | 日 |
| 涨停洗盘 | 形态结构 | baostock | 强势调整 | 日 |
| 上升趋势跌停 | 形态结构 | baostock | 错杀机会 | 日 |
| RPS 相对强度 | 相对强度 | baostock | 牛市/反弹 | 日 |
| 定增公告 | 事件驱动 | akshare | 信息扩散期 | 不定期 |
七套策略数据源不同、信号类型不同、市况适配不同——互补而非互斥。
| 场景 | 策略表现 |
|---|---|
| 信息扩散期(公告刚发布) | 信号最有效——市场还在消化 |
| 内幕消化期(公告前已大涨) | 容易接盘——内幕资金已高位出货 |
| 定增失败(董事会撤回) | 假信号——公告有过但实际未实施 |
| 定增中止(市场环境变化) | 历史公告仍被策略筛出 |
不建议把定增策略作为「独立买入信号」,应作为「研究提示」。
定增公告策略 ✅ ← 本节 │ ▼ 下一节(第 02 节)飞书卡片:把选股结果变成「**看一眼就懂**」的消息
配套教学脚本:
images/private_placement_demo.py——用合成数据演示定增筛选。
下一节,我们把选股结果从「一组代码」变成「飞书卡片」——讲 Sequoia-X 的触达层。