Quantcast

Documentation Center

  • Trial Software
  • Product Updates

Estimate Efficient Portfolios

There are two ways to look at a portfolio optimization problem that depends on what you are trying to do. One goal is to estimate efficient portfolios and the other is to estimate efficient frontiers. This section focuses on the former goal and Estimate Efficient Frontiers focuses on the latter goal.

Obtaining Portfolios Along the Entire Efficient Frontier

The most basic way to obtain optimal portfolios is to obtain points over the entire range of the efficient frontier. Given a portfolio optimization problem in a Portfolio object, the estimateFrontier method computes efficient portfolios spaced evenly according to the return proxy from the minimum to maximum return efficient portfolios. The number of portfolios estimated is controlled by the hidden property defaultNumPorts which is set to 10. A different value for the number of portfolios estimated is specified as input to estimateFrontier. This example shows the default number of efficient portfolios over the entire range of the efficient frontier:

m = [ 0.05; 0.1; 0.12; 0.18 ];
C = [ 0.0064 0.00408 0.00192 0; 
      0.00408 0.0289 0.0204 0.0119;
      0.00192 0.0204 0.0576 0.0336;
      0 0.0119 0.0336 0.1225 ];
 
p = Portfolio;
p = p.setAssetMoments(m, C);
p = p.setDefaultConstraints;
pwgt = p.estimateFrontier;

disp(pwgt);
0.8891    0.7215    0.5540    0.3865    0.2190    0.0515         0         0         0         0
0.0369    0.1289    0.2209    0.3129    0.4049    0.4969    0.4049    0.2314    0.0579         0
0.0404    0.0567    0.0730    0.0893    0.1056    0.1219    0.1320    0.1394    0.1468         0
0.0336    0.0929    0.1521    0.2113    0.2705    0.3297    0.4630    0.6292    0.7953    1.0000

If you want only four portfolios in the previous example:

pwgt = p.estimateFrontier(4);
disp(pwgt);
    0.8891    0.3865         0         0
    0.0369    0.3129    0.4049         0
    0.0404    0.0893    0.1320         0
    0.0336    0.2113    0.4630    1.0000

Starting from the initial portfolio, estimateFrontier also returns purchases and sales to get from your initial portfolio to each efficient portfolio on the efficient frontier. For example, given an initial portfolio in pwgt0, you can obtain purchases and sales:

pwgt0 = [ 0.3; 0.3; 0.2; 0.1 ];
p = p.setInitPort(pwgt0);
[pwgt, pbuy, psell] = p.estimateFrontier;

display(pwgt);
display(pbuy);
display(psell);
pwgt =

0.8891    0.7215    0.5540    0.3865    0.2190    0.0515         0         0         0         0
0.0369    0.1289    0.2209    0.3129    0.4049    0.4969    0.4049    0.2314    0.0579         0
0.0404    0.0567    0.0730    0.0893    0.1056    0.1219    0.1320    0.1394    0.1468         0
0.0336    0.0929    0.1521    0.2113    0.2705    0.3297    0.4630    0.6292    0.7953    1.0000


pbuy =

0.5891    0.4215    0.2540    0.0865         0         0         0         0         0         0
     0         0         0    0.0129    0.1049    0.1969    0.1049         0         0         0
     0         0         0         0         0         0         0         0         0         0
     0         0    0.0521    0.1113    0.1705    0.2297    0.3630    0.5292    0.6953    0.9000


psell =

0         0         0         0    0.0810    0.2485    0.3000    0.3000    0.3000    0.3000
0.2631    0.1711    0.0791         0         0         0         0    0.0686    0.2421    0.3000
0.1596    0.1433    0.1270    0.1107    0.0944    0.0781    0.0680    0.0606    0.0532    0.2000
0.0664    0.0071         0         0         0         0         0         0         0         0

If you do not specify an initial portfolio, the purchase and sale weights assume that your initial portfolio is 0.

Obtaining Endpoints of the Efficient Frontier

In many cases, you might be interested in the endpoint portfolios for the efficient frontier. Suppose you want to determine the range of returns from minimum to maximum to refine a search for a portfolio with a specific target return. Use the estimateFrontierLimits method to obtain the endpoint portfolios:

m = [ 0.05; 0.1; 0.12; 0.18 ];
C = [ 0.0064 0.00408 0.00192 0; 
      0.00408 0.0289 0.0204 0.0119;
      0.00192 0.0204 0.0576 0.0336;
      0 0.0119 0.0336 0.1225 ];
 
