Code covered by the BSD License  

Highlights from
Analyzing Investment Strategies with CVaR Portfolio Optimization

image thumbnail

Analyzing Investment Strategies with CVaR Portfolio Optimization

by

Bob Taylor (view profile)

 

18 Dec 2012 (Updated )

Scripts and data to demonstrate the new PortfolioCVaR object in Financial Toolbox.

cvarwebinar_optimization.m
%% Analyzing Investment Strategies with CVaR Portfolio Optimization in MATLAB - Optimization
%
% Robert Taylor
% The MathWorks, Inc.

% Copyright (C) 2012 The MathWorks, Inc.

%% Introduction

% Portfolio weights generated by this script.

% pwgt - CVaR efficient portfolios for covered and uncovered positions
% qwgt - MV efficient portfolios for covered and uncovered positions
% rwgt - MV efficient portfolios for uncovered only
% qmatchwgt - MV efficient portfolios from qwgt with std that match std for pwgt

%% Load scenarios

load BuyWriteScenarios

%% Set up CVaR portfolio optimization

AU = Assets;
AC1 = Assets;
for i = 1:26
	AU{i} = [ AU{i} ' Uncovered' ];
	AC1{i} = [ AC1{i} ' Covered @ 5%' ];
end

AssetList = [ AU; AC1 ];
Scenarios = [ XU, XC1 ];

% Uncomment these lines and comment out previous lines in this section to incorporate two strike
% prices in the portfolio optimization. No other changes are needed in this script.

% AU = Assets;
% AC1 = Assets;
% AC2 = Assets;
% for i = 1:26
% 	AU{i} = [ AU{i} ' Uncovered' ];
% 	AC1{i} = [ AC1{i} ' Covered @ 5%' ];
% 	AC2{i} = [ AC2{i} ' Covered @ 10%' ];
% end
% 
% AssetList = [ AU; AC1; AC2 ];
% Scenarios = [ XU, XC1; XC2 ];

%% Do CVaR Portfolio Optimization

tic

p = PortfolioCVaR('AssetList', AssetList);
p = p.setScenarios(Scenarios);
p = p.setDefaultConstraints;
p = p.setProbabilityLevel(0.9);

pwgt = p.estimateFrontier(10);

pstd = p.estimatePortStd(pwgt);
pret = p.estimatePortReturn(pwgt);
pcvar = p.estimatePortRisk(pwgt);

toc_frontier = toc;

fprintf('Time to estimate CVaR efficient frontier %g\n',toc_frontier);

%% Do Mean-Variance Portfolio Optimization

q = Portfolio('AssetList', AssetList);
q = q.estimateAssetMoments(p.getScenarios);		% use scenarios from PortfolioCVaR object
q = q.setDefaultConstraints;

qwgt = q.estimateFrontier(10);

[qstd, qret] = q.estimatePortMoments(qwgt);

%% Do Mean-Variance Portfolio Optimization with Uncovered Positions Only

r = Portfolio('AssetList', Assets);
r = r.estimateAssetMoments(XU);
r = r.setDefaultConstraints;

rwgt = r.estimateFrontier;

[rstd, rret] = r.estimatePortMoments(rwgt);

%% Match Risks

qmatchwgt = q.estimateFrontierByRisk(pstd);

[qmatchstd, qmatchret] = q.estimatePortMoments(qmatchwgt);

%% Look at Raw Distribution of Portfolio Weights

% For one covered position -
%	"Bluer" bands are uncovered positions, "redder" bands are covered positions.
% For two covered positions -
%	"Bluer" bands are uncovered positions, "yellow/green" bands are covered positions at lower strike,
%	"redder" bands are covered positions at higher strike

figure(1);

subplot(2,1,1);
area(qwgt');
axis([1,10,0,1]);
title('\bfMean-Variance Portfolio Weights');

subplot(2,1,2);
area(pwgt');
axis([1,10,0,1]);
title('\bfCVaR Portfolio Weights');

%% Match Risks

figure(2);

subplot(2,1,1);
area(pstd, qmatchwgt');
axis([min(pstd), max(pstd), 0, 1]);
title('\bfMean-Variance Portfolio Weights');
xlabel('Standard Deviation of Portfolio Returns');

subplot(2,1,2);
area(pstd, pwgt');
axis([min(pstd), max(pstd), 0, 1]);
title('\bfCVaR Portfolio Weights');
xlabel('Standard Deviation of Portfolio Returns');

%% Compare Efficient Frontiers

figure(3);

plot(pstd, pret, 'b');
hold on
plot(qstd, qret,'g');
plot(rstd, rret,'r');
legend('CVaR with Covered-Call','Mean-Variance with Covered-Call', ...
	'Mean-Variance without Covered-Call','Location','SouthEast');
title('\bfEfficient Frontiers');
xlabel('Standard Deviation of Portfolio Returns');
ylabel('Mean of Portfolio Returns');
hold off

%% Examine Portfolios

ii = sum(pwgt,2) > 1.0e-4;					% keep only assets with at least 1 non-zero weight
iiwgt = pwgt(ii,:);
iiwgt(iiwgt < 1.0e-4) = 0;					% set negligible portfolio weights to 0
iiwgt = 0.01*floor(10000*iiwgt + 0.5);		% round weights down to nearest basis point weight

CVaRblotter = dataset({iiwgt(:,1),'CV1'},{iiwgt(:,2),'CV2'},{iiwgt(:,3),'CV3'}, ...
	{iiwgt(:,4),'CV4'},{iiwgt(:,5),'CV5'},{iiwgt(:,6),'CV6'},{iiwgt(:,7),'CV7'}, ...
	{iiwgt(:,8),'CV8'},{iiwgt(:,9),'CV9'},{iiwgt(:,10),'CV10'},'ObsNames', AssetList(ii));

ii = sum(qmatchwgt,2) > 1.0e-4;				% keep only assets with at least 1 non-zero weight
iiwgt = qmatchwgt(ii,:);
iiwgt(iiwgt < 1.0e-4) = 0;					% set negligible portfolio weights to 0
iiwgt = 0.01*floor(10000*iiwgt + 0.5);		% round weights down to nearest basis point weight

MVblotter = dataset({iiwgt(:,1),'MV1'},{iiwgt(:,2),'MV2'},{iiwgt(:,3),'MV3'}, ...
	{iiwgt(:,4),'MV4'},{iiwgt(:,5),'MV5'},{iiwgt(:,6),'MV6'},{iiwgt(:,7),'MV7'}, ...
	{iiwgt(:,8),'MV8'},{iiwgt(:,9),'MV9'},{iiwgt(:,10),'MV10'},'ObsNames', AssetList(ii));

CVaRblotter
MVblotter

Contact us