Asset Returns and Moments of Asset Returns

Since mean-variance portfolio optimization problems require estimates for the mean and covariance of asset returns, the Portfolio object has several ways to set and get the properties AssetMean (for the mean) and AssetCovar (for the covariance). In addition, the return for a riskless asset is kept in the property RiskFreeRate so that all assets in AssetMean and AssetCovar are risky assets. For information on the workflow when using Portfolio objects, see Portfolio Object Workflow.

Assignment Using the Portfolio Constructor

Suppose you have a mean and covariance of asset returns in variables m and C. The properties for the moments of asset returns are set using the constructor:

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;
p = Portfolio('AssetMean', m, 'AssetCovar', C);
disp(p.NumAssets);
disp(p.AssetMean);
disp(p.AssetCovar);
4
    0.0042
    0.0083
    0.0100
    0.0150

    0.0005    0.0003    0.0002         0
    0.0003    0.0024    0.0017    0.0010
    0.0002    0.0017    0.0048    0.0028
         0    0.0010    0.0028    0.0102

Notice that the Portfolio object determines the number of assets in NumAssets from the moments. The portfolio constructor enables separate initialization of the moments, for example:

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;
 
p = Portfolio;
p = Portfolio(p, 'AssetMean', m);
p = Portfolio(p, 'AssetCovar', C);
[assetmean, assetcovar] = p.getAssetMoments
assetmean =

    0.0042
    0.0083
    0.0100
    0.0150


assetcovar =

    0.0005    0.0003    0.0002         0
    0.0003    0.0024    0.0017    0.0010
    0.0002    0.0017    0.0048    0.0028
         0    0.0010    0.0028    0.0102

The getAssetMoments method lets you get the values for AssetMean and AssetCovar properties at the same time.

Assignment Using the setAssetMoments Method

You can also set asset moment properties using the setAssetMoments method. For example, given the mean and covariance of asset returns in the variables m and C, the asset moment properties can be set:

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;
 
p = Portfolio;
p = setAssetMoments(p, m, C);
[assetmean, assetcovar] = getAssetMoments(p)
assetmean =

    0.0042
    0.0083
    0.0100
    0.0150

assetcovar =

    0.0005    0.0003    0.0002         0
    0.0003    0.0024    0.0017    0.0010
    0.0002    0.0017    0.0048    0.0028
         0    0.0010    0.0028    0.0102

Scalar Expansion of Arguments

Both the constructor Portfolio and the setAssetMoments method perform scalar expansion on arguments for the moments of asset returns. When using the constructor, the number of assets must be already specified in the variable NumAssets. If NumAssets has not already been set, a scalar argument is interpreted as a scalar with NumAssets set to 1. setAssetMoments provides an additional optional argument to specify the number of assets so that scalar expansion works with the correct number of assets. In addition, if either a scalar or vector is input for the covariance of asset returns, a diagonal matrix is formed such that a scalar expands along the diagonal and a vector becomes the diagonal. This example demonstrates scalar expansion for four jointly independent assets with a common mean 0.1 and common variance 0.03:

p = Portfolio;
p = setAssetMoments(p, 0.1, 0.03, 4);
[assetmean, assetcovar] = getAssetMoments(p)
assetmean =

    0.1000
    0.1000
    0.1000
    0.1000

assetcovar =

    0.0300         0         0         0
         0    0.0300         0         0
         0         0    0.0300         0
         0         0         0    0.0300

If at least one argument is properly dimensioned, you don't need to include the additional NumAssets argument. This example illustrates a constant-diagonal covariance matrix and a mean of asset returns for four assets:

p = Portfolio;
p = setAssetMoments(p, [ 0.05; 0.06; 0.04; 0.03 ], 0.03);
[assetmean, assetcovar] = getAssetMoments(p)
assetmean =

    0.0500
    0.0600
    0.0400
    0.0300

assetcovar =

    0.0300         0         0         0
         0    0.0300         0         0
         0         0    0.0300         0
         0         0         0    0.0300

In addition, scalar expansion works with the portfolio constructor if NumAssets is known, or is deduced from the inputs.

Estimating Asset Moments from Prices or Returns

