Main Content

estimateFrontier

Estimate specified number of optimal portfolios on the efficient frontier

Description

example

[pwgt,pbuy,psell] = estimateFrontier(obj) estimates the specified number of optimal portfolios on the efficient frontier for Portfolio, PortfolioCVaR, or PortfolioMAD objects. For details on the respective workflows when using these different objects, see Portfolio Object Workflow, PortfolioCVaR Object Workflow, and PortfolioMAD Object Workflow.

example

[pwgt,pbuy,psell] = estimateFrontier(obj,NumPorts) estimates the specified number of optimal portfolios on the efficient frontier with an additional option specified for NumPorts.

Examples

collapse all

Create efficient portfolios:

load CAPMuniverse

p = Portfolio('AssetList',Assets(1:12));
p = estimateAssetMoments(p, Data(:,1:12),'missingdata',true);
p = setDefaultConstraints(p);
plotFrontier(p);

Figure contains an axes object. The axes object with title Efficient Frontier, xlabel Standard Deviation of Portfolio Returns, ylabel Mean of Portfolio Returns contains an object of type line.

pwgt = estimateFrontier(p, 5);

pnames = cell(1,5);
for i = 1:5
	pnames{i} = sprintf('Port%d',i);
end

Blotter = dataset([{pwgt},pnames],'obsnames',p.AssetList);

disp(Blotter);
            Port1        Port2       Port3       Port4      Port5
    AAPL     0.017926    0.058247    0.097816    0.12955    0    
    AMZN            0           0           0          0    0    
    CSCO            0           0           0          0    0    
    DELL    0.0041906           0           0          0    0    
    EBAY            0           0           0          0    0    
    GOOG      0.16144     0.35678     0.55228    0.75116    1    
    HPQ      0.052566    0.032302    0.011186          0    0    
    IBM       0.46422     0.36045     0.25577    0.11928    0    
    INTC            0           0           0          0    0    
    MSFT      0.29966     0.19222    0.082949          0    0    
    ORCL            0           0           0          0    0    
    YHOO            0           0           0          0    0    

Create a Portfolio object for 12 stocks based on CAPMuniverse.mat.

load CAPMuniverse
p0 = Portfolio('AssetList',Assets(1:12));
p0 = estimateAssetMoments(p0, Data(:,1:12),'missingdata',true);
p0 = setDefaultConstraints(p0);

Use setMinMaxNumAssets to define a maximum number of 3 assets.

p1 = setMinMaxNumAssets(p0, [], 3);

Use setBounds to define a lower and upper bound and a BoundType of 'Conditional'.

p1 = setBounds(p1, 0.1, 0.5,'BoundType', 'Conditional');
pwgt = estimateFrontier(p1, 5);     

The following table shows that the optimized allocations only have maximum 3 assets invested, and small positions less than 0.1 are avoided.

