σμ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 学习路线›模块 2 · 用于市场数据的 NumPy 与 pandas›主题 2.20·~35分钟中级

直方图与分布

路线进度模块 2/11 · 主题 20/20
2.20 直方图与分布
—实验得分— / 100总 XP—连续天数—

按区间计数

均值和标准差把上千个收益率压缩成两个数字。直方图保留了形状:它把取值范围切成若干区间(bin),统计落入每个区间的观测个数。中间高、两端低是熟悉的钟形;不对称或两端偏重的形状则是警告。np.histogram(values, bins=edges) 对整个数组计数并返回各区间个数。第 i 个区间取 edges[i](含)到 edges[i + 1](不含)的值,只有最后一个区间还包含右端点。

import numpy as np

returns = np.array([-0.021, -0.012, -0.008, -0.004, -0.002, 0.000, 0.001, 0.003, 0.004, 0.006, 0.009, 0.015, 0.032])
edges = np.array([-0.03, -0.01, 0.0, 0.01, 0.03])      # four bins: -3%..-1%, -1%..0%, 0%..1%, 1%..3%

counts, _ = np.histogram(returns, bins=edges)
print(counts.tolist(), counts.sum(), len(returns))      # [2, 3, 6, 1] 12 13   the 3.2% return is outside every bin

# bins=4 asks numpy for 4 equal-width bins between the minimum and the maximum
counts, edges4 = np.histogram(returns, bins=4)
print(counts.tolist(), edges4.round(4).tolist())        # [3, 6, 3, 1] [-0.021, -0.0078, 0.0055, 0.0188, 0.032]

频数还是密度

频数取决于观测数量和区间宽度,因此样本量不同的两个直方图无法比较。密度解决了这个问题:把每个频数除以计入的总数和区间宽度,使所有柱的面积之和为 1。这样密度就可以与理论曲线(如正态钟形)或另一个样本比较。np.histogram(values, bins=edges, density=True) 能做到,counts / (counts.sum() * np.diff(edges)) 也一样。

counts, _ = np.histogram(returns, bins=edges)
density = counts / (counts.sum() * np.diff(edges))
print(density.round(2).tolist())              # [8.33, 25.0, 50.0, 4.17]
print((density * np.diff(edges)).sum())        # 1.0   the areas add up to 1

绘制它并读取尾部

ax.hist(values, bins=10) 一次调用就完成计数和绘制:每个区间一根柱(ax.patches),柱高就是频数。一定要给坐标轴加标签,因为收益率直方图下面没有「日收益率」就毫无意义。形状很重要,而真正伤人的是尾部:统计偏离均值超过 k 个标准差的观测占比 np.mean(np.abs(x - mean) > k * std),就知道极端值出现得多频繁。对正态分布,约 4.6% 的值落在 2 个标准差之外,0.27% 落在 3 个标准差之外。市场比这糟糕得多,后面的主题会看到。

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.hist(returns, bins=5)
ax.set_xlabel("Daily return")
ax.set_ylabel("Frequency")
print(len(ax.patches), [round(p.get_height()) for p in ax.patches])   # 5 [2, 4, 5, 1, 1]   one bar per bin; the heights are the counts

# How often are the returns more than 1 standard deviation from the mean?
mean, std = returns.mean(), returns.std(ddof=1)
print(round(float(np.mean(np.abs(returns - mean) > 1 * std)), 3))     # 0.308   about 4 of 13 days
# The number of bins changes the picture: compare a few
for bins in (2, 4, 8):
    print(bins, np.histogram(returns, bins=bins)[0].tolist())
# 2 [9, 4]
# 4 [3, 6, 3, 1]
# 8 [1, 2, 2, 4, 2, 1, 0, 1]
区间的选择会改变图像区间太少会掩盖形状,太多又会产生噪声。没有唯一正确的个数;多试几个,并用相同的边界比较直方图。还要记住直方图只是样本:下一个样本看起来会略有不同,所以要看整体形状,而不是单个柱。
  • np.histogram(values, bins=edges) 统计每个区间的值;最后一个区间包含右端点。
  • 密度除以计入总数和区间宽度,面积之和为 1,样本因此可以比较。
  • ax.hist(values, bins=n) 绘制它;np.mean(np.abs(x - mean) > k * std) 衡量尾部。给坐标轴加标签,并用相同边界比较。

下一节:收益率的均值与方差,从定义出发计算概括分布的两个数字。

实验:评分内容

  • 用 bin_counts 统计每个区间的收益率个数25 分
  • 用 density 把频数转换为密度25 分
  • 用 fraction_beyond 衡量尾部占比25 分
  • 用 plot_histogram 画出直方图25 分
资源管理器 · lab-53-1
▾ lab-53-1
…
bash · 浏览器内
learner@quantcraft:~/lab-53-1$
Python 尚未加载PythonLn 1, Col 1Spaces: 4UTF-8

要重置此主题吗?

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

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

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

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

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