p = Portfolio;
p = p.setAssetMoments(m, C);
p = p.setDefaultConstraints;
pwgt = p.estimateFrontierLimits;

disp(pwgt);   
    0.8891         0
    0.0369         0
    0.0404         0
    0.0336    1.0000

The estimatePortMoments method shows the range of risks and returns for efficient portfolios:

[prsk, pret] = p.estimatePortMoments(pwgt);
disp([prsk, pret]);
 0.0769    0.0590
 0.3500    0.1800

Starting from an initial portfolio, estimateFrontierLimits also returns purchases and sales to get from the initial portfolio to the endpoint portfolios on the efficient frontier. For example, given an initial portfolio in pwgt0, you can obtain purchases and sales:

m = [ 0.05; 0.1; 0.12; 0.18 ];
C = [ 0.0064 0.00408 0.00192 0; 
      0.00408 0.0289 0.0204 0.0119;
      0.00192 0.0204 0.0576 0.0336;
      0 0.0119 0.0336 0.1225 ];
 
p = Portfolio;
p = p.setAssetMoments(m, C);
p = p.setDefaultConstraints;

pwgt0 = [ 0.3; 0.3; 0.2; 0.1 ];
p = p.setInitPort(pwgt0);
[pwgt, pbuy, psell] = p.estimateFrontierLimits;
	
display(pwgt);
display(pbuy);
display(psell);
pwgt =

    0.8891         0
    0.0369         0
    0.0404         0
    0.0336    1.0000

pbuy =

    0.5891         0
         0         0
         0         0
         0    0.9000

psell =

         0    0.3000
    0.2631    0.3000
    0.1596    0.2000
    0.0664         0

If you do not specify an initial portfolio, the purchase and sale weights assume that your initial portfolio is 0.

Obtaining Efficient Portfolios for Target Returns

To obtain efficient portfolios that have targeted portfolio returns, the estimateFrontierByReturn method accepts one or more target portfolio returns and obtains efficient portfolios with the specified returns. For example, assume that you have a universe of four assets where you want to obtain efficient portfolios with target portfolio returns of 6%, 9%, and 12%:

m = [ 0.05; 0.1; 0.12; 0.18 ];
C = [ 0.0064 0.00408 0.00192 0; 
      0.00408 0.0289 0.0204 0.0119;
      0.00192 0.0204 0.0576 0.0336;
      0 0.0119 0.0336 0.1225 ];
 
p = Portfolio;
p = p.setAssetMoments(m, C);
p = p.setDefaultConstraints;
pwgt = p.estimateFrontierByReturn([0.06, 0.09, 0.12]);

display(pwgt);
pwgt =

    0.8772    0.5032    0.1293
    0.0434    0.2488    0.4541
    0.0416    0.0780    0.1143
    0.0378    0.1700    0.3022

In some cases, you can request a return for which no efficient portfolio exists. Based on the previous example, suppose you want a portfolio with a 5% return (which is the return of the first asset). A portfolio that is fully invested in the first asset, however, is inefficient. estimateFrontierByReturn warns if your target returns are outside the range of efficient portfolio returns and replaces it with the endpoint portfolio of the efficient frontier closest to your target return:

m = [ 0.05; 0.1; 0.12; 0.18 ];
C = [ 0.0064 0.00408 0.00192 0; 
      0.00408 0.0289 0.0204 0.0119;
      0.00192 0.0204 0.0576 0.0336;
      0 0.0119 0.0336 0.1225 ];
 
p = Portfolio;
p = p.setAssetMoments(m, C);
p = p.setDefaultConstraints;
pwgt = p.estimateFrontierByReturn([0.05, 0.09, 0.12]);

display(pwgt);
Warning: One or more target return values are outside the feasible range [ 0.0590468, 0.18 ].
	Will return portfolios associated with endpoints of the range for these values. 
> In Portfolio.estimateFrontierByReturn at 71 

pwgt =

    0.8891    0.5032    0.1293
    0.0369    0.2488    0.4541
    0.0404    0.0780    0.1143
    0.0336    0.1700    0.3022

The best way to avoid this situation is to bracket your target portfolio returns with estimateFrontierLimits and estimatePortReturn (see Obtaining Endpoints of the Efficient Frontier and Obtaining Portfolio Risks and Returns).

pret = p.estimatePortReturn(p.estimateFrontierLimits);

display(pret);
pret =

    0.0590
    0.1800

