【AI+量化实战 #05】财报季的信息洪流:用LLM给业绩预告分类+算事件窗口收益

系列进度:AI+量化实战 #05 / 共 12 篇

痛点开场

财报季一到,交易所的公告像洪水一样涌来。你打开股票软件,弹窗里是"预增""预降""扭亏""减亏",眼睛都看花了,却不知道哪条真值得跟进。

更头疼的是:

  • 预告类型本身不能直接当信号------市场对同样的"预增"反应可能完全不同;
  • 想算"公告后 1 天/5 天涨了多少",要一只一只股票扒日线;
  • 样本一多,手动归类和计算几乎不可能。

今天这篇文章,就把这件事自动化:先用 Python 把业绩预告分类,再批量计算事件窗口收益。LLM 负责理解文本里的"弦外之音",规则负责兜底和规模化。

本文你将得到什么

  1. company_earnings_forecaststock_history 两个接口的配合用法。
  2. 一套把预告类型映射为 positive / neutral / negative 的规则分类器。
  3. 一个 LLM 分类 Prompt 模板(未配置 key 时自动回退到规则)。
  4. 一段已跑通的代码:批量拉预告 → 分类 → 计算 T+0/T+1/T+5 事件窗口收益。
  5. 一组 6 只样本股的真实运行结果,供你参考数据形态。

一、数据从哪来

业绩预告:company_earnings_forecast

字段 含义
abs 预告正文(含利润区间和增速)
type 预告类型,如预增、预升、预降、预亏、减亏等
pdate 预告发布日期
rdate 报告期,如 2024-12-31
old 上年同期 EPS

拿到预告类型还不够。比如"减亏"虽然是亏损,但亏损幅度在收窄,市场情绪可能是中性偏正面;"预降"则是实打实的利空。我们需要把 typeabs 一起交给规则或 LLM 来判断方向。

日线行情:stock_history

字段 含义
t 交易日期
c 收盘价
o / h / l 开盘/最高/最低价

事件窗口收益就是比较"公告日收盘价"和"公告后第 N 个交易日收盘价"的涨跌幅。

python 复制代码
import mairui
import os

api = mairui.Client("LICENCE-66D8-9F96-0C7F0FBCD073")  # 演示证书,演示证书(读者复制即用,无需替换)

# 业绩预告
forecasts = api.company_earnings_forecast("600519")
for f in forecasts[:3]:
    print(f["pdate"], f["type"], f["abs"][:60])

# 日线
hist = api.stock_history("600519")
for row in hist[-3:]:
    print(row["t"], row["c"])

二、规则分类:把预告类型翻译成市场方向

规则分类器适合批量跑全量数据,零成本、可解释、速度快。

python 复制代码
POSITIVE_TYPES = {"预增", "预升", "预盈", "扭亏"}
NEGATIVE_TYPES = {"预减", "预亏", "首亏", "续亏", "大幅下降"}

def rule_label(type_text: str, abs_text: str) -> str:
    t = (type_text or "").strip()
    if t in POSITIVE_TYPES:
        return "positive"
    if t in NEGATIVE_TYPES:
        return "negative"

    # 兜底:从正文中找关键词
    txt = abs_text or ""
    if any(w in txt for w in ("亏损", "下降", "减少", "大幅下滑")):
        return "negative"
    if any(w in txt for w in ("增长", "上升", "盈利", "扭亏为盈")):
        return "positive"
    return "neutral"

三、LLM 分类 Prompt:让 AI 读"弦外之音"

规则再精细也覆盖不了所有表述。比如"业绩同比大幅下降,但环比明显改善"该算什么方向?LLM 更擅长处理这种语义级别的转折。

下面是一个可直接套用的 Prompt:

text 复制代码
请阅读以下 A 股业绩预告,判断其对股价的短期情绪方向,
只返回三个标签之一:positive(利好)/ negative(利空)/ neutral(中性)。

预告类型:{type_text}
预告文本:{abs_text}

标签:

代码封装:

python 复制代码
def llm_classify(abs_text: str, type_text: str) -> str:
    api_key = os.environ.get("LLM_API_KEY", "")
    base_url = os.environ.get("LLM_BASE_URL", "")
    if not api_key or not base_url:
        # 没配 LLM key 时自动回退到规则分类
        return rule_label(type_text, abs_text)
    # 否则调用 openai / 兼容接口
    ...

这样脚本在任何环境下都能跑通,不会因为缺 LLM key 而中断。

四、事件窗口收益怎么算

关键概念:公告日不一定是交易日。如果 pdate 落在周末或假期,事件日要取"公告后的第一个交易日"。

python 复制代码
import pandas as pd

def compute_event_return(hist_df: pd.DataFrame, pdate: str, offset: int):
    """
    offset=0: 事件日相对前一日收盘涨跌幅
    offset=1: T+1
    offset=5: T+5
    """
    hist_df["date"] = pd.to_datetime(hist_df["t"])
    hist_df = hist_df.sort_values("date").reset_index(drop=True)

    # 找到大于等于 pdate 的第一个交易日
    d = pd.to_datetime(pdate)
    pos = hist_df.index[hist_df["date"] >= d]
    if len(pos) == 0:
        return None
    base = pos[0]

    prev = base - 1
    target = base + offset
    if prev < 0 or target >= len(hist_df):
        return None

    base_close = float(hist_df.at[base, "c"])
    prev_close = float(hist_df.at[prev, "c"])
    target_close = float(hist_df.at[target, "c"])

    if offset == 0:
        return (base_close - prev_close) / prev_close * 100
    return (target_close - base_close) / base_close * 100

