举例说明如何寻找多资产组合下的全局最小方差点。
这里用到了第三方数据库下载的数据,为7只基金在2023年的收益数据,如下图所示(原始数据算不出来所以这里小小的编了一下)。
# 多资产投资组合分析
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import scipy.optimize as sco
# 读入数据
path_file = r'定义路径'
data = pd.read_csv(path_file, header=0, index_col=0)
# 计算资产间的相关系数矩阵
mean_vector = data.mean()
vol_vector = data.std()
correlation_vector = data.corr()
covariance_vector = data.cov()
# 画出均值和方差点
fig, ax = plt.subplots()
ax.scatter(mean_vector, vol_vector, color='r')
for x_pos, y_pos, label in zip(mean_vector, vol_vector, mean_vector.index):
ax.annotate(s=label, xy=(x_pos, y_pos), xytext=(7, 0), textcoords="offset points", size=8, va="center")
ax.set(xlabel='Portfolio Volatility', ylabel='Portfolio Return')
plt.show()
# 对该组合进行线性优化,求出风险最小的组合对应的权重
# 定义一个求解最优化的函数
def f(w):
w = np.array(w)
R_opt = w * mean_vector
V_opt = np.sqrt(np.dot(w, np.dot(covariance_vector, w.T)))
return np.array([R_opt, V_opt])
# 定义一个使波动率为最小的函数
def Vmin(w):
return f(w)[1]
# 定义最优化的限制条件:权重和为1
cons = ({'type':'eq','fun':lambda x:np.sum(x)-1})
bnds = tuple((0, 1) for x in range(len(mean_vector)))
Matrix = len(mean_vector)*[1/len(mean_vector)]
results = sco.minimize(Vmin, Matrix, method='SLSQP', bounds=bnds, constraints=cons)
weight = []
for i in range(len(mean_vector)):
weight.append(results['x'][i])
print("%s的权重为%.4f" % (mean_vector.index[i], results['x'][i]))
# 画图
fig, ax = plt.subplots()
ax.barh(mean_vector.index,weight)
ax.set(xlabel='Global minimal variance point weight', ylabel='index')
plt.show()
输出结果