第28章 价格发现实证研究设计:数据清洗、事件研究、回归分析、稳健性检验
做价格发现研究,说白了就是跟数据较劲。我做了这么多年量化,最深的体会是:80%的时间花在数据清洗上,15%的时间在跑模型,5%的时间在写报告。这一章,我就把实证研究的完整流程拆开揉碎了讲给你听。
28.1 数据清洗:别让垃圾数据毁了你的研究
我记得刚入行那会儿,拿到一批高频数据就急着跑回归。结果R²高达0.99,兴奋得不行。后来发现——数据里混着未来信息。嗯,这种坑我踩过不止一次。
28.1.1 常见的数据污染问题
- 前视偏差:用未来数据回填历史。比如用收盘价计算当日指标,但收盘价在盘中是未知的
- 幸存者偏差:只保留当前还在交易的标的。退市的、被收购的全被剔除了
- 时间戳错位:不同数据源的时间基准不一致。我遇到过某交易所的毫秒级时间戳和另一家的微秒级对不上
- 异常值:比如某只股票突然涨了1000倍,其实是除权除息没处理
28.1.2 清洗流程示例
我个人习惯用Python做数据清洗。下面这个流程,我用了好几年,基本没出过大问题:
# 伪代码示例:数据清洗流水线
def clean_market_data(df):
# 1. 去重
df = df.drop_duplicates(subset=['symbol', 'timestamp'])
# 2. 时间对齐
df = df.set_index('timestamp').resample('1min').last()
# 3. 异常值处理
df['return'] = df['close'].pct_change()
df = df[df['return'].between(-0.1, 0.1)] # 剔除涨跌幅超过10%的
# 4. 填充缺失值
df = df.fillna(method='ffill').fillna(method='bfill')
# 5. 剔除交易量异常的
df = df[df['volume'] > 0]
return df
28.2 事件研究:捕捉价格对信息的反应
事件研究是价格发现的核心工具。你想知道某个消息出来之后,价格是怎么反应的?用事件研究就对了。
28.2.1 事件窗口设计
我一般把事件窗口分成三段:
| 窗口名称 | 时间范围 | 作用 |
|---|---|---|
| 估计窗口 | 事件前[-120, -21]天 | 估计正常收益率 |
| 事件窗口 | 事件前后[-20, +20]天 | 计算异常收益率 |
| 事后窗口 | 事件后[+21, +60]天 | 检验价格是否反转 |
为什么会这样设计?因为太短的窗口可能捕捉不到完整的价格发现过程,太长的窗口又会混入其他噪音。我个人习惯用[-20, +20]作为标准窗口,如果是高频数据,可以缩到[-60min, +60min]。
28.2.2 异常收益率的计算
计算异常收益率,说白了就是「实际收益率 - 预期收益率」。预期收益率怎么算?最常用的有三种模型:
- 市场模型:用CAPM回归,Rit = α + βRmt + εit
- 市场调整模型:直接用市场收益率作为预期收益率
- 均值调整模型:用估计窗口的平均收益率作为预期收益率
我个人的经验: 市场模型虽然最常用,但有个前提——你的β系数要稳定。如果事件前后公司基本面发生重大变化(比如并购重组),β会漂移。这时候用市场调整模型反而更稳健。
28.3 回归分析:量化价格发现的驱动因素
事件研究告诉你「有没有异常收益」,回归分析告诉你「为什么会有」。这两者结合起来,才能讲好一个完整的故事。
28.3.1 核心回归模型
我常用的回归框架是这样的:
# 截面回归:解释累计异常收益率(CAR)
CAR_i = β₀ + β₁*Size_i + β₂*Turnover_i + β₃*Volatility_i + ε_i
# 时间序列回归:解释价格发现贡献度
ΔPrice_t = α + β₁*OrderFlow_t + β₂*NewsSentiment_t + ε_t
你想想看,如果β₁显著为正,说明大市值股票的价格发现效率更高。如果β₂显著为负,说明高换手率的股票反而价格发现更慢——这听起来反直觉,但我在A股市场确实观察到过这种现象。
28.3.2 内生性问题的处理
做回归最怕什么?内生性。比如你发现「新闻情绪」和「价格变化」正相关,但到底是新闻影响了价格,还是价格变化影响了新闻的报道?
我一般用两种方法处理:
- 工具变量法:用同行业其他公司的新闻情绪作为工具变量
- 格兰杰因果检验:先检验时间上的先后顺序
28.4 稳健性检验:别让你的结论一碰就碎
做实证研究,最怕的是「换个样本、换个时间、换个方法,结论就没了」。稳健性检验就是用来验证你的结论是不是真的靠谱。
28.4.1 常见的稳健性检验方法
| 检验类型 | 具体做法 | 我踩过的坑 |
|---|---|---|
| 样本敏感性 | 剔除极端值、分样本回归 | 剔除极端值后结果不显著,说明结论被少数样本驱动 |
| 时间敏感性 | 改变事件窗口长度、换样本期 | 窗口从[-20,+20]改成[-10,+10]后结果反转 |
| 方法敏感性 | 换异常收益率计算模型 | 市场模型显著,市场调整模型不显著 |
| 聚类标准误 | 按行业、时间聚类 | 不聚类时t值3.0,聚类后t值1.2 |
28.4.2 一个完整的稳健性检验流程
我个人习惯按这个顺序做:
- 基础回归:用最标准的方法跑一遍
- 剔除极端值:去掉上下1%的样本,看结果是否稳健
- 换窗口:把事件窗口从[-20,+20]改成[-10,+10]和[-30,+30]
- 换模型:从市场模型换成市场调整模型
- 聚类标准误:按行业和年份双聚类
- 安慰剂检验:随机生成事件日,看是否还能得到显著结果
28.5 知识体系总览
下面这张图,是我做价格发现实证研究的心法总结。你照着这个框架走,基本不会跑偏:
这个框架我用了好几年,每次做实证研究都按这个流程走。你刚开始做的时候,可能会觉得步骤太多、太繁琐。但相信我——跳过任何一步,都可能让你的结论变成废纸。
最后说一句: 实证研究不是跑代码,是讲故事。数据清洗是准备素材,事件研究是发现线索,回归分析是构建逻辑,稳健性检验是加固证据。四步走完,你的故事才能站得住脚。