第 7 章 · 02 主观观点融合


文档摘要

第 7 章 · 02 主观观点融合 本节摘要:有了先验还不够——你总有些「AAPL 要涨 20%」「GOOG 会跑赢 FB」的判断。Black-Litterman 的第二块基石是「贝叶斯融合」:把主观观点(view)通过 P/Q 矩阵编码,通过 Ω 矩阵表达观点的不确定度,用贝叶斯公式把先验和观点加权融合,得到后验收益。本节讲清 类的两大输入——观点(P/Q 或 absoluteviews)、置信度(omega),以及 BL 后验公式 的实现细节。读完本节,你能把任意主观观点融合成稳定的后验收益。 内容来源:原项目源码 、文档 、cookbook ,汉化并套用体系化模板。 学习目标 阅读完本节,你应当能够: 区分 绝对观点 与 相对观点,分别用 和 编码。

第 7 章 · 02 主观观点融合

本节摘要:有了先验还不够——你总有些「AAPL 要涨 20%」「GOOG 会跑赢 FB」的判断。Black-Litterman 的第二块基石是「贝叶斯融合」:把主观观点(view)通过 P/Q 矩阵编码,通过 Ω 矩阵表达观点的不确定度,用贝叶斯公式把先验和观点加权融合,得到后验收益。本节讲清 BlackLittermanModel 类的两大输入——观点(P/Q 或 absolute_views)、置信度(omega),以及 BL 后验公式 E(R)=[(τΣ)⁻¹+PᵀΩ⁻¹P]⁻¹[(τΣ)⁻¹Π+PᵀΩ⁻¹Q] 的实现细节。读完本节,你能把任意主观观点融合成稳定的后验收益。

内容来源:原项目源码 pypfopt/black_litterman.py、文档 docs/BlackLitterman.rst、cookbook 4-Black-Litterman-Allocation.ipynb,汉化并套用体系化模板。

学习目标

阅读完本节,你应当能够:

  1. 区分 绝对观点相对观点,分别用 absolute_viewsP/Q 编码。
  2. 写出 picking matrix Pviews vector Q 的构造规则。
  3. 理解 omega 矩阵 的三种来源:default、idzorek、自定义。
  4. 说清 BL 后验公式 的加权直觉。
  5. bl_returns / bl_cov 取出后验估计。

一、两类观点:绝对 vs 相对

BL 模型支持两种观点:

  • 绝对观点:某个资产将收益 X%。「AAPL 涨 20%」「XOM 跌 30%」。
  • 相对观点:资产 A 跑赢资产 B 一定幅度。「GOOG outperform FB by 10%」。

绝对观点对应 P 矩阵里只有一个 1 的行,相对观点对应多个非零项(正负各半)且和为 0 的行

二、绝对观点:absolute_views 字典

最简单的输入方式——传一个 {ticker: 收益} 字典,库自动构造 P 和 Q:

viewdict = { "AAPL": 0.20, "BBY": -0.30, "BAC": 0, "SBUX": -0.20, "T": 0.15, } bl = BlackLittermanModel(cov_matrix, pi=market_prior, absolute_views=viewdict)

源码 _parse_views 自动构造 P/Q:每行只有一个 1(在 ticker 对应位置):

def _parse_views(self, absolute_views): views = pd.Series(absolute_views) k = len(views) Q = np.zeros((k, 1)) P = np.zeros((k, self.n_assets)) for i, view_ticker in enumerate(views.keys()): Q[i] = views[view_ticker] P[i, list(self.tickers).index(view_ticker)] = 1 # 该行只有 1 个 1 return Q, P

💡 不必对每个资产都有观点:你只需对关心的几个资产表达看法,其他资产通过协方差自动「连带」。这正是 BL 的优雅之处。

三、相对观点:手动构造 P 和 Q

相对观点必须手动写 P。文档里的经典例子:宇宙是 [SBUX, GOOG, FB, AAPL, BAC, JPM, T, GE, MSFT, XOM],四个观点:

  1. SBUX 跌 20%(绝对)
  2. MSFT 涨 5%(绝对)
  3. GOOG 跑赢 FB 10%(相对)
  4. BAC+JPM 跑赢 T+GE 15%(相对)
