Main Content

Troubleshooting Portfolio Optimization Results

Portfolio Object Destroyed When Modifying

If a Portfolio object is destroyed when modifying, remember to pass an existing object into the Portfolio object if you want to modify it, otherwise it creates a new object. See Creating the Portfolio Object for details.

Optimization Fails with “Bad Pivot” Message

If the optimization fails with a "bad pivot" message from lcprog, try a larger value for tolpiv which is a tolerance for pivot selection in the lcprog algorithm (try 1.0e-7, for example) or try the interior-point-convex version of quadprog. For details, see Choosing and Controlling the Solver for Mean-Variance Portfolio Optimization, the help header for lcprog, and quadprog.

Speed of Optimization

Although it is difficult to characterize when one algorithm is faster than the other, the default solver, lcprog is faster for smaller problems and the quadprog solver is faster for larger problems. If one solver seems to take too much time, try the other solver. To change solvers, use setSolver.

Matrix Incompatibility and "Non-Conformable" Errors

If you get matrix incompatibility or "non-conformable" errors, the representation of data in the tools follows a specific set of basic rules described in Conventions for Representation of Data.

Missing Data Estimation Fails

If asset return data has missing or NaN values, the estimateAssetMoments function with the 'missingdata' flag set to true may fail with either too many iterations or a singular covariance. To correct this problem, consider this:

  • If you have asset return data with no missing or NaN values, you can compute a covariance matrix that may be singular without difficulties. If you have missing or NaN values in your data, the supported missing data feature requires that your covariance matrix must be positive-definite, that is, nonsingular.

  • estimateAssetMoments uses default settings for the missing data estimation procedure that might not be appropriate for all problems.

In either case, you might want to estimate the moments of asset returns separately with either the ECM estimation functions such as ecmnmle or with your own functions.

mv_optim_transform Errors

If you obtain optimization errors such as:

Error using mv_optim_transform (line 233)
Portfolio set appears to be either empty or unbounded. Check constraints.

Error in Portfolio/estimateFrontier (line 63)
	[A, b, f0, f, H, g, lb] = mv_optim_transform(obj);
or
Error using mv_optim_transform (line 238)
Cannot obtain finite lower bounds for specified portfolio set.

Error in Portfolio/estimateFrontier (line 63)
	[A, b, f0, f, H, g, lb] = mv_optim_transform(obj);
Since the portfolio optimization tools require a bounded portfolio set, these errors (and similar errors) can occur if your portfolio set is either empty and, if nonempty, unbounded. Specifically, the portfolio optimization algorithm requires that your portfolio set have at least a finite lower bound. The best way to deal with these problems is to use the validation functions in Validate the Portfolio Problem for Portfolio Object. Specifically, use estimateBounds to examine your portfolio set, and use checkFeasibility to ensure that your initial portfolio is either feasible and, if infeasible, that you have sufficient turnover to get from your initial portfolio to the portfolio set.

Tip

To correct this problem, try solving your problem with larger values for turnover or tracking-error and gradually reduce to the value that you want.

solveContinuousCustomObjProb or solveMICustomObjProb Errors

These errors can occur if the portfolio set is empty or unbounded. If the portfolio set is empty, the error states that the problem is infeasible. The best way to deal with these problems is to use the validation functions in Validate the Portfolio Problem for Portfolio Object. Specifically, use estimateBounds to examine your portfolio set, and use checkFeasibility to ensure that your initial portfolio is either feasible or, if infeasible, that you have sufficient turnover to get from your initial portfolio to the portfolio set.

Efficient Portfolios Do Not Make Sense

If you obtain efficient portfolios that do not seem to make sense, this can happen if you forget to set specific constraints or you set incorrect constraints. For example, if you allow portfolio weights to fall between 0 and 1 and do not set a budget constraint, you can get portfolios that are 100% invested in every asset. Although it may be hard to detect, the best thing to do is to review the constraints you have set with display of the object. If you get portfolios with 100% invested in each asset, you can review the display of your object and quickly see that no budget constraint is set. Also, you can use estimateBounds and checkFeasibility to determine if the bounds for your portfolio set make sense and to determine if the portfolios you obtained are feasible relative to an independent formulation of your portfolio set.