result = table(p0.AssetList', pwgt)
result=12×2 table
      Var1                             pwgt                        
    ________    ___________________________________________________

    {'AAPL'}          0          0          0    0.14232          0
    {'AMZN'}          0          0          0          0          0
    {'CSCO'}          0          0          0          0          0
    {'DELL'}          0          0          0          0          0
    {'EBAY'}          0          0          0          0        0.5
    {'GOOG'}    0.16891    0.29534    0.42177        0.5        0.5
    {'HPQ' }          0          0          0          0          0
    {'IBM' }    0.49968    0.43657    0.37326    0.35768          0
    {'INTC'}          0          0          0          0          0
    {'MSFT'}     0.3314     0.2681    0.20496          0          0
    {'ORCL'}          0          0          0          0          0
    {'YHOO'}          0          0          0          0          0

The estimateFrontier function uses the MINLP solver to solve this problem. Use the setSolverMINLP function to configure the SolverType and options.

p1.solverTypeMINLP
ans = 
'OuterApproximation'
p1.solverOptionsMINLP
ans = struct with fields:
                           MaxIterations: 1000
                    AbsoluteGapTolerance: 1.0000e-07
                    RelativeGapTolerance: 1.0000e-05
                  NonlinearScalingFactor: 1000
                  ObjectiveScalingFactor: 1000
                                 Display: 'off'
                           CutGeneration: 'basic'
                MaxIterationsInactiveCut: 30
                      ActiveCutTolerance: 1.0000e-07
                    IntMainSolverOptions: [1x1 optim.options.Intlinprog]
    NumIterationsEarlyIntegerConvergence: 30
                     ExtendedFormulation: 0
                            NumInnerCuts: 10
                     NumInitialOuterCuts: 10

Create efficient portfolios:

load CAPMuniverse

p = PortfolioCVaR('AssetList',Assets(1:12));
p = simulateNormalScenariosByData(p, Data(:,1:12), 20000 ,'missingdata',true);
p = setDefaultConstraints(p);
p = setProbabilityLevel(p, 0.95);

plotFrontier(p);

Figure contains an axes object. The axes object with title Efficient Frontier, xlabel Conditional Value-at-Risk of Portfolio, ylabel Mean of Portfolio Returns contains an object of type line.

pwgt = estimateFrontier(p, 5);

pnames = cell(1,5);
for i = 1:5
	pnames{i} = sprintf('Port%d',i);
end

Blotter = dataset([{pwgt},pnames],'obsnames',p.AssetList);

disp(Blotter);
            Port1       Port2        Port3       Port4      Port5
    AAPL     0.01024     0.073698     0.11968    0.12961    0    
    AMZN           0            0           0          0    0    
    CSCO           0            0           0          0    0    
    DELL     0.02161            0           0          0    0    
    EBAY           0            0           0          0    0    
    GOOG     0.20311      0.38012     0.56206    0.75948    1    
    HPQ     0.042472    0.0092573           0          0    0    
    IBM      0.44453       0.3638     0.26262    0.11092    0    
    INTC           0            0           0          0    0    
    MSFT     0.27805      0.17313    0.055642          0    0    
    ORCL           0            0           0          0    0    
    YHOO           0            0           0          0    0    

Create efficient portfolios:

load CAPMuniverse

p = PortfolioMAD('AssetList',Assets(1:12));
p = simulateNormalScenariosByData(p, Data(:,1:12), 20000 ,'missingdata',true);
p = setDefaultConstraints(p);

plotFrontier(p);

Figure contains an axes object. The axes object with title Efficient Frontier, xlabel Mean Absolute Deviation of Portfolio Returns, ylabel Mean of Portfolio Returns contains an object of type line.

pwgt = estimateFrontier(p, 5);

pnames = cell(1,5);
for i = 1:5
	pnames{i} = sprintf('Port%d',i);
end

Blotter = dataset([{pwgt},pnames],'obsnames',p.AssetList);

disp(Blotter);
            Port1       Port2       Port3       Port4      Port5
    AAPL    0.030177    0.075105     0.11316    0.13349    0    
    AMZN           0           0           0          0    0    
    CSCO           0           0           0          0    0    
    DELL    0.010371           0           0          0    0    
    EBAY           0           0           0          0    0    
    GOOG     0.16086      0.3518     0.54447    0.74908    1    
    HPQ     0.056247    0.023952           0          0    0    
    IBM      0.45826     0.37958     0.29504    0.11743    0    
    INTC           0           0           0          0    0    
    MSFT     0.28409     0.16956    0.047322          0    0    
    ORCL           0           0           0          0    0    
    YHOO           0           0           0          0    0    

Obtain 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 = setAssetMoments(p, m, C);
p = setDefaultConstraints(p);
pwgt = estimateFrontier(p);
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

Starting from the initial portfolio, the estimateFrontier function returns purchases and sales to get from your initial portfolio to each efficient portfolio on the efficient frontier. 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 = setAssetMoments(p, m, C);
p = setDefaultConstraints(p);
pwgt0 = [ 0.3; 0.3; 0.2; 0.1 ];
p = setInitPort(p, pwgt0);
[pwgt, pbuy, psell] = estimateFrontier(p);

display(pwgt);
pwgt = 4×10

    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

display(pbuy);
pbuy = 4×10

    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

display(psell);
psell = 4×10

         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

Obtain 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 ];
m = m/12;
C = C/12;