import numpy as np Q = np.array([-0.20, 0.05, 0.10, 0.15]).reshape(-1, 1) P = np.array([ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], # SBUX [0, 0, 0, 0, 0, 0, 0, 0, 1, 0], # MSFT [0, 1, -1, 0, 0, 0, 0, 0, 0, 0], # GOOG - FB [0, 0, 0, 0, 0.5, 0.5, -0.5, -0.5, 0, 0], # (BAC+JPM)/2 - (T+GE)/2 ]) bl = BlackLittermanModel(cov_matrix, pi=market_prior, Q=Q, P=P)

P 矩阵规则:

行特征 含义 P 矩阵那行
绝对观点 单资产 对应位置 1,其他 0
相对观点 A 跑赢 B A 位置 +x,B 位置 -y,行和 = 0

⚠️ 行和必须为 0:相对观点的 P 行必须正负抵消,否则会引入「绝对偏向」破坏模型。多资产相对用 +0.5, +0.5, -0.5, -0.5 这种均衡写法。

四、Omega 置信度矩阵:三种来源

omega 是 K×K 对角矩阵,表示「每个观点的不确定度」(方差越大越不信)。BL 库支持三种来源:

来源 用法 含义
default omega=None(默认) Ω = diag(diag(τ·P·Σ·Pᵀ)),与观点组合的方差成比例
idzorek omega="idzorek", view_confidences=[...] 用百分比置信度(0~1)推
自定义 omega=np.diag([...]) 直接传 K×K 矩阵

default 模式(He-Litterman)

源码:

@staticmethod def default_omega(cov_matrix, P, tau): return np.diag(np.diag(tau * P @ cov_matrix @ P.T))

逻辑:观点越涉及高波动资产,自动越不确定。简单稳健,无需额外输入。

Idzorek 方法:百分比置信度

允许你用 0~1 的百分比表达「我有多信这个观点」:

confidences = [0.6, 0.4, 0.2, 0.5, 0.7, 0.7, 0.7, 0.5, 0.1, 0.4] bl = BlackLittermanModel( S, pi=market_prior, absolute_views=viewdict, omega="idzorek", view_confidences=confidences )

源码 idzorek_method 的核心:

alpha = (1 - conf) / conf # conf 越低,alpha 越大 omega = tau * alpha * P_view @ cov_matrix @ P_view.T

conf=0 时 omega 设为 1e6(完全不信,等于无观点);conf=1 时 omega=0(完全信,等于强制观点)。

💡 置信度的语义:0.7 表示「我认为这个观点有 70% 的把握」,库会把它换算成 omega 的具体数值。这比直接拍脑袋写方差更直觉。

用置信区间换算

cookbook 4 给了第三种实用做法——用「1 标准差置信区间」反推:

intervals = [(0, 0.25), (0.1, 0.4), ...] # 每个观点的 68% 置信区间 variances = [((ub - lb) / 2) ** 2 for lb, ub in intervals] omega = np.diag(variances)

五、BL 后验公式:贝叶斯加权

BL 公式看着吓人,本质是先验和观点的加权平均:

E(R) = [(τΣ)⁻¹ + PᵀΩ⁻¹P]⁻¹ [(τΣ)⁻¹Π + PᵀΩ⁻¹Q]
  • (τΣ)⁻¹:先验的「置信度」(τ 越小越信先验)
  • PᵀΩ⁻¹P:观点的「置信度」(Ω 越小越信观点)
  • 后验是两者按各自置信度的加权融合

源码 bl_returns 用线性方程求解避免显式求逆(数值更稳):

def bl_returns(self): if self._tau_sigma_P is None: self._tau_sigma_P = self.tau * self.cov_matrix @ self.P.T if self._A is None: self._A = (self.P @ self._tau_sigma_P) + self.omega b = self.Q - self.P @ self.pi solution = np.linalg.solve(self._A, b) post_rets = self.pi + self._tau_sigma_P @ solution return pd.Series(post_rets.flatten(), index=self.tickers)

💡 τ 的可忽略性:如果你用 default omega 或 idzorek,τ 在矩阵运算中会约掉,最终结果对 τ 不敏感。这就是为什么库默认 τ=0.05 但不强调调参。

六、后验协方差 bl_cov

BL 也会更新协方差(观点信息让分布更确定):

def bl_cov(self): # ... M = self.tau * self.cov_matrix - self._tau_sigma_P @ M_solution posterior_cov = self.cov_matrix + M return pd.DataFrame(posterior_cov, index=self.tickers, columns=self.tickers)

portfolio_performance 会自动调 bl_cov 算 Sharpe 等指标。日常用法:

ret_bl = bl.bl_returns() # 后验收益 S_bl = bl.bl_cov() # 后验协方差

本节要点回顾

  1. 两类观点:绝对(单资产)用 absolute_views 字典;相对(A 跑赢 B)必须手写 P/Q,P 的相对行必须正负抵消、行和为 0。
  2. P 是 K×N picking matrix,Q 是 K×1 观点值向量,把观点映射到 N 个资产的宇宙。
  3. Omega 三种来源:default(与方差成比例,推荐默认)、idzorek(百分比置信度)、自定义(直接传矩阵或用置信区间反推)。
  4. BL 公式本质是先验和观点按各自置信度的加权融合;(τΣ)⁻¹PᵀΩ⁻¹P 是两侧权重。
  5. τ 通常不敏感:default 和 idzorek 模式下 τ 会被约掉,默认 0.05 不必纠结。
  6. 输出:bl_returns() 给后验收益,bl_cov() 给后验协方差,后验收益总是介于先验和观点之间。

下一节,我们把这些拼成一条完整流水线——先验 → 观点 → 后验 → 优化,与 Cookbook 4 配套实战。


发布者: 作者: 灏天文库 转发
评论区 (0)
U