Efficient Frontiers Do Not Make Sense

If you obtain efficient frontiers that do not seem to make sense, this can happen for some cases of mean and covariance of asset returns. It is possible for some mean-variance portfolio optimization problems to have difficulties at the endpoints of the efficient frontier. It is rare for standard portfolio problems, but this can occur. For example, this can occur when using unusual combinations of turnover constraints and transaction costs. Usually, the workaround of setting the hidden property enforcePareto produces a single portfolio for the entire efficient frontier, where any other solutions are not Pareto optimal (which is what efficient portfolios must be).

An example of a portfolio optimization problem that has difficulties at the endpoints of the efficient frontier is this standard mean-variance portfolio problem (long-only with a budget constraint) with the following mean and covariance of asset returns:

m = [ 1; 2; 3 ];
C = [ 1 1 0; 1 1 0; 0 0 1 ]; 

p = Portfolio;
p = Portfolio(p, 'assetmean', m, 'assetcovar', C);
p = Portfolio(p, 'lowerbudget', 1, 'upperbudget', 1);
p = Portfolio(p, 'lowerbound', 0);

plotFrontier(p)

To work around this problem, set the hidden Portfolio object property for enforcePareto. This property instructs the optimizer to perform extra steps to ensure a Pareto-optimal solution. This slows down the solver, but guarantees a Pareto-optimal solution.

p.enforcePareto = true;
plotFrontier(p)

Troubleshooting estimateCustomObjectivePortfolio

When using estimateCustomObjectivePortfolio, nonconvex functions are not supported for problems with cardinality constraints or conditional bounds. Specifically, the following error displays when using estimateCustomObjectivePortfolio with a Portfolio object that includes 'Conditional' BoundType (semicontinuous) constraints using setBounds or MinNumAssets and MaxNumAssets (cardinality) constraints using setMinMaxNumAssets.

Error using solveMICustomObjProb
Objective function must be convex in problems with cardinality constraints and/or conditional bounds.

Error in Portfolio/estimateCustomObjectivePortfolio (line 88)
    [pwgt,exitflag] = solveMICustomObjProb(obj,prob,fun,flags);

Note

This error applies only to quadratic functions. This error is not detected in nonlinear functions. Therefore, if you are using a nonlinear function, you must validate your input.

For more information, see Role of Convexity in Portfolio Problems.

Troubleshooting for Setting 'Conditional' BoundType, MinNumAssets, and MaxNumAssets Constraints

When configuring a Portfolio, PortfolioCVaR, or PortfolioMAD object to include 'Conditional' BoundType (semicontinuous) constraints using setBounds or MinNumAssets and MaxNumAssets (cardinality) constraints using setMinMaxNumAssets, the values of the inputs that you supply can result in warning messages.

Conditional Bounds with LowerBound Defined as Empty or Zero

When using setBounds with the BoundType set to 'Conditional' and the LowerBound input argument is empty ([ ]) or 0, the Conditional bound is not effective and is equivalent to a Simple bound.

AssetMean = [ 0.0101110; 0.0043532; 0.0137058 ];
AssetCovar = [ 0.00324625 0.00022983 0.00420395;
    0.00022983 0.00049937 0.00019247;
    0.00420395 0.00019247 0.00764097 ];
p = Portfolio('AssetMean', AssetMean, 'AssetCovar', AssetCovar, 'Budget', 1);
p = setBounds(p, 0, 0.5, 'BoundType', 'Conditional');  
p = setMinMaxNumAssets(p, 3, 3);
estimateFrontier(p, 10)
Warning: Conditional bounds with 'LowerBound' as zero are equivalent to simple bounds.
Consider either using strictly positive 'LowerBound' or 'simple' as the 'BoundType'
instead. 
> In internal.finance.PortfolioMixedInteger/checkBoundType (line 46)
  In Portfolio/checkarguments (line 204)
  In Portfolio/setBounds (line 80) 
