Portfolio Optimization Demo (with Distributed Arrays and SPMD)
This demo calculates returns the risk-return relationship in the stock portfolio that is optimal in the mean-variance sense. covMat and expRet are the covariance and mean returns of a collection of stocks and muVec is a vector of desired returns.
The covariance matrix (covMat) is calculated using distributed arrays. To calculate the covariance matrix we must process a large data set comprising several thousand time points for each stock. For this exercise, for demostration purposes, we use a reduced dataset so as to fit all the data in a single computer running four local workers. However, for higher-fidelity simulations one would require higher number of data points for a larger number of stocks. This can quickly breach the limits of a single desktop computer.
Once the covariance matrix is computed, since it is N x N where N is just the number of stocks, it can be held in a single computer's memory and used locally.
Contents
Clear out all old variables
clear all
Opening a matlabpool
if matlabpool('size') == 0 matlabpool open 2 else warning('MATLAB:poolOpen', 'matlabpool already open') end
Starting matlabpool using the parallel configuration 'local'. Waiting for parallel job to start... Connected to a matlabpool session with 2 labs.
Loading in historical stock data
numFiles = 4; % number of files to use numStocks = 200; % number of stocks to use numPoints = 10; % number of points on the efficency frontier x = Exercise2_loadReturns(numFiles,numStocks);
1 ans =
144004 200
2 ans =
144004 200
Calculating the covariance matrix
spmd [n,m] = size(x); display(size(x)); % calculating the covariance and expected return expRet = sum(x)/m; expRet = gather(expRet); x = bsxfun(@minus,localPart(x),sum(localPart(x),1)./m); % Remove mean x = codistributed(x, codistributor('1d',1)); covMat = (x' * x) / (m-1); covMat = gather(covMat,1); end
Calculating range and points along the efficency frontier
expRet = expRet{1}; % getting data back from workers
covMat = covMat{1}; % getting data back from workers
retRange = [min(expRet(expRet > 0)) max(expRet)];
rangeFudge = abs(diff(retRange))/20; % a little above and below the range
retRange = retRange + [rangeFudge -rangeFudge];
muVec = linspace(retRange(1), retRange(2), numPoints); % points along frontier
Find the frontier for the stock portfolio
This function uses a parfor. You can combine parfor and spmd in the same program along with serial code. View code for Exercise2_task_optim
[risk, ret] = Exercise2_task_optim(covMat, expRet, muVec);
Visualization
fig2 = figure; Exercise2_plot_optim(fig2, risk, ret);
Close the matlabpool
if matlabpool('size') ~= 0 matlabpool close else warning('MATLAB:poolClose', 'matlabpool already closed') end
Sending a stop signal to all the labs... Waiting for parallel job to finish... Performing parallel job cleanup... Done.