## Minimum variance with tracking error constraint

Find the optimal trade to minimize variance given a constraint on the tracking error and some other simple constraints, including that the portfolio is long-only.

## Preparation

• vector of asset prices
• variance matrix for the assets
• current portfolio (if it exists)
• Portfolio Probe

You need the prices at which assets trade and a variance matrix of the asset returns.  You need either the benchmark to be an asset in the variance matrix or the weight vector of assets for the benchmark.

The holdings of the current portfolio need to be in a vector with names that are the asset identifiers.

You also need to have the Portfolio Probe package loaded into your R session:

`require(PortfolioProbe)`

If you don’t have Portfolio Probe, see “Demo or Buy”.

### Doing the example

`require(pprobeData)`

## Doing it

The inputs we need in order to get our minimum variance portfolio are:

• vector of prices at which the assets may be traded
• variance matrix of the asset returns
• desired value of the new portfolio
• appropriate constraints
• current portfolio (optional)

#### prices

We start by naming the vector of prices that we want to use:

`priceVector <- xassetPrices[251,]`

These are the prices at the close of the last trading day of 2006.  The first few values are:

```> head(priceVector)
XA101  XA103  XA105  XA107  XA108  XA111
33.56  72.25  74.39 192.06   5.91  15.98```

The requirement for the prices is that it be a vector of positive numbers with names (that are the asset identifiers).

#### current portfolio

We create an object to serve as the current portfolio:

```curPortfol <- (1:10) * 1000
names(curPortfol) <- colnames(xassetPrices)[1:10]```

What is expected is a numeric vector of the number of units of each asset in the portfolio.  The names of the vector are the identifiers of the assets that are used in the price vector and the variance matrix.

```> curPortfol
XA101 XA103 XA105 XA107 XA108 XA111 XA113 XA115
1000  2000  3000  4000  5000  6000  7000  8000
XA120 XA126
9000 10000```

#### portfolio value

The value of the portfolio that we should specify is the current value of the existing portfolio adjusted by whatever cash flow is desired.  Here we assume we want to take out \$30,000 from the portfolio:

```cashFlow <- -30000
grossVal <- as.numeric(valuation(curPortfol,
priceVector, collapse=TRUE)) + cashFlow```

We get the value of the current portfolio assuming the prices we are using and then add the cash flow.  (The `as.numeric` is merely for cosmetic reasons to make the result simpler.)  We end up with:

```> grossVal
[1] 2983430```

The gross value of the portfolio that we want is slightly less than \$3 million.

### Optimization with simple variance matrix

For this option we need:

• a vector of the asset weights that comprise the benchmark

Further, we need the variance matrix to contain all of those assets.  But the vector of benchmark weights need not contain all the assets in the variance nor need they be in any particular order.

#### create benchmark weight vector

For the example, we will create a weight vector that equally weights all of the assets in the universe:

```benwt <- rep(1/350, 350)
names(benwt) <- rownames(xaLWvar06)```

The first few values are:

```> head(benwt)
XA101       XA103       XA105       XA107
0.002857143 0.002857143 0.002857143 0.002857143
XA108       XA111
0.002857143 0.002857143```

The vector of benchmark weights need not have all of the assets that are in the variance matrix nor be in any particular order.  It is mandatory, however, that all of the assets in the benchmark weight vector be in the variance.

#### optimization specification

We need to specify the gross value, that the portfolio is long-only, and the tracking error constraint of 5%.

We need to translate the 5% tracking error — the annualized standard deviation — to daily variance (which is the variance matrix that we have).  We square the tracking error and divide by 252.

We’re now ready to do an optimization.  We also demand that no more than 10 assets be in the portfolio.

```opMinVarTEcon <- trade.optimizer(priceVector, variance=xaLWvar06,
existing=curPortfol, gross=grossVal, long.only=TRUE,
port.size=10, utility="minimum variance",
bench.constraint=c(EqualWt=.05^2/252),
bench.weights=list(EqualWt=benwt))```

We specify the utility to be minimum variance.  We still would have got the same thing without the specification, but there would have been a warning that it was guessing what utility we wanted.

#### print result

The resulting object is printed like:

```> opMinVarTEcon
\$new.portfolio
XA336 XA448 XA461 XA486 XA530 XA577 XA683 XA709
6587  6260  2046  7877  6043 10336  4571 10886
XA870 XA966
53547  8461

XA101  XA103  XA105  XA107  XA108  XA111  XA113
-1000  -2000  -3000  -4000  -5000  -6000  -7000
XA115  XA120  XA126  XA336  XA448  XA461  XA486
-8000  -9000 -10000   6587   6260   2046   7877
XA530  XA577  XA683  XA709  XA870  XA966
6043  10336   4571  10886  53547   8461

\$results
objective      negutil         cost
3.489308e-05 3.489308e-05 0.000000e+00
penalty
0.000000e+00

\$converged
[1] FALSE

\$objective.utility
[1] "minimum variance"

\$alpha.values
[1] NA

\$var.values
V0 V0 -- EqualWt
3.489308e-05  9.920628e-06

\$utility.values
[1] 3.489308e-05

\$existing
XA101 XA103 XA105 XA107 XA108 XA111 XA113 XA115
1000  2000  3000  4000  5000  6000  7000  8000
XA120 XA126
9000 10000

\$violated
NULL

\$timestamp
[1] "Fri Sep 07 17:55:06 2012"
[2] "Fri Sep 07 17:55:19 2012"

\$call
trade.optimizer(prices = priceVector, variance = xaLWvar06, existing = curPortfol,
gross = grossVal, long.only = TRUE, port.size = 10, utility = "minimum variance",
bench.constraint = c(EqualWt = 0.05^2/252), bench.weights = list(EqualWt = benwt))```

