如果市场是有效的,一家公司发布超预期的季报,股价应该在那一秒就跳到合理价位,之后不再有系统性便宜可捡。但 1968 年 Ball 与 Brown、以及后来 Bernard 与 Thomas 的一系列研究反复告诉我们:股价在盈余公告后还会沿着同方向慢吞吞地漂几十天。这个「慢半拍」就叫 PEAD(Post-Earnings Announcement Drift,盈余公告后漂移)。
它之所以是量化圈最常被复现、也最让人又爱又恨的异象,是因为它逻辑干净、信号明确,却难在实盘里稳定吃到——本文就用标准化未预期盈利(SUE) 把这个异象从头搭一遍,并诚实标出它真正会咬人的地方。
一、SUT 与 SUE:把「惊喜」量化成一个数字#
公司自己不报「我这次超没超预期」,所以我们得自己算。最朴素的口径是未预期盈利(Unexpected Earnings):
即用本季 EPS 减去去年同期(跨四个季度,消除季节性)。但不同股票的盈利波动尺度差太远——一只银行股 EPS 变动 0.1 元是小事,一只小盘股变动 0.1 元可能是天大的惊喜。所以 Foster、Olsen、Shevlin(1984)把它标准化,得到 SUE:
分母是该股票过往若干个同比变化的标准差,相当于「这次惊喜是几个标准差」。这样 SUE 在截面里就可比:SUE=2 表示这次盈利惊喜是历史波动的两步之外,市场多半还没 fully price in。

二、异象本身:按 SUE 分十组,漂移立刻现形#
把某一期所有股票的 SUE 从高到低切成十个组合(decile),然后追踪公告后持有窗口内的异常收益(Abnormal Return)——注意是「异常」而非「总收益」,必须用市场模型或行业中性把大盘beta剥掉,否则你赚的只是市场 beta,不是 PEAD:
把每组在持有期内的累积异常收益(CAR)画出来,会看到一条漂亮的单调梯度:SUE 最高的第 10 组一路向上漂,最低的组一路向下漂。

多空组合(第 10 组减第 1 组)是一条稳定向上的净值曲线——这就是 PEAD 能拿来交易的核心:

