把收益与风险合成一个数
最小方差忽略了收益。均值-方差优化(马科维茨)两者都用:投资者希望预期收益 w @ mu 高、方差 w @ cov @ w 低。一种简单的权衡办法是效用 w @ mu - 0.5 * lambda * w @ cov @ w,其中 lambda 是风险厌恶系数:它越大,一单位方差的代价越高。预期相同但 lambda 不同的两位投资者会选不同的组合,每人的最佳组合都是一个光滑凹函数的最大值点。
import numpy as np
mu = np.array([0.08, 0.05, 0.10]) # expected annual returns
cov = np.array([[0.0400, 0.0060, 0.0100],
[0.0060, 0.0100, 0.0020],
[0.0100, 0.0020, 0.0225]])
def utility(weights, mu, cov, risk_aversion):
return weights @ mu - 0.5 * risk_aversion * weights @ cov @ weights
equal = np.full(3, 1 / 3)
print(round(float(equal @ mu), 4), round(float(equal @ cov @ equal), 4)) # 0.0767 0.0121
print(round(float(utility(equal, mu, cov, 4.0)), 4)) # 0.0526给定风险厌恶下的最佳仓位
在没有预算约束时(其余资金赚取无风险利率,这里按超额收益视为零),最佳仓位在梯度 mu - lambda * cov @ w 为零之处:w = cov^-1 * mu / lambda。代码中就是 np.linalg.solve(cov, mu) / lambda。它按常识缩放:风险厌恶翻倍,仓位减半。权重之和是多少就是多少;剩下的 1 - w.sum() 是现金。
# The best position for several risk aversions: more aversion, smaller bets
import numpy as np
mu = np.array([0.08, 0.05, 0.10])
cov = np.array([[0.0400, 0.0060, 0.0100],
[0.0060, 0.0100, 0.0020],
[0.0100, 0.0020, 0.0225]])
for aversion in (5.0, 10.0, 20.0):
w = np.linalg.solve(cov, mu) / aversion
print(aversion, np.round(w, 3), "invested", round(float(w.sum()), 3))切点组合
有无风险资产时,所有投资者持有相同的风险资产组合,只是数量不同。这个组合就是夏普比率 (w @ mu - rf) / sqrt(w @ cov @ w) 最高的那个,即切点组合:w 与 cov^-1 * (mu - rf) 成比例,并重新缩放到和为 1。谨慎的投资者只把部分资金放进去,其余持有现金;大胆的投资者借钱持有更多。决定承担多少风险和决定持有哪些风险资产,是两个独立的问题。
# The tangency portfolio: no other mix of the three assets has a higher Sharpe ratio
import numpy as np
mu = np.array([0.08, 0.05, 0.10])
cov = np.array([[0.0400, 0.0060, 0.0100],
[0.0060, 0.0100, 0.0020],
[0.0100, 0.0020, 0.0225]])
rf = 0.02
x = np.linalg.solve(cov, mu - rf)
best = x / x.sum()
def sharpe(w):
return (w @ mu - rf) / np.sqrt(w @ cov @ w)
rng = np.random.default_rng(1)
trials = rng.normal(size=(2000, 3))
trials = trials / trials.sum(axis=1, keepdims=True)
print(np.round(best, 4), round(float(sharpe(best)), 4))
print(round(max(float(sharpe(w)) for w in trials), 4)) # the best of 2000 random mixes comes close, never above实现目标收益
换一种问法:在所有权重和为 1 且预期收益给定的组合中,哪个方差最小?有两个约束时,解是两个已解向量 s1 = cov^-1 * 1 和 sm = cov^-1 * mu 的组合,系数来自概括市场的四个数 a, b, c, d。每个目标收益对应一个组合;把它们的风险画出来,就是下一节的有效前沿。
# Minimum-variance portfolios for three target returns
import numpy as np
mu = np.array([0.08, 0.05, 0.10])
cov = np.array([[0.0400, 0.0060, 0.0100],
[0.0060, 0.0100, 0.0020],
[0.0100, 0.0020, 0.0225]])
ones = np.ones(3)
s1, sm = np.linalg.solve(cov, ones), np.linalg.solve(cov, mu)
a, b, c = ones @ s1, ones @ sm, mu @ sm
d = a * c - b ** 2
for target in (0.06, 0.08, 0.09):
w = ((c - b * target) * s1 + (a * target - b) * sm) / d
print(target, np.round(w, 3), round(float(w @ mu), 4), round(float(np.sqrt(w @ cov @ w)), 4))优化器会放大你的误差均值-方差权重对
mu 非常敏感:某个预期收益的微小变化就能让组合从一个资产摆向另一个。优化器完全信任输入,所以任何被高估的收益都会变成大仓位。实践中会对收益做收缩、限制权重,并且输入来自模型或观点,而不是原始的过去平均值。均值-方差是很好的思考工具,盲目使用则很危险。- 效用是
w @ mu - 0.5 * lambda * w @ cov @ w;无预算时最佳仓位是solve(cov, mu) / lambda,lambda翻倍则减半。 - 有无风险资产时,最佳风险组合是切点组合
solve(cov, mu - rf)缩放到和为 1:夏普比率最高。 - 对于目标收益,最小方差权重是
solve(cov, ones)与solve(cov, mu)的组合;结果的好坏取决于估计的mu。
下一节:有效前沿,每个收益水平对应的最优风险曲线。
实验:评分内容
- 用
utility给组合打分25 分 - 用
utility_weights找到最佳仓位25 分 - 用
tangency_weights最大化夏普比率25 分 - 用
target_return_weights达到目标收益25 分