Main Content

estimateCustomObjectivePortfolio

Estimate optimal portfolio for user-defined objective function for Portfolio object

Description

example

[pwgt,pbuy,psell,exitflag] = estimateCustomObjectivePortfolio(obj,fun) estimates optimal portfolio with a user-defined objective function for a Portfolio object. For details on using estimateCustomObjectivePortfolio, see Solver Guidelines for Custom Objective Problems Using Portfolio Objects.

example

[pwgt,pbuy,psell,exitflag] = estimateCustomObjectivePortfolio(___,Name=Value) adds optional name-value arguments.

Examples

collapse all

This example shows how to use estimateCustomObjectivePortfolio to solve a portfolio problem with a custom objective. You define the constraints for portfolio problems using functions for the Portfolio object and then you specify the objective function as an input to estimateCustomObjectivePortfolio. The objective function must be continuous (and preferably smooth).

Create Portfolio Object

Find the portfolio that solves the problem:

minx  xTxs.t.ixi=1         x0

Create a Portfolio object and set the default constraints using setDefaultConstraints. In this case, the portfolio problem does not involve the mean or covariance of the assets returns. Therefore, you do not need to define the assets moments to create the Portfolio object. You need only to define the number of assets in the problem.

% Create a Portfolio object
p = Portfolio(NumAssets=6);
% Define the constraints of the portfolio methods
p = setDefaultConstraints(p); % Long-only, fully invested weights

Define Objective Function

Define a function handle for the objective function xTx.

% Define the objective function
objFun = @(x) x'*x;

Solve Portfolio Problem

Use estimateCustomObjectivePortfolio to compute the solution to the problem.

% Solve portfolio problem
wMin = estimateCustomObjectivePortfolio(p,objFun)
wMin = 6×1

    0.1667
    0.1667
    0.1667
    0.1667
    0.1667
    0.1667

The estimateCustomObjectivePortfolio function automatically assumes that the objective sense is to minimize. You can change that default behavior by using the estimateCustomObjectivePortfolio name-value argument ObjectiveSense='maximize'.

This example shows how to use estimateCustomObjectivePortfolio to solve a portfolio problem with a custom objective and a return constraint. You define the constraints for portfolio problems, other than the return constraint, using functions for the Portfolio object and then you specify the objective function as an input to estimateCustomObjectivePortfolio. The objective function must be continuous (and preferably smooth). To specify a return constraint, you use the TargetReturn name-value argument.

Create Portfolio Object

Find the portfolio that solves the problem:

minx  xTxs.t.ixi=1         x0

Create a Portfolio object and set the default constraints using setDefaultConstraints.

% Create a Portfolio object
load('SixStocks.mat')
p = Portfolio(AssetMean=AssetMean,AssetCovar=AssetCovar);
% Define the constraints of the portfolio methods
p = setDefaultConstraints(p); % Long-only, fully invested weights

Define Objective Function

Define a function handle for the objective function xTx.

% Define the objective function
objFun = @(x) x'*x;

Add Return Constraints

When using the Portfolio object, you can use estimateFrontierByReturn to add a return constraint to the portfolio. However, when using the estimateCustomObjectivePortfolio function with a Portfolio object, you must add return constraints by using the TargetReturn name-value argument with a return target value.

The Portfolio object supports two types of return constraints: gross return and net return. The type of return constraint that is added to the portfolio problem is implicitly defined by whether you provide buy or sell costs to the Portfolio object using setCosts. If no buy or sell costs are present, the added return constraint is a gross return constraint. Otherwise, a net return constraint is added.

Gross Return Constraint

The gross portfolio return constraint for a portfolio is

r0+(μ-r0)Txμ0,

where r0 is the risk-free rate (with 0 as default), μ is the mean of assets returns, and μ0 is the target return.

Since buy or sell costs are not needed to add a gross return constraint, the Portfolio object does not need to be modified before using estimateCustomObjectivePortfolio.

% Set a return target
ret0 = 0.03;
% Solve portfolio problem with a gross return constraint
wGross = estimateCustomObjectivePortfolio(p,objFun, ...
    TargetReturn=ret0)
wGross = 6×1

    0.1377
    0.1106
    0.1691
    0.1829
    0.1179
    0.2818

The return constraint is not added to the Portfolio object. In other words, the Portfolio properties are not modified by adding a gross return constraint in estimateCustomObjectivePortfolio.

Net Return Constraint

The net portfolio return constraint for a portfolio is

r0+(μ-r0)Tx-cBTmax{0,x-x0}-cSTmax{0,x0-x}μ0,

where r0 is the risk-free rate (with 0 as default), μ is the mean of assets returns, cB is the proportional buy cost, cS is the proportional sell cost, x0 is the initial portfolio, and μ0 is the target return.

To add net return constraints to the portfolio problem, you must use setCosts with the Portfolio object. If the Portfolio object has either of these costs, estimateCustomObjectivePortfolio automatically assumes that any added return constraint is a net return constraint.

