σμ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.1·~45分钟中级

协方差矩阵与相关矩阵

路线进度模块 5/11 · 主题 1/5
5.1 协方差矩阵与相关矩阵
—实验得分— / 100总 XP—连续天数—

从一个资产到多个资产

到目前为止我们只看一条收益率序列。投资组合持有许多资产,它的风险不仅取决于每个资产本身的风险,还取决于它们如何*一起*变动。两个资产的协方差是它们各自偏离均值的偏差之积的平均:如果倾向于同涨同跌则为正,一个涨时另一个跌则为负。n 个资产有 n * n 个协方差,排成协方差矩阵,它是对称的,对角线上是方差。

import numpy as np

# Five days of returns for two assets: shape (days, assets)
returns = np.array([[0.01, 0.02], [-0.02, -0.01], [0.03, 0.01], [0.00, -0.02], [0.01, 0.03]])

centered = returns - returns.mean(axis=0)            # subtract each column's mean
cov = centered.T @ centered / (len(returns) - 1)     # (assets x days) @ (days x assets) -> (assets x assets)
print(np.round(cov, 6))
print(np.allclose(cov, np.cov(returns, rowvar=False)))     # True

样本协方差矩阵

对于形状为 (days, assets) 的收益率表,整个矩阵只需一行线性代数。先减去每列的均值(axis=0,按天求平均),再用中心化后的表的转置乘以它自己:centered.T @ centered 的 (i, j) 项是各天 x_i * x_j 之和。然后像样本方差那样除以 days - 1。np.cov(returns, rowvar=False) 和 DataFrame.cov() 计算的就是它;注意 rowvar=False,因为 np.cov 默认资产在行上。

相关系数:去掉单位的协方差

0.0004 的协方差说明不了什么:它取决于两个资产本身的波动有多大。除以两个标准差的乘积会去掉尺度,得到总是介于 -1 和 1 之间的相关系数:corr[i, j] = cov[i, j] / (std[i] * std[j]),其中 std 是对角线的平方根。代码中 np.outer(std, std) 构造乘积表,一次除法就重新缩放整个矩阵,对角线上是 1。相关系数说明两个资产联动得多紧;而保留尺度的协方差才是风险公式所需要的。

# From covariance to correlation and annualised volatilities
import numpy as np

returns = np.array([[0.01, 0.02], [-0.02, -0.01], [0.03, 0.01], [0.00, -0.02], [0.01, 0.03]])
cov = np.cov(returns, rowvar=False)

std = np.sqrt(np.diag(cov))
corr = cov / np.outer(std, std)
print(np.round(corr, 4))
print(np.round(np.sqrt(np.diag(cov) * 252), 4))      # daily variances scaled to a year: volatility grows with sqrt(252)

这个矩阵可能成立吗?

随便一张数表并不是协方差矩阵。它必须是对称的和半正定的:对任意权重 w,w' C w 是一个投资组合的方差,不可能为负。等价地说,没有小于零的特征值。估计出来的矩阵能通过,但手工修改过的,或由不同来源的相关系数拼凑起来的(例如 A~B = 0.9、B~C = 0.9、A~C = -0.9)则通不过。用 np.linalg.eigvalsh 检查,它针对对称矩阵并返回实特征值,同时为舍入误差留一个很小的容差。

# A validity check: symmetry and no negative eigenvalue
import numpy as np

def is_valid_cov(matrix, tol=1e-10):
    symmetric = bool(np.all(np.abs(matrix - matrix.T) <= tol))
    return symmetric and bool(np.linalg.eigvalsh(matrix).min() >= -tol)

good = np.array([[1.0, 0.5, 0.2], [0.5, 1.0, 0.3], [0.2, 0.3, 1.0]])
bad = np.array([[1.0, 0.9, -0.9], [0.9, 1.0, 0.9], [-0.9, 0.9, 1.0]])
print(is_valid_cov(good), np.round(np.linalg.eigvalsh(good), 3))
print(is_valid_cov(bad), np.round(np.linalg.eigvalsh(bad), 3))
# Few days, many assets: the sample covariance matrix is singular
import numpy as np

rng = np.random.default_rng(0)
returns = rng.normal(0, 0.01, size=(5, 8))              # 5 days, 8 assets
cov = np.cov(returns, rowvar=False)
print(np.linalg.matrix_rank(cov), "of", cov.shape[0])  # 4 of 8: some portfolios seem to have zero variance
观测少、资产多500 只股票的矩阵有 125,250 个不同的元素,却可能只用 250 天数据来估计。天数少于资产数时,样本矩阵是奇异的:某个组合看起来方差为零,任何优化器都不该相信这一点。从业者会把矩阵向一个简单目标收缩,或使用因子模型。估计值还是对过去的平均:平静时期和危机时期的协方差差别很大。
  • (days, assets) 表的协方差矩阵是 centered.T @ centered / (days - 1):对称,对角线为方差。
  • 相关系数是 cov / np.outer(std, std):无单位,介于 -1 和 1 之间,对角线为 1;方差乘以 periods 年化,波动率乘以其平方根。
  • 有效的协方差矩阵是对称的且没有负特征值(np.linalg.eigvalsh);天数太少的估计或手工修补的矩阵可能违反这一点。

下一节:投资组合的收益与方差,把权重和这个矩阵变成组合的风险。

实验:评分内容

  • 用 cov_matrix 构建协方差表25 分
  • 用 corr_from_cov 缩放为相关系数25 分
  • 用 annualised_vols 读出每个资产的波动率25 分
  • 用 is_valid_cov 检验它是否可能成立25 分
资源管理器 · lab-82-1
▾ lab-82-1
…
bash · 浏览器内
learner@quantcraft:~/lab-82-1$
Python 尚未加载PythonLn 1, Col 1Spaces: 4UTF-8

要重置此主题吗?

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

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

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

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

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