Warning: The solution may have less than 'MinNumAssets' assets with nonzero weight. To
enforce 'MinNumAssets' requirement, set strictly positive lower conditional bounds. 
> In internal.finance.PortfolioMixedInteger/hasIntegerConstraints (line 44)
  In Portfolio/estimateFrontier (line 51) 

ans =

  Columns 1 through 8

    0.5000    0.3555    0.3011    0.3299    0.3585    0.3873    0.4160    0.4448
    0.5000    0.5000    0.4653    0.3987    0.3322    0.2655    0.1989    0.1323
    0.0000    0.1445    0.2335    0.2714    0.3093    0.3472    0.3850    0.4229

  Columns 9 through 10

    0.4735    0.5000
    0.0657         0
    0.4608    0.5000

In all the 10 optimal allocations, there are allocations (the first and last ones) that only have two assets, which is in conflict with the MinNumAssets constraint that three assets should be allocated. Also there are two warnings, which actually explain what happens. In this case, the 'Conditional' bound constraints are defined as xi = 0 or 0 <= xi <= 0.5, which are internally modeled as 0*vi<=xi<=0.5*vi, where vi is 0 or 1, where 0 indicates not allocated, and 1 indicates allocated. Here, vi=1, which still allows the asset to have a weight of 0. In other words, setting LowerBound as 0 or empty, doesn’t clearly define the minimum allocation for an allocated asset. Therefore, a 0 weighted asset is also considered as an allocated asset. To fix this warning, follow the instructions in the warning message, and set a LowerBound value that is strictly positive.

AssetMean = [ 0.0101110; 0.0043532; 0.0137058 ];
AssetCovar = [ 0.00324625 0.00022983 0.00420395;
    0.00022983 0.00049937 0.00019247;
    0.00420395 0.00019247 0.00764097 ];
p = Portfolio('AssetMean', AssetMean, 'AssetCovar', AssetCovar, 'Budget', 1);
p = setBounds(p, 0.3, 0.5, 'BoundType', 'Conditional');  
p = setMinMaxNumAssets(p, 3, 3);
estimateFrontier(p, 10)
ans =

  Columns 1 through 8

    0.3000    0.3180    0.3353    0.3489    0.3580    0.3638    0.3694    0.3576
    0.4000    0.3820    0.3642    0.3479    0.3333    0.3199    0.3067    0.3001
    0.3000    0.3000    0.3005    0.3032    0.3088    0.3163    0.3240    0.3423

  Columns 9 through 10

    0.3289    0.3000
    0.3000    0.3000
    0.3711    0.4000

Length of 'BoundType' Must Be Conformable with NumAssets

The setBounds optional name-value argument for 'BoundType' must be defined for all assets in a Portfolio, PortfolioCVaR, or PortfolioMAD object. By default, the 'BoundType' is 'Simple' and applies to all assets. Using setBounds, you can choose to define a 'BoundType' for each asset. In this case, the number of 'BoundType' specifications must match the number of assets (NumAssets) in the Portfolio, PortfolioCVaR, or PortfolioMAD object. The following example demonstrates the error when the number of 'BoundType' specifications do not match the number of assets in the Portfolio object.

AssetMean = [ 0.0101110; 0.0043532; 0.0137058 ];
AssetCovar = [ 0.00324625 0.00022983 0.00420395;
    0.00022983 0.00049937 0.00019247;
    0.00420395 0.00019247 0.00764097 ];
p = Portfolio('AssetMean', AssetMean, 'AssetCovar', AssetCovar, 'Budget', 1);
p = setBounds(p, 0.1, 0.5, 'BoundType',["simple"; "conditional"])
Cannot create bound constraints.

Caused by:
    Error using internal.finance.PortfolioMixedInteger/checkBoundType (line 28)
    Length of 'BoundType' must be conformable with 'NumAssets'=3.

