Documentation

## Asset Returns and Scenarios Using PortfolioCVaR Object

### How Stochastic Optimization Works

The CVaR of a portfolio is a conditional expectation. (For the definition of the CVaR function, see Risk Proxy.) Therefore, the CVaR portfolio optimization problem is a stochastic optimization problem. Given a sample of scenarios, the conditional expectation that defines the sample CVaR of the portfolio can be expressed as a finite sum, a weighted average of losses. The weights of the losses depend on their relative magnitude; for a confidence level α, only the worst (1 − α) x 100% losses get a positive weight. As a function of the portfolio weights, the CVaR of the portfolio is a convex function (see ,  Rockafellar & Uryasev at Portfolio Optimization). It is also a nonsmooth function, but its edges are less sharp as the sample size increases.

There are reformulations of the CVaR portfolio optimization problem (see ,  at Rockafellar & Uryasev) that result in a linear programming problem, which can be solved either with standard linear programming techniques or with stochastic programming solvers. The `PortfolioCVaR` object, however, does not reformulate the problem in such a manner. The `PortfolioCVaR` object computes the CVaR as a nonlinear function. The convexity of the CVaR, as a function of the portfolio weights and the dull edges when the number of scenarios is large, make the CVaR portfolio optimization problem tractable, in practice, for certain nonlinear programming solvers, such as `fmincon` from Optimization Toolbox™. The problem can also be solved using a cutting-plane method (see Kelley  at Portfolio Optimization). For more information, see Algorithms section of `setSolver`. To learn more about the workflow when using `PortfolioCVaR` objects, see PortfolioCVaR Object Workflow.

### What Are Scenarios?

Since conditional value-at-risk portfolio optimization works with scenarios of asset returns to perform the optimization, several ways exist to specify and simulate scenarios. In many applications with CVaR portfolio optimization, asset returns may have distinctly nonnormal probability distributions with either multiple modes, binning of returns, truncation of distributions, and so forth. In other applications, asset returns are modeled as the result of various simulation methods that might include Monte-Carlo simulation, quasi-random simulation, and so forth. Often, the underlying probability distribution for risk factors may be multivariate normal but the resultant transformations are sufficiently nonlinear to result in distinctively nonnormal asset returns.

For example, this occurs with bonds and derivatives. In the case of bonds with a nonzero probability of default, such scenarios would likely include asset returns that are −100% to indicate default and some values slightly greater than −100% to indicate recovery rates.

Although the `PortfolioCVaR` object has functions to simulate multivariate normal scenarios from either data or moments (`simulateNormalScenariosByData` and `simulateNormalScenariosByMoments`), the usual approach is to specify scenarios directly from your own simulation functions. These scenarios are entered directly as a matrix with a sample for all assets across each row of the matrix and with samples for an asset down each column of the matrix. The architecture of the CVaR portfolio optimization tools references the scenarios through a function handle so scenarios that have been set cannot be accessed directly as a property of the `PortfolioCVaR` object.

### Setting Scenarios Using the PortfolioCVaR Function

Suppose that you have a matrix of scenarios in the `AssetScenarios` variable. The scenarios are set through the `PortfolioCVaR` object with:

```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; AssetScenarios = mvnrnd(m, C, 20000); p = PortfolioCVaR('Scenarios', AssetScenarios); disp(p.NumAssets); disp(p.NumScenarios);```
```4 20000```

Notice that the `PortfolioCVaR` object determines and fixes the number of assets in `NumAssets` and the number of scenarios in `NumScenarios` based on the scenario’s matrix. You can change the number of scenarios by calling the `PortfolioCVaR` object with a different scenario matrix. However, once the `NumAssets` property has been set in the object, you cannot enter a scenario matrix with a different number of assets. The `getScenarios` function lets you recover scenarios from a `PortfolioCVaR` object. You can also obtain the mean and covariance of your scenarios using `estimateScenarioMoments`.

Although not recommended for the casual user, an alternative way exists to recover scenarios by working with the function handle that points to scenarios in the `PortfolioCVaR` object. To access some or all the scenarios from a `PortfolioCVaR` object, the hidden property `localScenarioHandle` is a function handle that points to a function to obtain scenarios that have already been set. To get scenarios directly from a `PortfolioCVaR` object `p`, use