% Add buy and sell costs to the Portfolio object
buyCost = 0.002;
sellCost = 0.001;
initPort = zeros(p.NumAssets,1);
p = setCosts(p,buyCost,sellCost,initPort);
% Solve portfolio problem with a net return constraint
% wNet = estimateCustomObjectivePortfolio(p,objFun, ...
%    TargetReturn=ret0)

As with the gross return constraint, the net return constraint is not added to the Portfolio object properties, however the Portfolio object is modified by the addition of buy or sell costs. Adding buy or sell costs to the Portfolio object does not affect any constraints besides the return constraint, but these costs do affect the solution of maximum return problems because the solution is the maximum net return instead of the maximum gross return.

This example shows how to use estimateCustomObjectivePortfolio to solve a portfolio problem with a custom objective and cardinality constraints. You define the constraints for portfolio problems using functions for the Portfolio object and then you specify the objective function as an input to estimateCustomObjectivePortfolio. For problems with cardinality constraints or continuous bounds, the objective function must be continuous and convex.

Create Portfolio Object

Find a long-only, fully weighted portfolio with half the assets that minimizes the tracking error to the equally weighted portfolio. Furthermore, if an asset is present in the portfolio, at least 10% should be invested in that asset. The porfolio problem is as follows:

minx  (x-x0)TΣ(x-x0)s.t.ixi=1,         i#(xi0)=3,         xi0.1orxi=0

Create a Portfolio object and set the assets moments.

load('SixStocks.mat')
p = Portfolio(AssetMean=AssetMean,AssetCovar=AssetCovar);
nAssets = size(AssetMean,1);

Define the Portfolio constraints.

% Fully invested portfolio
p = setBudget(p,1,1);
% Cardinality constraint
p = setMinMaxNumAssets(p,3,3);
% Conditional bounds
p = setBounds(p,0.1,[],BoundType="conditional");

Define Objective Function

Define a function handle for the objective function.

% Define the objective function
EWP = 1/nAssets*ones(nAssets,1);
trackingError = @(x) (x-EWP)'*p.AssetCovar*(x-EWP);

Solve Portfolio Problem

Use estimateCustomObjectivePortfolio to compute the solution to the problem.

% Solve portfolio problem
wMinTE = estimateCustomObjectivePortfolio(p,trackingError)
wMinTE = 6×1

    0.1795
    0.3507
         0
    0.4698
         0
         0

Input Arguments

collapse all

Object for portfolio, specified using a Portfolio object. When using a Portfolio object in the custom objective workflow, you do not need to use the mean-variance framework to estimate the mean and covariance. However, the custom objective workflow does require that you specify portfolio constraints. The Portfolio object that you use with the estimateCustomObjectivePortfolio function supports only the following constraints:

Note

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

Data Types: object

Function handle that defines the objective function, specified using a function handle in terms of the portfolio weights.

Note

The objective function must be continuous and defined using only the portfolio weights as variables. If the portfolio problem has cardinality constraints and/or conditional bounds using setMinMaxNumAssets or setBounds, the objective function must also be convex. For more information, see Role of Convexity in Portfolio Problems.

Data Types: function_handle

Name-Value Arguments

Specify optional pairs of arguments as Name1=Value1,...,NameN=ValueN, where Name is the argument name and Value is the corresponding value. Name-value arguments must appear after other arguments, but the order of the pairs does not matter.

Example: pwgt = estimateCustomObjectivePortfolio(p,fun,ObjectiveSense="maximize",TargetReturn=0.05)

Sense of the optimization, specified as ObjectiveSense and a string or character vector with one of the following values:

  • "minimize" — The solution minimizes the objective function.

  • "maximize" — The solution maximizes the objective function.

Data Types: string | char

Target value for the portfolio return, specified as TargetReturn and a positive or negative scalar.

Note

In the Portfolio object, use estimateFrontierByReturn to add a return constraint to the portfolio. When you use estimateCustomObjectivePortfolio, return constraints are added by passing the name-value argument TargetReturn with the return target.

Data Types: double

Output Arguments

collapse all

Optimal weight allocation of the portfolio problem, returned as a NumAssets-by-1 vector.

Purchases relative to initial portfolio to achieve the optimal weight allocation of the portfolio problem, returned as a NumAssets-by-1 vector.

Sales relative to initial portfolio to achieve the optimal weight allocation of the portfolio problem, returned as a NumAssets vector.

Reason the solver stopped, returned as an enumeration variable or integer. There are two types of exitflag output. If the problem is continuous, the exitflag output is an enumeration variable. If the problem is mixed-integer, then the exitflag output is an integer.

References

[1] Cornuejols, G. and Reha Tütüncü. Optimization Methods in Finance. Cambridge University Press, 2007.

Version History

Introduced in R2022b