Black-Litterman Allocation ¶
作者:Robert Andrew Martin
译者:片刻小哥哥
项目地址:https://www.dafeiyang.cn/finance/stock/tools/PyPortfolioOpt/BlackLitterman
原始地址:https://pyportfolioopt.readthedocs.io/en/latest/BlackLitterman.html
Black-Litterman (BL) 模型 [1] 采用贝叶斯方法进行资产配置。 具体来说,它将先前的回报估计(例如,市场隐含回报)与对某些资产的观点相结合,以产生预期回报的后验估计。 这样做的优点是:
- 您可以仅提供资产子集的观点,BL 将有意义地传播它,同时考虑与其他资产的协方差。
- 您可以对自己的观点充满信心。
- 使用 Black-Litterman 后验收益比使用平均历史收益产生更稳定的投资组合。
本质上,Black-Litterman 将预期收益向量本身视为一个要估计的量。 Black-Litterman 公式如下:
- \(E(R)\) 是预期收益的 Nx1 向量,其中 N 是资产数量。
- \(𝑄\) 是 Kx1 观点向量。
- \(𝑃\) 是 KxN 选取矩阵,它将观点映射到资产范围。 本质上,它告诉模型哪个观点对应于哪个资产。
- \(\Omega\) 是 KxK 观点的 不确定性矩阵。
- \(\Pi\) 是先验预期收益的 Nx1 向量。
- \(\Sigma\) 是资产回报的 NxN 协方差矩阵(一如既往)
- \(\tau\) 是标量调整常数。
尽管该公式看起来相当笨拙,但事实证明该公式只是表示先前估计的收益和观点之间的加权平均值,其中权重由观点的置信度和参数 \(\tau\) 确定。
类似地,我们可以计算协方差矩阵的后验估计:
尽管该算法相对简单,但从软件工程的角度来看,BL 被证明是一个挑战,因为尚不清楚如何最好地将其融入 PyPortfolioOpt 的 API 中。 完整的讨论可以在 Github 问题线程 中找到,但我最终决定,虽然 BL 在技术上不是优化器,但将其方法拆分为预期回报或风险模型是没有意义的。 因此我将它作为一个独立的模块,并且由于理论相对广泛,所以给了它一个专门的文档页面。 我要感谢 Felipe Schneider 对 Black-Litterman 实施的多项贡献。 其使用的完整示例,包括免费获取市值数据,请参阅 cookbook recipe 。
提示
Thomas Kirschenmann 在 PyPortfolioOpt 之上构建了一个简洁的交互式 Black-Litterman 工具,它允许您可视化 BL 输出并比较优化目标。
先验者 ¶
在没有任何信息的情况下,您可以将先验视为“默认”估计。 Black 和 Litterman (1991) [2] 提出了这样的见解:此先验的自然选择是市场对回报的估计,该估计嵌入到资产的市值中。
市场投资组合中的每项资产都会给投资组合带来一定的风险。 标准理论表明,投资者必须为其承担的风险获得补偿,因此我们可以为每项资产赋予预期补偿(即事先估计的回报)。 这是通过市场隐含风险溢价来量化的,即市场的超额收益除以其方差:
为了计算市场隐含回报,我们使用以下公式:
这里,\(w_{mkt}\) 表示市值权重。 该公式计算资产贡献的风险总额,并将其与风险的市场价格相乘,得出市场隐含收益向量 \(\Pi\)。 我们可以使用 PyPortfolioOpt 来计算,如下所示:
from pypfopt import black_litterman, risk_models
"""
cov_matrix is a NxN sample covariance matrix
mcaps is a dict of market caps
market_prices is a series of S&P500 prices
"""
delta = black_litterman.market_implied_risk_aversion(market_prices)
prior = black_litterman.market_implied_prior_returns(mcaps, delta, cov_matrix)
没有什么可以阻止您使用任何您认为合适的先验(但它必须具有与宇宙相同的维度)。 如果您认为平均历史回报是一个很好的先验,您可以接受。 但大量研究表明,平均历史收益是一个完全没有信息的先验。
笔记
从技术上讲,您不必为 Black-Litterman 模型提供事先估计。 如果您的观点(和置信度)是由某些专有模型生成的,这尤其有用,在这种情况下,BL 本质上是混合您的观点的一种聪明方式。
观点 ¶
在 Black-Litterman 模型中,用户可以提供 绝对 或 相对 观点。 绝对观点是这样的陈述:“AAPL的收益率为 10%”或“XOM 将下降 40%”。 另一方面,相对观点是这样的陈述:“GOOG 将比 FB 的回报率高出 3%”。
这些观点必须在向量 \(Q\) 中指定,并通过选取矩阵 \(P\) 映射到资产域。 下面显示了一个简短的示例,但 Idzorek 提供了全面的指南。 假设我们的宇宙是由有序列表定义的:SBUX、GOOG、FB、AAPL、BAC、JPM、T、GE、MSFT、XOM。 我们想要表达对这 10 项资产的四种观点,两种是绝对的,两种是相对的:
- SBUX将下降20%(绝对值)
- MSFT将上涨5%(绝对值)
- GOOG 比 FB 领先 10%
- BAC和JPM的表现将比T和GE高出15%
相应的观点向量是通过将上面的数字放入一列中形成的:
Q = np.array([-0.20, 0.05, 0.10, 0.15]).reshape(-1, 1)
挑选矩阵更有趣。请记住,它的作用是将观点(提到 8 个资产)链接到 10 个资产的范围。可以说,这是模型中最重要的部分,因为它使我们能够传播我们的期望(并且 期望的置信度)代入模型:
P = np.array(
[
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
[0, 1, -1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0.5, 0.5, -0.5, -0.5, 0, 0],
]
)
对上述内容的简单解释:
- 每个观点在拾取矩阵中都有对应的行(顺序很重要)
- 绝对观点在对应于代码在 Universe 中的顺序的列中具有单个 1。
- 相对观点在名义上表现优异的资产栏中为正数,在名义上表现不佳的资产栏中为负数。 每行中的数字之和应为 0。
PyPortfolioOpt 提供了一个辅助方法,用于将绝对观点输入为 dict
或 pd.Series
– 如果您有相对观点,则必须手动构建选取矩阵:
from pypfopt.black_litterman import BlackLittermanModel
viewdict = {"AAPL": 0.20, "BBY": -0.30, "BAC": 0, "SBUX": -0.2, "T": 0.15}
bl = BlackLittermanModel(cov_matrix, absolute_views=viewdict)
置信矩阵和 tau ¶
置信矩阵是包含每个观点的方差的对角协方差矩阵。 计算 \(\Omega\) 的一种启发式方法是,它与先验的方差成正比。 这是合理的 —— 移动频繁的数量更难预测! 因此 PyPortfolioOpt 不需要您输入置信矩阵,默认为:
或者,我们提供 Idzorek 方法的实现 [1]。 这允许您将观点不确定性指定为百分比置信度。 要使用此功能,请选择 omega="idzorek"
并将置信度列表(从 0 到 1)传递到 view_confidences
参数中。
当然,欢迎您提供自己的估计。 如果您的观点是某些统计模型的输出,这尤其适用,这也可能提供观点的不确定性。
控制先验观点相对权重的另一个参数是 \(\tau\)。关于调整此参数有很多话要说,其中有许多相互矛盾的经验法则。事实上,已经有一篇完整的论文写在上面了 [3]。 我们选择合理的默认值 \(\tau = 0.05\) 。
笔记
如果您使用 \(\Omega\) 的默认估计值或 omega="idzorek"
,则 \(\tau\) 的值并不重要。 这是数学的结果:矩阵乘法中的 \(\tau\) 被抵消。
BL模型的输出 ¶
BL 模型输出收益和协方差矩阵的后验估计。文献中的默认建议是将这些输入优化器(参见 通用有效前沿 )。一种对于调试非常有用的快速替代方案是计算返回向量隐含的权重 [4]。它实际上与我们用来计算市场权重隐含回报的过程相反。
在 PyPortfolioOpt 中,这可以在 BlackLittermanModel.bl_weights()
下使用。 由于 BlackLittermanModel
类继承自 BaseOptimizer
,因此它遵循与 EfficientFrontier
对象相同的 API:
from pypfopt import black_litterman
from pypfopt.black_litterman import BlackLittermanModel
from pypfopt.efficient_frontier import EfficientFrontier
viewdict = {"AAPL": 0.20, "BBY": -0.30, "BAC": 0, "SBUX": -0.2, "T": 0.15}
bl = BlackLittermanModel(cov_matrix, absolute_views=viewdict)
rets = bl.bl_returns()
ef = EfficientFrontier(rets, cov_matrix)
# OR use return-implied weights
delta = black_litterman.market_implied_risk_aversion(market_prices)
bl.bl_weights(delta)
weights = bl.clean_weights()
文档参考 ¶
black_litterman
模块包含 BlackLittermanModel
类,该类根据先前的估计和用户提供的观点生成预期回报的后验估计。此外,定义了两个效用函数,计算:
- 市场隐含的事先估计回报
- 市场隐含风险规避参数
class pypfopt.black_litterman.BlackLittermanModel(cov_matrix, pi=None, absolute_views=None, Q=None, P=None, omega=None, view_confidences=None, tau=0.05, risk_aversion=1, **kwargs)
[来源] ¶
BlackLittermanModel 对象(继承自 BaseOptimizer)包含需要 特定的输入格式,指定先验、观点、观点的不确定性, 以及将观点映射到资产范围的选取矩阵。然后我们可以计算 回报和协方差的后验估计。已提供辅助方法 尽可能提供默认值。
实例变量:
- 输入:
cov_matrix
- np.ndarrayn_assets
- inttickers
- str listQ
- np.ndarrayP
- np.ndarraypi
- np.ndarrayomega
- np.ndarraytau
- float
- 输出:
posterior_rets
- pd.Seriesposterior_cov
- pd.DataFrameweights
- np.ndarray
公共方法:
default_omega()
- 查看与资产方差成正比的不确定性idzorek_method()
- 将指定为百分比的观点转换为 BL 不确定性bl_returns()
- 回报的后验估计bl_cov()
- 协方差的后验估计bl_weights()
- 后验回报隐含的权重portfolio_performance()
计算预期回报、波动率和分配投资组合的夏普比率。set_weights()
从权重字典创建 self.weights (np.ndarray)clean_weights()
将 weights and clips 四舍五入到接近零。save_weights_to_file()
将权重保存为 csv、json 或 txt。
__init__(cov_matrix, pi=None, absolute_views=None, Q=None, P=None, omega=None, view_confidences=None, tau=0.05, risk_aversion=1, **kwargs)
[来源] ¶
Parameters:
- cov_matrix ( pd.DataFrame 或者 np.ndarray ) – NxN 收益协方差矩阵
- pi ( np.ndarray, pd.Series, optional ) – Nx1 先前的回报估计,默认为“无”。如果 pi=”market”,计算市场隐含先验(需要通过 market_caps)。如果 pi=”equal”,则使用等权重先验。
- absolute_views ( pd.Series 或者 dict, optional ) – 对资产子集的 K 个绝对观点的集合, 默认为无。如果提供了,我们就不需要 P、Q。
- Q ( np.ndarray 或者 pd.DataFrame, optional ) – Kx1 观点向量,默认为 None
- P ( np.ndarray 或者 pd.DataFrame, optional ) – KxN 选取矩阵,默认为 None
- omega ( np.ndarray 或者 Pd.DataFrame, 或者 string, optional ) – KxK 观点不确定性矩阵(对角线),默认为 None。可以通过传递“idzorek”来使用 Idzorek 的方法(需要你传递 view_confidences)。如果 omega=“default” 或 None,我们将不确定性设置为与方差成比例。
- view_confidences ( np.ndarray, pd.Series, list, optional ) – 观点置信度百分比的 Kx1 向量(0 到 1 之间),需要通过 Idzorek 方法计算 omega。
- τ ( float, optional ) – 观点权重标量(默认值为 0.05)
- risk_aversion ( 正float, optional ) – 风险规避参数,默认为1
- market_caps ( np.ndarray, pd.Series, optional ) – (kwarg) 资产的市值,如果 pi=”market” 则需要
- risk_free_rate ( float, 默认为 0.02 ) – (kwarg) 在某些方法中需要risk_free_rate
警告
您必须指定协方差矩阵以及绝对观点 或 Q和P,除非您为每个资产提供一个观点(在这种情况下会推断出 P)的特殊情况。
计算协方差矩阵的后验估计, 给出了对某些资产的看法。改编自 He 和 Litterman (2002)。 假设 omega 是对角线。如果情况并非如此, 请手动设置omega_inv。
Returns: 后验协方差矩阵
Return type: pd.DataFrame
计算返回向量的后验估计, 给出了对某些资产的看法。
Returns: 后验返回向量
Return type: pd.Series
计算后验回报隐含的权重,给定 风险的市场价格。从技术上讲,这可以应用于任何 预期回报的估计,实际上是一种特殊情况 均值方差优化
Parameters: risk_aversion ( 正float, optional ) – 风险规避参数,默认为1
Returns: 回报隐含的资产权重
Return type: 有序字典
如果未提供不确定性矩阵 omega,我们使用以下方法计算 他和 Litterman (1999) 认为 omega/tau 的比率与 观点投资组合的方差。
Returns: KxK 对角线不确定性矩阵
Return type: np.ndarray
static idzorek_method(view_confidences, cov_matrix, pi, Q, P, tau, risk_aversion=1)
[来源] ¶
使用 Idzorek 方法根据用户指定的置信百分比创建不确定性矩阵。 我们使用 Jay Walters 在 The Black-Litterman Model in Detail (2014) 中描述的封闭式解决方案。
Parameters: view_confidences ( np.ndarray, pd.Series, list, , optional* ) – 观点置信度百分比的 Kx1 向量(0 到 1 之间),需要通过 Idzorek 方法计算 omega。
Returns: KxK 对角线不确定性矩阵
Return type: np.ndarray
bl_weights 的别名是为了与其他方法保持一致。
portfolio_performance(verbose=False, risk_free_rate=0.02)
[来源] ¶
优化后,计算(并可选择打印)最佳性能 文件夹。目前计算预期回报、波动率和夏普比率。 该方法使用 BL 后验回报和协方差矩阵。
Parameters:
- verbose ( bool, optional ) – 是否应该打印性能,默认为 False
- risk_free_rate ( float, optional ) – 无风险借贷利率,默认为0.02。无风险利率的期限应与预期回报的频率。
Raises: ValueError – 如果尚未计算权重
Returns: 预期回报、波动性、夏普比率。
Return type: (float、float、float)
pypfopt.black_litterman.market_implied_prior_returns(market_caps, risk_aversion, cov_matrix, risk_free_rate=0.02)
[来源] ¶
计算市场权重隐含的回报的先前估计。 换句话说,考虑到每种资产对市场风险的贡献 投资组合,我们期望获得多少补偿?
Parameters:
- market_caps ( {ticker: cap} dict 或者 pd.Series ) – 所有资产的市值
- risk_aversion ( 正float ) – 风险厌恶参数
- cov_matrix ( pd.DataFrame ) – 资产收益的协方差矩阵
- risk_free_rate ( float, optional ) – 无风险借贷利率,默认为0.02。您应该使用适当的时间段,相应到协方差矩阵。
Returns: 市值隐含的事先估计回报
Return type: pd.Series
pypfopt.black_litterman.market_implied_risk_aversion(market_prices, frequency=252, risk_free_rate=0.02)
[来源] ¶
计算市场隐含风险规避参数(即风险的市场价格) 根据市场价格。例如,如果市场每年的超额收益为10% 方差为 5% 时,风险规避参数为 2,即您必须获得 2 倍的补偿 方差。
Parameters:
- market_prices ( 带有 DatetimeIndex 的 pd.Series。 ) – 市场投资组合的 (daily) 价格,例如 SPY。
- frequency ( int, optional ) – 一年中的时间段数,默认为 252(一年中的交易日数)
- risk_free_rate ( float, optional ) – 无风险借贷利率,默认为0.02。无风险利率的期限应与预期回报的频率。
Raises: TypeError – 如果无法解析 market_prices
Returns: 市场隐含风险规避
Return type: float
参考文献 ¶
- [1] (1 , 2) Idzorek T. A step-by-step guide to the Black-Litterman model: Incorporating user-specified confidence levels. In: Forecasting Expected Returns in the Financial Markets. Elsevier Ltd; 2007. p. 17–38.
- [2] Black, F; Litterman, R. Combining investor views with market equilibrium. The Journal of Fixed Income, 1991.
- [3] Walters, Jay, The Factor Tau in the Black-Litterman Model (October 9, 2013). Available at SSRN: https://ssrn.com/abstract=1701467 or http://dx.doi.org/10.2139/ssrn.1701467
- [4] Walters J. The Black-Litterman Model in Detail (2014). SSRN Electron J.;(February 2007):1–65.