halo 的技术博客

返回

问题:正态分布对收益撒了两个谎#

打开任何一门金融工程课,收益率建模的起点几乎都是正态分布——数学漂亮、参数只有两个、什么都能算。但只要你把真实股票收益的直方图叠上一条正态曲线,两个谎言立刻现形:

  1. 收益不对称。 股票暴跌起来又快又狠,涨起来却慢慢磨。这意味着收益分布有一条向左伸出的长尾——负偏(negative skew)。正态分布是完美对称的,它假装暴跌和暴涨一样罕见。

  2. 收益是肥尾的。 「六个标准差的事件百年一遇」——正态分布这么说,可现实里每隔几年就来一次。真实收益中间比正态更尖、两端比正态更胖,这叫超额峰度(excess kurtosis)。

这两个谎的代价不是学术上的不优雅,而是真金白银:你用正态分布算出来的 VaR(在险价值)会系统性低估左尾风险。你以为 1% 概率最多亏 3.8%,结果真实的 1% 分位在 -5% 开外——风控模型天天被击穿,却总以为是「小概率巧合」。

正态分布只有均值和方差两个自由度,它结构上没有能力表达偏度和峰度。要如实描述收益,你需要一个能独立调节这四样东西的分布。Johnson SU 就是干这个的。

Johnson SU:一次 arcsinh 变换造出四个自由度#

Johnson 在 1949 年提出一族分布,核心思路朴素得惊人:如果一个变量不服从正态,那就找一个变换 g(·),让变换后的它服从正态。

Johnson SU(“SU” = System Unbounded,无界系统)用的变换是反双曲正弦 arcsinh:

z=γ+δsinh1(xξλ),zN(0,1)z = \gamma + \delta \cdot \sinh^{-1}\left(\frac{x - \xi}{\lambda}\right), \quad z \sim N(0, 1)

四个参数各司其职:

  • ξ(xi,位置):把分布整体左右平移,管中心在哪。
  • λ(lambda,尺度):管分布有多宽,类似标准差的角色。
  • γ(gamma,形状1):管偏度。γ 让 z=0 对应的 x 偏离中心,制造不对称。
  • δ(delta,形状2):管尾部厚度。δ 越小,arcsinh 的压缩越强,尾巴越肥。

关键在 sinh⁻¹。双曲正弦 sinh 在原点附近近似线性,但在两端指数级增长——反过来,arcsinh 把大的极端值压缩回正态的钟形里。换句话说:一个在 Johnson SU 下「6 个尺度单位」的极端亏损,经过 arcsinh 压缩后,在正态世界里可能只是「2.5 个标准差」,因此它的发生概率被大幅提高。这正是肥尾的数学来源。

而 γ 打破对称:它让压缩不再关于中心对称,一边的尾巴被拉得比另一边长——这就是偏度。

scipy 里的参数化(a=γ, b=δ),我们可以直观看到两个形状参数各自控制什么:

参数 a(γ)控制偏度、参数 b(δ)控制尾部厚度,位置和尺度不受影响

左图固定 b=1.5,只动 a:a>0 时分布向左偏(长左尾,对应股票的崩盘尾),a<0 向右偏,a=0 对称。右图固定 a=0,只动 b:b 越小尾巴越肥、峰越尖。两个形状参数正交可调——这是正态分布永远给不了的表达力。

实测:拟合一段有偏肥尾的收益#

光说不练没意义。我们造一段有真实统计特征的收益序列:2000 个观测,真实偏度约 -1.1(明显负偏)、真实超额峰度约 2.4(明显肥尾)——这大致对应一只波动偏大的个股或一个杠杆策略的日收益。

import numpy as np
from scipy import stats

np.random.seed(42)

# 用一个已知的 Johnson SU 作为"真实"数据生成过程
# a>0 -> 负偏(长左尾),模拟股票的崩盘尾特征
true_a, true_b, true_loc, true_scale = 0.9, 1.4, 0.0008, 0.011
r = stats.johnsonsu.rvs(true_a, true_b, loc=true_loc,
                        scale=true_scale, size=2000)