The first two components are the new (optimal) portfolio and the trade to achieve that.  There are some additional components in the object that are not shown.

### Optimization with benchmark in the variance matrix

For this option we need:

• a variance matrix that includes the benchmark

See “Add benchmark to variance matrix” to create a variance matrix that includes a benchmark.

The only difference between this version and the previous optimization is that the `bench.weights` argument is not used here, we need a different variance matrix, and we need the name given in `bench.constraint` to match whatever the benchmark is called in the variance.

## Explanation

The `trade.optimizer` function does the optimization.  Its first argument is the asset prices.

### Portfolio value

It is mandatory that the value of the resulting portfolio be specified.  For long-only portfolios it is sufficient to state the desired gross value.  The actual value of the portfolio will (usually) be slightly less than the specification:

```> format(grossVal, nsmall=2, big.mark=",")
[1] "2,983,430.00"
> grossVal - as.numeric(valuation(opMinVarTEcon, collapse=TRUE))
[1] 287.42```

### Specifying the tracking error constraint

The constraint on the tracking error was imposed with:

`bench.constraint = c(EqualWt = 0.05^2/252)`

The object given to `bench.constraint` looks like:

```> c(EqualWt = 0.05^2/252)
EqualWt
9.920635e-06```

Alternatively we could have first created such an object:

`benCon <- c(EqualWt = 0.05^2/252)`

or:

```benCon <- 0.05^2/252
names(benCon) <- "EqualWt"```

and then imposed the constraint as:

`bench.constraint = benCon`

If we just gave a number without it having names, then the optimizer wouldn’t know what was to be used as the benchmark.

### Minimum variance

Let’s look at the `var.values` and `utility.values` components of the output:

```\$var.values
V0 V0 -- EqualWt
3.489308e-05  9.920628e-06

\$utility.values
[1] 3.489308e-05```

The `var.values` component has two elements.  The first has a name that only involves the variance, the second’s name includes the benchmark as well.  That means that the first is the portfolio variance and the second is the variance relative to the benchmark.

The first variance value is equal to the utility value.  This indicates that it really is the portfolio variance that is being optimized.

### Resulting volatility and tracking error

The volatility and tracking error for the optimal portfolio is a modification of the `var.values` component:

```> sqrt(opMinVarTEcon\$var.values * 252) * 100
V0 V0 -- EqualWt
9.377129      4.999998```

So the tracking error is right up against the 5% constraint (as should be expected).  The portfolio volatility is about 9.5%.

Remember that this is predicted volatility.  Since it was the quantity being optimized, it will be biased downward.  The tracking error is also a predicted value.  But since the tracking error is only being constrained and not optimized, we have no particular reason to believe it to be biased.

### Other results

One component of the output to pay special attention to is ‘`violated`‘ — this states which constraints, if any, are violated.  You want this to be `NULL`.

It is probably not important whether ‘`converged`‘ is `TRUE` or `FALSE`.  The optimization is likely to be good enough with or without convergence.

## Further Details

You can see more about the optimization with the summary of the object:

```> summary(opMinVarTEcon)
\$results
objective      negutil         cost
3.489308e-05 3.489308e-05 0.000000e+00
penalty
0.000000e+00

\$objective.utility
[1] "minimum variance"

\$alpha.values
[1] NA

\$var.values
V0 V0 -- EqualWt
3.489308e-05  9.920628e-06

\$number.of.assets
10                20
new              open
10                10
close    universe.total
10               351
350               351
0

\$opening.positions
[1] "XA336" "XA448" "XA461" "XA486" "XA530"
[6] "XA577" "XA683" "XA709" "XA870" "XA966"

\$closing.positions
[1] "XA101" "XA103" "XA105" "XA107" "XA108"
[6] "XA111" "XA113" "XA115" "XA120" "XA126"

\$value.limits
lower   upper
gross 2983132 2983430
net   2983132 2983430
long  2983132 2983430
short       0       0

\$valuation.new.portfolio
gross     net    long   short
2983143 2983143 2983143       0

gross        net       long      short
5996572.58  -30287.42 2983142.58 3013430.00

gross         net        long       short
2.01015286 -0.01015286  1.00000000  1.01015286```

This has some pieces that are also in the `print` method, but new information as well.  All of the current portfolio was sold off — a trade to make the broker really happy.

## Troubleshooting

• The variance matrix needs to contain all of the assets that are in the price vector.  It can have additional assets — these will be ignored (except for benchmarks).  The order of the assets in the variance does not matter.
• All of the prices need to be in the same currency.  You have to check that — the code has no way of knowing.
• It will still work if the object given as the prices is a one-column or one-row matrix.  But it will complain about other matrices.