σμ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 学习路线›模块 8 · 随机模型与机器学习›主题 8.7·~50分钟高级

控制变量法

路线进度模块 8/11 · 主题 7/10
8.7 控制变量法
—实验得分— / 100总 XP—连续天数—

利用已知信息

模拟看涨期权时,你同时也模拟了到期股价 S_T,它的真实均值 S0 * exp(r * T) 是精确已知的。样本里 S_T 的平均偏离了一点,比如偏高。由于看涨期权收益与 S_T 同向变动,看涨期权的样本均值很可能也偏高。控制变量正是利用这一点:从想要的量的估计中,减去已知量观测误差的若干倍。

import numpy as np

rng = np.random.default_rng(1)
z = rng.standard_normal(2000)
s_t = 100.0 * np.exp((0.05 - 0.5 * 0.2 ** 2) + 0.2 * z)             # terminal prices
call = np.maximum(s_t - 100.0, 0.0)                                  # the payoff we want

known = 100.0 * np.exp(0.05)                                         # E[S_T], exactly
print(round(float(s_t.mean()), 3), round(known, 3))                  # the sample mean of S_T vs its true mean
print(round(float(s_t.mean() - known), 3))                           # the observed error of the control

最优倍数

应该减去多少控制变量的误差?使 payoff - b * control 方差最小的倍数是 b = cov(payoff, control) / var(control),恰好是收益对控制变量回归的斜率(与 CAPM 一节中贝塔用的是相同的各项和)。修正后的估计是 mean(payoff) - b * (mean(control) - known_mean)。它是无偏的,因为被减去的项期望为零。

import numpy as np

def control_coefficient(payoff, control):
    dev = control - control.mean()
    return float(np.sum(dev * (payoff - payoff.mean())) / np.sum(dev ** 2))

rng = np.random.default_rng(1)
z = rng.standard_normal(2000)
s_t = 100.0 * np.exp((0.05 - 0.5 * 0.2 ** 2) + 0.2 * z)
call = np.maximum(s_t - 100.0, 0.0)
known = 100.0 * np.exp(0.05)

b = control_coefficient(call, s_t)
controlled = call.mean() - b * (s_t.mean() - known)
print(round(b, 4), round(float(call.mean()), 4), round(float(controlled), 4))       # the plain mean and the corrected one
# A payoff that is exactly proportional to the control is estimated without any error
import numpy as np

x = np.random.default_rng(2).standard_normal(50) + 5.0          # the control, known mean 5.0
y = 2.0 * x                                                      # the payoff
dev = x - x.mean()
b = np.sum(dev * (y - y.mean())) / np.sum(dev ** 2)
print(round(float(b), 6), round(float(y.mean() - b * (x.mean() - 5.0)), 6))      # 2.0 and exactly 10.0

节省多少误差

携带噪声的是调整后的样本 payoff - b * control,所以修正后估计的标准误就是其标准差(ddof=1)除以 sqrt(n)。设收益与控制变量的相关系数为 rho,方差会降为原来的 1 - rho^2:相关 0.9 去掉 81%,0.99 去掉 98%。控制变量不需要额外的模拟,只多几行代码。

import numpy as np

def control_variate_error(payoff, control):
    dev = control - control.mean()
    b = np.sum(dev * (payoff - payoff.mean())) / np.sum(dev ** 2)
    return float((payoff - b * control).std(ddof=1) / np.sqrt(len(payoff)))

rng = np.random.default_rng(1)
z = rng.standard_normal(20000)
s_t = 100.0 * np.exp((0.05 - 0.5 * 0.2 ** 2) + 0.2 * z)
for strike in (80.0, 100.0, 120.0):
    call = np.maximum(s_t - strike, 0.0)
    plain = float(call.std(ddof=1) / np.sqrt(len(call)))
    print(strike, round(plain, 4), round(control_variate_error(call, s_t), 4), round(plain / control_variate_error(call, s_t), 2))
好的控制变量既相关又已知两个条件都重要。控制变量必须与收益同向变动(否则 b 接近 0,毫无收益),其精确均值必须已知(否则修正只是猜测)。亚式期权算术平均的好控制变量是价格有公式的几何平均,或到期价格本身。也可以同时使用多个控制变量,此时系数来自多元回归。
  • 控制变量是均值已知的模拟量;从估计中减去其观测误差的若干倍:mean(Y) - b * (mean(X) - E[X])。
  • 最优倍数是回归斜率 b = cov(Y, X) / var(X);误差为 Y - b * X 的标准差除以 sqrt(n)。
  • 方差降为 1 - rho^2 倍;好的控制变量与收益高度相关、均值精确已知,且不需要额外模拟。

下一节:用于收益率的 scikit-learn 流水线,在收益率数据上拟合并评估预测模型。

实验:评分内容

  • 用 control_coefficient 选取合适的倍数25 分
  • 用 control_variate_estimate 修正估计25 分
  • 用 control_variate_error 缩小误差条25 分
  • 用 error_reduction 计算改进倍数25 分
资源管理器 · lab-108-1
▾ lab-108-1
…
bash · 浏览器内
learner@quantcraft:~/lab-108-1$
Python 尚未加载PythonLn 1, Col 1Spaces: 4UTF-8

要重置此主题吗?

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

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

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

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

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