Another way to set the moments of asset returns is to use the method estimateAssetMoments which accepts either prices or returns and estimates the mean and covariance of asset returns. Either prices or returns are stored as matrices with samples going down the rows and assets going across the columns. In addition, prices or returns can be stored in a financial time series (fints) object (see Estimating Asset Moments from Time Series Data). To illustrate using estimateAssetMoments, generate random samples of 120 observations of asset returns for four assets from the mean and covariance of asset returns in the variables m and C with portsim. The default behavior of portsim creates simulated data with estimated mean and covariance identical to the input moments m and C. In addition to a return series created by portsim in the variable X, a price series is created in the variable Y:

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;
X = portsim(m', C, 120);
Y = ret2tick(X);

    Note:   Portfolio optimization requires that you use total returns and not just price returns. Consequently, "returns" should be total returns and "prices" should be total return prices.

Given asset returns and prices in variables X and Y from above, this sequence of examples demonstrates equivalent ways to estimate asset moments for the Portfolio object. A Portfolio object is created in p with the moments of asset returns set directly in the constructor, and a second Portfolio object is created in q to obtain the mean and covariance of asset returns from asset return data in X using estimateAssetMoments:

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;
 
X = portsim(m', C, 120);
p = Portfolio('mean', m, 'covar', C);
q = Portfolio;
q = estimateAssetMoments(q, X);
 
[passetmean, passetcovar] = getAssetMoments(p)
[qassetmean, qassetcovar] = getAssetMoments(q)
passetmean =

    0.0042
    0.0083
    0.0100
    0.0150

passetcovar =

    0.0005    0.0003    0.0002         0
    0.0003    0.0024    0.0017    0.0010
    0.0002    0.0017    0.0048    0.0028
         0    0.0010    0.0028    0.0102

qassetmean =

    0.0042
    0.0083
    0.0100
    0.0150

qassetcovar =

    0.0005    0.0003    0.0002    0.0000
    0.0003    0.0024    0.0017    0.0010
    0.0002    0.0017    0.0048    0.0028
    0.0000    0.0010    0.0028    0.0102

Notice how either approach has the same moments. The default behavior of estimateAssetMoments is to work with asset returns. If, instead, you have asset prices in the variable Y, estimateAssetMoments accepts an argument name 'DataFormat' with a corresponding value set to 'prices' to indicate that the input to the method is in the form of asset prices and not returns (the default value for the 'DataFormat' argument is 'returns'). This example compares direct assignment of moments in the Portfolio object p with estimated moments from asset price data in Y in the Portfolio object q:

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;
 
X = portsim(m', C, 120);
Y = ret2tick(X);

p = Portfolio('mean',m,'covar',C);
        
q = Portfolio;
q = estimateAssetMoments(q, Y, 'dataformat', 'prices');
 
[passetmean, passetcovar] = getAssetMoments(p)
[qassetmean, qassetcovar] = getAssetMoments(q)
passetmean =

    0.0042
    0.0083
    0.0100
    0.0150

passetcovar =

    0.0005    0.0003    0.0002         0
    0.0003    0.0024    0.0017    0.0010
    0.0002    0.0017    0.0048    0.0028
         0    0.0010    0.0028    0.0102

qassetmean =

    0.0042
    0.0083
    0.0100
    0.0150

qassetcovar =

    0.0005    0.0003    0.0002    0.0000
    0.0003    0.0024    0.0017    0.0010
    0.0002    0.0017    0.0048    0.0028
    0.0000    0.0010    0.0028    0.0102

Estimating Asset Moments with Missing Data

Often when working with multiple assets, you have missing data indicated by NaN values in your return or price data. Although Multivariate Normal Regression goes into detail about regression with missing data, the method estimateAssetMoments has an argument name 'MissingData' that indicates with a Boolean value whether to use the missing data capabilities of Financial Toolbox™ software. The default value for 'MissingData' is false which removes all samples with NaN values. If, however, 'MissingData' is set to true, estimateAssetMoments uses the ECM algorithm to estimate asset moments. This example illustrates how this works on price data with missing values:

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;
 
X = portsim(m', C, 120);
Y = ret2tick(X);
Y(1:20,1) = NaN;
Y(1:12,4) = NaN;

p = Portfolio('mean',m,'covar',C);
        
q = Portfolio;
q = estimateAssetMoments(q, Y, 'dataformat', 'prices');
 
r = Portfolio;
r = estimateAssetMoments(r, Y, 'dataformat', 'prices', 'missingdata', true);

[passetmean, passetcovar] = getAssetMoments(p)
[qassetmean, qassetcovar] = getAssetMoments(q)
[rassetmean, rassetcovar] = getAssetMoments(r)
passetmean =

    0.0042
    0.0083
    0.0100
    0.0150


passetcovar =

    0.0005    0.0003    0.0002         0
    0.0003    0.0024    0.0017    0.0010
    0.0002    0.0017    0.0048    0.0028
         0    0.0010    0.0028    0.0102


qassetmean =

    0.0045
    0.0082
    0.0101
    0.0091


qassetcovar =

    0.0006    0.0003    0.0001   -0.0000
    0.0003    0.0023    0.0017    0.0011
    0.0001    0.0017    0.0048    0.0029
   -0.0000    0.0011    0.0029    0.0112


rassetmean =

    0.0045
    0.0083
    0.0100
    0.0113


rassetcovar =

    0.0008    0.0005    0.0001   -0.0001
    0.0005    0.0032    0.0022    0.0015
    0.0001    0.0022    0.0063    0.0040
   -0.0001    0.0015    0.0040    0.0144

The Portfolio object p contains raw moments, the object q contains estimated moments in which NaN values are discarded, and the object r contains raw moments that accommodate missing values. Each time you run this example, you will get different estimates for the moments in q and r, and these will also differ from the moments in p.

Estimating Asset Moments from Time Series Data

The estimateAssetMoments method also accepts asset returns or prices stored in financial time series (fints) objects. estimateAssetMoments implicitly works with matrices of data or data in a fints object using the same rules for whether the data are returns or prices.

To illustrate, use fints to create a fints objects Xfts that contains asset returns generated with portsim (see Estimating Asset Moments from Prices or Returns) and add series labels:

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;
 
X = portsim(m', C, 120);

d = (datenum('31-jan-2001'):datenum('31-dec-2010'))';
Xfts = fints(d, zeros(numel(d),4), {'Bonds', 'LargeCap', 'SmallCap', 'Emerging'});
Xfts = tomonthly(Xfts);

Xfts.Bonds = X(:,1);
Xfts.LargeCap = X(:,2);
Xfts.SmallCap = X(:,3);
Xfts.Emerging = X(:,4);

p = Portfolio('mean',m,'covar',C);
        
q = Portfolio;
q = estimateAssetMoments(q, Xfts);
 
[passetmean, passetcovar] = getAssetMoments(p)
[qassetmean, qassetcovar] = getAssetMoments(q)
passetmean =

    0.0042
    0.0083
    0.0100
    0.0150

passetcovar =

    0.0005    0.0003    0.0002         0
    0.0003    0.0024    0.0017    0.0010
    0.0002    0.0017    0.0048    0.0028
         0    0.0010    0.0028    0.0102

qassetmean =

    0.0042
    0.0083
    0.0100
    0.0150

qassetcovar =

    0.0005    0.0003    0.0002    0.0000
    0.0003    0.0024    0.0017    0.0010
    0.0002    0.0017    0.0048    0.0028
    0.0000    0.0010    0.0028    0.0102

As you can see, the moments match. The argument name-value inputs 'DataFormat' to handle return or price data and 'MissingData' to ignore or use samples with missing values also work for fints data. In addition, estimateAssetMoments also extracts asset names or identifiers from a fints object with the argument name 'GetAssetList' set to true (its default value is false). If the 'GetAssetList' value is true, the identifiers are used to set the AssetList property of the object. Thus, repeating the formation of the Portfolio object q from the previous example with the 'GetAssetList' flag set to true extracts the series labels from the fints object:

q = estimateAssetMoments(q, Xfts, 'getassetlist', true);
disp(q.AssetList)
'Bonds'    'LargeCap'    'SmallCap'    'Emerging'

Note if you set the 'GetAssetList' flag set to true and your input data is in a matrix, estimateAssetMoments uses the default labeling scheme from setAssetList described in Setting Up a List of Asset Identifiers.

Working with a Riskless Asset

You can specify a riskless asset with the mean and covariance of asset returns in the AssetMean and AssetCovar properties such that the riskless asset has variance of 0 and is completely uncorrelated with all other assets. In this case, the Portfolio object uses a separate RiskFreeRate property that stores the rate of return of a riskless asset. Thus, you can separate your universe into a riskless asset and a collection of risky assets. For example, assume that your riskless asset has a return in the scalar variable r0, then the property for the RiskFreeRate is set using the constructor:

r0 = 0.01/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('RiskFreeRate', r0, 'AssetMean', m, 'AssetCovar', C);
disp(p.RiskFreeRate);
 8.3333e-004

    Note:   If your problem has a budget constraint such that your portfolio weights must sum to 1, then the riskless asset is irrelevant.

Working with Transaction Costs

The difference between net and gross portfolio returns is transaction costs. The net portfolio return proxy has distinct proportional costs to purchase and to sell assets which are maintained in the Portfolio object properties BuyCost and SellCost. Transaction costs are in units of total return and, as such, are proportional to the price of an asset so that they enter the model for net portfolio returns in return form. For example, suppose you have a stock currently priced $40 and your usual transaction costs are 5 cents per share. Then the transaction cost for the stock is 0.05/40 = 0.00125 (as defined in Net Portfolio Returns). Costs are entered as positive values and credits are entered as negative values.

Setting Transaction Costs Using the Constructor

To set up transaction costs, you must specify an initial or current portfolio in the InitPort property. If the initial portfolio is not set when you set up the transaction cost properties, InitPort is 0. The properties for transaction costs can be set using the constructor Portfolio. For example, assume that purchase and sale transaction costs are in the variables bc and sc and an initial portfolio is in the variable x0, then transaction costs are set:

bc = [ 0.00125; 0.00125; 0.00125; 0.00125; 0.00125 ];
sc = [ 0.00125; 0.007; 0.00125; 0.00125; 0.0024 ];
x0 = [ 0.4; 0.2; 0.2; 0.1; 0.1 ];
p = Portfolio('BuyCost', bc, 'SellCost', sc, 'InitPort', x0);
disp(p.NumAssets);
disp(p.BuyCost);
disp(p.SellCost);
disp(p.InitPort); 
    5

    0.0013
    0.0013
    0.0013
    0.0013
    0.0013

    0.0013
    0.0070
    0.0013
    0.0013
    0.0024

    0.4000
    0.2000
    0.2000
    0.1000
    0.1000

Setting Transaction Costs Using the setCosts Method

You can also set the properties for transaction costs using setCosts. Assume that you have the same costs and initial portfolio as in the previous example. Given a Portfolio object p with an initial portfolio already set, use setCosts to set up transaction costs:

bc = [ 0.00125; 0.00125; 0.00125; 0.00125; 0.00125 ];
sc = [ 0.00125; 0.007; 0.00125; 0.00125; 0.0024 ];
x0 = [ 0.4; 0.2; 0.2; 0.1; 0.1 ];

p = Portfolio('InitPort', x0);
p = setCosts(p, bc, sc);
        
disp(p.NumAssets);
disp(p.BuyCost);
disp(p.SellCost);
disp(p.InitPort);    
    5

    0.0013
    0.0013
    0.0013
    0.0013
    0.0013

    0.0013
    0.0070
    0.0013
    0.0013
    0.0024

    0.4000
    0.2000
    0.2000
    0.1000
    0.1000

You can also set up the initial portfolio's InitPort value as an optional argument to setCosts so that the following is an equivalent way to set up transaction costs:

bc = [ 0.00125; 0.00125; 0.00125; 0.00125; 0.00125 ];
sc = [ 0.00125; 0.007; 0.00125; 0.00125; 0.0024 ];
x0 = [ 0.4; 0.2; 0.2; 0.1; 0.1 ];

p = Portfolio;
p = setCosts(p, bc, sc, x0);
        
disp(p.NumAssets);
disp(p.BuyCost);
disp(p.SellCost);
disp(p.InitPort);  
    5

    0.0013
    0.0013
    0.0013
    0.0013
    0.0013

    0.0013
    0.0070
    0.0013
    0.0013
    0.0024

    0.4000
    0.2000
    0.2000
    0.1000
    0.1000

Setting Transaction Costs with Scalar Expansion

Both the constructor Portfolio and setCosts method implement scalar expansion on the arguments for transaction costs and the initial portfolio. If the NumAssets property is already set in the Portfolio object, scalar arguments for these properties are expanded to have the same value across all dimensions. In addition, setCosts lets you specify NumAssets as an optional final argument. For example, assume that you have an initial portfolio x0 and you want to set common transaction costs on all assets in your universe. You can set these costs in any of these equivalent ways:

x0 = [ 0.4; 0.2; 0.2; 0.1; 0.1 ];
p = Portfolio('InitPort', x0, 'BuyCost', 0.002, 'SellCost', 0.002);

or

x0 = [ 0.4; 0.2; 0.2; 0.1; 0.1 ];
p = Portfolio('InitPort', x0);
p = setCosts(p, 0.002, 0.002);

or

x0 = [ 0.4; 0.2; 0.2; 0.1; 0.1 ];
p = Portfolio;
p = setCosts(p, 0.002, 0.002, x0);

To clear costs from your Portfolio object, use either the constructor or setCosts with empty inputs for the properties to be cleared. For example, you can clear sales costs from the Portfolio object p in the previous example:

p = Portfolio(p, 'SellCost', []);

See Also

| | | |

Related Examples

More About

Was this topic helpful?