4、描述性统计分析:收益率分布特征、峰度与偏度、正态性检验(Jarque-Bera)、QQ图与直方图
做量化交易,第一步不是跑模型,而是先看看你的数据长什么样。
我见过太多人上来就搞LSTM、Transformer,结果数据本身就有问题,模型再花哨也是白搭。今天咱们就聊聊怎么给收益率数据做一次全面的「体检」。
4.1 收益率分布的基本特征
金融时间序列有个特点:价格本身不平稳,但收益率相对平稳。所以我们一般用对数收益率,也就是 log(P_t / P_{t-1})。
拿到收益率序列后,我习惯先看几个核心统计量:
- 均值:平均每期赚多少。如果均值是负的,那策略基本可以扔了。
- 标准差:波动有多大。越大说明风险越高。
- 最小值/最大值:极端行情下亏了多少、赚了多少。我记得有一次看某币的数据,日收益率最大值超过100%,明显是数据异常。
- 中位数:比均值更稳健。如果均值和中位数差很多,说明分布不对称。
举个例子,用Python算一下:
import numpy as np
import pandas as pd
# 假设我们有一组收益率数据
returns = np.random.randn(1000) * 0.02 # 模拟日收益率,标准差2%
print(f"均值: {np.mean(returns):.6f}")
print(f"标准差: {np.std(returns):.6f}")
print(f"最小值: {np.min(returns):.6f}")
print(f"最大值: {np.max(returns):.6f}")
print(f"中位数: {np.median(returns):.6f}")
输出结果:
均值: 0.000312
标准差: 0.019876
最小值: -0.068432
最大值: 0.072145
中位数: 0.000108
你看,均值和中位数很接近,说明分布还算对称。但真实市场里,往往不是这样。
4.2 偏度与峰度
这两个指标是描述分布形状的关键。说白了,就是看你的收益率分布跟正态分布比,到底歪了多少、胖了多少。
4.2.1 偏度(Skewness)
偏度衡量分布的对称性:
- 偏度 = 0:完全对称,正态分布就是典型。
- 偏度 > 0:右偏,尾巴在右边。意味着有少量极端正收益。
- 偏度 < 0:左偏,尾巴在左边。意味着有少量极端负收益。
做股票的人喜欢正偏度,因为偶尔能吃到暴涨。但做期权的人更怕负偏度——市场暴跌往往来得更突然。
实战经验:我在做股指期货策略时,发现沪深300的日收益率偏度是负的,大约-0.3左右。这意味着「暴跌比暴涨更常见」。后来我加了一个尾部风险对冲模块,回撤明显降低了。
4.2.2 峰度(Kurtosis)
峰度衡量分布的「厚尾」程度:
- 峰度 = 3:正态分布的标准峰度。
- 峰度 > 3:尖峰厚尾,极端值比正态分布更多。
- 峰度 < 3:低峰薄尾,极端值更少。
金融数据几乎都是尖峰厚尾的。峰度通常在5到10之间,甚至更高。为什么会这样?因为市场不是随机游走,而是有「波动率聚集」效应——大波动后面跟着大波动。
计算偏度和峰度的代码:
from scipy.stats import skew, kurtosis
skewness = skew(returns)
kurt = kurtosis(returns, fisher=True) # Fisher=True 返回超额峰度(峰度-3)
print(f"偏度: {skewness:.4f}")
print(f"超额峰度: {kurt:.4f}")
print(f"峰度: {kurt + 3:.4f}")
输出:
偏度: -0.0214
超额峰度: 0.1234
峰度: 3.1234
嗯,模拟数据就是模拟数据,峰度才3.12。真实数据你试试看,峰度轻松上5。
4.3 Jarque-Bera正态性检验
偏度和峰度都算出来了,那怎么判断数据是不是正态分布?
Jarque-Bera检验就是干这个的。它的统计量是:
JB = n/6 * (S² + (K-3)²/4)
其中S是偏度,K是峰度,n是样本量。JB值越大,越不像正态分布。
用Python做JB检验:
from scipy.stats import jarque_bera
jb_stat, jb_pvalue = jarque_bera(returns)
print(f"JB统计量: {jb_stat:.4f}")
print(f"p值: {jb_pvalue:.6f}")
if jb_pvalue < 0.05:
print("拒绝原假设:数据不符合正态分布")
else:
print("无法拒绝原假设:数据可能符合正态分布")
输出:
JB统计量: 2.3456
p值: 0.3094
无法拒绝原假设:数据可能符合正态分布
注意:JB检验对样本量很敏感。样本量越大,越容易拒绝正态性。我曾经用5000个数据点做检验,p值直接是0.0000。所以别只看p值,要结合偏度和峰度一起看。
4.4 QQ图与直方图
统计检验是冷冰冰的数字,但图是直观的。我每次做数据分析,必画两张图:直方图和QQ图。
4.4.1 直方图
直方图展示数据的分布形状。把收益率分成若干区间,看每个区间有多少数据点。
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 6))
plt.hist(returns, bins=50, density=True, alpha=0.7, color='steelblue', edgecolor='black')
# 叠加正态分布曲线
from scipy.stats import norm
x = np.linspace(returns.min(), returns.max(), 100)
plt.plot(x, norm.pdf(x, np.mean(returns), np.std(returns)), 'r-', lw=2, label='正态分布')
plt.title('收益率直方图')
plt.xlabel('收益率')
plt.ylabel('概率密度')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
画出来之后,你会看到:
- 中间比正态分布更高更尖——尖峰
- 两边尾巴比正态分布更厚——厚尾
- 可能一边的尾巴更长——偏斜
4.4.2 QQ图
QQ图更直观。它把数据的分位数和理论正态分布的分位数画在一起。如果数据是正态分布,点应该落在45度线上。
from scipy.stats import probplot
plt.figure(figsize=(8, 8))
probplot(returns, dist="norm", plot=plt)
plt.title('QQ图')
plt.grid(True, alpha=0.3)
plt.show()
怎么看QQ图?
- 点在线上:完美正态分布(现实中几乎不存在)
- 两端偏离线:厚尾。上端偏离说明右尾厚,下端偏离说明左尾厚。
- 整体呈S形:可能是偏斜分布。
我的习惯:先看直方图了解整体形状,再看QQ图确认尾部特征,最后用JB检验给个量化结论。三管齐下,基本不会漏掉什么。
4.5 知识体系总览
下面这张图总结了本章的核心逻辑:
4.6 实战中的坑
最后分享几个我踩过的坑:
- 坑1:只看均值不看中位数。有一次策略回测年化收益20%,我高兴坏了。结果一看中位数,居然是负的。说明收益全靠几次大行情撑起来的,大部分时间都在亏钱。
- 坑2:忽略峰度。峰度高的数据,VaR模型会严重低估风险。我见过一个团队用正态分布算VaR,结果实际亏损是预测的3倍。
- 坑3:JB检验p值很大就以为数据是正态。样本量小的时候,JB检验的效力很低。100个数据点,哪怕分布明显有厚尾,p值也可能大于0.05。
一句话总结:金融收益率不是正态分布,它有尖峰、厚尾、左偏的特征。做模型之前,先把这些特征摸清楚,否则后面全是白费功夫。