print(f"样本偏度   = {stats.skew(r):.3f}")        # ≈ -1.11
print(f"样本超额峰度 = {stats.kurtosis(r):.3f}")   # ≈ 2.36
python

现在分别用正态和 Johnson SU 去拟合,看谁更贴:

# 正态拟合:只有两个参数
mu, sigma = np.mean(r), np.std(r, ddof=1)

# Johnson SU 拟合:MLE 一次求出四个参数
a_hat, b_hat, loc_hat, scale_hat = stats.johnsonsu.fit(r)

print(f"正态:       μ={mu:.4f}, σ={sigma:.4f}")
print(f"Johnson SU: a={a_hat:.3f}, b={b_hat:.3f}, "
      f"loc={loc_hat:.5f}, scale={scale_hat:.5f}")
# 拟合结果: a≈1.00, b≈1.51 —— 成功识别出负偏和肥尾特征
python

scipy.fit() 内部跑的是极大似然估计(MLE)。把两条拟合曲线叠到经验直方图上:

正态拟合无法表达不对称,把左尾风险压平;Johnson SU 贴合真实的偏肥尾形状

蓝色虚线(正态)是对称的钟形,它既够不着左边的长尾、又高估了右尾的概率,中间的峰也不够尖。红色实线(Johnson SU)几乎描摹出直方图的每一处扭曲——左尾拖长、峰更尖锐。

QQ 图:诊断拟合好坏的照妖镜#

直方图看个大概,QQ 图(分位数-分位数图)才是判断分布拟合优劣的标准工具。它的逻辑很简单:把数据的分位数和理论分布的分位数一一配对,如果拟合完美,所有点应该落在一条 45° 直线上。点偏离直线的地方,就是模型撒谎的地方。

import matplotlib.pyplot as plt

# 正态 QQ:直接对比
stats.probplot(r, dist="norm", sparams=(mu, sigma), plot=plt)

# Johnson SU QQ:先用拟合的 CDF 做概率积分变换,再看是否标准正态
u = stats.johnsonsu.cdf(r, a_hat, b_hat, loc=loc_hat, scale=scale_hat)
u = np.clip(u, 1e-6, 1 - 1e-6)
z = stats.norm.ppf(u)   # 若拟合好,z 应服从标准正态
stats.probplot(z, dist="norm", plot=plt)
python

正态 QQ 图两端明显翘起,说明尾部被系统性错估;Johnson SU QQ 图点贴直线

左图(正态)是教科书级的「肥尾+负偏」病征:两端都翘离直线,左下角的点远远掉到直线下方——这说明真实的极端亏损比正态预测的更极端、更频繁。右图(Johnson SU)经过反变换后,点密密麻麻贴在直线上,只在最边缘有微小偏离。这就是四参数 vs 两参数的差距在尾部的直接体现。

落地:Johnson SU 算出的 VaR 才不会天天被击穿#

分布拟合的终极目的是度量风险。VaR 就是分布的一个左尾分位数:「95% 的日子里,亏损不超过多少?」——这直接是分布 ppf(分位数函数)在 5% 处的取值。

Johnson SU 的一大优势是它的 CDF 和分位数函数解析可算(因为 arcsinh 有闭式反函数),算 VaR 不需要蒙特卡洛,一行搞定:

levels = [0.10, 0.05, 0.01, 0.005]  # VaR 置信水平

for lv in levels:
    emp  = np.percentile(r, lv * 100)                              # 经验真值
    norm = stats.norm.ppf(lv, mu, sigma)                          # 正态 VaR
    jsu  = stats.johnsonsu.ppf(lv, a_hat, b_hat,
                               loc=loc_hat, scale=scale_hat)      # Johnson SU VaR
    print(f"{lv*100:>4.1f}% | 经验 {emp*100:6.2f}% | "
          f"正态 {norm*100:6.2f}% | JSU {jsu*100:6.2f}%")
python

实测结果(单位:日收益 %):

分位经验真值正态 VaRJohnson SU VaR
10.0%-2.50-2.49-2.44
5.0%-3.33-2.95-3.22
1.0%-5.09-3.80-5.24
0.5%-5.50-4.11-6.24

