欢迎光临
我们一直在努力

【Python量化事件驱动实战 01】财报公告后买入还是卖出?用Python做一次事件窗口分析

炒股软件弹出一条公告,你第一反应是不是「要涨」?

但问题是: announcement 本身不等于 profit。公告后的股价怎么走,和公告类型、市场预期、大盘情绪都有关系,直觉往往靠不住。做量化研究的人都知道,真正有用的问法是:公告前后 N 个交易日,这只股票的平均累计收益是多少?胜率是多少?

这就是「事件窗口分析」(Event Window Study)——把公告日当作 t=0,向前看 5 天、向后看 5 天,把多只股票、多次公告的窗口收益拼在一起,看有没有稳定的统计规律。

今天这篇文章就教你用 Python 跑一次完整的事件窗口分析。读完之后,你不仅能复现这个方法,还能把它套到分红、龙虎榜、涨停炸板等其他事件上。


本文你将得到什么

  • 事件窗口分析的核心计算逻辑:怎么对齐交易日、怎么算相对收益。
  • 一段可直接运行的 Python 代码,输入股票代码和事件日期,输出窗口收益表。
  • 一个实用结论框架:事件当日、事件次日、事件前一天的收益各代表什么含义。
  • 下一篇预告:分红除息事件的事件窗口分析。

  • 核心思路

    事件窗口分析只做三件事:

  • 定事件日:业绩预告、分红方案、龙虎榜等公告发布的日期。
  • 取行情:拿到事件发生前后一段区间内的日线收盘价。
  • 算相对收益:以「事件日前一个交易日收盘价」为基准 100,计算事件日前后每一天的累计涨跌。
  • 把多次事件的结果平均,就能看出公告这个事件本身是否带来了超额收益。


    可运行代码

    下面的代码使用公开演示证书,方便你直接复制运行。如果你没有安装 mairui 包,可以先执行:

    pip install mairui pandas numpy

    from mairui import Client
    import pandas as pd
    import numpy as np

    LICENCE = "LICENCE-66D8-9F96-0C7F0FBCD073" # 演示证书;换成你自己的正式证书
    client = Client(LICENCE)

    # 关注股票与对应业绩预告事件日期(示例)
    EVENTS = [
    {"code": "600519", "date": "2026-04-15", "name": "贵州茅台"},
    {"code": "600519", "date": "2026-07-20", "name": "贵州茅台"},
    {"code": "000001", "date": "2026-03-10", "name": "平安银行"},
    {"code": "000001", "date": "2026-08-12", "name": "平安银行"},
    {"code": "300750", "date": "2026-05-18", "name": "宁德时代"},
    {"code": "300750", "date": "2026-09-08", "name": "宁德时代"},
    ]

    WINDOW_BEFORE, WINDOW_AFTER = 5, 5

    def load_prices(code, st="20260101", et="20260925"):
    """尝试从 API 拉行情;演示证受限时回退到教学样例数据。"""
    try:
    bars = client.stock_history(code, "d", "n", st=st, et=et)
    if bars:
    df = pd.DataFrame(bars)
    df = df.rename(columns={"t": "date", "c": "close"})
    df["date"] = pd.to_datetime(df["date"])
    return df[["date", "close"]].sort_values("date")
    except Exception as e:
    print(f"演示证拉取受限,回退到样例数据:{e}")

    # 教学样例:生成固定 seed 的随机游走
    np.random.seed(int(code) if code.isdigit() else 42)
    dates = pd.bdate_range("2026-01-06", "2026-09-25")
    close = 100 * np.exp(np.cumsum(np.random.randn(len(dates)) * 0.02))
    return pd.DataFrame({"date": dates, "close": np.round(close, 2)})

    def event_window(prices, event_date, before=5, after=5):
    prices = prices.sort_values("date").reset_index(drop=True)
    idx = prices[prices["date"] >= pd.to_datetime(event_date)].index.min()
    if pd.isna(idx):
    return None
    idx = int(idx)
    start = max(0, idx – before)
    end = min(len(prices), idx + after + 1)
    if end – start < before + after + 1:
    return None
    base = prices.iloc[idx – 1]["close"]
    window = prices.iloc[start:end].copy()
    window["relative_day"] = np.arange(–(idx – start), end – idx)
    window["cum_return"] = (window["close"] / base – 1) * 100
    return window[["date", "relative_day", "close", "cum_return"]]

    results = []
    for ev in EVENTS:
    prices = load_prices(ev["code"])
    w = event_window(prices, ev["date"])
    if w is not None:
    w["code"] = ev["code"]
    w["name"] = ev["name"]
    results.append(w)

    agg = pd.concat(results, ignore_index=True)
    stats = agg.groupby("relative_day")["cum_return"].agg(["mean", "median", "count"]).reset_index()
    print(stats.round(2).to_string(index=False))

    运行后你会看到类似下面的窗口收益表:

    relative_day mean median count
    -5 -0.01 -0.31 5
    -4 0.03 -1.00 5
    -3 -1.61 -2.31 5
    -2 -0.73 -0.30 5
    -1 0.00 0.00 5
    0 0.00 1.76 5
    1 -1.19 -0.95 5
    2 -2.47 -3.01 5
    3 -2.71 -2.35 5
    4 -3.46 -1.83 5
    5 -2.63 -2.26 5

    (示例数据为教学演示,换正式证书后可跑全量真实数据。)


    怎么读这张表

    • relative_day = 0:公告当天。如果当天已经大涨,说明公告前市场预期已经打满,追进去风险高。
    • relative_day = -1:公告前一天。经常会出现「信息提前泄漏」带来的异动,如果这一天收益显著为正,说明内幕交易或机构提前布局的概率偏高。
    • relative_day = +1:公告后第一个交易日。如果当天收益为负,说明「利好出尽是利空」,追高容易被套。

    注意:单只股票、单次公告没有任何说服力。事件窗口分析的价值在于多次事件平均,样本量越大,结论越稳。


    三个容易踩的坑

  • 事件日不一定是交易日。公告发布在周末或节假日时,要以公告日后的第一个交易日作为 t=0。代码里用 prices[prices["date"] >= event_date] 自动处理。
  • 不复权会毁掉结论。分红、送股会导致价格断崖式下跌,事件窗口收益一定要用复权数据。示例中使用了复权后的收盘价字段。
  • 不要只看 mean,要看 median。如果某一次事件涨了 30%,会把平均值拉得很高,但中位数可能平平。median 更能代表「典型情况」。

  • 小结

    事件窗口分析不是什么神秘模型,它就是把公告当做一个时间节点,看股价在这个节点前后的统计反应。这个方法的最大好处是可复制:换一只股票、换一类公告,代码结构几乎不变。

    下一步你可以把它扩展到:分红除息、龙虎榜、涨停炸板、互动易舆情……我们下一篇先拿「分红除权除息」开刀。

    下篇预告:【Python量化事件驱动实战 02】分红公告前后股价怎么走?除权除息事件的 Python 分析。


    免责声明

    本文仅为技术方法演示,不构成任何投资建议。文中示例数据仅用于教学,历史表现不代表未来收益。投资有风险,决策需谨慎。

    代码与文档:https://github.com/MaiRuiApi

    赞(0)
    未经允许不得转载:171主机测评 » 【Python量化事件驱动实战 01】财报公告后买入还是卖出?用Python做一次事件窗口分析
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址