To correct this, modify the BoundType to include three specifications because the Portfolio object has three assets.

AssetMean = [ 0.0101110; 0.0043532; 0.0137058 ];
AssetCovar = [ 0.00324625 0.00022983 0.00420395;
    0.00022983 0.00049937 0.00019247;
    0.00420395 0.00019247 0.00764097 ];

p = Portfolio('AssetMean', AssetMean, 'AssetCovar', AssetCovar, 'Budget', 1);
p = setBounds(p, 0.1, 0.5, 'BoundType',["simple"; "conditional";"conditional"])
p.BoundType
p = 

  Portfolio with properties:

          BuyCost: []
         SellCost: []
     RiskFreeRate: []
        AssetMean: [3×1 double]
       AssetCovar: [3×3 double]
    TrackingError: []
     TrackingPort: []
         Turnover: []
      BuyTurnover: []
     SellTurnover: []
             Name: []
        NumAssets: 3
        AssetList: []
         InitPort: []
      AInequality: []
      bInequality: []
        AEquality: []
        bEquality: []
       LowerBound: [3×1 double]
       UpperBound: [3×1 double]
      LowerBudget: 1
      UpperBudget: 1
      GroupMatrix: []
       LowerGroup: []
       UpperGroup: []
           GroupA: []
           GroupB: []
       LowerRatio: []
       UpperRatio: []
        BoundType: [3×1 categorical]
     MinNumAssets: []
     MaxNumAssets: []

ans = 

  3×1 categorical array

     simple 
     conditional 
     conditional 

Redundant Constraints from 'BoundType', 'MinNumAssets', 'MaxNumAssets' Constraints

When none of the constraints from 'BoundType', 'MinNumAssets', or 'MaxNumAssets' are active, the redundant constraints from 'BoundType', 'MinNumAssets', 'MaxNumAssets' warning occurs. This happens when you explicitly use setBounds and setMinMaxNumAssets but with values that are inactive. That is, the 'Conditional' BoundType has a LowerBound = [ ] or 0, 'MinNumAssets' is 0, or 'MaxNumAssets' is the same value as NumAssets. In other words, if any of these three are active, the warning will not show up when using the estimate functions or plotFrontier. The following two examples show the rationale.

The first example is when the BoundType is explicitly set as 'Conditional' but the LowerBound is 0, and no 'MinNumAssets' and 'MaxNumAssets' constraints are defined using setMinMaxNumAssets.

AssetMean = [ 0.0101110; 0.0043532; 0.0137058 ];
AssetCovar = [ 0.00324625 0.00022983 0.00420395;
    0.00022983 0.00049937 0.00019247;
    0.00420395 0.00019247 0.00764097 ];
p = Portfolio('AssetMean', AssetMean, 'AssetCovar', AssetCovar, 'Budget', 1);
p = setBounds(p, 0, 0.5, 'BoundType', 'Conditional');   
estimateFrontier(p, 10)
Warning: Redundant constraints from 'BoundType', 'MinNumAssets', 'MaxNumAssets'. 
> In internal.finance.PortfolioMixedInteger/hasIntegerConstraints (line 24)
  In Portfolio/estimateFrontier (line 51) 

ans =

  Columns 1 through 8

    0.5000    0.3555    0.3011    0.3299    0.3586    0.3873    0.4160    0.4448
    0.5000    0.5000    0.4653    0.3987    0.3321    0.2655    0.1989    0.1323
         0    0.1445    0.2335    0.2714    0.3093    0.3471    0.3850    0.4229

  Columns 9 through 10

    0.4735    0.5000
    0.0657         0
    0.4608    0.5000

The second example is when you explicitly set the three constraints, but all with inactive values. In this example, the BoundType is 'Conditional' and the LowerBound is 0, thus specifying ineffective 'Conditional' BoundType constraints, and the 'MinNumAssets' and 'MaxNumAssets' values are 0 and 3, respectively. The setMinMaxNumAssets function specifies ineffective 'MinNumAssets' and 'MaxNumAssets' constraints.

