第四章:组合优化理论——马科维茨模型在固收中的应用
各位同行,今天我们来聊聊组合优化。说实话,很多做固收的朋友一听到「马科维茨模型」就觉得这是搞权益的人玩的。我刚开始也这么想,直到有一次在管理一个信用债组合时,被领导问「你的组合到底在哪个风险水平上最优?」——嗯,那时候我才意识到,固收组合同样需要一套科学的优化框架。
4.1 马科维茨模型:不只是股票的事
马科维茨在1952年提出的均值-方差模型,核心思想其实很简单:在给定风险水平下追求最大收益,或者在给定收益目标下追求最小风险。这个逻辑放在固收里完全成立,只不过我们需要重新定义「风险」和「收益」的度量方式。
我个人习惯把固收组合的优化问题拆成三步:
- 确定输入参数:各券种的预期收益率、方差、协方差矩阵
- 设定约束条件:久期限制、信用评级下限、流动性要求等
- 求解有效前沿:找到帕累托最优的权重组合
你想想看,固收资产的协方差矩阵其实比权益资产更「友好」——因为利率债之间的相关性往往很高,而信用债之间的相关性则受行业和评级影响。我在项目中遇到过一个问题:直接用历史收益率算协方差,结果优化出来的组合全是国债,因为国债之间的相关性太强了。后来我改用因子模型来分解风险,效果就好多了。
4.2 有效前沿:固收版的「最优边界」
有效前沿就是那条「在相同风险下收益最高」的曲线。对于固收组合,这条曲线通常比权益组合更「陡峭」——因为固收资产的波动率本身就低,稍微增加一点久期或信用下沉,收益提升就很明显。
下面这张图展示了固收组合的有效前沿。我特意把利率债、信用债和混合策略三条曲线画在一起,方便对比。
从图上可以明显看出:混合策略的有效前沿位于利率债和信用债之间,但更靠近信用债一侧。这说明在固收领域,适度加入信用债确实能提升组合的收益-风险比。
4.3 约束条件设定:固收组合的「紧箍咒」
马科维茨模型在固收中最大的挑战不是数学,而是约束条件。权益组合的约束通常就是「个股仓位不超过5%」这种,但固收组合的约束要复杂得多。
我曾经踩过一个坑:给一个保险资管做优化时,只加了久期和评级约束,结果优化出来的组合里全是永续债——因为永续债的收益率高、久期长,在模型里看起来「很划算」。但实际执行时发现,永续债的流动性极差,根本买不到量。
所以,我建议大家在设定约束时,至少考虑以下五类:
| 约束类型 | 具体内容 | 常见参数 |
|---|---|---|
| 久期约束 | 控制利率风险暴露 | 组合久期 ≤ 基准久期 ± 0.5年 |
| 信用约束 | 限制信用下沉程度 | AAA级占比 ≥ 60%,AA+ ≤ 30% |
| 流动性约束 | 确保可交易性 | 单券持仓 ≤ 日均成交量 × 5天 |
| 集中度约束 | 分散化要求 | 单发行人 ≤ 5%,单行业 ≤ 20% |
| 合规约束 | 监管或合同要求 | 杠杆率 ≤ 140%,质押率 ≥ 110% |
4.4 实战中的优化流程
说了这么多理论,咱们来点实际的。下面是我在项目中常用的优化流程,用Python伪代码表示:
# 步骤1:定义目标函数
def portfolio_returns(weights, expected_returns):
return np.dot(weights, expected_returns)
def portfolio_volatility(weights, cov_matrix):
return np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
# 步骤2:设定约束
constraints = [
{'type': 'eq', 'fun': lambda x: np.sum(x) - 1}, # 权重和为1
{'type': 'ineq', 'fun': lambda x: 0.6 - x[0]}, # 利率债 ≥ 60%
{'type': 'ineq', 'fun': lambda x: x[1] - 0.1}, # 信用债 ≤ 10%
{'type': 'ineq', 'fun': lambda x: 4.5 - duration(x)}, # 久期 ≤ 4.5
]
# 步骤3:求解有效前沿
def efficient_frontier(target_return):
# 使用scipy.optimize.minimize求解
result = minimize(
lambda w: portfolio_volatility(w, cov_matrix),
initial_weights,
method='SLSQP',
bounds=bounds,
constraints=constraints + [{'type': 'eq', 'fun': lambda w: portfolio_returns(w, expected_returns) - target_return}]
)
return result.x
这段代码看起来简单,但实际跑起来坑不少。我记得有一次优化结果里出现了负权重——因为忘了加权重下限约束。还有一次协方差矩阵不是正定的,优化器直接报错。嗯,这些细节都要注意。
4.5 避坑指南:我踩过的三个坑
- 坑一:历史数据外推失效。我曾经直接用过去3年的收益率数据做优化,结果优化出来的组合在2022年债市大跌时回撤巨大。后来我改用预期收益率(基于宏观模型预测)而不是历史均值,效果好了很多。
- 坑二:忽略交易成本。优化出来的权重和实际持仓往往有偏差,如果频繁再平衡,交易成本会吃掉收益。我建议在目标函数里加入交易成本惩罚项。
- 坑三:过度依赖数学。有一次优化结果建议全仓10年期国债,但当时市场预期加息,这个组合明显不合理。记住:模型是辅助,不是决策。
4.6 小结
马科维茨模型在固收中的应用,说白了就是在约束条件下找最优解。难点不在于数学,而在于如何把固收特有的约束条件(久期、信用、流动性)合理地塞进模型里。我个人觉得,一个好的固收优化模型,应该做到「80%的数学 + 20%的经验判断」。
最后提醒一句:有效前沿上的每一个点,都对应一个具体的组合权重。不要只看曲线,要看看曲线背后的持仓是否真的能执行。我曾经见过一个优化结果建议持有0.3%的某只信用债——这种仓位在实际操作中根本买不到,因为最小交易单位就是1000万。
好了,这一章就到这里。下一章我们会聊再平衡技术,到时候再分享一些实战中的调仓策略。