如何用MATLAB优化投资组合的风险(方差)或得到投资组合的有效前沿
在金融领域,如果降低投资的风险是一个非常重要的问题,没有风险控制的投资无异于在资本的汪洋大海里裸奔。
我们一般用资产收益率的方差来表示资产的风险(资产收益率的标准差称为波动率), 而计算投资组合的风险则是一般人比较难理解的,这里我们不进行推导,直接给出计算表达式
其中Var§为资产组合p的风险,w为各资产的权重,X为各个资产的收益率矩阵,Cov(X)为各资产收益率的协方差矩阵。
那么如何用MATLAB来优化投资组合的风险呢?我们采用优化的方法来实现,也即建立一个优化模型:
其中Z为目标函数(也即资产组合的方差),而w作为待优化的资产组合(也即各个资产的权重),rE为各个资产的预期收益率,rpE为我们设定的投资组合收益率。
clc;close all;clear all;warning off;%清除变量
rand(‘seed’, 100);
randn(‘seed’, 100);
format long g;%% 1.读取数据和计算收益率,协方差等
filename=‘投资组合股票日收益率.xls’;
[adata201,bdata201,cdata201]=xlsread(filename);% 计算收益率
price=adata201;
stocknamecell=cdata201(1,2:end);
figure;
plot(price);
legend(stocknamecell,‘fontname’,‘宋体’);
xlabel(‘时间’,‘fontname’,‘宋体’);
ylabel(‘资产价格’,‘fontname’,‘宋体’);
title(’’,‘fontname’,‘宋体’);returns=price(2:end,:)./price(1:end-1,:)-1; % 收益率
figure;
plot(returns);
legend(stocknamecell,‘fontname’,‘宋体’);
xlabel(‘时间’,‘fontname’,‘宋体’);
ylabel(‘收益率’,‘fontname’,‘宋体’);
title(’’,‘fontname’,‘宋体’);n=size(returns,2);% 资产数
% 计算协方差
mycov=cov(returns);
retE=mean(returns);
varE=var(returns);% 单项资产的方差=风险rmat=linspace(min(retE),max(retE),40)’;
K=length(rmat);
riskmat_noshort=zeros(K,1);
riskmat_short=zeros(K,1);wait_hand = waitbar(0,‘running…’, ‘tag’, ‘TMWWaitbar’);
for k=1:K% 每种收益率循环
r=rmat(k);% 设定目标回报
%% 2.fmincon函数优化投资组合
A=[];
b=[];
……
lb=zeros(n,1);
ub=ones(n,1);
w0=ones(n,1)/n;
opts=optimset(‘Display’,‘off’);% 不显示过程
[w,fval]=fmincon(@(x) myobjfun(mycov,x),w0,A,b,Aeq,beq,lb,ub,[],opts);% 调用fmincon计算最小方差
riskmat_noshort(k,1)=fval;
%%
A=[];
b=[];
……
lb=-1*ones(n,1);
ub=ones(n,1);
w0=ones(n,1)/n;
opts=optimset(‘Display’,‘off’);% 不显示过程
[w,fval]=fmincon(@(x) myobjfun(mycov,x),w0,A,b,Aeq,beq,lb,ub,[],opts);% 调用fmincon计算最小方差
riskmat_short(k,1)=fval;
waitbar(k/K,wait_hand);
end
delete(wait_hand);% 求最小方差组合
%% 不允许卖空
A=[];
b=[];
……
lb=zeros(n,1);
ub=ones(n,1);
w0=ones(n,1)/n;
opts=optimset(‘Display’,‘off’);% 不显示过程
[w_minrisk,fval_minrisk]=fmincon(@(x) myobjfun(mycov,x),w0,A,b,Aeq,beq,lb,ub,[],opts);% 调用fmincon计算最小方差
disp(‘最小风险’);
risk_min=fval_minrisk
disp(‘最小风险时对应的收益率’);
ret_minrisk=sum(w_minrisk’.*retE)
disp(‘最小风险时对应的权重’);
w_minriskfigure;
hold on;
plot(riskmat_short,rmat,‘b’,‘linewidth’,1);
plot(risk_min,ret_minrisk,‘m.’,‘markersize’,30);
plot(varE,retE,‘g.’,‘markersize’,25);
legend({‘有效前沿’,‘最小方差组合’,‘单独资产’},‘fontname’,‘宋体’);
xlabel(‘风险’,‘fontname’,‘宋体’);
ylabel(‘收益率’,‘fontname’,‘宋体’);
title(‘投资组合的有效前沿’,‘fontname’,‘宋体’);
程序结果:
最小风险
risk_min =
0.00117561007628918
最小风险时对应的收益率
ret_minrisk =
4.84661601286441e-05
最小风险时对应的权重
w_minrisk =
0.412535528609794
0.285445046885802
0.284734805971426
0.0172846185329782