跳到主要内容

描述统计与假设检验

直觉

算出「策略平均日收益 0.03%」之后,真正的问题是:这 0.03% 是真的,还是运气? 假设检验就是给「一个估计值」配上一个置信度的工具——它告诉你,如果真相其实是 0,观察到当前样本的概率有多大。

数学原理

样本均值与标准误

nn 个样本,样本均值 xˉ\bar x、样本标准差 ss。均值估计的标准误(standard error)为:

SE=sn\text{SE} = \frac{s}{\sqrt{n}}

t 统计量与 p 值

检验 H0: μ=0H_0:\ \mu=0

t=xˉ0SE=xˉs/n,p=P(Tt)t = \frac{\bar x - 0}{\text{SE}} = \frac{\bar x}{s/\sqrt n}, \qquad p = P(|T| \ge |t|)
「人话」解释:t 和 p 在说什么?
  • t:均值是「标准误」的多少倍。t|t| 越大,均值离 0 越远(相对于抽样误差)。
  • p 值:假设真实均值真的为 0,靠运气得到这么极端的 t|t| 的概率。p 越小,越有理由拒绝「均值为 0」。
  • 经验门槛:p<0.05p<0.05 常被称为「显著」,但这只是约定,不等于「策略一定赚钱」(见模块 9 多重检验陷阱)。

可运行案例:合成 SPY 的日均收益显著为正吗?

读取 spy_daily.csv 的对数收益,做单样本 t 检验H0H_0 为「日均收益=0」。

import numpy as np
import pandas as pd
from scipy import stats

df = pd.read_csv('/data/spy_daily.csv', parse_dates=['date']).set_index('date')
r = np.log(df['close'] / df['close'].shift(1)).dropna()

n = len(r)
mean = r.mean()
se = r.std(ddof=1) / np.sqrt(n)          # 标准误
t_stat = mean / se

res = stats.ttest_1samp(r, 0.0)          # H0: 均值 = 0
print(f"样本数 n     : {n}")
print(f"日均收益     : {mean:.6f}   (年化 {mean*252:.4f})")
print(f"标准误 SE    : {se:.6f}")
print(f"t 统计量     : {t_stat:.3f}")
print(f"p 值         : {res.pvalue:.4f}")
print(f"95% 置信区间 : [{mean - 1.96*se:.6f}, {mean + 1.96*se:.6f}]")

if res.pvalue < 0.05:
  print("→ p<0.05:拒绝'均值为0',日均收益在统计上显著异于 0")
else:
  print("→ p>=0.05:无法拒绝'均值为0',不显著")

动手改一改

试着只取最近 252 天r = r.tail(252))再检验——样本变少,标准误变大,p 值通常变差。这就是「小样本难以证实规律」的体现。

小结

  • 均值估计的波动用标准误 s/ns/\sqrt n 衡量;
  • t 检验判断均值是否显著异于某值;p 值是「纯属运气」的概率;
  • 显著性 \ne 实战有效性——样本量、多重检验、效应大小都要一起看(模块 9 详谈)。