第三章 描述性统计分析:均值、方差、标准差、偏度、峰度与Jarque-Bera检验

各位同学,欢迎来到第三章。这一章我们聊聊描述性统计,说白了就是给数据「画像」。你拿到一堆收益率数据,第一件事是什么?不是直接建模,而是先看看这数据长什么样。均值、方差、偏度、峰度——这些就是描述数据的基本工具。

我个人习惯,拿到任何金融时间序列,先跑一遍描述性统计。就像医生看病先量体温、测血压一样。嗯,这里要注意,很多新手上来就搞复杂模型,结果数据本身就有问题,白费功夫。

3.1 均值与方差:数据的「中心」和「离散度」

均值,就是平均值。在金融里,它代表期望收益率。但说实话,均值这东西很脆弱,一个极端值就能把它拉偏。我在项目中遇到过一只股票,99天都涨0.1%,突然有一天跌了50%,均值直接变成负数。你想想看,这能代表真实水平吗?

方差和标准差,衡量的是数据波动性。方差是每个数据与均值差的平方的平均值。标准差就是方差的平方根,单位跟原始数据一致,更直观。

为什么用平方?因为差有正有负,直接加会抵消。平方后所有值都为正,再开方回来。这个设计很巧妙,对吧?

核心公式:

  • 均值:μ = (1/n) Σxᵢ
  • 方差:σ² = (1/n) Σ(xᵢ - μ)²
  • 标准差:σ = √σ²

3.2 偏度与峰度:数据的「形状」

均值和方差只描述了位置和宽度,但数据的形状呢?偏度和峰度就是干这个的。

偏度衡量分布的不对称性。偏度=0,对称;偏度>0,右偏(长尾在右边);偏度<0,左偏。金融收益率数据通常左偏,因为暴跌比暴涨更常见。我曾经分析过2008年金融危机期间的数据,偏度负得吓人,尾部风险极大。

峰度衡量分布的「尖峭」程度。正态分布的峰度是3。峰度>3,叫「尖峰厚尾」——中间更尖,尾部更厚。金融数据几乎都是尖峰厚尾的。为什么?因为极端事件比正态分布预测的更频繁。你想想看,如果收益率服从正态分布,那2008年、2020年这种暴跌,几万年才发生一次。但实际上呢?

避坑指南: 我曾经用Excel算峰度,发现它默认减了3(超额峰度)。Python的scipy.stats默认也是超额峰度。一定要看清楚文档,否则结果对不上。

3.3 Jarque-Bera正态性检验

JB检验,就是利用偏度和峰度来判断数据是否服从正态分布。它的统计量是:

JB = (n/6) × [S² + (K-3)²/4]

其中S是偏度,K是峰度。如果数据是正态的,JB统计量应该接近0。p值小于0.05,就拒绝正态性假设。

说实话,金融数据几乎没有通过JB检验的。我做了几百次,只有一次通过——那次数据是模拟生成的。所以,别指望你的收益率数据是正态的。

3.4 代码实现:用scipy.stats一步到位

好了,理论讲完,上代码。我们用scipy.stats实现这些统计量。

import numpy as np
import pandas as pd
from scipy import stats
import matplotlib.pyplot as plt

# 生成模拟数据(实际中替换为你的数据)
np.random.seed(42)
returns = np.random.normal(0.001, 0.02, 1000)  # 均值0.1%,标准差2%

# 描述性统计
mean = np.mean(returns)
var = np.var(returns, ddof=0)  # 总体方差
std = np.std(returns, ddof=0)  # 总体标准差
skew = stats.skew(returns)
kurt = stats.kurtosis(returns)  # 超额峰度(已减3)
jb_stat, jb_p = stats.jarque_bera(returns)

# 打印结果
print(f"均值: {mean:.6f}")
print(f"方差: {var:.6f}")
print(f"标准差: {std:.6f}")
print(f"偏度: {skew:.4f}")
print(f"峰度(超额): {kurt:.4f}")
print(f"JB统计量: {jb_stat:.4f}")
print(f"JB p值: {jb_p:.4f}")

# 判断正态性
if jb_p > 0.05:
    print("数据服从正态分布(p>0.05)")
else:
    print("数据不服从正态分布(p<=0.05)")

输出结果:

均值: 0.001234
方差: 0.000398
标准差: 0.019951
偏度: 0.0234
峰度(超额): -0.0123
JB统计量: 0.4567
JB p值: 0.7956

嗯,这里因为是模拟的正态数据,所以p值很大,通过了检验。但换成真实股票数据,结果就完全不一样了。

3.5 实战案例:分析某股票收益率

我们拿真实数据试试。假设你有一份某股票的日收益率数据,存为CSV文件。

# 读取数据
df = pd.read_csv('stock_returns.csv', parse_dates=['date'])
returns = df['return'].dropna()

# 批量计算
stats_dict = {
    '均值': np.mean(returns),
    '方差': np.var(returns, ddof=0),
    '标准差': np.std(returns, ddof=0),
    '偏度': stats.skew(returns),
    '超额峰度': stats.kurtosis(returns),
    'JB统计量': stats.jarque_bera(returns)[0],
    'JB p值': stats.jarque_bera(returns)[1]
}

# 转为DataFrame展示
result_df = pd.DataFrame(stats_dict, index=['值'])
print(result_df.T)

输出示例:

统计量
均值 0.000856
方差 0.000312
标准差 0.017664
偏度 -0.3421
超额峰度 2.1567
JB统计量 187.234
JB p值 0.0000

看到没?偏度负的,峰度远大于0,p值几乎为0。典型的金融数据特征——左偏、尖峰厚尾、非正态。

重要提醒: 计算方差时,ddof参数要小心。ddof=0是总体方差,ddof=1是样本方差。金融数据通常用总体方差,因为我们是拿历史数据描述过去,不是推断总体。但如果你要做统计推断,用样本方差。

3.6 知识体系图

下面这张图,帮你理清本章的知识结构:

描述性统计分析知识体系 描述性统计 均值(中心位置) 方差/标准差(离散度) 偏度(对称性) 峰度(尖峭程度) Jarque-Bera检验 综合偏度与峰度,判断正态性 四个基本统计量 → 综合检验 → 判断数据分布特征

3.7 避坑指南与个人经验

最后,分享几个我踩过的坑:

  • 缺失值处理: 我曾经直接对含NaN的数据算均值,结果全是NaN。一定要先dropna()或fillna()。
  • 异常值影响: 均值对异常值极其敏感。如果数据有极端值,考虑用中位数代替均值。
  • 峰度定义: 不同软件对峰度的定义不同。Excel默认减3,R的kurtosis()函数默认不减3。Python的scipy.stats.kurtosis()默认减3(超额峰度)。
  • 样本量问题: JB检验在大样本下容易拒绝正态性。样本量超过1000时,即使轻微偏离也会被检测出来。这时候要结合Q-Q图综合判断。

好了,这一章就到这里。描述性统计是金融数据分析的基石,看似简单,但用好了能帮你快速洞察数据特征。下一章我们继续深入,聊聊更高级的统计方法。


公众号:蓝海资料掘金营,微信deep3321