🔴
入学要求
💯
能力测试
🛣️
课程安排
🕹️
研究资源

第8讲:统计矩 (Statistical Moments)

💡

查看全集:💎Quantopia量化分析56讲


1. 偏度(Skewness)

1.1 对称与偏态分布

正态分布示例

import matplotlib.pyplot as plt
import numpy as np
import scipy.stats as stats

# 生成正态分布数据
xs = np.linspace(-6, 6, 300)
normal = stats.norm.pdf(xs, loc=0, scale=2)  # 均值0,标准差2
plt.plot(xs, normal)
plt.title("正态分布(对称)")
plt.show()

1.2 偏度公式

偏度衡量分布的不对称性,公式为:

Skewness=1ni=1n(Xiμσ)3\text{Skewness} = \frac{1}{n} \sum_{i=1}^n \left( \frac{X_i - \mu}{\sigma} \right)^3

其中 μ为均值,σ为标准差。

偏态分布示例

# 生成偏态数据
xs2 = np.linspace(0.01, 0.99, 100)
lognormal = stats.lognorm.pdf(xs2, s=0.7)

plt.plot(xs2, lognormal, label='正偏态(右偏)')
plt.plot(xs2, lognormal[::-1], label='负偏态(左偏)')
plt.legend()
plt.title("偏态分布对比")
plt.show()

1.3 实际数据中的偏度

使用标普500收益率分析偏度:

import yfinance as yf

# 下载标普500历史数据
start = '2012-01-01'
end = '2015-01-01'
data = yf.download('SPY', start=start, end=end)
prices = data['Close']
returns = prices.pct_change().dropna()

# 计算偏度、均值、中位数
from scipy import stats
print(f"偏度: {stats.skew(returns):.4f}")
print(f"均值: {returns.mean():.6f}")
print(f"中位数: {returns.median():.6f}")

# 绘制收益率直方图
plt.hist(returns, bins=30)
plt.title("标普500收益率分布")
plt.show()

2. 峰度(Kurtosis)

2.1 峰度的定义

不同峰度分布对比

xs = np.linspace(-6, 6, 300)
plt.plot(xs, stats.laplace.pdf(xs), label='尖峰厚尾(超额峰度>0)')
plt.plot(xs, stats.norm.pdf(xs), label='正态分布(超额峰度=0)')
plt.plot(xs, stats.cosine.pdf(xs), label='低峰薄尾(超额峰度<0)')
plt.legend()
plt.title("峰度对比")
plt.show()

2.2 峰度公式

峰度计算公式:

Kurtosis=1ni=1n(Xiμσ)4\text{Kurtosis} = \frac{1}{n} \sum_{i=1}^n \left( \frac{X_i - \mu}{\sigma} \right)^4

超额峰度为 Kurtosis - 3。

标普500峰度计算

print(f"超额峰度: {stats.kurtosis(returns):.4f}")

3. 正态性检验:Jarque-Bera 测试

3.1 测试原理

测试标普500收益率的正态性

from statsmodels.stats.stattools import jarque_bera

# 执行Jarque-Bera测试
jb_stat, pvalue, _, _ = jarque_bera(returns)
print(f"Jarque-Bera p值: {pvalue:.4f}")

if pvalue > 0.05:
    print("收益率可能服从正态分布。")
else:
    print("收益率可能不服从正态分布。")

3.2 测试校准

通过模拟正态数据验证测试准确性:

np.random.seed(42)
p_values = []
for _ in range(1000):
    sample = np.random.normal(0, 1, 1000)
    _, pval, _, _ = jarque_bera(sample)
    p_values.append(pval)

# 计算显著比例(应接近5%)
significant = sum(np.array(p_values) < 0.05) / len(p_values)
print(f"错误拒绝比例: {significant:.3f}")

关键点总结

附:练习合集