AssetMean = [ 0.0101110; 0.0043532; 0.0137058 ];
AssetCovar = [ 0.00324625 0.00022983 0.00420395;
    0.00022983 0.00049937 0.00019247;
    0.00420395 0.00019247 0.00764097 ];
p = Portfolio('AssetMean', AssetMean, 'AssetCovar', AssetCovar, 'Budget', 1);
p = setBounds(p, 0, 0.5, 'BoundType', 'Conditional');   
p = setMinMaxNumAssets(p, 0, 3);   
estimateFrontier(p, 10)
Warning: Redundant constraints from 'BoundType', 'MinNumAssets', 'MaxNumAssets'. 
> In internal.finance.PortfolioMixedInteger/hasIntegerConstraints (line 24)
  In Portfolio/estimateFrontier (line 51) 

ans =

  Columns 1 through 8

    0.5000    0.3555    0.3011    0.3299    0.3586    0.3873    0.4160    0.4448
    0.5000    0.5000    0.4653    0.3987    0.3321    0.2655    0.1989    0.1323
         0    0.1445    0.2335    0.2714    0.3093    0.3471    0.3850    0.4229

  Columns 9 through 10

    0.4735    0.5000
    0.0657         0
    0.4608    0.5000

Infeasible Portfolio Problem with 'BoundType', 'MinNumAssets', 'MaxNumAssets'

The Portfolio, PortfolioCVaR, or PortfolioMAD object performs validations of all the constraints that you set before solving any specific optimization problems. The Portfolio, PortfolioCVaR, or PortfolioMAD object first considers all constraints other than 'Conditional' BoundType, 'MinNumAssets', and 'MaxNumAssets' and issues an error message if they are not compatible. Then the Portfolio, PortfolioCVaR, or PortfolioMAD object adds the three constraints to check if they are compatible with the already checked constraints. This separation is natural because 'Conditional' BoundType, 'MinNumAssets', and 'MaxNumAssets' require additional binary variables in the mathematical formulation that leads to a MINLP, while other constraints only need continuous variables. You can follow the error messages to check when the infeasible problem occurs and take actions to fix the constraints.

One possible scenario is when the BoundType is 'Conditional' and Groups are defined for the Portfolio object. In this case, the Group definitions are themselves in conflict. Consequently, the 'Conditional' bound constraint cannot be applied when running estimateFrontierLimits.

AssetMean = [ 0.0101110; 0.0043532; 0.0137058 ];
AssetCovar = [ 0.00324625 0.00022983 0.00420395;
    0.00022983 0.00049937 0.00019247;
    0.00420395 0.00019247 0.00764097 ];

p = Portfolio('AssetMean', AssetMean, 'AssetCovar', AssetCovar, 'Budget', 1);
p = setBounds(p, 0.1, 0.5, 'BoundType','Conditional');
p = setGroups(p, [1,1,0], 0.3, 0.5);
p = addGroups(p, [0,1,0], 0.6, 0.7);
pwgt = estimateFrontierLimits(p)
Error using Portfolio/buildMixedIntegerProblem (line 31)
Infeasible portfolio problem prior to considering 'BoundType', 'MinNumAssets',
'MaxNumAssets'. Verify if constraints from groups, bounds, group ratios, inequality,
equality, etc. are compatible.

Error in Portfolio/estimateFrontierLimits>int_frontierLimits (line 93)
ProbStruct = buildMixedIntegerProblem(obj);

Error in Portfolio/estimateFrontierLimits (line 73)
    pwgt = int_frontierLimits(obj, minsolution, maxsolution);

To correct this error, change the LowerGroup in the addGroups function to also be 0.3 to match the GroupMatrix input from setGroups.

AssetMean = [ 0.0101110; 0.0043532; 0.0137058 ];
AssetCovar = [ 0.00324625 0.00022983 0.00420395;
    0.00022983 0.00049937 0.00019247;
    0.00420395 0.00019247 0.00764097 ];

