σμ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 学习路线›模块 5 · 投资组合优化›主题 5.2·~45分钟中级

投资组合的收益与方差

路线进度模块 5/11 · 主题 2/5
5.2 投资组合的收益与方差
—实验得分— / 100总 XP—连续天数—

投资组合就是一个权重向量

投资组合由每个资产的权重描述:即其价值中投入该资产的比例。权重之和为 1,负权重是为其他资产融资的空头头寸。一个期间的收益是各资产收益的加权平均,所以预期收益是点积 w @ mu。收益是容易的那一半:它是线性的,资产之间没有相互作用。风险则不是。

import numpy as np

weights = np.array([0.6, 0.4])             # 60% in asset A, 40% in asset B
mu = np.array([0.08, 0.05])                # expected annual returns

print(weights.sum())                       # 1.0
print(weights @ mu)                        # 0.068   = 0.6 * 0.08 + 0.4 * 0.05

方差是一个二次型

对两个资产,w1 * A + w2 * B 的方差是 w1**2 * var(A) + w2**2 * var(B) + 2 * w1 * w2 * cov(A, B):每个资产自身的方差,再加一个交叉项。n 个资产有 n * n 项 w_i * w_j * cov[i, j],整个和就是二次型 w @ cov @ w,在 NumPy 中只要一行。关键在交叉项:当两个资产不完全相关时,它们会部分抵消,于是组合的风险小于各自风险的加权平均。

# The variance two ways: the explicit formula and the matrix form
import numpy as np

weights = np.array([0.6, 0.4])
cov = np.array([[0.04, 0.006], [0.006, 0.01]])      # variances 0.04 and 0.01 (volatilities 20% and 10%), covariance 0.006

explicit = weights[0] ** 2 * cov[0, 0] + weights[1] ** 2 * cov[1, 1] + 2 * weights[0] * weights[1] * cov[0, 1]
matrix_form = weights @ cov @ weights
print(round(explicit, 6), round(matrix_form, 6))     # 0.01888 0.01888
print(round(float(np.sqrt(matrix_form)), 4))         # 0.1374   a 13.7% volatility, below 0.6*20% + 0.4*10% = 16%
# Diversification: 50/50 in two assets of 20% volatility, for several correlations
import numpy as np

weights = np.array([0.5, 0.5])
for rho in (1.0, 0.5, 0.0, -0.5):
    cov = 0.2 * 0.2 * np.array([[1.0, rho], [rho, 1.0]])
    print(rho, round(float(np.sqrt(weights @ cov @ weights)), 4))      # 1.0: 0.2, 0.5: 0.1732, 0.0: 0.1414, -0.5: 0.1

风险从哪里来?

基金经理想知道哪些仓位在制造风险。资产 i 的风险贡献是 w_i * (cov @ w)_i / sigma_p:它的权重,乘以它与整个组合的联动强度,再除以组合波动率 sigma_p。各项贡献之和恰好等于 sigma_p,把总风险拆成几个部分。权重小但与其余资产协方差很高的资产,贡献可能远超其权重所暗示的,而对冲仓位的贡献可以是负的。

# Risk contributions of a three-asset portfolio: they add up to the volatility
import numpy as np

weights = np.array([0.5, 0.3, 0.2])
cov = np.array([[0.0400, 0.0060, 0.0100],
                [0.0060, 0.0100, 0.0020],
                [0.0100, 0.0020, 0.0225]])

variance = weights @ cov @ weights
contributions = weights * (cov @ weights) / np.sqrt(variance)
print(np.round(contributions, 4), round(float(contributions.sum()), 4))
print(round(float(np.sqrt(variance)), 4))
输入比公式更重要公式是精确的,但 mu 和 cov 是估计值,而且方差比预期收益可靠得多:预期收益噪声很大,协方差则小得多。权重、mu 和 cov 还必须对应同一个期间:把日协方差与年收益率混用是常见错误;方差乘以期数,波动率乘以其平方根。
  • 组合收益是线性的:w @ mu。方差是二次型 w @ cov @ w,含 n * n 项和交叉项,相关系数小于 1 就能降低风险。
  • 波动率是 sqrt(variance * periods);年化必须与 cov 的期间一致。
  • 风险贡献 w_i * (cov @ w)_i / sigma_p 把波动率恰好按资产拆分;对冲仓位的贡献可能为负。

下一节:最小方差组合,选取使这一风险尽可能小的权重。

实验:评分内容

  • 用 portfolio_return 汇总预期收益25 分
  • 用 portfolio_variance 衡量风险25 分
  • 用 portfolio_vol 给出波动率25 分
  • 用 risk_contributions 按资产拆分风险25 分
资源管理器 · lab-83-1
▾ lab-83-1
…
bash · 浏览器内
learner@quantcraft:~/lab-83-1$
Python 尚未加载PythonLn 1, Col 1Spaces: 4UTF-8

要重置此主题吗?

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

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

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

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

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