This result indicates that efficient portfolios have returns that range between 5.9% and 18%.

If you have an initial portfolio, estimateFrontierByReturn also returns purchases and sales to get from your initial portfolio to the target portfolios on the efficient frontier. For example, given an initial portfolio in pwgt0, to obtain purchases and sales with target returns of 6%, 9%, and 12%:

pwgt0 = [ 0.3; 0.3; 0.2; 0.1 ];
p = p.setInitPort(pwgt0);
[pwgt, pbuy, psell] = p.estimateFrontierByReturn([0.06, 0.09, 0.12]);

display(pwgt);
display(pbuy);
display(psell);
pwgt =

    0.8772    0.5032    0.1293
    0.0434    0.2488    0.4541
    0.0416    0.0780    0.1143
    0.0378    0.1700    0.3022

pbuy =

    0.5772    0.2032         0
         0         0    0.1541
         0         0         0
         0    0.0700    0.2022

psell =

         0         0    0.1707
    0.2566    0.0512         0
    0.1584    0.1220    0.0857
    0.0622         0         0

If you do not have an initial portfolio, the purchase and sale weights assume that your initial portfolio is 0.

Obtaining Efficient Portfolios for Target Risks

To obtain efficient portfolios that have targeted portfolio risks, the estimateFrontierByRisk method accepts one or more target portfolio risks and obtains efficient portfolios with the specified risks. Suppose you have a universe of four assets where you want to obtain efficient portfolios with target portfolio risks of 12%, 14%, and 16%.

m = [ 0.05; 0.1; 0.12; 0.18 ];
C = [ 0.0064 0.00408 0.00192 0; 
      0.00408 0.0289 0.0204 0.0119;
      0.00192 0.0204 0.0576 0.0336;
      0 0.0119 0.0336 0.1225 ];
 
 p = Portfolio;
 p = p.setAssetMoments(m, C);
 p = p.setDefaultConstraints;
 pwgt = p.estimateFrontierByRisk([0.12, 0.14, 0.16]);

 display(pwgt);
pwgt =

    0.3984    0.2659    0.1416
    0.3064    0.3791    0.4474
    0.0882    0.1010    0.1131
    0.2071    0.2540    0.2979

In some cases, you can request a risk for which no efficient portfolio exists. Based on the previous example, suppose you want a portfolio with 7% risk (individual assets in this universe have risks ranging from 8 to 35%). It turns out that a portfolio with 7% risk cannot be formed with these four assets. estimateFrontierByRisk warns if your target risks are outside the range of efficient portfolio risks and replaces it with the endpoint of the efficient frontier closest to your target risk:

pwgt = p.estimateFrontierByRisk(0.07)
Warning: One or more target risk values are outside the feasible range [ 0.0769288, 0.35 ].
	Will return portfolios associated with endpoints of the range for these values. 
> In Portfolio.estimateFrontierByRisk at 83 

pwgt =

    0.8891
    0.0369
    0.0404
    0.0336

The best way to avoid this situation is to bracket your target portfolio risks with estimateFrontierLimits and estimatePortRisk (see Obtaining Endpoints of the Efficient Frontier and Obtaining Portfolio Risks and Returns).

prsk = p.estimatePortRisk(p.estimateFrontierLimits);

display(prsk);
prsk =

    0.0769
    0.3500

This result indicates that efficient portfolios have risks that range from 7.7 to 35%.

Starting with an initial portfolio, estimateFrontierByRisk also returns purchases and sales to get from your initial portfolio to the target portfolios on the efficient frontier. For example, given an initial portfolio in pwgt0, you can obtain purchases and sales from the example with target risks of 12%, 14%, and 16%:

pwgt0 = [ 0.3; 0.3; 0.2; 0.1 ];
p = p.setInitPort(pwgt0);
[pwgt, pbuy, psell] = p.estimateFrontierByRisk([0.12, 0.14, 0.16]);

display(pwgt);
display(pbuy);
display(psell);
pwgt =

    0.3984    0.2659    0.1416
    0.3064    0.3791    0.4474
    0.0882    0.1010    0.1131
    0.2071    0.2540    0.2979


pbuy =

    0.0984         0         0
    0.0064    0.0791    0.1474
         0         0         0
    0.1071    0.1540    0.1979


psell =

         0    0.0341    0.1584
         0         0         0
    0.1118    0.0990    0.0869
         0         0         0

If you do not specify an initial portfolio, the purchase and sale weights assume that your initial portfolio is 0.

