#导入所需要的库
import pandas as pd
import numpy as np
import numpy as np
from scipy.optimize import minimize
import numpy as np
import matplotlib.pyplot as plt
计算组合收益率和协方差
df.pct_change(axis=0).mean()
df.pct_change(axis=0).cov()
根据刚刚计算r和cov,再输入不同人的厌恶系数t就可以得到对应厌恶系数下的不同股票的权重系数
def funx(t,r_parm,cov_parm):
ee = [1 for i in range(len(r_parm))]
a = np.dot(np.dot(np.linalg.inv(cov_parm),ee),ee)
b = np.dot(np.dot(np.linalg.inv(cov_parm),r_parm),[1 for i in range(len(r_parm))])
c = np.dot(np.dot(np.linalg.inv(cov_parm),r_parm),r_parm)
d = a*c - b*b
ajz = 1/a * np.dot(np.linalg.inv(cov_parm),ee)
bjz = np.dot(np.linalg.inv(cov_parm),[i-b/a for i in r_parm])
xt = ajz + t*bjz
return xt
随后画出有效前沿
num_portfolios = 5000
num_assets = 5
# 生成随机权重,允许做空头交易
portfolios = np.random.rand(num_portfolios, num_assets) - 0.5
# 对每个投资组合的权重进行归一化,使其总和为1
portfolios /= np.sum(portfolios, axis=1, keepdims=True)
# 5000个组合
mulist = []
silist = []
for i in range(5000):
portfolio_returns = np.dot(portfolios[i], r)
portfolio_volatility = np.sqrt(np.dot(portfolios[i], np.dot(rcov, portfolios[i])))
mulist.append(portfolio_returns)
silist.append(portfolio_volatility)
names = df.columns.values.tolist()
plt.scatter(silist, mulist, marker='o', s=10, alpha=0.5)
plt.scatter([si], [mu], marker='^', s=100, alpha=1)
plt.xlabel('std')
plt.ylabel('mu')
plt.title('question 4')
plt.xlim(0.005, 0.02)
plt.ylim(-0.001, 0.002)
plt.plot(upps, uppr, 'r-', linewidth=2)
plt.plot(lows, lowr, 'b-', linewidth=2)
plt.scatter(std, r, marker='s', s=50, alpha=1)
for i, name in enumerate(names):
plt.text(std[i], r[i], name, fontsize=12, ha='center', va='bottom')
plt.grid(True)
plt.show()
截图如图:
再画一个cml线
# 有效前沿
sig0 = np.sqrt( q3[3][0]/q3[3][3] * (0.0001- mu)**2 + 1/q3[3][0] )
uppr = []
upps = []
lowr = []
lows = []
for i in range(-200,200):
uu = i/100000
ss = np.sqrt(1/q3[3][0]+q3[3][0]/q3[3][3]*(uu-mu)**2)
ss1 = (uu-0.0001)/(sig0*np.sqrt(q3[3][3]))
uppr.append(uu)
upps.append(ss)
lows.append(ss1)
plt.scatter([si], [mu], marker='^', s=100, alpha=1)
plt.scatter([sigm], [um], marker='s', s=100, alpha=1)
plt.xlabel('std')
plt.ylabel('r')
plt.title('question 5')
plt.xlim(0, 0.02) # 替换为你想要的x轴范围
plt.ylim(-0.001, 0.002) # 替换为你想要的y轴范围
#plt.plot(uhat, shat, 'r-', linewidth=1)
plt.plot(upps, uppr, 'r-', linewidth=2)
plt.plot(lows, uppr, 'b-', linewidth=2)
plt.scatter(std, r, marker='s', s=50, alpha=1)
for i, name in enumerate(names):
plt.text(std[i], r[i], name, fontsize=12, ha='center', va='bottom')
plt.grid(True)
plt.show()