Hauptinhalt

Asset Returns and Moments of Asset Returns Using Portfolio Object

R2026b

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 Function

Suppose that 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 Portfolio object:

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 object 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 function lets you get the values for AssetMean and AssetCovar properties at the same time.

Assignment Using the setAssetMoments Function

You can also set asset moment properties using the setAssetMoments function. 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 Portfolio object and the setAssetMoments function perform scalar expansion on arguments for the moments of asset returns. When using the Portfolio object, 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 do not 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 object if NumAssets is known, or is deduced from the inputs.

Estimate Mean and Covariance of Asset Returns from Data for a Portfolio Object

This example shows how to use the estimateAssetMoments function to estimate the mean and covariance of asset returns from data for a Portfolio object.

Generate random samples of 120 observations of asset returns for four assets from known mean and covariance values using the portsim function. Also create a corresponding price series from the returns.

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);

Create a Portfolio object and estimate asset moments from the return data in X using the estimateAssetMoments function. Compare the estimated moments with directly assigned moments.

p = Portfolio(AssetMean=m,AssetCovar=C);
q = Portfolio;
q = estimateAssetMoments(q,X);

[pMean,pCovar] = getAssetMoments(p)
pMean = 4×1

    0.0042
    0.0083
    0.0100
    0.0150

pCovar = 4×4

    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

[qMean,qCovar] = getAssetMoments(q)
qMean = 4×1

    0.0042
    0.0083
    0.0100
    0.0150

qCovar = 4×4

    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

Both approaches yield the same moments because the portsim function creates simulated data with estimated mean and covariance identical to the input moments.

If you have asset prices instead of returns, specify the DataFormat name-value argument set as "Prices" to indicate that the input data contains prices.

r = Portfolio;
r = estimateAssetMoments(r,Y,DataFormat="Prices");

[rMean,rCovar] = getAssetMoments(r)
rMean = 4×1

    0.0042
    0.0083
    0.0100
    0.0150

rCovar = 4×4

    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

The estimated moments from prices match those estimated from returns.

Estimating Asset Moments with Missing Data

This example shows how to work with 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 estimateAssetMoments function has a name-value pair 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. The following code 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)
passetmean = 4×1

    0.0042
    0.0083
    0.0100
    0.0150

passetcovar = 4×4

    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, qassetcovar] = getAssetMoments(q)
qassetmean = 4×1

    0.0039
    0.0128
    0.0153
    0.0238

qassetcovar = 4×4

    0.0006    0.0004    0.0001    0.0001
    0.0004    0.0023    0.0015    0.0005
    0.0001    0.0015    0.0043    0.0024
    0.0001    0.0005    0.0024    0.0084

[rassetmean, rassetcovar] = getAssetMoments(r)
rassetmean = 4×1

    0.0033
    0.0083
    0.0100
    0.0176

rassetcovar = 4×4

    0.0006    0.0004    0.0001    0.0001
    0.0004    0.0024    0.0017    0.0007
    0.0001    0.0017    0.0048    0.0025
    0.0001    0.0007    0.0025    0.0083

The Portfolio object p contains raw moments, the Portfolio object q contains estimated moments in which NaN values are discarded, and the Portfolio object r contains raw moments that accommodate missing values. Each time you run this code, 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

This example shows how the estimateAssetMoments function also accepts asset returns or prices stored in a table or timetable. estimateAssetMoments implicitly works with matrices of data or data in a table or timetable object using the same rules for whether the data are returns or prices.

To illustrate the use of a table and timetable, use array2table and array2timetable to create a table and a timetable that contain asset returns generated with portsim (see Estimate Mean and Covariance of Asset Returns from Data for a Portfolio Object). Two portfolio objects are then created with the AssetReturns based on a table and a timetable object.

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;
 
assetRetnScenarios = portsim(m', C, 120);
dates = datetime(datenum(2001,1:120,31), 'ConvertFrom', 'datenum');
assetsName = {'Bonds', 'LargeCap', 'SmallCap', 'Emerging'};
assetRetnTimeTable = array2timetable(assetRetnScenarios,'RowTimes',dates, 'VariableNames', assetsName);      
assetRetnTable = array2table(assetRetnScenarios, 'VariableNames', assetsName);


% Create two Portfolio objects:
% p with predefined mean and covar and q with asset return scenarios to estimate mean and covar.
p = Portfolio('mean', m, 'covar', C);
q = Portfolio;

% Estimate asset moments using a timetable
q = estimateAssetMoments(q, assetRetnTimeTable);
[passetmean, passetcovar] = getAssetMoments(p)
passetmean = 4×1

    0.0042
    0.0083
    0.0100
    0.0150

passetcovar = 4×4

    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, qassetcovar] = getAssetMoments(q)