`scenarios = p.localScenarioHandle([], []);`
and to obtain a subset of scenarios from rows `startrow` to `endrow`, use
`scenarios = p.localScenarioHandle(startrow, endrow);`
where `1``startrow``endrow``numScenarios`.

### Setting Scenarios Using the setScenarios Function

You can also set scenarios using `setScenarios`. 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; AssetScenarios = mvnrnd(m, C, 20000); p = PortfolioCVaR; p = setScenarios(p, AssetScenarios); disp(p.NumAssets); disp(p.NumScenarios);```
```4 20000```

### Estimating the Mean and Covariance of Scenarios

The `estimateScenarioMoments` function obtains estimates for the mean and covariance of scenarios in a `PortfolioCVaR` 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; AssetScenarios = mvnrnd(m, C, 20000); p = PortfolioCVaR; p = setScenarios(p, AssetScenarios); [mean, covar] = estimateScenarioMoments(p)```
```mean = 0.0043 0.0085 0.0098 0.0153 covar = 0.0005 0.0003 0.0002 0.0000 0.0003 0.0024 0.0017 0.0010 0.0002 0.0017 0.0049 0.0029 0.0000 0.0010 0.0029 0.0102```

### Simulating Normal Scenarios

As a convenience, the two functions (`simulateNormalScenariosByData` and `simulateNormalScenariosByMoments`) exist to simulate scenarios from data or moments under an assumption that they are distributed as multivariate normal random asset returns.

### Simulating Normal Scenarios from Returns or Prices

