Mixed-Integer CVaR Portfolio Optimization Problem
This example shows how to solve a CVaR portfolio optimization problem with constraints in the number of selected assets or conditional (semicontinuous) bounds. To solve this problem, you can use a PortfolioCVaR
object along with different mixed integer nonlinear programming (MINLP) solvers.
CVaR Portfolio
Load the returns data in CAPMuniverse.mat
. Then, create a PortfolioCVaR
object with default constraints and a long-only portfolio whose weights sum to 1
. For this example, you can define the feasible region of weights as
% Load data load CAPMuniverse.mat % Create portfolio with default constraints p = PortfolioCVaR(ProbabilityLevel=0.95); p = simulateNormalScenariosByData(p,Data(:,1:12),1000,missingdata=true); p = setDefaultConstraints(p);
Include binary variables for this scenario by setting conditional (semicontinuous) bounds. Conditional bounds are those such that or . In this example, for all assets.
% Set conditional bounds condLB = 0.1; condUB = 0.5; p = setBounds(p,condLB,condUB,BoundType="conditional");
Use estimateFrontier
to estimate a set of portfolios on the efficient frontier. The efficient frontier is a curve that shows the trade-off between the return and risk achieved by Pareto-optimal portfolios. For a given return level, the portfolio on the efficient frontier is the one that minimizes the risk while maintaining the desired return. Conversely, for a given risk level, the portfolio on the efficient frontier is the one that maximizes return while maintaining the desired risk level.
% Compute efficient frontier p = setSolverMINLP(p,'TrustRegionCP',DeltaLowerBound=condLB); pwgt = estimateFrontier(p)
pwgt = 12×10
0 0 0 0 0 0 0 0 0 0
0 0 0 -0.0000 0 0 -0.0000 0 0 0
0 0 0 0 0 0 0 0 0 0
0.1000 0.1094 0.1000 0.1000 0 0 0 0.0000 0 0
0 0 0 0.1000 0.1662 0.2634 0.3369 0.4051 0.4647 0.5000
0.1328 0.2387 0.3331 0.3263 0.3622 0.3543 0.3701 0.3854 0.4287 0.5000
0.1000 0 0 0 0 0 0 0 0 0
0.4132 0.3888 0.2755 0.2552 0.2288 0.1812 0.1110 0 0 0
0 0 0 0 0 0 0 0 0 0
0.2540 0.2631 0.2914 0.2185 0.2427 0.2011 0.1821 0.2095 0.1067 0
⋮
% Compute risk and returns of the portfolios on the efficient frontier
rsk = estimatePortRisk(p,pwgt)
rsk = 10×1
0.0368
0.0377
0.0398
0.0423
0.0453
0.0485
0.0520
0.0558
0.0598
0.0647
ret = estimatePortReturn(p,pwgt)
ret = 10×1
0.0009
0.0012
0.0014
0.0016
0.0019
0.0021
0.0023
0.0026
0.0028
0.0030
Plot the weights from the frontier estimation using plotFrontier
. The resulting curve is piece-wise concave with possible vertical jumps (discontinuities) between the concave intervals.
% Plot efficient frontier
plotFrontier(p,pwgt)
Changing MINLP Solvers
In the previous section, you use the default solver for estimateFrontier
. However, you can solve mixed-integer portfolio problems using any of the three algorithms supported by setSolverMINLP
: OuterApproximation
, ExtendedCP
, and TrustRegionCP
. Furthermore, the OuterApproximation
algorithm accepts an additional name-value argument (ExtendedFormulation
) for Portfolio
problems, which reformulates problems with quadratic functions to work in an extended space that usually decreases the computation time. All algorithms, including the extended formulation variation of the OuterApproximation
algorithm, return the same values within numerical accuracy. The available solvers are:
OuterApproximation
— The default algorithm, which is robust and usually faster thanExtenedCP
OuterApproximation
withExtendedFormulation
set totrue
— A robust algorithm that is usually faster than other algorithms, but only supported forPortfolio
object problemsExtendedCP
— The most robust solver, but usually the slowestTrustRegionCP
— The fastest algorithm, but one that is less robust and may provide suboptimal solutions
For more information on solvers for mixed-integer portfolio problems, see Choose MINLP Solvers for Portfolio Problems.
To change the MINLP solvers, use setSolverMINLP
.
% Select 'TrustRegionCP' as solver p_OA = setSolverMINLP(p,'OuterApproximation'); pwgt_OA = estimateFrontier(p_OA); rskOA = estimatePortRisk(p,pwgt_OA); retOA = estimatePortReturn(p,pwgt_OA); % Select 'ExtendedCP' as solver using 'midway' cuts as 'CutGeneration' p_ECP = setSolverMINLP(p,'ExtendedCP',CutGeneration="midway"); pwgt_ECP = estimateFrontier(p_ECP); rskECP = estimatePortRisk(p,pwgt_ECP); retECP = estimatePortReturn(p,pwgt_ECP);
Compare the returns and risks obtained by the portfolios on the efficient frontier from the different solvers. They are all the same within a numerical accuracy that is an absolute difference .
retTable = table(retOA,ret,retECP,'VariableNames',{'OA','TR','ECP'})
retTable=10×3 table
OA TR ECP
__________ __________ __________
0.00092881 0.00092876 0.00092876
0.0011614 0.0011613 0.0011613
0.001394 0.0013939 0.0013939
0.0016265 0.0016265 0.0016265
0.0018591 0.0018591 0.0018591
0.0020917 0.0020917 0.0020917
0.0023243 0.0023243 0.0023243
0.0025569 0.0025569 0.0025569
0.0027894 0.0027894 0.0027894
0.003022 0.003022 0.003022
rskTable = table(rskOA,rsk,rskECP,'VariableNames',{'OA','TR','ECP'})
rskTable=10×3 table
OA TR ECP
________ ________ ________
0.036808 0.036808 0.036808
0.037658 0.037658 0.037658
0.039808 0.039808 0.039808
0.042256 0.042256 0.042256
0.04527 0.045269 0.045269
0.048489 0.048488 0.048488
0.051963 0.051963 0.051963
0.055783 0.055783 0.055783
0.059828 0.059828 0.059828
0.064705 0.064705 0.064705
% Compare risks from the different OuterApproximation formulations
norm(rskTable.OA-rskTable.TR,Inf) <= 1e-4
ans = logical
1
See Also
Related Examples
- Troubleshooting CVaR Portfolio Optimization Results
- Creating the PortfolioCVaR Object
- Working with CVaR Portfolio Constraints Using Defaults
- Asset Returns and Scenarios Using PortfolioCVaR Object
- Estimate Efficient Portfolios for Entire Frontier for PortfolioCVaR Object
- Estimate Efficient Frontiers for PortfolioCVaR Object
- Hedging Using CVaR Portfolio Optimization
More About
- PortfolioCVaR Object
- Portfolio Optimization Theory
- PortfolioCVaR Object Workflow
- Choose MINLP Solvers for Portfolio Problems