看 1% 这一行——这才是风控真正在意的深尾:经验真值是亏 5.09%,正态却告诉你只会亏 3.80%,低估了 1.3 个百分点。 对一个上了杠杆或做期权的账户,这 1.3% 的低估足以在一次真实的尾部事件里把你打穿。Johnson SU 报的是 5.24%,几乎贴住真值,甚至在 0.5% 的极深尾略微保守(-6.24% vs -5.50%)——保守在风控里恰恰是安全边际。

左尾 VaR 对比:分位越深,正态低估越严重;Johnson SU 在深尾贴合甚至略保守

注意一个细节:在 10% 这种「浅尾」,三者几乎没差别——正态的谎言只在尾部才致命。 平时看着没事,真出事的那一天你才发现风控模型早就失效了。这正是肥尾风险最阴险的地方。

什么时候用它,什么时候别用#

Johnson SU 不是银弹,用错地方一样翻车。三条边界必须记住:

第一,它是风险度量工具,不是收益预测工具。 用它拟合历史收益的形状、算 VaR/CVaR、做压力测试——很好。但别指望用它预测明天涨跌:分布描述的是「收益的散布规律」,不是「下一个收益的方向」。把它当水晶球,是把统计描述误当成因果预测。

第二,高阶矩的估计本身噪声极大。 偏度是三阶矩、峰度是四阶矩,它们对极端值极其敏感——样本里多一个崩盘日,峰度估计能翻倍。 这意味着 δ 和 γ 的拟合值在小样本下很不稳。经验法则:拟合 Johnson SU 至少要几百个观测,最好上千;样本太短时,四参数的自由度反而会去拟合噪声(过拟合)。

第三,MLE 偶尔不收敛或落到局部解。 scipy.fit() 对初值敏感,遇到极端数据可能给出离谱参数。实践中要做两件事:(1) 拟合后务必画 QQ 图目检,别信手就用;(2) 和更稳健的历史模拟法(直接取经验分位数)交叉验证,两者在深尾差太多时,以更保守的一方为准。


A. 实现细节: 数据生成用已知参数的 johnsonsu.rvs 造 2000 个观测(真实偏度 -1.1、超额峰度 2.4),保证「真值」可对照。拟合用 scipy.stats 的 MLE(正态用矩估计 mean/std(ddof=1),Johnson SU 用 .fit())。VaR 直接取拟合分布的 .ppf() 解析分位数,经验真值用 np.percentile。QQ 图对 Johnson SU 采用「概率积分变换 → 标准正态」的方式验证拟合优度。

B. 已知偏差: (1) 数据是从 Johnson SU 生成的,天然对 Johnson SU 有利,真实市场收益未必严格服从任何参数分布——实证中 Johnson SU 也只是「更好的近似」而非真相;(2) 高阶矩估计的抽样误差大,2000 样本下 δ/γ 仍有可观方差,单次拟合的 VaR 数字应带置信区间看;(3) 静态拟合假设分布不随时间变化,但真实波动率和尾部厚度在危机中会剧烈漂移,滚动重估或配合 GARCH 才更现实。

C. 结果解读: 核心结论是正态分布的错只在尾部致命——10% 分位三种方法几乎无差别,但到 1% 分位正态低估 1.3 个百分点、0.5% 分位低估 1.4 个百分点,而这正是爆仓发生的区域。Johnson SU 的价值不在于「更精确」,而在于它结构上能表达负偏和肥尾,从而不会系统性地低估崩盘风险。QQ 图上正态两端翘起、Johnson SU 贴线,是这种表达力差距最直观的证据。适用边界很清楚:把它当风控的分位数计算器(VaR/CVaR/压力测试),别当收益方向的预测器;样本要够长、拟合完要目检、深尾处宁可信更保守的估计。

Johnson SU 分布拟合收益:用四参数分布同时抓住偏度与厚尾
https://blog.halo26812.eu.org/blog/johnson-su-distribution
Author halo
Published at 2026年7月27日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