4、Black-Litterman模型:先验与后验、观点矩阵、置信度设置、实战应用
说起资产配置,很多人第一反应就是马科维茨的均值-方差模型。理论很完美,但我在实战中用它时,经常遇到一个尴尬的问题——输入参数稍微变一点,最优权重就天差地别。说白了,这个模型对预期收益率的估计太敏感了,而我们对未来收益率的预测,往往又不太靠谱。
后来我接触到了Black-Litterman模型,嗯,这玩意儿确实解决了我的痛点。它把市场均衡收益作为起点,再融入你自己的主观判断,最后得出一个既尊重市场、又体现个人观点的配置方案。今天我就带大家把这个模型拆开揉碎了讲清楚。
核心思想:先相信市场是有效的(先验),再用你的观点去修正它(后验)。
4.1 先验与后验:从贝叶斯视角理解
Black-Litterman模型的底层逻辑,其实就是贝叶斯统计。你想想看,我们做投资决策时,手里通常有两类信息:一是市场的历史数据,二是你自己的分析判断。怎么把这两者结合起来?
先验分布——就是市场均衡状态下的预期收益。我一般用逆向优化法,从市值权重反推出隐含的收益率。这相当于说:「如果市场是有效的,那么当前价格已经反映了所有信息,预期收益应该是什么水平?」
后验分布——就是结合了你个人观点之后的修正结果。贝叶斯公式告诉我们:后验 = 先验 × 似然。在这里,似然就是你观点的概率分布。
我在项目中遇到过这样的情况:某次做全球资产配置,先验给出的新兴市场预期收益是8%,但我基于基本面分析认为应该更高。通过Black-Litterman模型,最终后验收益调整到了10.5%,而且整个协方差结构也变得更合理了。
我的习惯:先验参数用滚动窗口计算,避免单点估计的偏差。一般用36个月的历史数据做逆向优化。
4.2 观点矩阵:把你的判断变成数学语言
观点矩阵,说白了就是把你对资产的看法,翻译成模型能理解的数学形式。这步做不好,后面全是白搭。
观点分为两种:
- 绝对观点:「我认为A资产未来收益率是X%」
- 相对观点:「我认为A资产比B资产表现好Y%」
举个例子,假设我们有3个资产:股票、债券、商品。你可能有这样的判断:
- 股票未来收益比债券高3%
- 商品收益为5%
那么观点矩阵P和观点向量Q就是:
# 观点矩阵 P:每行代表一个观点
P = np.array([
[1, -1, 0], # 股票 - 债券 = 3%
[0, 0, 1] # 商品 = 5%
])
# 观点向量 Q
Q = np.array([0.03, 0.05])
这里要注意,观点矩阵的行数等于观点数量,列数等于资产数量。每个观点对应的资产权重之和必须为0(相对观点)或1(绝对观点)。
我曾经踩过的坑:观点之间不能有矛盾。比如你同时说「股票比债券好3%」和「债券比股票好2%」,模型会直接崩溃。建议观点数量不要超过资产数量的一半。
4.3 置信度设置:别让你的观点太「自信」
置信度,就是你对每个观点的确信程度。这个参数直接影响后验结果对观点的敏感度。
在Black-Litterman模型中,置信度通过一个对角矩阵Ω来表示。Ω的对角线元素越小,代表你对这个观点越有信心。
怎么设置?我一般用两种方法:
- 主观法:根据你的分析深度来定。做了三个月研究的观点,置信度肯定比拍脑袋的高。
- 客观法:用历史回测的预测误差来校准。比如你过去预测收益的RMSE是2%,那Ω就设为(0.02)^2。
# 置信度设置示例
# 观点1:股票比债券好3%,置信度较高(方差小)
# 观点2:商品收益5%,置信度较低(方差大)
tau = 0.05 # 标量,控制先验的置信度
omega = np.diag([0.001, 0.01]) # 观点误差的协方差矩阵
我的经验:tau值一般取0.01-0.05之间。太小了模型太相信先验,太大了又过度拟合观点。我习惯用0.025作为默认值。
4.4 实战应用:完整代码实现
好了,理论讲完了,咱们直接上代码。下面是一个完整的Black-Litterman实现,包括逆向优化、观点融合、后验计算。
import numpy as np
import pandas as pd
class BlackLitterman:
def __init__(self, market_caps, cov_matrix, risk_aversion=2.5):
"""
market_caps: 各资产的市值
cov_matrix: 协方差矩阵
risk_aversion: 风险厌恶系数
"""
self.market_caps = market_caps
self.cov = cov_matrix
self.lambda_ = risk_aversion
self.n_assets = len(market_caps)
def implied_returns(self):
"""逆向优化:从市值权重反推隐含收益"""
weights = self.market_caps / np.sum(self.market_caps)
pi = self.lambda_ * self.cov @ weights
return pi, weights
def posterior_returns(self, P, Q, omega, tau=0.05):
"""计算后验收益"""
pi, _ = self.implied_returns()
# 后验均值
inv_term = np.linalg.inv(np.linalg.inv(tau * self.cov) + P.T @ np.linalg.inv(omega) @ P)
mu_posterior = inv_term @ (np.linalg.inv(tau * self.cov) @ pi + P.T @ np.linalg.inv(omega) @ Q)
# 后验协方差
cov_posterior = self.cov + inv_term
return mu_posterior, cov_posterior
def optimize_weights(self, mu, cov):
"""均值-方差优化求最优权重"""
inv_cov = np.linalg.inv(cov)
weights = inv_cov @ mu / self.lambda_
weights = weights / np.sum(weights) # 归一化
return weights
# 使用示例
if __name__ == "__main__":
# 模拟数据
assets = ['股票', '债券', '商品']
caps = np.array([500, 300, 200]) # 市值(亿)
cov = np.array([
[0.04, 0.01, 0.02],
[0.01, 0.02, 0.005],
[0.02, 0.005, 0.03]
])
bl = BlackLitterman(caps, cov)
# 设置观点
P = np.array([[1, -1, 0], [0, 0, 1]])
Q = np.array([0.03, 0.05])
omega = np.diag([0.001, 0.01])
# 计算后验
mu_post, cov_post = bl.posterior_returns(P, Q, omega)
# 最优权重
weights = bl.optimize_weights(mu_post, cov_post)
print("后验收益:", mu_post)
print("最优权重:", weights)
4.5 知识体系总览
下面这张图,是我自己总结的Black-Litterman模型核心逻辑。你看一遍就能明白整个流程。
你看,整个流程其实就三步:先验计算、观点设置、贝叶斯融合。每一步都有明确的数学表达,而且代码实现也不复杂。
实战建议:刚开始用Black-Litterman模型时,建议先用少量资产(3-5个)做测试。等熟悉了观点矩阵和置信度的设置逻辑后,再扩展到全资产组合。我当年就是先从股债商三个资产开始,慢慢加到了十几个。
最后说一句,Black-Litterman模型不是万能的。它假设市场是有效的,观点是线性的,这些在极端行情下可能不成立。但作为一个把主观判断和客观数据结合起来的工具,它在实战中的价值是毋庸置疑的。
公众号:蓝海资料掘金营,微信deep3321