rng(11);

AssetScenarios = mvnrnd(m, C, 20000);

p = PortfolioCVaR;
p = setScenarios(p, AssetScenarios);
p = setDefaultConstraints(p);
p = setProbabilityLevel(p, 0.95);

pwgt = estimateFrontier(p);

disp(pwgt);
    0.8454    0.6847    0.5166    0.3541    0.1897    0.0315         0         0         0         0
    0.0606    0.1429    0.2281    0.3167    0.3989    0.4732    0.3531    0.1804         0         0
    0.0456    0.0638    0.0944    0.1079    0.1344    0.1583    0.1733    0.1919    0.2212         0
    0.0484    0.1085    0.1609    0.2213    0.2770    0.3370    0.4736    0.6277    0.7788    1.0000

The function rng(seed) resets the random number generator to produce the documented results. It is not necessary to reset the random number generator to simulate scenarios.

Starting from the initial portfolio, the estimateFrontier function returns purchases and sales to get from your initial portfolio to each efficient portfolio on the efficient frontier. 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 ];
m = m/12;
C = C/12;

rng(11);

AssetScenarios = mvnrnd(m, C, 20000);
p = PortfolioCVaR;
p = setScenarios(p, AssetScenarios);
p = setDefaultConstraints(p);
p = setProbabilityLevel(p, 0.95);

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

display(pwgt);
pwgt = 4×10

    0.8454    0.6847    0.5166    0.3541    0.1897    0.0315         0         0         0         0
    0.0606    0.1429    0.2281    0.3167    0.3989    0.4732    0.3531    0.1804         0         0
    0.0456    0.0638    0.0944    0.1079    0.1344    0.1583    0.1733    0.1919    0.2212         0
    0.0484    0.1085    0.1609    0.2213    0.2770    0.3370    0.4736    0.6277    0.7788    1.0000

display(pbuy);
pbuy = 4×10

    0.5454    0.3847    0.2166    0.0541         0         0         0         0         0         0
         0         0         0    0.0167    0.0989    0.1732    0.0531         0         0         0
         0         0         0         0         0         0         0         0    0.0212         0
         0    0.0085    0.0609    0.1213    0.1770    0.2370    0.3736    0.5277    0.6788    0.9000

display(psell);
psell = 4×10

         0         0         0         0    0.1103    0.2685    0.3000    0.3000    0.3000    0.3000
    0.2394    0.1571    0.0719         0         0         0         0    0.1196    0.3000    0.3000
    0.1544    0.1362    0.1056    0.0921    0.0656    0.0417    0.0267    0.0081         0    0.2000
    0.0516         0         0         0         0         0         0         0         0         0

The function rng(seed) resets the random number generator to produce the documented results. It is not necessary to reset the random number generator to simulate scenarios.

Obtain 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 ];
m = m/12;
C = C/12;

rng(11);

AssetScenarios = mvnrnd(m, C, 20000);

p = PortfolioMAD;
p = setScenarios(p, AssetScenarios);
p = setDefaultConstraints(p);

pwgt = estimateFrontier(p);

disp(pwgt);
    0.8823    0.7151    0.5490    0.3819    0.2175    0.0499         0         0         0         0
    0.0420    0.1290    0.2130    0.2971    0.3822    0.4667    0.3615    0.1752         0         0
    0.0394    0.0600    0.0822    0.1068    0.1238    0.1487    0.1780    0.2101    0.2267         0
    0.0363    0.0959    0.1557    0.2142    0.2765    0.3347    0.4605    0.6147    0.7733    1.0000

The function rng(seed) resets the random number generator to produce the documented results. It is not necessary to reset the random number generator to simulate scenarios.