三、Python:从 EPS 到十组漂移的完整链路#
下面这段代码与配图完全对应,是自洽合成数据(每只股票一条带漂移的盈利序列,公告后异常收益与 SUE 正相关并叠加特异噪声),仅用于演示方法;真实落地请用 Wind/聚源拉取实际季报与复权价格(见文末)。
import numpy as np
def build_pead(N=600, T=40, H=20, seed=7):
rng = np.random.default_rng(seed)
# 1) 每只股票带漂移的盈利水平(随机游走 + 个股 drift)
g = rng.normal(0.012, 0.004, size=N) # 个股盈利漂移
level = np.cumsum(g[:, None] + rng.normal(0, 0.03, size=(N, T)), axis=1)
yoy = level[:, 4:] - level[:, :-4] # 同比变化
# 2) 个股 SUE:同比变化 / 其滚动标准差
sue = np.zeros((N, yoy.shape[1]))
for i in range(N):
s = yoy[i]
rs = np.array([s[max(0, j-8):j+1].std(ddof=1) for j in range(len(s))])
rs = np.where(rs < 1e-6, 1e-6, rs)
sue[i] = (s - s.mean()) / rs
sue = sue[:, -1] # 取最新一期截面
# 3) 公告后 H 日异常收益:与 SUE 正相关的漂移 + 特异噪声
drift = 0.10 * sue
abn = np.outer(drift / H, np.ones(H)) \
+ rng.normal(0, 0.02 / np.sqrt(H), size=(N, H))
car = abn.cumsum(axis=1) # 累积异常收益
return sue, car
def decile_drift(sue, car, K=10):
order = np.argsort(sue)
dec = np.array_split(order, K)
out = {}
for k, idx in enumerate(dec):
out[k] = car[idx].mean(axis=0) # 每组平均 CAR 序列
return dec, out
sue, car = build_pead()
dec, table = decile_drift(sue, car)
hi, lo = car[dec[-1]].mean(0), car[dec[0]].mean(0)
print("top decile final CAR %:", round(hi[-1]*100, 2))
print("bot decile final CAR %:", round(lo[-1]*100, 2))
print("long-short final %:", round((hi-lo)[-1]*100, 2))python跑出来最高组约 +22%、最低组约 −21%、多空约 +43%(合成参数下,含噪声;真实市场远低于此,见下一节)。梯度顺、多空正,PEAD 的「形状」就立住了。
把 SUE 算到一只虚拟股票上#
看得见的数字比公式好记。假设某股票过去 8 个同比变化的标准差 元,本季 EPS 同比变化 元、历史均值 元,则:
一个标准差出头的惊喜——这种票就该落进最高那组。把全部股票排好队、十等分后,演示参数下各组的平均累积异常收益大致长这样(与上一节配图一一对应):
| 组合 | 平均 SUE | 持有 20 日 CAR |
|---|---|---|
| D1(最低) | −1.42 | −21.4% |
| D5(中) | −0.05 | +0.5% |
| D10(最高) | +1.42 | +22.3% |
注意 D5 几乎零漂移:PEAD 的 alpha 几乎全挤在最极端的头尾两组,中间八组只是噪声。这直接决定了实盘打法——下一节说。
四、它为什么存在:不是市场傻,是套利有成本#
经典解释有三层:
- 分析师预测的惯性(underreaction)。卖方分析师调整盈利预测是黏的,一家连续超预期的公司,其预期修正往往滞后,价格也就滞后反映。
- 投资者的注意力与处置效应。散户倾向于在盈利兑现后过早卖出赢家、死扛输家,把漂移「熨」出来需要时间。
- 套利有限(limits to arbitrage)。这是最关键的实盘视角——PEAD 的多空组合里,做空腿(低 SUE 组)往往难借、贵、且会被挤空。当套利者无法自由做空时,负漂移就「压不回去」,于是长期存在。这恰恰说明 PEAD 不是「市场无效」的证伪、反而是「套利有摩擦」的证据:有效市场假说在它的框架里反而更站得住。
但「统计显著」不等于「你能赚到」。下面三个陷阱才是决定 PEAD 能不能进组合的真正关口。
五、实盘三大真实陷阱#
陷阱一:前视偏差(look-ahead)。 这是 PEAD 最致命的坑。SUE 用的是「本季 EPS 减去年同季」,你必须用公告日之前可得的信息:公告日当天的股价反应已经包含了部分惊喜,若你在公告前用「已知本季 EPS」下注,等于偷看了答案。真正可交易的做法是:在财报披露日之后、用已公开数据计算 SUE,再持有——但这时第一天跳空你已经吃不到,漂移被吃掉一大块。
陷阱二:成本吞噬窄价差。 上面的 +43% 是毛漂移、零成本。真实里最高/最低组的年化毛差往往只有个位数百分点,而 A 股双边佣金+印花税+冲击成本轻易吃掉 1%–2%/回合,持有 60 天里反复调仓更贵。PEAD 要赚钱,必须压在低换手、高确信(极端 SUE 组) 的尾部,而不是十组全用。
陷阱三:做空约束与季节性。 低 SUE 组要靠做空表达,而 A 股融券券源紧张、美股小盘借券成本高;更隐蔽的是季节性:Q4 的盈利往往含一次性项目、噪声大,Q1 的 SUE 反而信息含量最高。不控制季度哑变量,你会把噪音当信号。
陷阱四:样本衰减与市值结构。 PEAD 在 1990 年代之前最强、之后被显著「套利掉」——当越来越多量化基金盯着同一份财报,惊喜被更快消化,漂移窗口从 60 天压到 20 天量级。同时它高度集中在小市值、低分析师覆盖的票上,大票里几乎消失。实盘若只在流动性好的大票里做,往往捕不到多少 drift;去小票里做,又要重新面对流动性与卖空成本。这是个结构性两难,不是调参数能解的,落地前要先想清楚自己在赚哪一段、被谁挤。

六、落地路径与诚实结论#
真实复现时,把合成数据换成:
- 盈利数据:Wind/聚源/SEC EDGAR 的季度 EPS 与公告日期(公告日才是信号可用时点,不是财年截止日)。
- 异常收益:用 Fama-French 三/五因子或行业市值中性残差,而不是裸收益率,否则你量到的是 beta 不是 drift。
- 持有窗口:文献多用公告后 60 个交易日,但要做参数敏感性——持有 20/40/60 天、分组用 decile 还是极端 percentile,结论稳不稳一目了然。
- 正交化:SUE 常与动量因子共线,直接做多 SUE 可能只是变相做多动量。用截面回归把动量、规模、行业暴露剔掉,再看残差漂移还剩多少——真 PEAD 应该活在正交化之后,而不是被动量借壳。
结论:PEAD 是一个被复现了半个世纪、逻辑自洽的真实异象,但它不是「免费午餐」。它的收益藏在极端 SUE 组、低换手、可控做空成本 的交集里;一旦把前视、交易成本、卖空约束三项如实建模,毛漂移会大幅缩水——能剩下多少正的、净的 alpha,才是这篇该回答而你要在自己数据上验证的问题。