Efficient Portfolio that Maximizes Sharpe Ratio

The Sharpe ratio is defined as the ratio

where and r0 is the risk-free rate (μ and Σ proxies for portfolio return and risk). For more information, see Portfolio Optimization Theory.

Portfolios that maximize the Sharpe ratio are portfolios on the efficient frontier that satisfy a number of theoretical conditions in finance. For example, such portfolios are called tangency portfolios since the tangent line from the risk-free rate to the efficient frontier touches the efficient frontier at portfolios that maximize the Sharpe ratio.

To obtain efficient portfolios that maximizes the Sharpe ratio, the estimateMaxSharpeRatio method accepts a Portfolio object and obtains efficient portfolios that maximize the Sharpe Ratio.

Suppose you have a universe with four risky assets and a riskless asset and you want to obtain a portfolio that maximizes the Sharpe ratio, where, in this example, r0 is the return for the riskless asset.

r0 = 0.03;
m = [ 0.05; 0.1; 0.12; 0.18 ];
C = [ 0.0064 0.00408 0.00192 0;
      0.00408 0.0289 0.0204 0.0119;
      0.00192 0.0204 0.0576 0.0336;
      0 0.0119 0.0336 0.1225 ];
 
p = Portfolio('RiskFreeRate', r0);
p = p.setAssetMoments(m, C);
p = p.setDefaultConstraints;
pwgt = p.estimateMaxSharpeRatio;

display(pwgt);
pwgt =

    0.4251
    0.2917
    0.0856
    0.1977

If you start with an initial portfolio, estimateMaxSharpeRatio also returns purchases and sales to get from your initial portfolio to the portfolio that maximizes the Sharpe ratio. For example, given an initial portfolio in pwgt0, you can obtain purchases and sales from the previous example:

pwgt0 = [ 0.3; 0.3; 0.2; 0.1 ];
p = p.setInitPort(pwgt0);
[pwgt, pbuy, psell] = p.estimateMaxSharpeRatio;

display(pwgt);
display(pbuy);
display(psell);
pwgt =

    0.4251
    0.2917
    0.0856
    0.1977


pbuy =

    0.1251
         0
         0
    0.0977


psell =

         0
    0.0083
    0.1144
         0

If you do not specify an initial portfolio, the purchase and sale weights assume that you initial portfolio is 0.

Choosing and Controlling the Solver

The default solver for mean-variance portfolio optimization is lcprog, which implements a linear complementarity programming (LCP) algorithm. Although lcprog works for most problems, you can adjust arguments to control the algorithm. Alternatively, the mean-variance portfolio optimization tools let you use any of the variations of quadprog from Optimization Toolbox™ software. Unlike Optimization Toolbox which uses the trust-region-reflective algorithm as the default algorithm for quadprog, the portfolio optimization tools use the interior-point-convex algorithm. For details about quadprog and quadratic programming algorithms and options, see Quadratic Programming Algorithms.

To modify either lcprog or to specify quadprog as your solver, use the setSolver method to set the hidden properties solverType and solverOptions that specify and control the solver. Since the solver properties are hidden, you cannot set these using the portfolio constructor Portfolio. The default solver is lcprog so you do not need to use setSolver to specify this solver. To use quadprog, you must set up the interior-point-convex version of quadprog using:

p = p.setSolver('quadprog');
display(p.solverType);
quadprog

and you can switch back tolcprog with:

p = p.setSolver('lcprog');
display(p.solverType);
lcprog

In both cases, setSolver sets up default options associated with either solver. If you want to specify additional options associated with a given solver, setSolver accepts these options with argument name-value pair arguments in the function call. For example, if you intend to use quadprog and want to use the active-set algorithm, call setSolver with:

p = p.setSolver('quadprog', 'Algorithm', 'active-set');
display(p.solverOptions.Algorithm);
active-set

In addition, if you want to specify any of the options for quadprog that are normally set through optimoptions, setSolver accepts an optimoptions object as the second argument. For example, you can start with the default options for quadprog set by setSolver and then change the algorithm to 'trust-region-reflective' with no displayed output:

p = Portfolio;
options = optimoptions('quadprog', 'Algorithm', 'trust-region-reflective', 'Display', 'off');
p = p.setSolver('quadprog', options);
display(p.solverOptions.Algorithm);
display(p.solverOptions.Display);
trust-region-reflective
off

See Also

| | | | | | | | | |

Related Examples

More About

Was this topic helpful?