对每一只样本股,先拉全部历史日线,然后遍历它的每一条业绩预告,批量计算 T+0、T+1、T+5 收益。

五、真实运行结果

以 6 只样本股为例,共拉取 181 条业绩预告,分类后计算事件窗口收益:

分类 数量 平均 T+0 平均 T+1 平均 T+5 T+1 胜率 T+5 胜率
positive(利好) 139 +1.02% -0.03% +0.45% 51.08% 50.36%
neutral(中性) 14 -2.14% -1.03% +1.01% 21.43% 64.29%
negative(利空) 28 -0.48% +1.19% +1.76% 60.71% 60.71%

这里有两个反直觉的点:

  1. "利好"预告的 T+1 平均收益接近 0,并不是预增就一定涨。原因是市场对业绩预期已经部分 price in。
  2. "利空"预告的短期收益反而为正,可能是因为跌幅已在前几日释放,公告日出现超跌反弹。

这些现象说明:预告类型只是事件研究的一个维度,不能直接当交易策略。 把它当作"信号库"中的一条线索,配合仓位和择时才有意义。

正向样本中 T+1 涨幅较高的几条:

  • 比亚迪 2020-08-29 预增:T0=-0.46%,T1=+10.00%,T5=+11.46%
  • 招商银行 2013-03-02 预升:T0=-6.12%,T1=+8.88%,T5=+6.93%
  • 五粮液 2009-10-19 预升:T0=+2.66%,T1=+8.42%,T5=+5.00%

负向样本中 T+1 跌幅较大的几条:

  • 比亚迪 2011-07-13 预减:T0=-1.02%,T1=-3.82%,T5=-2.53%
  • 比亚迪 2011-08-23 预减:T0=+1.22%,T1=-3.34%,T5=-3.42%
  • 隆基绿能 2026-07-15 预亏:T0=+2.30%,T1=-1.17%,T5=+4.75%

六、常见坑

  1. 预告发布日 vs 事件日pdate 可能落在非交易日,直接按自然日偏移会算错。必须映射到交易日历。
  2. 同一报告期多条预告 :有些公司会发"首次预告"再发"修正预告",事件研究时要按 pdate 取最新一条。
  3. 区间预告的收益计算 :预告里给的是利润区间,本文主要用 type 分类;如果要更精细,可以把区间中值与市场预期对比。
  4. 样本偏倚:本文只用 6 只大盘股做演示,不能代表全市场。扩大样本时建议使用批量接口减少 API 调用次数。
  5. LLM 输出不稳定:生产环境要对 LLM 返回做格式校验和重试,未配置 key 时务必保留规则 fallback。

小结与下篇预告

今天我们做了一套"业绩预告事件研究"流水线:

  • 用规则 + LLM 把业绩预告分类为利好/中性/利空;
  • pdate 映射到交易日,计算 T+0/T+1/T+5 窗口收益;
  • 用真实数据说明:预告方向 ≠ 股价方向,事件研究需要大样本和严格归因。

下篇(#06)进入技术指标的"人话翻译":让 LLM 把金叉、死叉、MACD 红绿柱解释成普通人能听懂的交易语言。


风险提示:本文仅供技术学习交流,不构成投资建议。业绩预告分析存在数据覆盖、分类偏差和样本偏倚等风险,历史结果不代表未来收益。

API 文档与证书获取https://github.com/MaiRuiApi

相关推荐
热爱编程的小李2 小时前
基于若以开发的新版情怀麻将后台
java
步行cgn2 小时前
Spring Boot 将配置绑定到第三方对象详解
spring boot·后端·python
Zixhy3 小时前
手撕Reactor模型实现同步高并发服务器及Muduo网络库深入解析
linux·服务器·网络·数据库·c++
yyywxk4 小时前
ICML 2026 目标检测(object detection)方向上接收论文总结
人工智能·目标检测·计算机视觉
zhanghaha13145 小时前
HTML系列教程:14_HTML 表单与输入框 <form>、<input> 零基础详解
java·前端·javascript
vibecoding7710 小时前
一文搞懂企业级 API 网关选型:12 个维度、4 类企业、7 步落地
人工智能·大模型·ai编程
傻啦嘿哟10 小时前
某招聘平台爬虫:爬取招聘岗位数据,分析各城市薪资水平
开发语言·爬虫·python
2501_9336707910 小时前
2026秋招量化分析岗技能栈:Python、SQL、统计建模、回测项目怎么准备
开发语言·python·sql
Rocktech_ruixun10 小时前
机器人本地跑LLM大模型对主板硬件有什么要求?瑞迅科技RK3588/3568方案选型解析
人工智能·科技·嵌入式硬件·机器人·边缘计算