matlab 绘制有效前沿和资本市场线

版权声明:本文为博主原创文章,如能帮助到各位,荣幸之至,欢迎转载。 https://blog.csdn.net/m0_37639589/article/details/85804979

matlab 绘制有效前沿和资本市场线

这篇文章将介绍如何利用较新版本的 matlab 中的 Portfolio 对象绘制有效前沿和资本市场线等内容。

数据获取

注册tushare账号

首先,需要从 tushare 下载 tushare_matlab_sdk 稍后我们将使用该 sdk 中的接口获取数据,注意这里要求 matlab 的版本必须是 2016b 及更新的版本,并且你需要提前注册一个 tushare 账号,你可以点击注册tushare。注册账号之后,你需要获取你自己的 token ,token 会在下文代码中用到,还需要注意的一点是有些数据得你积分足够才有权限获取。

获取数据

代码如下:

close all
clear
clc
%% 数据准备
% get data from tushare:https://tushare.pro/
addpath(genpath(pwd));
token = 'ca928fb11765cd7c41b937459c8b611e0a97d0abf2daa1f8393c8ebc';
api = pro_api(token);
stockall = api.query('stock_basic');
% 获取指数数据,这里的市场基础取的是hs300
start_time = '20170101';
end_time = '';
ktype = 'D';
indexdata = pro_bar('000300.SH', api, start_time, end_time,ktype,'I');
indexdata = flipud(indexdata);
% 取10支股票
nstock = 10;
% 记录用到的10支股票
stocklist = [];
stockdata = cell(nstock,1);
nday = size(indexdata,1);
% closeprice 第一列为指数价格,其他列为股票数据
closeprice = indexdata.close;
temp = indexdata.trade_date;
temp = char(temp);
temp = str2num(temp);
tradedate = datetime(temp,'ConvertFrom','yyyymmdd','format','yyyy-MM-dd');

% 获取股票数据
m = 0;
for i = 1:size(stockall,1)
    temp = pro_bar(stockall.ts_code{i}, api, start_time, end_time,ktype,'E','qfq');
    % 有的股票有停牌,我们得选取没有停牌的股票
    if size(temp,1) == nday
        m = m+1;
        stockdata{m} = flipud(temp);
        closeprice(:,m+1) = stockdata{m}.close;
        stocklist = [stocklist;stockall(i,:)];
    end
    if size(stocklist,1) == nstock
        break;
    end
end
save('tempdata.mat');

tushare 是免费的数据源,它提供了非常多的数据,虽然有人说 tushare 的数据质量很差,但这对于没有钱买数据的业务研究人员(穷学生)而言仍然是非常实用的,具体用法详解请参考官网。这里需要特别提醒的是上文中的**end_time值为’‘表示的是至今,并且必须填’’,而不是’ '**否则会报错。

此外,你会发现从 tushare 中获取的数据是日期由近到远排列(和我平常使用的习惯相反),所以用了flipud翻转数据。还有从 tushare 中获取的时间是数值化的时间比如 20181011,我们需要将其转换为 datetime 形式的时间才便于利用,本文中使用了如下代码进行转换:

temp = indexdata.trade_date;
temp = char(temp);
temp = str2num(temp);
tradedate = datetime(temp,'ConvertFrom','yyyymmdd','format','yyyy-MM-dd');

有人可能会觉得先将时间转换成字符又转换成数字再转换成 datetime 步骤多余,但事实是必须按如下方法进行转换,不信可以尝试。另外 datetime 函数的这种用法也可以学习。

接下来我们通过上面获取的股票列表,从 tushare 中下载数据,因为股票会有停牌,所以我们特地找了 10 只期间内都没有停牌的股票绘制有效前沿。最后我们将获取的数据进行保存,数据准备部分就此完成。

绘制有效前沿

代码如下:

%% 画有效前沿和cal
% load tempdata;
% 计算收益率矩阵
retmat = tick2ret(closeprice(:,2:end));
p = Portfolio;
% 设置投资组合权重约束在0~1之间
p = p.setBudget(0,1);
% 设置无风险利率
riskless = 0.03;
p = Portfolio(p,'RiskFreeRate',riskless,'AssetList',stocklist.name);
% 输入收益率矩阵
p = p.estimateAssetMoments(retmat);
% 将数据年化
nyear = 250;
assetMean = p.AssetMean * nyear;
assetCovar = p.AssetCovar;
assetRisk = sqrt(diag(assetCovar)*nyear);
p = p.setAssetMoments(assetMean,assetRisk);
% 绘制无卖空情况下的图片
case1 = 'Efficient frontier without short sale(annualized)';
% 设置投资组合所有成分非负且和为
p = setDefaultConstraints(p);
% Plot efficient frontier
[prsk1,pret1] = plotFrontier(p);

这段代码需要提醒的是,我们需要将日收益、风险进行年化,很多人忽略了这一步将导致错误,绘出来的图片不可思议。

绘制CAL曲线

我们继续绘制 CAL 曲线,代码如下:

a = gca;
ef = a.Children;
% clf;
% ax = axes;
hold on
% plot cash
scatter(gca,0,riskless,70,'r','filled');
text(0.01,riskless,'rf');

title(case1)

srwgt = p.estimateMaxSharpeRatio;
[srRsk,srRet] = p.estimatePortMoments(srwgt);

scatter(gca,srRsk,srRet,70,'g','filled');
text(srRsk+0.01,srRet,'Sharp Ratio');


% plot CAL
cal = plot(gca,[0,srRsk],[riskless,srRet],'r','LineWidth',2);
legend([ef,cal],'Efficient Frotier','CAL','Location','best');

saveas(gcf,[case1 '.jpg']);

这里需要注意绘制 cal 曲线需要知道两点,一点是无风险利率点,而另一点则是有效前沿上夏普率最大的点。

另外,这段代码需要提示的是几个绘图技巧。首先,我们用 gca 获取当前坐标轴,ef 获取的是上面绘制好的有效前沿的句柄,记录下句柄主要是为了后文我们能准确的添加图例,cal 也是一样的道理。另一个就是用 scatter 画点并填充。最后,用saveas 函数自动保存图片。最终得到图片如下:

本文中所包含的代码已经上传至 csdn 我的资源页面,欢迎下载,如有错误请不吝赐教。

猜你喜欢

转载自blog.csdn.net/m0_37639589/article/details/85804979