σμ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 AcademyRoadmapsSkills
Ctrl K
AO
+1.2k Learners
LoginJoin ↗
RoadmapsSkills
AO
+1.2k Learners
Login
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
σμ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 AcademyRoadmapsSkills
Ctrl K
AO
+1.2k Learners
LoginJoin ↗
RoadmapsSkills
AO
+1.2k Learners
Login
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
SciPy skill›Module 1 · Fitting and finding›Topic 1.3·~45 minIntermediate

Hypothesis tests and the bootstrap

Skill positionModule 1 of 3 · Topic 3 of 8
1.3 Hypothesis tests and the bootstrap
—Lab score— / 100Total XP—Streak—

An error bar for every claim

A backtest says a strategy earned 0.05% a day. Is that skill or luck? A hypothesis test answers with a p-value: if the true mean were zero, how often would a sample look this good? stats.ttest_1samp(r, 0.0) tests one mean, and stats.ttest_ind(a, b, equal_var=False) compares two assets without assuming they are equally volatile (Welch's test, the safe default). stats.jarque_bera(r) checks whether returns are normal by looking at skewness and kurtosis. A small p-value is evidence against the idea you tested, not proof of the idea you like. And a test is only as good as its assumptions: the t-test assumes thin tails, which daily returns do not have.

When formulas are doubtful, resample. The bootstrap draws many samples with replacement from your data, recomputes a statistic each time (the mean, a Sharpe ratio, a quantile) and reads an interval from the spread of the results: stats.bootstrap((r,), stat, method='percentile', random_state=np.random.default_rng(seed)). The statistic must accept an axis argument, because SciPy passes a whole batch of resamples at once, and the seed makes the answer repeatable. A permutation test shuffles the labels of two groups to see how often chance alone gives a gap as large as the one observed. Finally, test 62 assets at the 5% level and about three will look significant by luck alone. stats.false_discovery_control(p) applies the Benjamini–Hochberg correction and tells you which discoveries survive.

What the real data saysOver the last 2,500 trading days SPY earned a mean daily return of 0.046%, with t=2.80 and p=0.005. Its annualised Sharpe ratio is 0.89, and a 95% bootstrap interval runs from 0.26 to 1.53: the data do not pin it down better than that. Of the 62 assets, 22 pass the 5% test for a non-zero mean, but only 12 survive the Benjamini–Hochberg correction. The Jarque–Bera test rejects normality for SPY with a p-value of 0.
  • Welch by default: do not assume two assets share a volatility.
  • Resample when unsure: a bootstrap needs a statistic with an axis argument and a seed.
  • Count your tests: 62 tests at 5% give about three false discoveries; correct for them.

Lab · what's graded

  • Is the mean zero?8 pts
  • Two assets, two volatilities8 pts
  • A normality test6 pts
  • A bootstrap interval18 pts
  • An annualised Sharpe ratio8 pts
  • A Sharpe ratio with an error bar10 pts
  • A permutation test14 pts
  • Counting false discoveries12 pts
  • The whole study16 pts
Explorer · lab-sp-13
▾ lab-sp-13
▾ data
…
bash · in-browser
learner@quantcraft:~/lab-sp-13$
Python not loaded yetPythonLn 1, Col 1Spaces: 4UTF-8

Reset this topic?

Everything in lab-sp-13 goes back to the starter files and the terminal is cleared. Your current solution will be lost — this can't be undone.

Will be reset
  • main.py → starter code
  • Terminal history and test output
  • Unsubmitted changes
Will be kept
  • Best lab score
  • Your XP and streak
  • Lecture progress and notes

Log in to run your code.

Every lecture is free to read. Create an account or log in to run code, run tests and submit this lab.

  • In-browser IDE with a bash terminal — nothing to install
  • Instant grading, XP and your place on the skill
Create an accountLog in
OR
Continue with GitHub