Starting from the initial portfolio, the estimateFrontier function returns purchases and sales to get from your initial portfolio to each efficient portfolio on the efficient frontier. 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 ];
m = m/12;
C = C/12;

rng(11);

AssetScenarios = mvnrnd(m, C, 20000);
p = PortfolioMAD;
p = setScenarios(p, AssetScenarios);
p = setDefaultConstraints(p);

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

display(pwgt);
pwgt = 4×10

    0.8823    0.7151    0.5490    0.3819    0.2175    0.0499         0         0         0         0
    0.0420    0.1290    0.2130    0.2971    0.3822    0.4667    0.3615    0.1752         0         0
    0.0394    0.0600    0.0822    0.1068    0.1238    0.1487    0.1780    0.2101    0.2267         0
    0.0363    0.0959    0.1557    0.2142    0.2765    0.3347    0.4605    0.6147    0.7733    1.0000

display(pbuy);
pbuy = 4×10

    0.5823    0.4151    0.2490    0.0819         0         0         0         0         0         0
         0         0         0         0    0.0822    0.1667    0.0615         0         0         0
         0         0         0         0         0         0         0    0.0101    0.0267         0
         0         0    0.0557    0.1142    0.1765    0.2347    0.3605    0.5147    0.6733    0.9000

display(psell);
psell = 4×10

         0         0         0         0    0.0825    0.2501    0.3000    0.3000    0.3000    0.3000
    0.2580    0.1710    0.0870    0.0029         0         0         0    0.1248    0.3000    0.3000
    0.1606    0.1400    0.1178    0.0932    0.0762    0.0513    0.0220         0         0    0.2000
    0.0637    0.0041         0         0         0         0         0         0         0         0

The function rng(seed) resets the random number generator to produce the documented results. It is not necessary to reset the random number generator to simulate scenarios.

Input Arguments

collapse all

Object for portfolio, specified using Portfolio, PortfolioCVaR, or PortfolioMAD object. For more information on creating a portfolio object, see

Data Types: object

Number of points to obtain on the efficient frontier, specified as a scalar integer.

Note

If no value is specified for NumPorts, the default value is obtained from the hidden property defaultNumPorts (default value is 10). If NumPorts = 1, this function returns the portfolio specified by the hidden property defaultFrontierLimit (current default value is 'min').

Data Types: double

Output Arguments

collapse all

Optimal portfolios on the efficient frontier with specified number of portfolios spaced equally from minimum to maximum portfolio return, returned as a NumAssets-by-NumPorts matrix. pwgt is returned for a Portfolio, PortfolioCVaR, or PortfolioMAD input object (obj).

Purchases relative to an initial portfolio for optimal portfolios on the efficient frontier, returned as NumAssets-by-NumPorts matrix.

Note

If no initial portfolio is specified in obj.InitPort, that value is assumed to be 0 such that pbuy = max(0, pwgt) and psell = max(0, -pwgt).

pbuy is returned for a Portfolio, PortfolioCVaR, or PortfolioMAD input object (obj).

Sales relative to an initial portfolio for optimal portfolios on the efficient frontier, returned as a NumAssets-by-NumPorts matrix.

Note

If no initial portfolio is specified in obj.InitPort, that value is assumed to be 0 such that pbuy = max(0, pwgt) and psell = max(0, -pwgt).

psell is returned for Portfolio, PortfolioCVaR, or PortfolioMAD input object (obj).

Tips

  • You can also use dot notation to estimate the specified number of optimal portfolios over the entire efficient frontier.

     	[pwgt, pbuy, psell] = obj.estimateFrontier(NumPorts);

  • When introducing transaction costs and turnover constraints to the Portfolio, PortfolioCVaR, or PortfolioMAD object, the portfolio optimization objective contains a term with an absolute value. For more information on how Financial Toolbox™ handles such cases algorithmically, see References.

References

[1] Cornuejols, G., and R. Tutuncu. Optimization Methods in Finance. Cambridge University Press, 2007.

Version History

Introduced in R2011a