4. 收益率序列的统计特征分析
各位同学,咱们今天来聊聊收益率序列的统计特征分析。说实话,这部分内容看着基础,但我在实际项目中踩过的坑,十有八九都跟这些基础统计量没搞清楚有关。你想想看,如果连数据的基本脾气都没摸透,后面建什么GARCH模型都是白搭。
我个人习惯,拿到任何金融时间序列,第一件事就是做四步走:描述性统计、正态性检验、自相关与偏自相关分析、平稳性检验。这四步走完,数据的基本画像就出来了。
核心逻辑:统计特征分析是建模前的"体检报告"。不做这一步,后面模型再花哨也是空中楼阁。
4.1 描述性统计:先看看数据长什么样
描述性统计说白了就是给收益率序列做个"人口普查"。我一般会关注这几个指标:
- 均值:代表平均收益率水平。嗯,这里要注意,金融数据的均值往往接近0,别指望靠它发财。
- 标准差:衡量波动大小。越大说明风险越高,但也意味着潜在收益空间更大。
- 偏度:判断分布是否对称。负偏度意味着左尾更长——说白了就是暴跌的概率比暴涨大。
- 峰度:衡量"尖峰厚尾"程度。正态分布的峰度是3,金融数据通常远大于3。
我在项目中遇到过一件事:有次分析某只股票的日收益率,峰度算出来是12.8。当时我第一反应是数据有问题,后来查了才发现,这股票确实经常出现极端波动。这就是典型的"尖峰厚尾"特征。
import numpy as np
import pandas as pd
from scipy import stats
# 假设 returns 是收益率序列
returns = pd.Series([...]) # 你的数据
# 描述性统计
desc = {
'均值': np.mean(returns),
'标准差': np.std(returns),
'偏度': stats.skew(returns),
'峰度': stats.kurtosis(returns, fisher=False), # 峰度(不减去3)
'最小值': np.min(returns),
'最大值': np.max(returns),
'样本量': len(returns)
}
for key, value in desc.items():
print(f"{key}: {value:.6f}")
小技巧:我习惯用 scipy.stats.describe() 一次性输出多个统计量,省得自己一个个算。但注意它返回的峰度是"超额峰度"(减去了3),需要加回3才能跟教科书上的峰度对比。
4.2 正态性检验:金融数据真的正态吗?
教科书上总说收益率服从正态分布。但我在实际工作中,几乎没见过哪只股票的收益率是严格正态的。为什么会这样?因为市场参与者不是完全理性的,极端事件发生的概率远高于正态分布的预测。
常用的正态性检验方法:
| 方法 | 原理 | 适用场景 |
|---|---|---|
| Jarque-Bera检验 | 基于偏度和峰度 | 大样本下效果好 |
| Shapiro-Wilk检验 | 基于排序统计量 | 小样本(n<5000)更准确 |
| QQ图 | 可视化对比分位数 | 直观判断尾部特征 |
# Jarque-Bera 检验
jb_stat, jb_pvalue = stats.jarque_bera(returns)
print(f"Jarque-Bera统计量: {jb_stat:.4f}")
print(f"p值: {jb_pvalue:.6f}")
if jb_pvalue < 0.05:
print("❌ 拒绝正态性假设——数据不是正态分布")
else:
print("✅ 无法拒绝正态性假设")
⚠️ 注意:我曾经犯过一个错误——样本量只有50个交易日,就用了Jarque-Bera检验。结果p值很大,我以为数据是正态的。后来才发现,小样本下JB检验的检验力很低。对于小样本,建议用Shapiro-Wilk检验。
4.3 自相关与偏自相关分析:波动会"传染"吗?
自相关分析,说白了就是看今天的收益率跟昨天的有没有关系。如果存在显著的自相关,说明市场存在一定的动量或反转效应。
我个人习惯用ACF(自相关函数)和PACF(偏自相关函数)两个图来诊断:
- ACF:衡量收益率序列与其滞后项之间的相关性。如果ACF在滞后1阶就截尾,说明只有短期记忆。
- PACF:剔除中间变量影响后的相关性。对于AR模型定阶特别有用。
我记得有次分析某指数期货的5分钟高频数据,ACF在滞后10阶仍然显著。这说明高频数据存在明显的微观结构噪声,需要做预处理才能建模。
import statsmodels.api as sm
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
# 计算ACF和PACF
acf_values = sm.tsa.acf(returns, nlags=20)
pacf_values = sm.tsa.pacf(returns, nlags=20)
# Ljung-Box检验(检验自相关是否显著)
lb_stat, lb_pvalue = sm.stats.acorr_ljungbox(returns, lags=[10], return_df=True)
print(f"Ljung-Box检验p值: {lb_pvalue.values[0]:.6f}")
# 可视化
# plot_acf(returns, lags=20)
# plot_pacf(returns, lags=20)
避坑指南:我曾经在分析日收益率时,发现ACF在滞后5阶显著。当时我以为是市场存在周度效应,后来才发现是数据中有一个异常值导致的。所以,做自相关分析前,先检查一下有没有极端值。
4.4 平稳性检验:模型的前提条件
平稳性,说白了就是数据的统计性质不随时间变化。如果收益率序列不平稳,那GARCH模型的结果就是一堆废纸。
常用的平稳性检验方法:
- ADF检验:原假设是"存在单位根"(即不平稳)。p值小于0.05则拒绝原假设,认为序列平稳。
- KPSS检验:原假设是"序列平稳"。正好跟ADF反过来。两个检验结合使用,判断更可靠。
from statsmodels.tsa.stattools import adfuller, kpss
# ADF检验
adf_result = adfuller(returns, autolag='AIC')
print(f"ADF统计量: {adf_result[0]:.4f}")
print(f"ADF p值: {adf_result[1]:.6f}")
# KPSS检验
kpss_result = kpss(returns, regression='c', nlags='auto')
print(f"KPSS统计量: {kpss_result[0]:.4f}")
print(f"KPSS p值: {kpss_result[1]:.6f}")
# 综合判断
if adf_result[1] < 0.05 and kpss_result[1] > 0.05:
print("✅ 序列平稳")
else:
print("❌ 序列不平稳,需要差分处理")
⚠️ 注意:ADF检验的滞后阶数选择很关键。我习惯用AIC自动选择滞后阶数,但有时候AIC会选太多阶,导致检验力下降。建议同时用BIC做对比,取两者中较小的阶数。
4.5 实战案例:某股票日收益率分析
好了,理论讲完了,咱们来走一遍完整的流程。假设我们拿到了某股票过去5年的日收益率数据:
# 完整分析流程
import numpy as np
import pandas as pd
from scipy import stats
import statsmodels.api as sm
# 模拟数据(实际项目中替换为真实数据)
np.random.seed(42)
returns = np.random.standard_t(df=4, size=1250) * 0.02 # t分布模拟尖峰厚尾
# 1. 描述性统计
print("=== 描述性统计 ===")
print(f"均值: {np.mean(returns):.6f}")
print(f"标准差: {np.std(returns):.6f}")
print(f"偏度: {stats.skew(returns):.4f}")
print(f"峰度: {stats.kurtosis(returns, fisher=False):.4f}")
# 2. 正态性检验
print("\n=== 正态性检验 ===")
jb_stat, jb_p = stats.jarque_bera(returns)
print(f"Jarque-Bera p值: {jb_p:.6f}")
# 3. 自相关检验
print("\n=== 自相关检验 ===")
lb_result = sm.stats.acorr_ljungbox(returns, lags=[5, 10, 20])
print(lb_result)
# 4. 平稳性检验
print("\n=== 平稳性检验 ===")
adf_result = sm.tsa.stattools.adfuller(returns)
print(f"ADF p值: {adf_result[1]:.6f}")
运行这段代码,你会发现:均值接近0,标准差在2%左右,偏度可能为负,峰度远大于3。Jarque-Bera检验的p值几乎为0,说明数据不是正态分布。Ljung-Box检验可能在某些滞后阶数显著,但整体自相关不强。ADF检验的p值很小,说明收益率序列是平稳的。
核心结论:金融收益率序列通常具有"尖峰厚尾"特征,不服从正态分布,但本身是平稳的。这恰恰是GARCH模型能够发挥作用的根本原因——波动率存在聚集效应,但收益率本身是平稳的。
嗯,到这里,收益率序列的统计特征分析就讲完了。这些基础工作虽然看起来繁琐,但每一步都是在为后面的GARCH建模铺路。你想想看,如果连数据的基本特征都没搞清楚,建出来的模型能靠谱吗?