halo 的技术博客

返回

Black-Litterman模型:超越Markowitz的投资组合优化#

为什么需要Black-Litterman?#

如果你用过Markowitz均值方差模型,一定遇到过这些头疼的问题:

  1. 输入敏感:预期收益率稍微改一点,最优组合就天差地别
  2. 集中化:优化结果往往集中在少数资产(如某只股票占90%)
  3. 估计误差:历史收益率不是未来的好预测器
  4. 缺乏观点:纯依赖历史数据,无法融入分析师判断

Black-Litterman模型(BL模型) 正是为了解决这些痛点而生。它由Fischer Black和Robert Litterman在1992年提出,结合了:

  • CAPM均衡组合(市场中性,稳定)
  • 投资者主观观点(灵活,个性化)
  • 贝叶斯框架(严谨,可量化不确定性)

高盛在1990年代就将BL模型用于资产配置,现在已成为机构标配。

Black-Litterman模型的理论框架#

核心思想#

BL模型的逻辑非常优雅:

  1. 起点:以市场均衡组合(如沪深300成分股权重)作为”先验分布”
  2. 输入观点:投资者可以对某些资产表达看多/看空观点
  3. 贝叶斯更新:将观点与先验结合,得到”后验分布”
  4. 优化:用后验预期收益率和协方差矩阵做Mean-Variance优化

关键优势

  • 均衡组合提供了稳定的基准(不会极端集中)
  • 观点可以是不确定的(用置信度表示)
  • 输出结果更直观(偏离均衡的幅度反映观点强度)

数学模型#

BL模型的核心公式:

E[R]=[(τΣ)1+PTΩ1P]1[(τΣ)1Π+PTΩ1Q]E[R] = [( \tau \Sigma )^{-1} + P^T \Omega^{-1} P]^{-1} [ ( \tau \Sigma )^{-1} \Pi + P^T \Omega^{-1} Q ]

其中:

  • E[R]E[R]:后验预期收益率(我们要的结果)
  • Π\Pi:先验预期收益率(均衡组合隐含的收益率)
  • Σ\Sigma:收益率协方差矩阵
  • τ\tau:缩放因子(通常取0.05-0.1)
  • PP:观点矩阵(哪些资产有观点)
  • QQ:观点收益向量(看多/看空多少)
  • Ω\Omega:观点不确定性矩阵(置信度)

不用被公式吓到!接下来我们用Python一步步实现。

Black-Litterman模型的Python实现#

Step 1: 计算均衡组合隐含收益率#

均衡组合(Equilibrium Portfolio)通常指市场组合(如沪深300指数)。我们可以用 逆向优化(Reverse Optimization) 计算均衡隐含收益率:

输出示例:

股票A: 0.0425 (4.25%)
股票B: 0.0475 (4.75%)
...
plaintext

Step 2: 定义投资者观点#

BL模型最强大的地方是 允许不确定的观点。我们可以表达:

  • 绝对观点:我认为股票A的年化收益是15%
  • 相对观点:我认为股票A会比股票B多涨5%

用矩阵表示:

Step 3: 计算后验预期收益率#

这是BL模型的核心公式:

关键观察

  • 股票A的后验收益率会 上调(因为我们有看多观点)
  • 股票B的后验收益率会 下调(因为相对观点中A>B)
  • 调整幅度取决于观点的置信度(Omega)

Step 4: 投资组合优化#

现在用后验收益率做Mean-Variance优化:

典型结果

  • BL模型:权重相对均衡(如30%, 25%, 20%, 15%, 10%)
  • Markowitz:权重极端(如90%, 0%, 0%, 5%, 5%)

这就是BL模型的魅力!

Black-Litterman模型的中国实战#

案例:沪深300成分股配置#

假设我们要配置沪深300前10大成分股,步骤如下:

1. 数据准备#

import tushare as ts
import pandas as pd

# 获取沪深300成分股
pro = ts.pro_api('your_token')
index_weight = pro.index_weight(index_code='000300.SH', start_date='20260101', end_date='20260131')
top10_stocks = index_weight.groupby('con_code')['weight'].mean().nlargest(10)

print("沪深300前10大成分股权重:")
print(top10_stocks)
python

2. 计算协方差矩阵#

# 获取过去252个交易日收益率
returns_df = pd.DataFrame()

for stock in top10_stocks.index:
    df = pro.daily(ts_code=stock, start_date='20250101', end_date='20260101')
    returns_df[stock] = df.set_index('trade_date')['close'].pct_change()

# 年化协方差矩阵
cov_matrix = returns_df.cov() * 252
python

3. 输入观点#

