用的是米筐的研究模块,从结果来看,均值方差模型对参数的敏感性很高,很多参数都不如随机权重,很难应用到实战。
import pandas as pd
import numpy as np
from scipy import linalg
import matplotlib.pyplot as plt
stockslist = ['000001.XSHE','000002.XSHE','600004.XSHG','600033.XSHG','000651.XSHE']
data = get_price_change_rate(stockslist,start_date = '20100101',end_date = '20200420')
data.to_csv('MeanVar.csv')
print(data.head(20))
train_set = data[data.index<'20171231']
#print(train_set.tail(20))
test_set = data[data.index>'20180101']
#print(test_set.head(20))
#看一下5个股票的历史表现
cumreturn = (1 + data).cumprod()
cumreturn.plot()
plt.title('Cumulative Return of Stocks')
plt.show()
#相关性分析
data.corr()
#核心模块,实现均值方差模型的计算
class MeanVariance:
#传入收益率数据
def __init__(self,returns):
self.returns = returns
#定义最小化方差函数,即求解二次规划
def minVar(self,goalRet):
covs = np.array(self.returns.cov())
means = np.array(self.returns.mean())
L1 = np.append(np.append(covs.swapaxes(0,1),[means],0),
[np.ones(len(means))],0).swapaxes(0,1)
L2 = list(np.ones(len(means)))
L2.extend([0,0])
L3 = list(means)
L3.extend([0,0])
L4 = np.array([L2,L3])
L = np.append(L1,L4,0)
results = linalg.solve(L,np.append(np.zeros(len(means)),[1,goalRet],0))
return np.array([list(self.returns.columns),results[:-2]])
#定义绘制最小方差前缘曲线函数
def frontierCurve(self):
goals = [x/500000 for x in range(-100,4000)]
variances = list(map(lambda x: self.calVar(self.minVar(x)[1,:].astype(np.float)),goals))
plt.plot(variances,goals)
#定义各资产比例,计算收益率均值
def meanRet(self,fracs):
meanRisky = ffn.to_returns(self.returns).mean()
#assert (len(meanRisky == len(fracs),'Length of fractions must be equal to number of assets')
return np.sum(np.multiply(meanRisky,np.array(fracs)))
#定义各资产比例,计算收益率方差
def calVar(self,fracs):
return np.dot(np.dot(fracs,self.returns.cov()),fracs)
#计算有效前缘
minVar = MeanVariance(data)
minVar.frontierCurve()
#计算训练集权重
varMinimizer = MeanVariance(train_set)
goal_return = 0.003
portfolio_weight = varMinimizer.minVar(goal_return)
portfolio_weight
#计算测试集收益率
test_return = np.dot(test_set,np.array([portfolio_weight[1,:].astype(np.float)]).swapaxes(0,1))
test_return = pd.DataFrame(test_return,index = test_set.index)
test_cum_return = (1+test_return).cumprod()
#计算随机权重组合
sim_weight = np.random.uniform(0,1,(100,len(stockslist)))
sim_weight = np.apply_along_axis(lambda x: x/sum(x),1,sim_weight)
sim_return = np.dot(test_set,sim_weight.swapaxes(0,1))
sim_return = pd.DataFrame(sim_return,index = test_cum_return.index)
sim_cum_return = (1+sim_return).cumprod()
plt.plot(sim_cum_return.index,sim_cum_return,color = 'green')
plt.plot(test_cum_return.index,test_cum_return,label = 'MeanVar')
plt.legend()
plt.title('MeanVar & Random')