Given either return or price data, use the function `simulateNormalScenariosByData` to simulate multivariate normal scenarios. Either returns or prices are stored as matrices with samples going down the rows and assets going across the columns. In addition, returns or prices can be stored in a `table` or `timetable` (see Simulating Normal Scenarios from Time Series Data). To illustrate using `simulateNormalScenariosByData`, 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.0042; 0.0083; 0.01; 0.15 ]; C = [ 0.005333 0.00034 0.00016 0; 0.00034 0.002408 0.0017 0.000992; 0.00016 0.0017 0.0048 0.0028; 0 0.000992 0.0028 0.010208 ]; X = portsim(m', C, 120); Y = ret2tick(X); ```

### Note

Portfolio optimization requires that you use total returns and not just price returns. So, “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 simulate multivariate normal scenarios for the `PortfolioCVaR` object. Assume a `PortfolioCVaR` object created in `p` that uses the asset returns in X uses `simulateNormalScenariosByData`:

```p = PortfolioCVaR; p = simulateNormalScenariosByData(p, X, 20000); [passetmean, passetcovar] = estimateScenarioMoments(p)```
```passetmean = 0.0043 0.0083 0.0102 0.1507 passetcovar = 0.0053 0.0003 0.0002 0.0000 0.0003 0.0024 0.0017 0.0010 0.0002 0.0017 0.0049 0.0028 0.0000 0.0010 0.0028 0.0101```
The moments that you obtain from this simulation will likely differ from the moments listed here because the scenarios are random samples from the estimated multivariate normal probability distribution of the input returns X.

The default behavior of `simulateNormalScenariosByData` is to work with asset returns. If, instead, you have asset prices as in the variable Y, `simulateNormalScenariosByData` accepts a name-value pair argument name `'DataFormat'` with a corresponding value set to `'prices'` to indicate that the input to the function is in the form of asset prices and not returns (the default value for the `'DataFormat'` argument is `'returns'`). This example simulates scenarios with the asset price data in Y for the `PortfolioCVaR` object `q`:

```p = PortfolioCVaR; p = simulateNormalScenariosByData(p, Y, 20000, 'dataformat', 'prices'); [passetmean, passetcovar] = estimateScenarioMoments(p)```
```passetmean = 0.0043 0.0084 0.0094 0.1490 passetcovar = 0.0054 0.0004 0.0001 -0.0000 0.0004 0.0024 0.0016 0.0009 0.0001 0.0016 0.0048 0.0028 -0.0000 0.0009 0.0028 0.0100```

### Simulating Normal Scenarios 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 `simulateNormalScenariosByData` 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™. The default value for `'MissingData'` is `false` which removes all samples with `NaN` values. If, however, `'MissingData'` is set to `true`, `simulateNormalScenariosByData` uses the ECM algorithm to estimate asset moments. This example shows how this works on price data with missing values:

```m = [ 0.0042; 0.0083; 0.01; 0.15 ]; C = [ 0.005333 0.00034 0.00016 0; 0.00034 0.002408 0.0017 0.000992; 0.00016 0.0017 0.0048 0.0028; 0 0.000992 0.0028 0.010208 ]; X = portsim(m', C, 120); Y = ret2tick(X); Y(1:20,1) = NaN; Y(1:12,4) = NaN; ```

Notice that the prices above in `Y` have missing values in the first and fourth series.

```p = PortfolioCVaR; p = simulateNormalScenariosByData(p, Y, 20000, 'dataformat', 'prices'); q = PortfolioCVaR; q = simulateNormalScenariosByData(q, Y, 20000, 'dataformat', 'prices', 'missingdata', true); [passetmean, passetcovar] = estimateScenarioMoments(p) [qassetmean, qassetcovar] = estimateScenarioMoments(q)```
```passetmean = 0.0020 0.0074 0.0078 0.1476 passetcovar = 0.0055 0.0003 -0.0001 -0.0003 0.0003 0.0024 0.0019 0.0012 -0.0001 0.0019 0.0050 0.0028 -0.0003 0.0012 0.0028 0.0101 qassetmean = 0.0024 0.0085 0.0106 0.1482 qassetcovar = 0.0071 0.0004 -0.0001 -0.0004 0.0004 0.0032 0.0022 0.0012 -0.0001 0.0022 0.0063 0.0034 -0.0004 0.0012 0.0034 0.0127```
The first `PortfolioCVaR` object, `p`, contains scenarios obtained from price data in `Y` where `NaN` values are discarded and the second `PortfolioCVaR` object, `q`, contains scenarios obtained from price data in `Y` that accommodate missing values. Each time you run this example, you get different estimates for the moments in `p` and `q`.

### Simulating Normal Scenarios from Time Series Data

The `simulateNormalScenariosByData` function 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, use `array2timetable` to create a timetable for 14 assets from `CAPMuniverse` and the use the timetable to simulate scenarios for PortfolioCVaR.

```load CAPMuniverse time = datetime(Dates,'ConvertFrom','datenum'); stockTT = array2timetable(Data,'RowTimes',time, 'VariableNames', Assets); stockTT.Properties % Notice that GOOG has missing data, because it was not listed before Aug 2004 head(stockTT, 5); ```
```ans = struct with fields: Description: '' UserData: [] DimensionNames: {'Time' 'Variables'} VariableNames: {'AAPL' 'AMZN' 'CSCO' 'DELL' 'EBAY' 'GOOG' 'HPQ' 'IBM' 'INTC' 'MSFT' 'ORCL' 'YHOO' 'MARKET' 'CASH'} VariableDescriptions: {} VariableUnits: {} VariableContinuity: [] RowTimes: [1471×1 datetime]```

Use the `'MissingData'` option offered by PortfolioCVaR to account for the missing data.

```p = PortfolioCVaR; p = simulateNormalScenariosByData(p, stockTT, 20000 ,'missingdata',true); [passetmean, passetcovar] = estimateScenarioMoments(p) ```
```passetmean = 0.0012 0.0007 -0.0005 -0.0000 0.0016 0.0043 -0.0001 0.0000 0.0001 -0.0002 0.0000 0.0004 0.0001 0.0001 passetcovar = 0.0013 0.0005 0.0006 0.0005 0.0006 0.0003 0.0005 0.0003 0.0006 0.0004 0.0005 0.0006 0.0002 -0.0000 0.0005 0.0024 0.0007 0.0005 0.0010 0.0005 0.0005 0.0003 0.0006 0.0004 0.0006 0.0011 0.0002 -0.0000 0.0006 0.0007 0.0013 0.0006 0.0007 0.0004 0.0006 0.0004 0.0008 0.0005 0.0008 0.0008 0.0002 -0.0000 0.0005 0.0005 0.0006 0.0009 0.0006 0.0002 0.0005 0.0003 0.0006 0.0004 0.0005 0.0006 0.0002 -0.0000 0.0006 0.0010 0.0007 0.0006 0.0018 0.0007 0.0005 0.0003 0.0006 0.0005 0.0007 0.0011 0.0002 -0.0000 0.0003 0.0005 0.0004 0.0002 0.0007 0.0013 0.0002 0.0002 0.0002 0.0002 0.0003 0.0011 0.0001 -0.0000 0.0005 0.0005 0.0006 0.0005 0.0005 0.0002 0.0010 0.0003 0.0005 0.0003 0.0005 0.0006 0.0002 -0.0000 0.0003 0.0003 0.0004 0.0003 0.0003 0.0002 0.0003 0.0005 0.0004 0.0002 0.0004 0.0004 0.0002 0.0000 0.0006 0.0006 0.0008 0.0006 0.0006 0.0002 0.0005 0.0004 0.0011 0.0005 0.0007 0.0007 0.0002 -0.0000 0.0004 0.0004 0.0005 0.0004 0.0005 0.0002 0.0003 0.0002 0.0005 0.0006 0.0004 0.0005 0.0002 -0.0000 0.0005 0.0006 0.0008 0.0005 0.0007 0.0003 0.0005 0.0004 0.0007 0.0004 0.0014 0.0007 0.0002 -0.0000 0.0006 0.0011 0.0008 0.0006 0.0011 0.0011 0.0006 0.0004 0.0007 0.0005 0.0007 0.0020 0.0002 -0.0000 0.0002 0.0002 0.0002 0.0002 0.0002 0.0001 0.0002 0.0002 0.0002 0.0002 0.0002 0.0002 0.0001 -0.0000 -0.0000 -0.0000 -0.0000 -0.0000 -0.0000 -0.0000 -0.0000 0.0000 -0.0000 -0.0000 -0.0000 -0.0000 -0.0000 0.0000```

Use the name-value input `'DataFormat'` to handle return or price data and `'MissingData'` to ignore or use samples with missing values. In addition, `simulateNormalScenariosByData` extracts asset names or identifiers from a `table` or `timetable` if the argument `'GetAssetList'` is set to `true` (the default value is `false`). If the `'GetAssetList'` value is `true`, the identifiers are used to set the `AssetList` property of the `PortfolioCVaR` object. Thus, repeating the formation of the `PortfolioCVaR` object `p` from the previous example with the `'GetAssetList'` flag set to `true` extracts the column names from the timetable object:

```p = simulateNormalScenariosByData(p, stockTT, 20000 ,'missingdata',true, 'GetAssetList', true); disp(p.AssetList)```
` 'AAPL' 'AMZN' 'CSCO' 'DELL' 'EBAY' 'GOOG' 'HPQ' 'IBM' 'INTC' 'MSFT' 'ORCL' 'YHOO' 'MARKET' 'CASH'`

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

### Simulating Normal Scenarios with Mean and Covariance

Given the mean and covariance of asset returns, use the `simulateNormalScenariosByMoments` function to simulate multivariate normal scenarios. The mean can be either a row or column vector and the covariance matrix must be a symmetric positive-semidefinite matrix. Various rules for scalar expansion apply. To illustrate using `simulateNormalScenariosByMoments`, start with moments in `m` and `C` and generate 20,000 scenarios:

```m = [ 0.0042; 0.0083; 0.01; 0.15 ]; C = [ 0.005333 0.00034 0.00016 0; 0.00034 0.002408 0.0017 0.000992; 0.00016 0.0017 0.0048 0.0028; 0 0.000992 0.0028 0.010208 ]; p = PortfolioCVaR; p = simulateNormalScenariosByMoments(p, m, C, 20000); [passetmean, passetcovar] = estimateScenarioMoments(p)```
```passetmean = 0.0049 0.0083 0.0101 0.1503 passetcovar = 0.0053 0.0003 0.0002 -0.0000 0.0003 0.0024 0.0017 0.0010 0.0002 0.0017 0.0047 0.0028 -0.0000 0.0010 0.0028 0.0101```

`simulateNormalScenariosByMoments` performs scalar expansion on arguments for the moments of asset returns. If `NumAssets` has not already been set, a scalar argument is interpreted as a scalar with `NumAssets` set to `1`. `simulateNormalScenariosByMoments` 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.