假设我们有这些观点:

  • 观点1:新能源板块(宁德时代、比亚迪)未来半年跑赢大盘10%
  • 观点2:金融板块(中国平安、招商银行)相对表现持平
  • 观点3:茅台未来半年收益15%

4. 运行BL模型#

输出示例

            市场权重  BL最优权重
600519.SH   0.15     0.22  # 茅台上调
300750.SZ   0.08     0.12  # 宁德时代上调
002594.SZ   0.06     0.09  # 比亚迪上调
601318.SH   0.12     0.10  # 平安下调
...
plaintext

实战要点#

  1. 观点要少而精:不要对所有股票都表达观点,聚焦最确定的2-3个
  2. 置信度要合理:不确定的观点用大Omega(低置信度),避免过度偏离市场
  3. 定期更新:观点不是永恒的,每月/季度重新评估
  4. 结合风控:BL输出也要检查集中度、行业偏离等

Black-Litterman模型的进阶话题#

1. 相对观点 vs 绝对观点#

BL模型支持两种观点:

  • 绝对观点:股票A收益15%(P是一行向量)
  • 相对观点:股票A比股票B多涨5%(P是两列差分)

实践建议

  • 相对观点更稳健(不受市场整体影响)
  • 绝对观点需要更强的置信度

2. 观点不确定性的设定#

Omega的设定有几种方法:

# 方法1:与预测误差成正比
omega = np.diag(np.diag(P @ (tau * cov_matrix) @ P.T))

# 方法2:手动设定(观点1置信度高,观点2置信度低)
omega = np.diag([0.01, 0.05])  # 越小越自信

# 方法3:基于历史准确率
# 如果过去类似观点的准确率是80%,可以设定omega = 0.2 * P @ Sigma @ P.T
python

3. 结合宏观因子#

BL模型可以扩展到 宏观因子(如利率、通胀、GDP):

4. 动态BL模型#

传统BL是静态的(每月更新一次观点)。可以改进为 动态BL

  • 用卡尔曼滤波跟踪观点准确性的变化
  • 用GARCH模型预测时变协方差矩阵
  • 用机器学习预测观点收益Q
# 动态BL伪代码
for t in range(T):
    # 更新协方差矩阵(GARCH)
    cov_matrix_t = garch_forecast(returns[:t])
    
    # 更新观点置信度(卡尔曼滤波)
    omega_t = kalman_update(omega_0, historical_accuracy[:t])
    
    # 运行BL
    posterior_return_t, _ = black_litterman(pi, cov_matrix_t, P, Q, tau, omega_t)
    
    # 优化
    weights_t = portfolio_optimization(posterior_return_t, cov_matrix_t)
python

常见陷阱与解决方案#

陷阱1:观点过多#

问题:对20只股票都表达观点,导致过度拟合

解决

  • 只表达3-5个高置信度观点
  • 用PCA降维,只对主成分表达观点

陷阱2:Omega设定不当#

问题:Omega太小(过度自信),导致组合极端集中

解决

  • 用交叉验证选择最优Omega
  • 设定Omega的下限(如不小于0.01)

陷阱3:忽略交易成本#

问题:BL模型建议大幅调仓,但交易成本吃掉收益

解决

# 在目标函数中加入交易成本
def objective_with_cost(weights, prev_weights):
    turnover = np.sum(np.abs(weights - prev_weights))
    transaction_cost = turnover * 0.001  # 假设单边成本0.1%
    
    portfolio_return = np.dot(weights, expected_returns) - transaction_cost
    portfolio_risk = np.dot(weights, np.dot(cov_matrix, weights))
    
    utility = portfolio_return - 0.5 * risk_aversion * portfolio_risk
    return -utility
python

总结#

Black-Litterman模型是投资组合优化的里程碑,核心要点:

  1. 理论基础:贝叶斯框架,结合市场均衡与投资者观点
  2. 核心优势:稳定、直观、灵活
  3. 实施步骤:计算均衡收益 → 输入观点 → BL公式 → 优化
  4. 实战建议:观点要少而精,置信度要合理,定期更新
  5. 进阶方向:宏观因子、动态模型、机器学习结合

对比Markowitz

  • Markowitz:纯依赖历史数据,结果不稳定
  • Black-Litterman:结合主观判断,结果更稳健

下期预告:我们将介绍 风险平价策略(Risk Parity),探讨如何放弃收益预测,纯粹从风险角度构建稳健组合。


本文代码仅供参考,实盘使用前请充分回测和风控。BL模型对观点质量依赖较高,垃圾进垃圾出(GIGO)。

Black-Litterman模型:超越Markowitz的投资组合优化
https://blog.halo26812.eu.org/blog/2026-06-14-black-litterman-model
Author halo
Published at 2026年6月14日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