3. 资产配置基础:大类资产分类、相关性矩阵、有效前沿理论回顾
做量化投资这些年,我越来越觉得资产配置才是真正的「免费午餐」。你想想看,选股选得再好,如果整个组合的底层逻辑是散的,那跟闭着眼睛扔飞镖没啥区别。这一章,咱们把最基础的东西掰扯清楚。
3.1 大类资产分类:别把鸡蛋放在一个篮子里
我个人习惯把大类资产分成这么几类。说白了,就是看它们赚的是什么钱。
- 权益类:股票、ETF、股指期货。赚的是企业成长的钱,波动最大。
- 固定收益类:国债、信用债、可转债。赚的是利息的钱,相对稳。
- 商品类:黄金、原油、农产品。赚的是通胀和供需错配的钱。
- 现金类:货币基金、短期国债。流动性最好,收益最低。
- 另类投资:REITs、私募股权、对冲基金。跟传统资产相关性低。
核心逻辑:不同资产在不同经济周期里表现不一样。比如通胀高的时候,商品和黄金往往走强,而债券会承压。组合的目的,就是让它们互相补位。
嗯,这里要注意一点。很多人把「另类投资」当成万能药。我曾经见过一个组合,塞了30%的私募股权和20%的房地产基金,结果流动性一收紧,整个组合直接卡死。所以分类归分类,流动性管理才是真功夫。
3.2 相关性矩阵:资产之间的「社交网络」
相关性矩阵,说白了就是看资产之间怎么「互动」。值在-1到1之间。1代表同涨同跌,-1代表你涨我跌,0代表没啥关系。
我建议你拿到数据后,先画个热力图。一眼就能看出哪些资产「抱团」,哪些资产「独来独往」。
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# 假设我们有5类资产的日收益率数据
data = {
'沪深300': [0.02, -0.01, 0.03, -0.02, 0.01],
'中证500': [0.015, -0.005, 0.025, -0.015, 0.02],
'国债指数': [0.001, 0.002, 0.0015, 0.002, 0.001],
'黄金': [0.005, 0.01, -0.005, 0.008, -0.002],
'原油': [0.01, -0.02, 0.015, -0.01, 0.005]
}
df = pd.DataFrame(data)
# 计算相关性矩阵
corr_matrix = df.corr()
# 画热力图
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0)
plt.title('大类资产相关性矩阵')
plt.show()
实战技巧:我一般会滚动计算36个月的相关性。因为静态的相关性会骗人。比如2008年金融危机时,所有资产的相关性都往1靠拢——这就是所谓的「相关性危机」。你平时看着不相关的资产,到了极端行情下全变成难兄难弟。
为什么会这样?因为流动性枯竭时,大家只能卖一切能卖的东西。所以相关性矩阵只能作为参考,不能完全依赖。
3.3 有效前沿理论回顾:找到那个「最优解」
有效前沿,是马科维茨老爷子在1952年提出的。核心思想就一句话:给定风险水平,追求最大收益;给定收益水平,追求最小风险。
我记得刚入行时,觉得这理论太完美了。后来在实际项目中碰了一鼻子灰——因为输入参数稍微变一点,最优解就飘到天边去了。这就是所谓的「输入敏感性问题」。
不过,理论框架本身是没问题的。我们来看怎么算。
import numpy as np
import scipy.optimize as sco
# 假设4类资产的预期收益率和协方差矩阵
returns = np.array([0.12, 0.08, 0.05, 0.03]) # 年化预期收益率
cov_matrix = np.array([
[0.04, 0.01, 0.005, 0.002],
[0.01, 0.03, 0.004, 0.001],
[0.005, 0.004, 0.01, 0.003],
[0.002, 0.001, 0.003, 0.005]
])
# 定义组合方差函数
def portfolio_variance(weights):
return np.dot(weights.T, np.dot(cov_matrix, weights))
# 定义约束条件:权重和为1,且每个权重在0到1之间
constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
bounds = tuple((0, 1) for _ in range(len(returns)))
# 生成有效前沿上的点
target_returns = np.linspace(0.03, 0.12, 50)
frontier_volatility = []
for target in target_returns:
constraints = (
{'type': 'eq', 'fun': lambda x: np.sum(x) - 1},
{'type': 'eq', 'fun': lambda x: np.dot(x, returns) - target}
)
opt = sco.minimize(portfolio_variance,
x0=np.array([0.25, 0.25, 0.25, 0.25]),
bounds=bounds,
constraints=constraints)
frontier_volatility.append(np.sqrt(opt.fun))
# 画出有效前沿
plt.plot(frontier_volatility, target_returns, 'b-', linewidth=2)
plt.xlabel('波动率(风险)')
plt.ylabel('预期收益率')
plt.title('有效前沿')
plt.grid(True)
plt.show()
避坑指南:我曾经用历史数据直接算有效前沿,结果回测时表现很好,实盘一跑就崩。为什么?因为历史均值不代表未来预期。我后来改用「隐含收益率」或者「贝叶斯收缩估计」来修正输入参数,效果好了不少。
有效前沿上有一个特殊点——最小方差组合。这是整个前沿上风险最低的点。对于保守型投资者,这个点往往是最优选择。
还有一个点叫最大夏普比率组合。夏普比率 = (组合收益 - 无风险利率) / 组合波动率。这个点代表「每单位风险获得的超额收益」最大。我个人的习惯是,先找到这个点,然后根据客户的风险偏好,在有效前沿上向左或向右移动。
3.4 知识体系总览
下面这张图,把这一章的核心逻辑串起来了。你可以把它当作一个思维导图来看。
这张图把三个核心模块串在了一起。大类资产分类是「食材」,相关性矩阵是「菜谱」,有效前沿是「烹饪方法」。三者缺一不可。
我的经验:刚开始做配置时,别一上来就搞几十个资产。我建议先从5-6个核心资产开始,把相关性矩阵和有效前沿跑通。等逻辑验证没问题了,再慢慢加资产。步子迈大了,容易扯着蛋。
好了,这一章的内容就这些。记住:资产配置不是选「最好的资产」,而是选「最合适的组合」。这个理念,贯穿整个课程。