Learn⚠️ RiskQ-Q Plot & Jarque-Bera — Are Your Returns Actually Normal?
⚠️ Risk7 min read

Q-Q Plot & Jarque-Bera — Are Your Returns Actually Normal?

Stock returns frequently deviate from normal: fat tails + left skew. Q-Q Plot and Jarque-Bera test reveal this empirically — the reason our VaR/CVaR uses historical simulation.

Q-Q Plot & Jarque-Bera — Are Your Returns Actually Normal?

4-section structure: Concept / How We Compute / How to Read / Caveats.

1. Concept

Many finance textbooks, risk models and portfolio theories assume normal returns:

  • Markowitz efficient frontier (mean + variance sufficient)
  • Black-Scholes option pricing (normal)
  • Parametric VaR (mean − 1.645σ)
  • Classical Sharpe Ratio (symmetry assumption)

Empirically, stock returns are not normal. Two characteristic deviations:

  1. Fat tails — extreme moves (±3σ+) happen far more often than normal predicts
  2. Skewness — typically left-skewed (down moves more violent)

Two complementary tools to test this:

ToolNatureQuestion
Q-Q PlotVisual"How far do points stray from the 45° line?"
Jarque-BeraStatistical test"p-value for rejecting normality?"

2. How We Compute

2.1 Q-Q Plot

1. Standardize: (r − mean) / σ (ddof=1)
2. Sort
3. For i-th sample (i = 0..n-1), plotting position p = (i + 0.5) / n
4. Theoretical quantile = Φ⁻¹(p)  (via statistics.NormalDist)
5. Plot (theoretical, sample) and overlay y=x reference line

Reading:

  • All points on green 45° line → perfectly normal
  • Tails straying upward → fat tails
  • Left-tail pulled down → negative skew
  • Widespread deviation → severely non-normal

Red dots mark points where |sample − theoretical| > 0.8. We downsample to 60 points for clean visuals.

2.2 Jarque-Bera Test

JB = n/6 × (skewness² + (excess_kurtosis)² / 4)
H₀: sample is normal
H₁: not normal
JB asymptotically ~ χ²(df=2)

For df=2, there's a closed-form p-value = exp(−JB/2) — no scipy dependency.

Verdicts (α = 0.05, critical = 5.991):

  • p ≥ 0.10 → fail_to_reject
  • 0.05 ≤ p < 0.10 → marginal
  • 0.001 ≤ p < 0.05 → reject
  • p < 0.001 → strong_reject

2.3 Data & Window

  • Past 252 trading days' simple daily returns
  • Sample < 60 → available: false

2.4 Fisher Excess Kurtosis (Normal = 0)

Consistent with v2.42 platform-wide fix. excess_kurt > 0 directly means "fatter than normal", more intuitive than raw kurtosis.


3. How to Read

3.1 Q-Q Plot Reading

PatternMeaning
Points on 45° linePerfectly normal (rare)
Center fits, tails stray upFat tails (most common in stocks)
Center fits, left dropsLeft skew (heavy down tail)
Widespread deviationSeriously non-normal (e.g., leveraged ETF)

Red dots (|theoretical − sample| > 0.8) usually cluster in the tails. More red + farther = more severe deviation.

3.2 Skewness & Excess Kurtosis Scales

MetricRangeReading
Skewness−0.5 to +0.5Near-symmetric
< −1Clear left skew (heavy down tail)
> +1Clear right skew (rare)
Excess Kurtosis< 1Near-normal
1 to 5Typical stock
> 5Severe fat tails

3.3 Decision Impact

If reject normality (most cases):

  1. Parametric VaR underestimates risk → use historical simulation (our choice)
  2. Sharpe incomplete risk picture → pair with Sortino + CVaR
  3. Portfolio correlations spike in extremes → P0.2 matrix misses this in normal times

If near normal (rare):

  • Trust Sharpe + parametric VaR
  • Typically liquid large-caps or steady dividend financials

4. Caveats

⚠️ JB Too Sensitive in Large Samples

With n > 1000, even near-normal samples almost always reject. Big-sample test issue.

Mitigation: look at absolute values of skew & excess kurt, not just p-value. If skew within ±0.5, excess kurt < 1, treat as "near-normal enough" even when p < 0.05.

⚠️ JB Is Asymptotic

Chi-square approximation breaks at small n. MIN_SAMPLE_DAYS = 60 ensures validity.

⚠️ Q-Q Plot Subjectivity

"How much deviation is significant?" — no hard answer. |Δ| > 0.8 threshold is visual aid, not formal test. Q-Q excels at comparing two samples (Stock A vs B) more than absolute judgments.

⚠️ Not for Extreme Samples

  • One-sided movement (only rising) → Q-Q tails distort
  • Structural breaks (M&A, business pivot) → mixing two distributions

JB rejection here means "history is heterogeneous", not "future is non-normal".

⚠️ Non-Normality Doesn't Invalidate Theory

Normal is the basis of Markowitz / Sharpe / Black-Scholes. Deviation means know the limits, not "abandon everything":

  • Fails during extreme events
  • Understates "true" risk
  • Portfolios may collapse in tail events

This awareness beats blanket rejection.


Further Reading

  • VaR vs CVaR: Worst 5% Loss
  • Sortino & Downside Deviation
  • Sharpe Ratio

Try It

  • Stock Analysis → Risk: scroll to "Return Normality Diagnostic"
  • Watch tail deviations and red dot count
  • Compare to skew / excess kurtosis values
  • Compare different stock types: blue-chip vs speculative — huge JB differences
  • Click 📐 for formulas, thresholds, data sources

Done reading? Try it hands-on

Practice with CTSstock tools to deepen your understanding

View TSMC's return distribution diagnostic