qassetmean = 4×1

    0.0042
    0.0083
    0.0100
    0.0150

qassetcovar = 4×4

    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

% Estimate asset moments using a table
q = estimateAssetMoments(q, assetRetnTable);
[passetmean, passetcovar] = getAssetMoments(p)
passetmean = 4×1

    0.0042
    0.0083
    0.0100
    0.0150

passetcovar = 4×4

    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, qassetcovar] = getAssetMoments(q)
qassetmean = 4×1

    0.0042
    0.0083
    0.0100
    0.0150

qassetcovar = 4×4

    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 between th two portfolios. In addition, estimateAssetMoments also extracts asset names or identifiers from a table or timetable when the argument name 'GetAssetList' is 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 Portfolio object. To show this, the formation of the Portfolio object q is repeated from the previous code with the 'GetAssetList' flag set to true and this extracts the column labels from a table or timetable object.

q = estimateAssetMoments(q,assetRetnTable,'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.

Estimate Weighted Asset Moments Using Entropy Pooling Probabilities

This example shows how to use the Probabilities name-value argument of the estimateAssetMoments function to estimate asset moments weighted by entropy pooling posterior probabilities. Entropy pooling produces posterior probabilities that incorporate your market views into an empirical distribution. You can pass these probabilities directly to the estimateAssetMoments function to compute the weighted mean and covariance for mean-variance portfolio optimization.

Load historical asset return data. For this example, simulate asset returns for a portfolio of four assets.

rng("default")
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;
AssetReturns = portsim(m,C,240);

Create an entropyViews object from the asset returns and specify a view that the mean return of the first asset is greater than its historical average.

obj = entropyViews(AssetReturns);
obj = setMeanViews(obj,"Var1",">",0.006);

Compute posterior probabilities that reflect the specified views while minimizing relative entropy.

p = posteriorProbabilities(obj);

Pass the posterior probabilities to the estimateAssetMoments function using the Probabilities name-value argument. The function computes the weighted mean and population covariance.

port = Portfolio;
port = estimateAssetMoments(port,AssetReturns,Probabilities=p);
[weightedMean,weightedCovar] = getAssetMoments(port)
weightedMean = 4×1

    0.0060
    0.0095
    0.0106
    0.0150

weightedCovar = 4×4

    0.0005    0.0003    0.0002    0.0000
    0.0003    0.0024    0.0017    0.0009
    0.0002    0.0017    0.0047    0.0027
    0.0000    0.0009    0.0027    0.0100

Compare the probability-weighted moments against the standard equally weighted estimation to see the impact of the entropy pooling views.

portNeutral = Portfolio;
portNeutral = estimateAssetMoments(portNeutral,AssetReturns);
[equalMean,equalCovar] = getAssetMoments(portNeutral)
equalMean = 4×1

    0.0042
    0.0083
    0.0100
    0.0150

equalCovar = 4×4

    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

The mean of the first asset in the portfolio that reflects the view is higher than the mean of the first asset in the neutral portfolio, reflecting the view that its expected return is at least 0.006.

Set default portfolio constraints and compute the efficient frontier for both the weighted and neutral portfolios.

port = setDefaultConstraints(port);
portNeutral = setDefaultConstraints(portNeutral);

pgt = estimateFrontier(port,20);
pngt = estimateFrontier(portNeutral,20);

Plot the efficient frontiers.

ax = axes;
hold(ax,"on")
[~,~,h1] = plotFrontier(port,pgt,Parent=ax);
[~,~,h2] = plotFrontier(portNeutral,pngt,Parent=ax);
h2.Color = "r";
h2.LineStyle = ":";
xlabel("Portfolio Risk (Standard Deviation)")
ylabel("Portfolio Return")
legend("Entropy Pooling Weighted","Neutral",Location="southeast")
title("Efficient Frontiers: Entropy Pooling Weighted vs. Neutral")

Figure contains an axes object. The axes object with title Efficient Frontiers: Entropy Pooling Weighted vs. Neutral, xlabel Portfolio Risk (Standard Deviation), ylabel Portfolio Return contains 2 objects of type line. These objects represent Entropy Pooling Weighted, Neutral.

The efficient frontier shifts when you incorporate entropy pooling views, reflecting the updated distribution of asset returns.

See Also

| | | | |

Topics

External Websites