p = Portfolio('AssetMean', AssetMean, 'AssetCovar', AssetCovar, 'Budget', 1);
p = setBounds(p, 0.1, 0.5, 'BoundType','Conditional');
p = setGroups(p, [1,1,0], 0.3, 0.5);
p = addGroups(p, [0,1,0], 0.3, 0.7);
pwgt = estimateFrontierLimits(p)
pwgt =

         0    0.2000
    0.5000    0.3000
    0.5000    0.5000

A second possible scenario is when the BoundType is 'Conditional' and the setEquality function is used with the bEquality parameter set to 0.04. This sets an equality constraint to have x1 + x3 = 0.04. At the same time, setBounds also set the semicontinuous constraints to have xi = 0 or 0.1 <= xi <= 2.5, which lead to x1 + x3 = 0 or 0.1 <= x1 + x3 <= 5. The semicontinuous constraints are not compatible with the equality constraint because there is no way to get x1 + x3 to equal 0.04. Therefore, the error message is displayed.

AssetMean = [ 0.05; 0.1; 0.12; 0.18 ];
AssetCovar = [ 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('AssetMean', AssetMean, 'AssetCovar', AssetCovar, 'Budget', 1);
A = [ 1 0 1 0 ];
b = 0.04;
p = setEquality(p, A, b);
p = setBounds(p, 0.1, 2.5, 'BoundType','Conditional');
p = setMinMaxNumAssets(p, 2, 2);  
pwgt = estimateFrontierLimits(p)
Error using Portfolio/buildMixedIntegerProblem (line 109)
Infeasible portfolio problem when considering 'BoundType', 'MinNumAssets',
'MaxNumAssets'. Verify if these are compatible with constraints from groups, bounds,
group ratios, inequality, equality, etc.

Error in Portfolio/estimateFrontierLimits>int_frontierLimits (line 93)
ProbStruct = buildMixedIntegerProblem(obj);

Error in Portfolio/estimateFrontierLimits (line 73)
    pwgt = int_frontierLimits(obj, minsolution, maxsolution);
 

To correct this error, change the bEquality parameter from 0.04 to .4.

AssetMean = [ 0.05; 0.1; 0.12; 0.18 ];
AssetCovar = [ 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('AssetMean', AssetMean, 'AssetCovar', AssetCovar, 'Budget', 1);
A = [ 1 0 1 0 ];
b = 0.4;
p = setEquality(p, A, b);
p = setBounds(p, 0.1, 2.5, 'BoundType','Conditional');
p = setMinMaxNumAssets(p, 2, 2);  
pwgt = estimateFrontierLimits(p)
pwgt =

    0.4000         0
    0.6000         0
         0    0.4000
         0    0.6000

Unbounded Portfolio Problem

This error occurs when you are using a Portfolio, PortfolioCVaR, or PortfolioMAD object and there is no UpperBound defined in setBounds and you are using setMinMaxNumAssets. In this case, this is formulated as a mixed integer programming problem and an UpperBound is required to enforce MinNumAssets and MaxNumAssets constraints.

The optimizer first attempts to estimate the upper bound of each asset, based on all the specified constraints. If the UpperBound cannot be found, an error message occurs which instructs you to set an explicit UpperBound. In most cases, as long as you set some upper bounds to the problem using any set function, the optimizer can successfully find a good estimation.

AssetMean = [ 0.05; 0.1; 0.12; 0.18 ];
AssetCovar = [ 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('AssetMean', AssetMean, 'AssetCovar', AssetCovar);
p = setBounds(p, 0.1, 'BoundType','Conditional');
p = setGroups(p, [1,1,1,0], 0.3, 0.5);
p = setMinMaxNumAssets(p, 3, 3);
pwgt = estimateFrontierLimits(p)
Error using Portfolio/buildMixedIntegerProblem (line 42)
Unbounded portfolio problem. Upper bounds cannot be inferred from the existing
constraints. Set finite upper bounds using 'setBounds'.

Error in Portfolio/estimateFrontierLimits>int_frontierLimits (line 93)
ProbStruct = buildMixedIntegerProblem(obj);

Error in Portfolio/estimateFrontierLimits (line 73)
    pwgt = int_frontierLimits(obj, minsolution, maxsolution);

To correct this error, specify an UpperBound value for setBounds.

AssetMean = [ 0.05; 0.1; 0.12; 0.18 ];
AssetCovar = [ 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('AssetMean', AssetMean, 'AssetCovar', AssetCovar);
p = setBounds(p, 0.1, .9, 'BoundType','Conditional');
p = setGroups(p, [1,1,1,0], 0.3, 0.5);
p = setMinMaxNumAssets(p, 3, 3);
pwgt = estimateFrontierLimits(p)
pwgt =

    0.1000         0
    0.1000    0.1000
    0.1000    0.4000
         0    0.9000

Total Number of Portfolio Weights with a Value > 0 Are Greater Than MaxNumAssets Specified

When using a Portfolio, PortfolioCVaR, or PortfolioMAD object, the optimal allocation w may contain some very small values that leads to sum(w>0) larger than MaxNumAssets, even though the MaxNumAssets constraint is specified using setMinMaxNumAssets. For example, in the following code when setMinMaxNumAssets is used to set MaxNumAssets to 15, the sum(w>0) indicates that there are 19 assets. A close examination of the weights shows that the weights are extremely small and are actually 0.

T = readtable('dowPortfolio.xlsx');
symbol = T.Properties.VariableNames(3:end);
assetReturn = tick2ret(T{:,3:end});
p = Portfolio('AssetList', symbol, 'budget', 1);
p = setMinMaxNumAssets(p, 10, 15);
p = estimateAssetMoments(p,assetReturn);
p = setBounds(p,0.01,0.5,'BoundType','Conditional','NumAssets',30);
p = setTrackingError(p,0.05,ones(1, p.NumAssets)/p.NumAssets);
w = estimateFrontierLimits(p,'min'); % minimum risk portfolio

sum(w>0)   % Number of assets that are allocated in the optimal portfolio
w(w<eps)   % Check the weights of the very small weighted assets
ans =

    19


ans =

   1.0e-20 *

   -0.0000
         0
         0
    0.0293
         0
    0.3626
    0.2494
         0
    0.0926
   -0.0000
         0
    0.0020
         0
         0
         0
         0

This situation only happens when the OuterApproximation algorithm is used with setSolverMINLP to solve a MINLP portfolio optimization problem. The OuterApproximation internally fixes the latest solved integer variables and runs an NLP with quadprog or fmincon, which introduces numerical issues and leads to weights that are very close to 0.

If you do not want to deal with very small values, you can use setSolverMINLP to select a different algorithm. In this example, the 'TrustRegionCP' algorithm is specified.

T = readtable('dowPortfolio.xlsx');
symbol = T.Properties.VariableNames(3:end);
assetReturn = tick2ret(T{:,3:end});
p = Portfolio('AssetList', symbol, 'budget', 1);
p = setMinMaxNumAssets(p, 10, 15);
p = estimateAssetMoments(p,assetReturn);
p = setBounds(p,0.01,0.5,'BoundType','Conditional','NumAssets',30);
p = setTrackingError(p,0.05,ones(1, p.NumAssets)/p.NumAssets);
p = setSolverMINLP(p,'TrustRegionCP');
w = estimateFrontierLimits(p,'min'); % minimum risk portfolio 

sum(w>0)   % Number of assets that are allocated in the optimal portfolio
w(w<eps)   % The weights of the very small weighted assets are strictly zeros
ans =

    14


ans =

     0
     0
     0
     0
     0
     0
     0
     0
     0
     0
     0
     0
     0
     0
     0
     0

See Also

| | | |

Related Examples

More About

External Websites