4. 收益率序列的统计特征分析

各位同学,咱们今天来聊聊收益率序列的统计特征分析。说实话,这部分内容看着基础,但我在实际项目中踩过的坑,十有八九都跟这些基础统计量没搞清楚有关。你想想看,如果连数据的基本脾气都没摸透,后面建什么GARCH模型都是白搭。

我个人习惯,拿到任何金融时间序列,第一件事就是做四步走:描述性统计、正态性检验、自相关与偏自相关分析、平稳性检验。这四步走完,数据的基本画像就出来了。

核心逻辑:统计特征分析是建模前的"体检报告"。不做这一步,后面模型再花哨也是空中楼阁。

收益率序列统计特征分析框架 收益率序列 描述性统计 均值、标准差、偏度、峰度 正态性检验 Jarque-Bera、QQ图 自相关与偏自相关 ACF、PACF、Ljung-Box 平稳性检验 ADF、KPSS检验

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建模铺路。你想想看,如果连数据的基本特征都没搞清楚,建出来的模型能靠谱吗?


专注资料整理