金融科技研究:如何定义公司公告中的事件
从国际金融数据平台的公开分类与 API 出发,讨论如何把公司公告转化为可检索、可关联、可解释、可追溯的事件数据。
一名投资者问:“今天有哪些公司发生了重大的股东卖出事件?”
这个问题听起来并不复杂。可是,如果信息系统只有公告标题、正文和下载接口,它就很难直接回答。系统不仅要找到当天发布的所有公告,还要识别“股东卖出”对应的规范概念,判断哪些事件足够重大,把同一减持计划的多次披露关联起来,并为每个结论提供可以核验的原文证据。
传统公告检索解决的是“哪些文档包含这些词”。事件搜索需要回答的则是“现实世界里发生了什么”。两者之间隔着一层并不显眼、却非常关键的基础设施:公司事件层。
本文从金融数据平台公开的分类、Schema 和 API 出发,讨论公司公告事件应该如何定义,以及一个面向中文公告的智能搜索引擎应当采用怎样的颗粒度。
公告不是事件
公告是一份文档,事件是对现实变化的结构化描述。二者并非一一对应。
一份《关于控股股东减持股份计划的公告》可能同时包含以下事实:
- 控股股东准备减持;
- 拟采用集中竞价和大宗交易两种方式;
- 减持期间尚未开始;
- 最大减持比例为公司总股本的 2%;
- 减持不会导致控制权变化。
半年之后,公司可能继续发布进展公告、数量过半公告、实施完毕公告或者提前终止公告。这些文档描述的不是多项互不相关的事件,而是同一项减持计划的不同生命周期节点。
反过来,一份年度报告也可能产生多项事件:业绩变化、分红方案、会计差错更正、管理层变动和重大诉讼进展等。因此,系统至少需要区分三种对象:
flowchart LR
D[公告文档] --> X[事实抽取]
X --> E1[事件记录一]
X --> E2[事件记录二]
D2[后续公告] --> X2[事实抽取]
X2 --> E3[事件进展]
E1 --> P[同一事件计划]
E3 --> P
- 文档 Document:公告原文及其版本、来源和发布时间;
- 事件 Event:一次披露所表达的结构化事实;
- 事件计划 Event Program:跨越多份公告的持续事项,例如一项减持计划或一笔并购交易。
如果不建立这三个层次,搜索结果很容易重复计数,也无法回答“这件事后来怎么样了”。
各个平台到底定义了多少类事件
公开资料里的数字差异很大:有的平台只有 4 类,有的平台有 60 多类,还有的平台声称能识别 7,400 多类。原因不是谁做得更认真,而是它们统计的层级不同。
| 平台或产品 | 公开数量 | 分类范围 | Schema 公开程度 |
|---|---|---|---|
| FactSet Event Calendar | 12 种事件类型 | 业绩会、股东大会、分红、拆股等日历事件 | API 公开完整枚举和字段 |
| Alpaca Corporate Actions | 4 个一级类型、9 个子类型 | 分红、合并、分拆、拆股 | SDK 公开完整枚举和对象模型 |
| LSEG Corporate Actions | 8 个请求筛选开关、50 多种 ISO 15022 事件类型、80 多种通知类型 | 标准化公司行动 | 公开 API 请求结构与产品覆盖数量 |
| Intrinio Corporate Actions | 45 多类 | 国际公司行动 | 提供 API,完整枚举未完全公开 |
| Bloomberg Corporate Actions | 50 种 | 全球公司行动 | 公司行动日历公开数量,详细字典面向客户 |
| S&P Global Managed Corporate Actions | 60 多类 | 全球公司行动 | 公开数量和交付方式,详细字典面向客户 |
| FactSet Alexandria | 31 类 | 新闻中的公司语义事件 | 公开数量和代表性类型 |
| RavenPack | 7,400 多类 | 新闻语义、主体角色和行业事件模板 | 公开总体数量,分类体系为专有资产 |
这些数字不能横向直接排序。
日历事件通常只有十余类
FactSet 的公开 Event Calendar SDK 定义了 12 个枚举,包括 Earnings、Guidance Call、Shareholders Meeting、Conference、Dividend 和 Split 等。这一层解决的是“公司什么时候开会、披露业绩或进行标准公司行动”,并不覆盖股东减持、诉讼、监管处罚和重大合同。
所以,“12 种”并不代表 FactSet 只能识别 12 种公司变化,而只反映了这一项 API 的覆盖范围。
公司行动产品通常覆盖数十种类型
LSEG 的 DataScope Select API 标准提取请求公开了 8 个事件筛选开关:资本变化、分红、业绩、并购、面值变化、公开股权发行、流通股本变化和投票权变化。其产品资料同时表示,系统覆盖 50 多种 ISO 15022 标准事件类型,以及 80 多种通知类型。
Bloomberg 的公司行动日历公开覆盖 50 种公司行动类型;S&P Global 的 Managed Corporate Actions 数据集覆盖 60 多种事件类型;Intrinio 的 Corporate Actions API 则覆盖 45 多种。虽然统计口径并不完全相同,但这些产品都采用数十种稳定业务类型来组织标准公司行动。
但公司行动仍然只是公司事件的一部分。重大合同、管理层离任、安全事故、产品召回和监管调查,通常不会被完整地归入 Corporate Actions。
新闻语义事件可以扩张到数千类
FactSet Alexandria 采用相对克制的体系,将新闻归入 31 类事件,例如业绩、并购、业绩指引、经营变化、管理层变化、临床试验和政府互动。
RavenPack 则公开表示能够识别 7,400 多种事件类型。这里的“类型”已经深入到语义层:谁起诉了谁、谁在交易中扮演收购方、盈利数字是多少、评级机构做了什么,以及不同行业中的专有动作。它更接近大量结构化语义模板,而不是产品导航中向用户展示的 7,400 个筛选项。
因此,事件数量至少要区分以下层级:
| 层级 | 常见数量 | 用途 |
|---|---|---|
| 事件大类 | 8—20 | 产品导航、订阅和粗粒度过滤 |
| 标准事件类型 | 30—200 | 用户查询和 API 中稳定的业务概念 |
| 子类型与属性维度 | 100—500 | 描述方式、主体角色、状态和影响 |
| 内部抽取模板 | 数百至数千 | 识别不同文风、句式和行业表达 |
国内平台提供了什么
国内平台的公开 Schema 明显少于国际数据服务商。
东方财富 Choice 的官方用户指南展示了行动事件库。股票目录下可见基本资料、交易、股本股东、业绩披露、IPO、增发、配股、分红、重大事项、股权激励、经营事件、并购重组、退市和三板转市等 14 个一级目录。这里既包含事件,也包含“基本资料”和“交易”这样的数据领域,因此不能把 14 直接理解为事件类型数量。
Wind 和 iFinD 的公开网页没有提供完整的事件枚举。能够确认的是,它们拥有股东增减持、并购重组、定向增发、股权质押、股东大会、解禁和重大事项等专题数据;具体字段和数据字典通常属于终端或数据接口权限的一部分。
Tushare 的优势是把许多常用数据做成可调用的专题接口,例如分红、回购、股东增减持、质押、大宗交易、解禁、停复牌、业绩预告和业绩快报。它更像一组结构化数据接口,而非一套统一的公司事件模型。使用者仍然需要知道应该调用哪个接口,并自行完成事件关联、重大性判断和自然语言映射。
这也说明,新的公告搜索产品不必复制所有历史数据表。更有价值的方向,是在不同专题之上建立一个稳定、统一、可解释的事件查询层。
事件分类不应是一张无限增长的枚举表
假设系统要表示“控股股东通过集中竞价减持,计划已经实施完毕”。最直接但也最危险的做法,是把整句话定义成一个叶子类型:
controlling-shareholder-auction-reduction-completed
继续扩展后,很快还会出现:
actual-controller-block-trade-reduction-planned
executive-auction-reduction-in-progress
major-shareholder-agreement-transfer-completed
shareholder-judicial-passive-reduction-completed
主体角色、交易方式、主动或被动、生命周期阶段相互组合,类型数量会指数式膨胀。更合理的模型,是把稳定的业务概念与可组合维度分开:
{
"event_family": "ownership_change",
"event_type": "shareholder_reduction",
"stage": "completed",
"holder_role": "controlling_shareholder",
"method": "auction",
"is_passive": false
}
其中:
-
event_family表示大类; -
event_type表示稳定、可查询的标准事件; -
event_subtype在需要时进一步细分子类型; -
stage表示生命周期; -
holder_role、method等字段表示事件维度。
这样,用户既可以搜索所有股东减持,也可以进一步筛选“控股股东”“集中竞价”或者“已经完成”,而系统不需要为每种组合维护一个独立类型。
建议采用四层事件体系
一个面向中国公司公告的第一版系统,可以采用以下颗粒度。
第一层:12 至 16 个事件大类
建议的大类包括:
- 股东与持股变动;
- 控制权变更;
- 质押、冻结与司法处置;
- 回购与注销;
- 分红送转;
- 业绩与财务披露;
- 股权及债务融资;
- 并购重组与资产交易;
- 重大合同与经营项目;
- 诉讼仲裁;
- 监管调查与处罚;
- 债务、违约与信用评级;
- 董监高与公司治理;
- 股权激励与员工持股;
- 停复牌、风险警示与退市;
- 经营异常、安全事故与产品事件。
大类主要用于产品导航、订阅和权限管理,不必承担全部业务表达。
第二层:40 至 60 个标准事件类型
这一层应当稳定地出现在搜索接口中,例如:
shareholder_reduction 股东减持
shareholder_increase 股东增持
control_change 控制权变更
equity_transfer 股权转让
share_pledge 股权质押
share_freeze 股份冻结
judicial_disposal 司法处置
share_repurchase 股份回购
earnings_forecast 业绩预告
earnings_revision 业绩预告修正
private_placement 定向增发
merger 合并
major_asset_restructuring 重大资产重组
major_contract 重大合同
litigation 诉讼仲裁
regulatory_investigation 监管调查
regulatory_penalty 监管处罚
debt_default 债务违约
executive_change 董监高变动
risk_warning 风险警示
delisting 退市
第一期不必对所有类型平均用力。股东变化、业绩、并购、诉讼、监管、债务和退市等高价值领域,应优先做到字段完整和关系准确。
第三层:100 至 150 个子类型与属性维度
这一层描述:
- 计划、进行中、完成、终止和修订;
- 集中竞价、大宗交易、协议转让和司法处置;
- 实际控制人、控股股东、持股 5% 以上股东和董监高;
- 主动或被动;
- 境内或境外;
- 是否跨越法定持股阈值;
- 是否可能引起控制权变化。
这些维度决定了事件能否支持真正有用的组合查询。
第四层:数百个内部抽取模板
用户只需要理解“股东减持”,但抽取系统必须理解:
- “拟减持不超过公司总股本的……”;
- “通过集中竞价累计减持……”;
- “持股比例由 5.23% 降至 4.98%”;
- “因司法强制执行导致被动减持”;
- “减持数量已过半”;
- “减持期限届满”;
- “决定提前终止本次减持计划”。
这些句式应当映射到同一个标准事件,再通过阶段和属性表达差异。内部模板可以不断增长,而公开 API 的核心类型必须保持稳定。
生命周期是事件系统的核心
Alpaca 的 Corporate Actions 模型提供了一个值得参考的设计:多次公告可以通过稳定的 corporate_action_id 归属于同一项公司行动。
中文公告系统同样需要一个 event_program_id。以减持为例,它可能经历:
stateDiagram-v2
[*] --> 计划披露
计划披露 --> 实施中
实施中 --> 数量过半
实施中 --> 时间过半
数量过半 --> 实施完成
时间过半 --> 实施完成
计划披露 --> 提前终止
实施中 --> 提前终止
实施完成 --> [*]
提前终止 --> [*]
系统要同时保留两种事实:
- 每一次公告当时表达了什么;
- 截至某个时间点,这项计划的最新状态是什么。
这要求数据具备版本和时点属性。后续公告不能简单覆盖旧记录,否则用户无法回测“当时市场已经知道什么”。
“重大”是一种判断,不是一种事件
用户会问“重大减持”“重大诉讼”或“重大合同”,但“重大”不应该成为新的事件类型。它应当由一组可解释规则和模型结果共同表达:
{
"materiality": {
"level": "high",
"score": 91,
"reasons": [
"controlling_shareholder",
"planned_ratio_above_1_percent",
"possible_threshold_crossing"
]
}
}
股东减持的重大性可以考虑:
- 减持主体是否为实际控制人或控股股东;
- 计划和实际减持比例;
- 是否跨越 5% 等法定持股阈值;
- 是否可能改变第一大股东或控制权;
- 涉及金额和相对市值;
- 多名一致行动人是否同时减持;
- 是否属于司法处置或被动减持;
- 是否在敏感窗口集中发生。
结果页面不能只显示一个来源不明的分数,还应解释:“减持主体为控股股东,最大比例为 2.5%,减持后可能接近关键持股阈值。”可解释性本身就是金融数据产品的一部分。
一个可用的统一 Schema
事件对象应采用“通用核心字段 + 事件专属载荷”的结构。下面以股东减持为例:
{
"event_id": "evt_01...",
"event_program_id": "program_01...",
"parent_event_id": null,
"event_family": "ownership_change",
"event_type": "shareholder_reduction",
"event_subtype": "market_sale",
"stage": "plan",
"status": "active",
"issuer_id": "issuer_cn_...",
"security_ids": ["600000.SH"],
"disclosed_at": "2026-08-05T19:32:00+08:00",
"occurred_at": null,
"effective_at": null,
"start_at": "2026-08-20",
"end_at": "2026-11-19",
"subjects": [
{
"entity_id": "entity_...",
"name": "某某集团",
"role": "controlling_shareholder"
}
],
"materiality": {
"level": "high",
"score": 86,
"reasons": [
"controlling_shareholder",
"planned_ratio_above_1_percent"
]
},
"payload": {
"method": ["auction", "block_trade"],
"planned_shares": 30000000,
"planned_ratio": 0.025,
"holding_before_ratio": 0.126,
"holding_after_min_ratio": 0.101,
"is_passive": false,
"may_change_control": false
},
"source": {
"document_id": "doc_01...",
"source_url": "https://...",
"page": 2,
"evidence_spans": [
{
"text": "拟通过集中竞价及大宗交易方式减持不超过三千万股",
"start": 812,
"end": 840
}
]
},
"confidence": 0.97,
"schema_version": "1.0",
"ingested_at": "2026-08-05T19:33:08+08:00"
}
其中有几项不能省略:
-
event_program_id:关联计划、进展、完成和终止; - 多种时间字段:区分披露时间、发生时间和生效时间;
-
subjects和角色:不能只保存一段主体名称文本; -
materiality.reasons:解释为什么被判断为重大; -
evidence_spans:把结构化事实定位回原文; -
schema_version和ingested_at:支持修订、回测和可追溯性。
从自然语言到事件查询
用户的问题:
今天有哪些公司发生了重大的股东卖出事件?
可以被转换为:
{
"time_field": "disclosed_at",
"date": "today",
"event_type": ["shareholder_reduction"],
"materiality_level": ["high", "critical"],
"group_by": "issuer_id",
"deduplicate_by": "event_program_id",
"sort": [
"materiality_score desc",
"disclosed_at desc"
]
}
这一步看似只是自然语言解析,实际依赖前面所有基础工作:
- “今天”默认映射到公告披露时间;
-
“股东卖出”归一到
shareholder_reduction; - “重大”映射到重大性等级和规则;
-
同一减持计划的多份公告按
event_program_id去重; - 公司、股东和证券完成实体消歧;
- 每项结论附带公告原文证据。
如果底层只有向量搜索,系统可能找到语义相似的段落,却难以保证结果完备,也难以证明“今天所有符合条件的公司都已经被找出”。面向监测和筛选的金融搜索需要结构化索引保障召回,语言模型更适合承担查询理解、结果解释和疑难文本抽取。
第一阶段应该做到多大
一个务实的第一版目标是:
- 12 个左右的事件大类;
- 40 至 60 个标准事件类型;
- 100 至 150 个子类型与属性维度;
- 300 至 800 个内部抽取模板;
- 15 至 20 个跨事件通用字段;
- 每个事件大类增加 10 至 30 个专属字段。
但建设顺序比总数量更重要。第一阶段可以优先做深以下事件:
- 股东减持与增持;
- 控制权变更;
- 股权质押、冻结和司法处置;
- 股份回购;
- 业绩预告及修正;
- 并购重组;
- 重大合同和中标;
- 诉讼仲裁;
- 监管调查和处罚;
- 债务违约;
- 董监高变动;
- 风险警示和退市。
每一种事件都应完整解决主体、数值、阶段、关联、重大性和证据,而不是先铺开几百个只有标题标签的类别。
结语
公司公告智能搜索的难点不在于让大模型读懂某一份 PDF,而在于持续处理全市场公告,把同一现实事项在不同时间、不同文档、不同措辞下的披露统一到一个稳定的事件体系中。
成熟平台给出的共同启示是:
- 用户可见的类型应当少而稳定;
- 复杂性应进入属性维度和内部抽取模板;
- 事件必须具有生命周期和稳定标识;
- “重大”必须可解释;
- 结构化结论必须能够回到公告原文;
- 公告时间、事件时间和系统知道该事实的时间必须分开。
类型数量可以逐步扩张,但时间、身份、关系和证据这些底层模型一旦设计错误,后续很难补救。
参考资料
- FactSet Event Calendar API
- Alpaca SDK:Corporate Action 枚举
- Alpaca SDK:Corporate Action Announcement 模型
- LSEG DataScope Select:Corporate Actions API 教程
- LSEG Corporate Actions 产品资料
- Bloomberg Event-Driven Feeds
- S&P Global Managed Corporate Actions
- S&P Global Key Developments
- Intrinio Corporate Actions API
- FactSet Alexandria Contextual Text Analytics
- RavenPack Classification
- 东方财富 Choice 用户指南