# Chapter 4 Managing Portfolios

In this chapter we show how to explore and analyze data using the dataset created in Chapter @ref(#s_2Data):

At first we will learn how to full-sample optimize portfolios, then (in the next chapters) we will do the same thing in a rolling analysis and also perform some backtesting. The major workhorse of this chapter is the `portfolioAnalytics`

-package developed by Peterson and Carl (2018).

`portfolioAnalytics`

comes with an excellent introductory vignette `vignette("portfolio_vignette")`

and includes more documents, detailing on the use of `ROI`

-solvers `vignette("ROI_vignette")`

, how to create custom moment functions `vignette("custom_moments_objectives")`

and how to introduce CVaR-budgets `vignette("risk_budget_optimization")`

.

## 4.1 Introduction

SHORT INTRODUCTION TO PORTFOLIOMANAGEMENT

We start by first creating a `portfolio`

object, before we…

## 4.2 Tools for Portfolio Management

### 4.2.1 The Portfolio Object

The portfolio object is a so-called `S3`

-object, which means, that it has a certain `class`

(portfolio) describing its properties, behavior and relation to other objects. Usually such an objects comes with a variety of `methods`

. To create such an object, we reuse the stock data set that we have created in Chapter @ref(#s_2Data):

```
load("stocks.RData")
glimpse(stocks.final)
```

```
## Observations: 2,160
## Variables: 10
## $ symbol <chr> "AAPL", "AAPL", "AAPL", "AAPL", "AAPL", "AAPL", "AAPL...
## $ date <S3: yearmon> Jan 2000, Feb 2000, Mrz 2000, Apr 2000, Mai 2...
## $ return <dbl> -0.07314358, 0.10481940, 0.18484208, -0.08651642, -0....
## $ adjusted <dbl> 2.489997, 2.750997, 3.259497, 2.977497, 2.015998, 2.5...
## $ volume <dbl> 175420000, 92240400, 101158400, 62395200, 108376800, ...
## $ sp500 <dbl> -0.041753145, -0.020108083, 0.096719828, -0.030795756...
## $ Mkt.RF <dbl> -0.0474, 0.0245, 0.0520, -0.0640, -0.0442, 0.0464, -0...
## $ SMB <dbl> 0.0505, 0.2214, -0.1728, -0.0771, -0.0501, 0.1403, -0...
## $ HML <dbl> -0.0045, -0.1057, 0.0794, 0.0856, 0.0243, -0.1010, 0....
## $ RF <dbl> 0.0041, 0.0043, 0.0047, 0.0046, 0.0050, 0.0040, 0.004...
```

`stocks.final %>% slice(1:2)`

```
## # A tibble: 2 x 10
## symbol date return adjusted volume sp500 Mkt.RF SMB HML
## <chr> <S3:> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 AAPL Jan ~ -0.0731 2.49 1.75e8 -0.0418 -0.0474 0.0505 -0.0045
## 2 AAPL Feb ~ 0.105 2.75 9.22e7 -0.0201 0.0245 0.221 -0.106
## # ... with 1 more variable: RF <dbl>
```

For the `portfolioAnalytics`

-package we need our data in `xts`

-format (see @ref(#sss_112xts)) and therefore first `spread`

the dataset returns in columns of stocks and the convert to `xts`

using `tk_xts()`

from the `timetk`

-package.

```
returns <- stocks.final %>%
select(symbol,date,return) %>%
spread(symbol,return) %>%
tk_xts(silent = TRUE)
```

Now its time to initialize the `portfolio.spec()`

object passing along the names of our assets. Afterwards we `print`

the object (most `S3`

obejcts come with a printing methods that nicely displays some nice information).

```
pspec <- portfolio.spec(assets = stocks.selection$symbol,
category_labels = stocks.selection$sector)
print(pspec)
```

```
## **************************************************
## PortfolioAnalytics Portfolio Specification
## **************************************************
##
## Call:
## portfolio.spec(assets = stocks.selection$symbol, category_labels = stocks.selection$sector)
##
## Number of assets: 10
## Asset Names
## [1] "AAPL" "MSFT" "AMZN" "CSCO" "NVDA" "ORCL" "AMGN" "ADBE" "QCOM" "GILD"
##
## Category Labels
## Information Technology : AAPL MSFT CSCO NVDA ORCL ADBE QCOM
## Consumer Discretionary : AMZN
## Health Care : AMGN GILD
```

`str(pspec)`

```
## List of 6
## $ assets : Named num [1:10] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
## ..- attr(*, "names")= chr [1:10] "AAPL" "MSFT" "AMZN" "CSCO" ...
## $ category_labels:List of 3
## ..$ Information Technology: int [1:7] 1 2 4 5 6 8 9
## ..$ Consumer Discretionary: int 3
## ..$ Health Care : int [1:2] 7 10
## $ weight_seq : NULL
## $ constraints : list()
## $ objectives : list()
## $ call : language portfolio.spec(assets = stocks.selection$symbol, category_labels = stocks.selection$sector)
## - attr(*, "class")= chr [1:2] "portfolio.spec" "portfolio"
```

Checking the structure of the object `str()`

we find that it contains several elements: *assets* which contains the asset names and initial weights that are equally distributed unless otherwise specified (e.g. `portfolio.spec(assets=c(0.6,0.4))`

), *category_labels* to categorize assets by sector (or geography etc.), *weight_seq* (sequence of weights for later use by `random_portfolios`

), *constraints* that we will set soon, *objectives* and the `call`

that initialised the object. Before we go and optimize any portfolio we will show how to set contraints.

### 4.2.2 Constraints

Constraints define restrictions and boundary conditions on the weights of a portfolio. Constraints are defined by `add.constraint`

specifying certain `types`

and arguments for each `type`

, as well as whether the constraint should be enabled or not (`enabled=TRUE`

is the default).

#### 4.2.2.1 Sum of Weights Constraint

Here we define how much of the available budget can/must be invested by specifying the maximum/minimum sum of portfolio weights. Usually we want to invest our entire budget and therefore set `type="full_investment"`

which sets the sum of weights to 1. Alternatively we can set the `type="weight_sum"`

to have mimimum/maximum `weight_sum`

equal to 1.

```
pspec <- add.constraint(portfolio=pspec,
type="full_investment")
# print(pspec)
# pspec <- add.constraint(portfolio=pspec,type="weight_sum", min_sum=1, max_sum=1)
```

Another common constraint is to have the portfolio dollar-neutral `type="dollar_neutral"`

(or equivalent formulations specified below)

```
# pspec <- add.constraint(portfolio=pspec,
# type="dollar_neutral")
# print(pspec)
# pspec <- add.constraint(portfolio=pspec, type="active")
# pspec <- add.constraint(portfolio=pspec, type="weight_sum", min_sum=0, max_sum=0)
```

#### 4.2.2.2 Box Constraint

Box constraints specify upper and lower bounds on the asset weights. If we pass `min`

and `max`

as scalars then the same max and min weights are set per asset. If we pass vectors (that should be of the same length as the number of assets) we can specify position limits on individual stocks

```
pspec <- add.constraint(portfolio=pspec,
type="box",
min=0,
max=0.4)
# print(pspec)
# add.constraint(portfolio=pspec,
# type="box",
# min=c(0.05, 0, rep(0.05,8)),
# max=c(0.4, 0.3, rep(0.4,8)))
```

Another special type of box constraints are *long-only* constraints, where we only allow positive weights per asset. These are set automatically, if no `min`

and `max`

are set or when we use `type="long_only"`

```
# pspec <- add.constraint(portfolio=pspec, type="box")
# pspec <- add.constraint(portfolio=pspec, type="long_only")
```

#### 4.2.2.3 Group Constraints

Group constraints allow the user to specify constraints per groups, such as industries, sectors or geography.^{3} These groups can be randomly defined, below we will set group constraints for the sectors as specified above. The input arguments are the following: `groups`

list of vectors specifying the groups of the assets, `group_labels`

character vector to label the groups (e.g. size, asset class, style, etc.), `group_min`

and `group_max`

specifying minimum and maximum weight per group, `group_pos`

to specifying the number of non-zero weights per group (optional).

```
pspec <- add.constraint(portfolio=pspec,
type="group",
groups=list(pspec$category_labels$`Information Technology`, # list of vectors specifying the groups of the assets
pspec$category_labels$`Consumer Discretionary`,
pspec$category_labels$`Health Care`),
group_min=c(0.1, 0.15,0.1),
group_max=c(0.85, 0.55,0.4),
group_labels=pspec$category_labels)
# print(pspec)
```

#### 4.2.2.4 Position Limit Constraint

The position limit constraint allows the user to specify limits on the number of assets with non-zero, long, or short positions. Its arguments are: `max_pos`

which defines the maximum number of assets with non-zero weights and `max_pos_long`

/ `max_pos_short`

that specify the maximum number of assets with long (i.e. buy) and short (i.e. sell) positions.^{4}

```
pspec <- add.constraint(portfolio=pspec, type="position_limit", max_pos=3)
# pspec <- add.constraint(portfolio=pspec, type="position_limit", max_pos_long=3, max_pos_short=3))
# print(pspec)
```

#### 4.2.2.5 Diversification Constraint

The diversification constraint enables to set a minimum diversification limit by penalizing the optimizer if the deviation is larger than 5%. Diversification is defined as \(\sum_{i=1}^{N}w_i^2\) for \(N\) assets.^{5} Its only argument is the diversification taregt `div_target`

.

```
pspec <- add.constraint(portfolio=pspec, type="diversification", div_target=0.7)
# print(pspec)
```

#### 4.2.2.6 Turnover Constraint

The turnover constraint allows to specify a maximum turnover from a set of initial weights that can either be given or are the weights initially specified for the portfolio object. It is also implemented as an optimization penalty if the turnover deviates more than 5% from the `turnover_target`

.^{6}

```
pspec <- add.constraint(portfolio=pspec, type="turnover", turnover_target=0.2)
# print(pspec)
```

#### 4.2.2.7 Target Return Constraint

The target return constraint allows the user to target an average return specified by `return_target`

.

```
pspec <- add.constraint(portfolio=pspec, type="return", return_target=0.007)
# print(pspec)
```

#### 4.2.2.8 Factor Exposure Constraint

The factor exposure constraint allows the user to set upper and lower bounds on exposures to risk factors. We will use the factor exposures that we have calculated in @(#sss_3FactorExposure). The major input is a vector or matrix `B`

and `upper`

/`lower`

bounds for the portfolio factor exposure. If `B`

is a vector (with length equal to the number of assets), lower and upper bounds must be scalars. If `B`

is a matrix, the number of rows must be equal to the number of assets and the number of columns represent the number of factors. In this case, the length of lower and upper bounds must be equal to the number of factors. `B`

should have column names specifying the factors and row names specifying the assets.

```
B <- stocks.factor_exposure %>% as.data.frame() %>% column_to_rownames("symbol")
pspec <- add.constraint(portfolio=pspec, type="factor_exposure",
B=B,
lower=c(0.8,0,-1),
upper=c(1.2,0.8,0))
# print(pspec)
```

#### 4.2.2.9 Transaction Cost Constraint

The transaction cost constraint enables the user to specify (porportional) transaction costs.^{7} Here we will assume the proportional transation cost `ptc`

to be equal to 1%.

```
pspec <- add.constraint(portfolio=pspec, type="transaction_cost", ptc=0.01)
# print(pspec)
```

#### 4.2.2.10 Leverage Exposure Constraint

The leverage exposure constraint specifies a maximum level of leverage. Below we set `leverage`

to 1.3 to create a 130/30 portfolio.

```
pspec <- add.constraint(portfolio=pspec, type="leverage_exposure", leverage=1.3)
# print(pspec)
```

#### 4.2.2.11 Checking and en-/disabling constraints

Every constraint that is added to the portfolio object gets a number according to the order it was set. If one wants to update (enable/disable) a specific constraints this can be done by the `indexnum`

argument.

```
summary(pspec)
# To get an overview on the specs, their indexnum and whether they are enabled I suggest the follwoing
consts <- plyr::ldply(pspec$constraints, function(x){c(x$type,x$enabled)})
consts
pspec$constraints[[which(consts$V1=="box")]]
pspec <- add.constraint(pspec, type="box",
min=0, max=0.5,
indexnum=which(consts$V1=="box"))
pspec$constraints[[which(consts$V1=="box")]]
# to disable constraints
pspec$constraints[[which(consts$V1=="position_limit")]]
pspec <- add.constraint(pspec, type="position_limit", enable=FALSE, # only specify argument if you do enable the constraint
indexnum=which(consts$V1=="position_limit"))
pspec$constraints[[which(consts$V1=="position_limit")]]
```

### 4.2.3 Objectives

For an **optimal portfolio** there first has to be specified what **optimal** in terms of the relevant (business) objective. Such objectives (target functions) can be added to the portfolio object with `add.objective`

. With this function, the user can specify the type of objective to add to the portfolio object. Currently available are ‘return’, ‘risk’, ‘risk budget’, ‘quadratic utility’, ‘weight concentration’, ‘turnover’ and ‘minmax’. Each type of objective has additional arguments that need to be specified. Several types of objectives can be added and enabled or disabled by specifying the `indexnum`

argument.

#### 4.2.3.1 Portfolio Risk Objective

Here, the user can specify a risk function that should be minimized. We start by adding a risk objective to minimize portfolio variance (minimum variance portfolio). Another example could be the *expected tail loss* with a confidence level 0.95. Whatever function (even user defined ones are possble, the name must correspond to a function in `R`

), necessary additional arguments to the function have to be passed as a named list to `arguments`

. Possible functions are:

```
pspec <- add.objective(portfolio=pspec,
type='risk',
name='var')
pspec <- add.objective(portfolio=pspec,
type='risk',
name='ETL',
arguments=list(p=0.95),
enabled=FALSE)
# print(pspec)
```

#### 4.2.3.2 Portfolio Return Objective

The return objective allows the user to specify a return function to maximize. Here we add a return objective to maximize the portfolio mean return.

```
pspec <- add.objective(portfolio=pspec,
type='return',
name='mean')
# print(pspec)
```

#### 4.2.3.3 Portfolio Risk Budget Objective

The portfolio risk objective allows the user to specify constraints to minimize component contribution (i.e. equal risk contribution) or specify upper and lower bounds on percentage risk contribution. Here we specify that no asset can contribute more than 30% to total portfolio risk.

See the risk budget optimization vignette for more detailed examples of portfolio optimizationswith risk budgets.

```
pspec <- add.objective(portfolio=pspec,
type="risk_budget",
name="var",
max_prisk=0.3)
pspec <- add.objective(portfolio=pspec,
type="risk_budget",
name="ETL",
arguments=list(p=0.95),
max_prisk=0.3,
enabled=FALSE)
# for an equal risk contribution portfolio, set min_concentration=TRUE
pspec <- add.objective(portfolio=pspec,
type="risk_budget",
name="ETL",
arguments=list(p=0.95),
min_concentration=TRUE,
enabled=FALSE)
print(pspec)
```

```
## **************************************************
## PortfolioAnalytics Portfolio Specification
## **************************************************
##
## Call:
## portfolio.spec(assets = stocks.selection$symbol, category_labels = stocks.selection$sector)
##
## Number of assets: 10
## Asset Names
## [1] "AAPL" "MSFT" "AMZN" "CSCO" "NVDA" "ORCL" "AMGN" "ADBE" "QCOM" "GILD"
##
## Category Labels
## Information Technology : AAPL MSFT CSCO NVDA ORCL ADBE QCOM
## Consumer Discretionary : AMZN
## Health Care : AMGN GILD
##
##
## Constraints
## Enabled constraint types
## - full_investment
## - box
## - group
## - position_limit
## - diversification
## - turnover
## - return
## - factor_exposure
## - transaction_cost
## - leverage_exposure
##
## Objectives:
## Enabled objective names
## - var
## - mean
## - var
## Disabled objective names
## - ETL
```

### 4.2.4 Solvers

Solvers are the workhorse of our portfolio optimization framework, and there are a variety of them available to us through the `portfolioAnalytics`

-package. I will briefly introduce the available solvers. Note that these solvers can be specified through `optimize_method`

in the `optimize.portfolio`

and `optimize.portfolio.rebalancing`

method.

#### 4.2.4.1 DEOptim

This solver comes from the R package `DEoptim`

and is a differential evolution algorithm (a global stochastic optimization algorithm) developed by (**???**). The help on `?DEoptim`

gives many more references. There is also a nice `vignette("DEoptimPortfolioOptimization")`

on large scale portfolio optimization using the `portfolioAnalytics`

-package.

#### 4.2.4.2 Random Portfolios

There are three methods to generate random portfolios contained in `portfolioAnalytics`

:^{8}

- The most flexible but also slowest method is ‘sample’. It can take leverage, box, group, and position limit constraints into account.
- The ‘simplex’ method is useful to generate random portfolios with the full investment and min box constraints (values for min_sum/ max_sum are ignored). Other constraints (box max, group and position limit constraints will be handled by elimination) which might leave only very few feasible portfolios. Sometimes it will also lead to suboptimal solutions.
- Using grid search, the ‘grid’ method only satisfies the min and max box constraints.

#### 4.2.4.3 pso

The `psoptim`

function from the R package `pso`

(Bendtsen. 2012) and uses particle swarm optimization.

#### 4.2.4.4 GenSA

The `GenSA`

function from the R package `GenSA`

(Gubian et al. 2018) and is based on generalized simmulated annealing (a generic probabilistic heuristic optimization algorithm)

#### 4.2.4.5 ROI

The `ROI`

(`R`

Optimization Infrastructure) is a framework to handle optimization problems in `R`

. It serves as an interface to the `Rglpk`

package and the `quadprog`

package which solve linear and quadratic programming problems. Available methods in the context of the `portfolioAnalytics`

-package are given below (see section @(#sss_4Objectives) for available objectives.

- Maxmimize portfolio return subject leverage, box, group, position limit, target mean return, and/or factor exposure constraints on weights.
- Globally minimize portfolio variance subject to leverage, box, group, turnover, and/or factor exposure constraints.
- Minimize portfolio variance subject to leverage, box, group, and/or factor exposure constraints given a desired portfolio return.
- Maximize quadratic utility subject to leverage, box, group, target mean return, turnover, and/or factor exposure constraints and risk aversion parameter. (The risk aversion parameter is passed into
`optimize.portfolio`

as an added argument to the portfolio object). - Minimize ETL subject to leverage, box, group, position limit, target mean return, and/or factor exposure constraints and target portfolio return.

#### 4.2.4.6 Multicore capabilities

For large sets of assets and solvers that can parallelize, the `doParallel`

-package provides multicore capabilities to the `portfolioAnalytics`

package.

```
# require(doParallel)
# registerDoParallel()
```

## 4.3 Optimization examples

Modern portfolio theory suggests how rational investors should optimize their portfolio(s) of risky assets to take advantage of diversification effects. This is possible, because risk as opposed to return is not additive and depends very much on the pairwise comovement (correlation) between the risky assets. The concepts of modern portfolio theory go back to Markowitz (1952) considers asset returns as random variables and estimates their risk and return plainly as mean and standard deviation within the available data sample. Usually we do not introduce any constraints except the full investment constraint that constrains the portfolio weights \(w\) to sum to \(1\), but allow for unlimited shortselling. The two basic portfolio problems are either to minimize the portfolio risk \(w'\Sigma w\) given a target return \(\bar{r}\) (4.1) or maximize the portfolio return \(w'\mu\) given a target level of risk \(\bar{\sigma}\) (4.2): \[\begin{align} & \underset{w}{\text{min}} & & w'\hat{\Sigma}w \\ & \text{subject to} & & w'\hat{\mu}=\bar{r}, \\ &&& w'\mathbf{1}=1. \tag{4.1} \end{align}\] and \[\begin{align} & \underset{w}{\text{max}} & & w'\hat{\mu}\\ & \text{subject to} & & w'\hat{\Sigma}w=\bar{\sigma}, \\ &&& w'\mathbf{1}=1. \tag{4.2} \end{align}\]The solutions to these two problems is a hyperbola that depicts the efficient frontier in the \(\mu\)-\(\sigma\)-diagram. We can plot the efficient frontier using `create.EfficientFrontier`

^{9} if we specify a return (mean) and a risk (sd) objective:^{10}

```
pspec <- portfolio.spec(assets = stocks.selection$symbol,
category_labels = stocks.selection$sector)
pspec <- add.constraint(portfolio=pspec,
type="full_investment") # weights sum to 1
p <- add.constraint(portfolio=p,
type="box",
min = -0.5,
max = +0.5)
# to create the efficient frontier
pspec <- add.objective(portfolio=pspec,
type="return",
name="mean") # mean
pspec <- add.objective(portfolio=pspec,
type="risk",
name="var") # uses sd
meansd.ef <- create.EfficientFrontier(
R = returns,
portfolio = pspec,
type = "mean-sd",
n.portfolios = 25,
)
# summary(meansd.ef, digits=2) # to print the whole efficient frontier
# meansd.ef$frontier[1:2,] # shows the first two portfolios
chart.EfficientFrontier(meansd.ef,
match.col="StdDev", # which column to use for risk
type="l",
RAR.text="Sharpe Ratio",
tangent.line = FALSE,
chart.assets=TRUE,
labels.assets=TRUE,xlim=c(0.03,0.20),ylim=c(0,0.055))
```