σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft Academy学习路线
Ctrl K
AO
+1.2k 位学习者
登录加入 ↗
学习路线
AO
+1.2k 位学习者
登录
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Python 学习路线›模块 3 · 概率与蒙特卡洛模拟›主题 3.4·~45分钟中级

假设检验:t 检验

路线进度模块 3/11 · 主题 4/12
3.4 假设检验:t 检验
—实验得分— / 100总 XP—连续天数—

平均收益率是真实的吗?

回测显示平均日收益为 +0.14%。策略是真的好,还是运气好?收益率有噪声,所以任何样本都有均值,连抛硬币策略也有一半的时候均值为正。假设检验提出一个精确的问题:如果真实均值是 mu0(通常为 0),那么样本均值偏离 mu0 这么远有多令人意外?答案就是 p 值。p 值小,说明在「什么都没发生」的假设下,这样的数据极不可能出现。

t = (mean - mu0) / (s / sqrt(n)) p = P(|Z| > |t|)

t 统计量以均值自身的不确定性为单位来衡量均值。均值的不确定性是标准误 s / sqrt(n):样本越大它越小,所以数据越多,同样的均值越有说服力。把所有收益率按比例缩放,均值和标准误同比例变化,因此 t 不变。经验上,|t| 大于 2 就不太可能是运气。

import math
import numpy as np

returns = np.array([0.004, -0.002, 0.001, 0.003, -0.004, 0.002, 0.006, -0.001, 0.005, 0.002, 0.003, -0.002])

n = len(returns)
mean = returns.mean()
std_error = returns.std(ddof=1) / math.sqrt(n)         # the uncertainty of the mean
t = mean / std_error                                   # testing against mu0 = 0

print(round(mean, 5), round(std_error, 6))             # 0.00142 0.000892   the mean is only 1.6 standard errors from 0
print(round(t, 3))                                     # 1.589

从 t 到 p 值

在原假设下,样本较大时 t 近似标准正态,所以双侧 p 值是落在离 0 超过 |t|(任一方向)的概率:erfc(|t| / sqrt(2))。当 t = 1.59 时是 11%:这样好的结果纯靠运气每九次就会出现一次,因此不能宣称有真实优势。常用阈值是 5%(|t| = 1.96)。对小样本,正确的参照是尾部更厚的学生 t 分布,所以正态近似的 p 值略小;少于 30 个点时应使用真正的 t 表。

p_value = math.erfc(abs(t) / math.sqrt(2))
print(round(p_value, 4))                      # 0.1121   an outcome this good happens by chance about 1 time in 9

print(round(math.erfc(1.96 / math.sqrt(2)), 4))   # 0.05     |t| = 1.96 is the usual 5% limit

# Testing against another value: is the mean different from 0.2% a day?
t_other = (mean - 0.002) / std_error
print(round(t_other, 3), round(math.erfc(abs(t_other) / math.sqrt(2)), 3))   # -0.654 0.513

置信区间与配对样本

置信区间比是/否的检验说得更多:均值 -/+ 1.96 * 标准误 是约有 95% 的概率包含真实均值的范围。若区间包含 0,则均值在 5% 水平上不显著。我们的区间是日均 -0.03% 到 +0.32%,跨过零,而且相对均值很宽。要比较在同样日期上测得的两个策略,就把它们每天的差值与 0 比较。配对消除了二者共有的噪声(市场的好日子和坏日子),因此比两次独立检验更敏锐地发现优势。

low, high = mean - 1.96 * std_error, mean + 1.96 * std_error
print(round(low, 5), round(high, 5))           # -0.00033 0.00316   the interval contains 0: not significant at 5%

# Paired: the same six days for two strategies
a = np.array([0.004, -0.002, 0.001, 0.003, -0.004, 0.002])
b = np.array([0.002, -0.003, 0.000, 0.001, -0.002, 0.0])
d = a - b
t_paired = d.mean() / (d.std(ddof=1) / math.sqrt(len(d)))
print(round(d.mean(), 5), round(t_paired, 3))   # 0.001 1.581   a daily edge of 0.1%, but only 6 days
# Same mean and spread, four times the data: t doubles and the p-value collapses
spread = returns.std(ddof=1)
for n in (12, 48):
    t_n = mean / (spread / math.sqrt(n))
    print(n, round(t_n, 3), round(math.erfc(abs(t_n) / math.sqrt(2)), 4))
# 12 1.589 0.1121
# 48 3.178 0.0015
显著不等于重要,而且很多检验会作弊足够多的数据下,很小的优势也可能非常显著;数据少时,很大的优势也可能不显著。请始终把效应大小与 p 值一起看。而且如果你检验 100 个策略,仅凭运气就有约 5 个在 5% 水平上通过:在同一批数据上尝试的变体越多,单个 p 值的意义就越小。
  • t = (mean - mu0) / (s / sqrt(n)):以标准误 s / sqrt(n) 为单位的均值;数据越多,|t| 越大。
  • 大样本下双侧 p 值是 erfc(|t| / sqrt(2));|t| > 1.96 即 p < 5%;区间 mean -/+ 1.96 * se 含 0 则不显著。
  • 用每日差值的 t 统计量在同样日期上比较策略;当心检验过多变体。

下一节:线性回归(OLS),拟合一条用一个收益率解释另一个收益率的直线。

实验:评分内容

  • 用 t_statistic 以噪声为单位衡量均值25 分
  • 用 two_sided_p 把 t 转换为 p 值25 分
  • 用 confidence_interval 框出真实均值的范围25 分
  • 用 paired_t_statistic 逐日比较两个策略25 分
资源管理器 · lab-57-1
▾ lab-57-1
…
bash · 浏览器内
learner@quantcraft:~/lab-57-1$
Python 尚未加载PythonLn 1, Col 1Spaces: 4UTF-8

要重置此主题吗?

lab-57-1 中的所有内容将恢复为初始文件,终端也会被清空。你当前的解答将丢失,且无法撤销。

将被重置
  • main.py → 初始代码
  • 终端历史与测试输出
  • 未提交的更改
将被保留
  • 实验最高得分
  • 你的 XP 与连续天数
  • 讲解进度与笔记

登录后即可运行你的代码。

所有讲解均可免费阅读。创建账户或登录后,即可运行代码、运行测试并提交此实验。

  • 浏览器内 IDE 与 bash 终端,无需安装
  • 即时评分、XP 以及你在学习路线中的位置
创建账户登录
或
使用 GitHub 继续