Portfolio Optimization with PortfolioAnalytics
Portfolio Optimization with PortfolioAnalytics
PortfolioAnalytics
Ross Bennett
Abstract
1 Getting Started 2
1.1 Load Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2 Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
4 Adding Objectives 15
4.1 Portfolio Risk Objective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.2 Portfolio Return Objective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.3 Portfolio Risk Budget Objective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1
4.4 Portfolio Weight Concentration Objective . . . . . . . . . . . . . . . . . . . . . . . 17
5 Solvers 29
5.1 DEoptim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
5.2 Random Portfolios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
5.3 pso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
5.4 GenSA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
5.5 ROI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
6 Optimization 33
6.1 Initial Portfolio Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
6.2 Maximize mean return with ROI . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
6.3 Minimize variance with ROI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
6.4 Maximize quadratic utility with ROI . . . . . . . . . . . . . . . . . . . . . . . . . . 35
6.5 Minimize expected tail loss with ROI . . . . . . . . . . . . . . . . . . . . . . . . . . 36
6.6 Maximize mean return per unit ETL with random portfolios . . . . . . . . . . . . 37
6.7 Maximize mean return per unit ETL with ETL risk budgets . . . . . . . . . . . . . 39
6.8 Maximize mean return per unit ETL with ETL equal contribution to risk . . . . . 41
1 Getting Started
> library(PortfolioAnalytics)
1.2 Data
The edhec data set from the PerformanceAnalytics package will be used as example data.
> data(edhec)
> # Use the first 4 columns in edhec for a returns object
> returns <- edhec[, 1:4]
> colnames(returns) <- c("CA", "CTAG", "DS", "EM")
> print(head(returns, 5))
CA CTAG DS EM
1997-01-31 0.0119 0.0393 0.0178 0.0791
2
1997-02-28 0.0123 0.0298 0.0122 0.0525
1997-03-31 0.0078 -0.0021 -0.0012 -0.0120
1997-04-30 0.0086 -0.0170 0.0030 0.0119
1997-05-31 0.0156 -0.0015 0.0233 0.0315
$name
[1] "portfolio"
$assets
CA CTAG DS EM
0.25 0.25 0.25 0.25
$category_labels
NULL
$weight_seq
NULL
3
$constraints
list()
$objectives
list()
$call
[Link](assets = [Link])
attr(,"class")
[1] "[Link]" "portfolio"
The weight_sum constraint specifies the constraint on the sum of the weights. Aliases for the
weight_sum constraint type include weight and leverage. Here we add a constraint that the
weights must sum to 1, or the full investment constraint.
> # Add the full investment constraint that specifies the weights must sum to 1.
> pspec <- [Link](portfolio=pspec,
+ type="weight_sum",
+ min_sum=1,
+ max_sum=1)
1. The sum of the weights equal 1, i.e. the full investment constraint. The full investment con-
straint can be specified with type="full_investment". This automatically sets min_sum=1
and max_sum=1.
4
2. The sum of the weights equal 0, i.e. the dollar neutral or active constraint. This constraint
can be specified with type="dollar_neutral" or type="active".
> # The full investment constraint can also be specified with type="full_investment"
> # pspec <- [Link](portfolio=pspec, type="full_investment")
>
> # Another common constraint is that portfolio weights sum to 0.
> # This can be specified any of the following ways
> # pspec <- [Link](portfolio=pspec, type="weight_sum",
> # min_sum=0,
> # max_sum=0)
> # pspec <- [Link](portfolio=pspec, type="dollar_neutral")
> # pspec <- [Link](portfolio=pspec, type="active")
Box constraints allows the user to specify upper and lower bounds on the weights of the assets.
Here we add box constraints for the asset weights so that the minimum weight of any asset must
be greater than or equal to 0.05 and the maximum weight of any asset must be less than or equal
to 0.4. The values for min and max can be passed in as scalars or vectors. If min and max are
scalars, the values for min and max will be replicated as vectors to the length of assets. If min and
max are not specified, a minimum weight of 0 and maximum weight of 1 are assumed. Note that
min and max can be specified as vectors with different weights for linear inequality constraints.
5
> # The default action is long only if min and max are not specified
> # pspec <- [Link](portfolio=pspec, type="box")
> # pspec <- [Link](portfolio=pspec, type="long_only")
Group constraints allow the user to specify the the sum of weights by group. Group constraints
are currently supported by the ROI, DEoptim, and random portfolio solvers. The following code
groups the assets such that the first 3 assets are grouped together labeled GroupA and the fourth
asset is in its own group labeled GroupB. The group_min argument specifies that the sum of the
weights in GroupA must be greater than or equal to 0.1 and the sum of the weights in GroupB
must be greater than or equal to 0.15. The group_max argument specifies that the sum of the
weights in GroupA must be less than or equal to 0.85 and the sum of the weights in GroupB must
be less than or equal to [Link] group_labels argument is optional and is useful if groups is not
a named list for labeling groups in terms of market capitalization, sector, etc.
The position limit constraint allows the user to specify limits on the number of assets with non-
zero, long, or short positions. The ROI solver interfaces to the Rglpk package (i.e. using the glpk
plugin) for solving maximizing return and ETL/ES/cVaR objectives. The Rglpk package supports
integer programming and thus supports position limit constraints for the max_pos argument. The
quadprog package does not support integer programming, and therefore max_pos is not supported
for the ROI solver using the quadprog plugin. Note that max_pos_long and max_pos_short are
not supported for either ROI solver. All position limit constraints are fully supported for DEoptim
and random solvers.
> # Add position limit constraint such that we have a maximum number of three assets with non-zero
> pspec <- [Link](portfolio=pspec, type="position_limit", max_pos=3)
>
6
> # Can also specify maximum number of long positions and short positions
> # pspec <- [Link](portfolio=pspec, type="position_limit", max_pos_long=3, max_pos_short=
The diversification constraint allows the user to target diversification. Diversification is defined
PN
as diversif ication = i=1 wi2 for N assets. The diversification constraint is implemented for the
global optimizers by applying a penalty if the diversification value is more than 5% away from
div_target. Note that diversification as a constraint is not supported for the ROI solvers, it is
only supported for the global numeric solvers.
A target turnover can be specified as a constraint. The turnover is calculated from a set of initial
weights. The initial weights can be specified, by default they are the initial weights in the portfolio
object. The turnover constraint is implemented for the global optimizers by applying a penalty
if the turnover value is more than 5% away from turnover_target. Note that the turnover
constraint is not currently supported for quadratic utility and minimum variance problems using
the ROI solver.
The target return constraint allows the user to specify a target mean return.
The factor exposure constraint allows the user to set upper and lower bounds on exposures to risk
factors. The exposures can be passed in as a vector or matrix. Here we specify a vector for B with
arbitrary values, e.g. betas of the assets, with a market risk exposure range of 0.6 to 0.9.
7
3.9 Transaction Cost Constraint
The transaction cost constraint allows the user to specify proportional transaction costs. Propor-
tional transaction cost constraints can be implemented for quadratic utility and minimum variance
problems using the ROI solver. Transaction costs are supported as a penalty for the global numeric
solvers. Here we add the transaction cost contraint with the proportional transaction cost value
of 1%.
The print method for the portfolio object shows a concise view of the portfolio and the con-
straints that have been added.
> print(pspec)
**************************************************
PortfolioAnalytics Portfolio Specification
**************************************************
Call:
[Link](assets = [Link])
Number of assets: 4
Asset Names
[1] "CA" "CTAG" "DS" "EM"
Constraints
Enabled constraint types
- weight_sum
- box
- group
- position_limit
- diversification
- turnover
- return
- factor_exposure
- transaction_cost
8
> summary(pspec)
$assets
CA CTAG DS EM
0.25 0.25 0.25 0.25
$enabled_constraints
$enabled_constraints[[1]]
$type
[1] "weight_sum"
$enabled
[1] TRUE
$message
[1] FALSE
$min_sum
[1] 1
$max_sum
[1] 1
$call
[Link](portfolio = pspec, type = "weight_sum", min_sum = 1,
max_sum = 1)
attr(,"class")
[1] "weight_sum_constraint" "constraint"
$enabled_constraints[[2]]
$type
[1] "box"
$enabled
9
[1] TRUE
$min
CA CTAG DS EM
0.05 0.05 0.05 0.05
$max
CA CTAG DS EM
0.4 0.4 0.4 0.4
$call
[Link](portfolio = pspec, type = "box", min = 0.05, max = 0.4)
attr(,"class")
[1] "box_constraint" "constraint"
$enabled_constraints[[3]]
$type
[1] "group"
$enabled
[1] TRUE
$groups
$groups$groupA
[1] 1 2 3
$groups$grouB
[1] 4
$group_labels
[1] "groupA" "grouB"
$cLO
10
[1] 0.10 0.15
$cUP
[1] 0.85 0.55
$call
[Link](portfolio = pspec, type = "group", groups = list(groupA = c(1,
2, 3), grouB = 4), group_min = c(0.1, 0.15), group_max = c(0.85,
0.55))
attr(,"class")
[1] "group_constraint" "constraint"
$enabled_constraints[[4]]
$type
[1] "position_limit"
$enabled
[1] TRUE
$assets
CA CTAG DS EM
0.25 0.25 0.25 0.25
$max_pos
[1] 3
$call
[Link](portfolio = pspec, type = "position_limit", max_pos = 3)
attr(,"class")
[1] "position_limit_constraint" "constraint"
$enabled_constraints[[5]]
$type
11
[1] "diversification"
$enabled
[1] TRUE
$div_target
[1] 0.7
$call
[Link](portfolio = pspec, type = "diversification", div_target = 0.7)
attr(,"class")
[1] "diversification_constraint" "constraint"
$enabled_constraints[[6]]
$type
[1] "turnover"
$enabled
[1] TRUE
$turnover_target
[1] 0.2
$call
[Link](portfolio = pspec, type = "turnover", turnover_target = 0.2)
attr(,"class")
[1] "turnover_constraint" "constraint"
$enabled_constraints[[7]]
$type
[1] "return"
$enabled
12
[1] TRUE
$return_target
[1] 0.007
$call
[Link](portfolio = pspec, type = "return", return_target = 0.007)
attr(,"class")
[1] "return_constraint" "constraint"
$enabled_constraints[[8]]
$type
[1] "factor_exposure"
$enabled
[1] TRUE
$B
factor1
CA -0.08
CTAG 0.37
DS 0.79
EM 1.43
$lower
[1] 0.6
$upper
[1] 0.9
$call
[Link](portfolio = pspec, type = "factor_exposure", B = c(-0.08,
0.37, 0.79, 1.43), lower = 0.6, upper = 0.9)
13
attr(,"class")
[1] "factor_exposure_constraint" "constraint"
$enabled_constraints[[9]]
$type
[1] "transaction_cost"
$enabled
[1] TRUE
$ptc
[1] 0.01 0.01 0.01 0.01
$call
[Link](portfolio = pspec, type = "transaction_cost",
ptc = 0.01)
attr(,"class")
[1] "transaction_cost_constraint" "constraint"
$disabled_constraints
list()
$enabled_objectives
list()
$disabled_objectives
list()
attr(,"class")
[1] "[Link]"
14
3.10 Specifying Constraints as Separate Objects
The following examples will demonstrate how to specify constraints as separate objects for all
constraints types.
4 Adding Objectives
Objectives can be added to the portfolio object with [Link]. The [Link] func-
tion is the main function for adding and/or updating business objectives to the portfolio object.
This function allows the user to specify the portfolio to add the objectives to, the type (cur-
15
rently ’return’, ’risk’, ’risk_budget’, or ’weight_concentration’), name of the objective function,
arguments to the objective function, and whether or not to enable the objective. If updating an
existing constraint, the indexnum argument can be specified.
The portfolio risk objective allows the user to specify a risk function to minimize Here we add
a risk objective to minimize portfolio expected tail loss with a confidence level of 0.95. Other
default arguments to the function can be passed in as a named list to arguments. Note that the
name of the function must correspond to a function in R. Many functions are available in the
PerformanceAnalytics package or a user defined function.
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.
The portfolio risk objective allows the user to specify constraints to minimize component con-
tribution (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 optimizations
with risk budgets.
16
> # pspec <- [Link](portfolio=pspec, type="risk_budget", name="ETL",
> # arguments=list(p=0.95), min_concentration=TRUE)
The weight concentration objective allows the user to specify an objective to minimize concentra-
tion as measured by the Herfindahl-Hirschman Index. For otpimization problems solved with the
global numeric optimizers, the portfolio HHI value is penalized using conc_aversion value as the
multiplier.
For quadratic utility problems with weight concentration as an objective using the ROI solver,
this is implemented as a penalty to the objective function. The objective function is implemented
as follows:
λ ′
maximizew′ µ − (w Σw + λhhi ∗ HHI) (1)
w 2
(2)
Where µ is the estimated mean asset returns, λ is the risk aversion parameter, lambdahhi is the
concentration aversion parameter, HHI is the portfolio HHI, Σ is the estimated covariance matrix
of asset returns and w is the set of weights.
Here we add a weight concentration objective for the overall portfolio HHI.
The weight concentration aversion parameter by groups can also be specified. Here we add a
weight concentration objective specifying groups and concentration aversion parameters by group.
The print method for the portfolio object will now show all the constraints and objectives that
have been added.
> print(pspec)
17
**************************************************
PortfolioAnalytics Portfolio Specification
**************************************************
Call:
[Link](assets = [Link])
Number of assets: 4
Asset Names
[1] "CA" "CTAG" "DS" "EM"
Constraints
Enabled constraint types
- weight_sum
- box
- group
- position_limit
- diversification
- turnover
- return
- factor_exposure
- transaction_cost
Objectives:
Enabled objective names
- ETL
- mean
- ETL
- HHI
- HHI
> summary(pspec)
$assets
CA CTAG DS EM
18
0.25 0.25 0.25 0.25
$enabled_constraints
$enabled_constraints[[1]]
$type
[1] "weight_sum"
$enabled
[1] TRUE
$message
[1] FALSE
$min_sum
[1] 1
$max_sum
[1] 1
$call
[Link](portfolio = pspec, type = "weight_sum", min_sum = 1,
max_sum = 1)
attr(,"class")
[1] "weight_sum_constraint" "constraint"
$enabled_constraints[[2]]
$type
[1] "box"
$enabled
[1] TRUE
$min
CA CTAG DS EM
19
0.05 0.05 0.05 0.05
$max
CA CTAG DS EM
0.4 0.4 0.4 0.4
$call
[Link](portfolio = pspec, type = "box", min = 0.05, max = 0.4)
attr(,"class")
[1] "box_constraint" "constraint"
$enabled_constraints[[3]]
$type
[1] "group"
$enabled
[1] TRUE
$groups
$groups$groupA
[1] 1 2 3
$groups$grouB
[1] 4
$group_labels
[1] "groupA" "grouB"
$cLO
[1] 0.10 0.15
$cUP
[1] 0.85 0.55
20
$call
[Link](portfolio = pspec, type = "group", groups = list(groupA = c(1,
2, 3), grouB = 4), group_min = c(0.1, 0.15), group_max = c(0.85,
0.55))
attr(,"class")
[1] "group_constraint" "constraint"
$enabled_constraints[[4]]
$type
[1] "position_limit"
$enabled
[1] TRUE
$assets
CA CTAG DS EM
0.25 0.25 0.25 0.25
$max_pos
[1] 3
$call
[Link](portfolio = pspec, type = "position_limit", max_pos = 3)
attr(,"class")
[1] "position_limit_constraint" "constraint"
$enabled_constraints[[5]]
$type
[1] "diversification"
$enabled
[1] TRUE
21
$div_target
[1] 0.7
$call
[Link](portfolio = pspec, type = "diversification", div_target = 0.7)
attr(,"class")
[1] "diversification_constraint" "constraint"
$enabled_constraints[[6]]
$type
[1] "turnover"
$enabled
[1] TRUE
$turnover_target
[1] 0.2
$call
[Link](portfolio = pspec, type = "turnover", turnover_target = 0.2)
attr(,"class")
[1] "turnover_constraint" "constraint"
$enabled_constraints[[7]]
$type
[1] "return"
$enabled
[1] TRUE
$return_target
[1] 0.007
22
$call
[Link](portfolio = pspec, type = "return", return_target = 0.007)
attr(,"class")
[1] "return_constraint" "constraint"
$enabled_constraints[[8]]
$type
[1] "factor_exposure"
$enabled
[1] TRUE
$B
factor1
CA -0.08
CTAG 0.37
DS 0.79
EM 1.43
$lower
[1] 0.6
$upper
[1] 0.9
$call
[Link](portfolio = pspec, type = "factor_exposure", B = c(-0.08,
0.37, 0.79, 1.43), lower = 0.6, upper = 0.9)
attr(,"class")
[1] "factor_exposure_constraint" "constraint"
$enabled_constraints[[9]]
23
$type
[1] "transaction_cost"
$enabled
[1] TRUE
$ptc
[1] 0.01 0.01 0.01 0.01
$call
[Link](portfolio = pspec, type = "transaction_cost",
ptc = 0.01)
attr(,"class")
[1] "transaction_cost_constraint" "constraint"
$disabled_constraints
list()
$enabled_objectives
$enabled_objectives[[1]]
$name
[1] "ETL"
$target
NULL
$arguments
$arguments$p
[1] 0.95
$arguments$portfolio_method
[1] "single"
24
$enabled
[1] TRUE
$multiplier
[1] 1
$call
[Link](portfolio = pspec, type = "risk", name = "ETL",
arguments = list(p = 0.95))
attr(,"class")
[1] "portfolio_risk_objective" "objective"
$enabled_objectives[[2]]
$name
[1] "mean"
$target
NULL
$arguments
list()
$enabled
[1] TRUE
$multiplier
[1] -1
$call
[Link](portfolio = pspec, type = "return", name = "mean")
attr(,"class")
[1] "return_objective" "objective"
25
$enabled_objectives[[3]]
$name
[1] "ETL"
$target
NULL
$arguments
$arguments$p
[1] 0.95
$arguments$portfolio_method
[1] "component"
$enabled
[1] TRUE
$multiplier
[1] 1
$max_prisk
CA CTAG DS EM
0.3 0.3 0.3 0.3
$min_concentration
[1] FALSE
$min_difference
[1] FALSE
$call
[Link](portfolio = pspec, type = "risk_budget", name = "ETL",
arguments = list(p = 0.95), max_prisk = 0.3)
26
attr(,"class")
[1] "risk_budget_objective" "objective"
$enabled_objectives[[4]]
$name
[1] "HHI"
$target
NULL
$arguments
list()
$enabled
[1] TRUE
$multiplier
[1] 1
$conc_aversion
[1] 0.1
$call
[Link](portfolio = pspec, type = "weight_concentration",
name = "HHI", conc_aversion = 0.1)
attr(,"class")
[1] "weight_concentration_objective" "objective"
$enabled_objectives[[5]]
$name
[1] "HHI"
$target
27
NULL
$arguments
$arguments$groups
$arguments$groups[[1]]
[1] 1 2
$arguments$groups[[2]]
[1] 3 4
$enabled
[1] TRUE
$multiplier
[1] 1
$conc_aversion
[1] 0.03 0.06
$conc_groups
$conc_groups[[1]]
[1] 1 2
$conc_groups[[2]]
[1] 3 4
$call
[Link](portfolio = pspec, type = "weight_concentration",
name = "HHI", conc_aversion = c(0.03, 0.06), conc_groups = list(c(1,
2), c(3, 4)))
attr(,"class")
28
[1] "weight_concentration_objective" "objective"
$disabled_objectives
list()
attr(,"class")
[1] "[Link]"
5 Solvers
The PortfolioAnalytics package currently supports random portfolios, DEoptim, pso, GenSA, and
ROI as back ends. Note that some of the QP/LP problems are solved directly with Rglpk and quad-
prog. The solver can be specified with the optimize_method argument in [Link]
and [Link].
5.1 DEoptim
PortfolioAnalytics uses the DEoptim function from the R package DEoptim. Differential evolution
is a stochastic global optimization algorithm. See ?DEoptim and the references contained therein
for more information. See also Large scale portfolio optimization with DEoptim.
1. The ’sample’ method to generate random portfolios is based on an idea by Pat Burns. This is
the most flexible method, but also the slowest, and can generate portfolios to satisfy leverage,
box, group, and position limit constraints.
2. The ’simplex’ method to generate random portfolios is based on a paper by W. T. Shaw. The
simplex method is useful to generate random portfolios with the full investment constraint,
where the sum of the weights is equal to 1, and min box constraints. Values for min_sum
and max_sum of the leverage constraint will be ignored, the sum of weights will equal 1. All
other constraints such as the box constraint max, group and position limit constraints will
be handled by elimination. If the constraints are very restrictive, this may result in very
few feasible portfolios remaining. Another key point to note is that the solution may not
29
be along the vertexes depending on the objective. For example, a risk budget objective will
likely place the portfolio somewhere on the interior.
3. The ’grid’ method to generate random portfolios is based on the gridSearch function in
package NMOF. The grid search method only satisfies the min and max box constraints. The
min_sum and max_sum leverage constraint will likely be violated and the weights in the random
portfolios should be normalized. Normalization may cause the box constraints to be violated
and will be penalized in constrained_objective.
The following plots illustrate the various methods to generate random portfolios.
30
+ col=c("gray", "red", "lightgreen"),
+ pch=c(1, 2, 5), bty="n")
Figure 1 shows the feasible space using the different random portfolio methods. The ’sample’
method has relatively even coverage of the feasible space. The ’simplex’ method also has relatively
even coverage of the space, but it is also more concentrated around the assets. The ’grid’ method
is pushed to the interior of the space due to the normalization.
The fev argument controls the face-edge-vertex biasing. Higher values for fev will result in
the weights vector more concentrated on a single asset. This can be seen in the following charts.
31
> [Link] <- apply(rp_sample, 1, function(x) StdDev(R=R, weights=x))
> plot(x=[Link], y=[Link], main="rp_method=sample",
+ ylab="mean", xlab="StdDev", col=rgb(0, 0, 100, 50, maxColorValue=255))
> par(mfrow=c(1,1))
5.3 pso
PortfolioAnalytics uses the psoptim function from the R package pso. Particle swarm optimization
is a heuristic optimization algorithm. See ?psoptim and the references contained therein for more
information.
5.4 GenSA
PortfolioAnalytics uses the GenSA function from the R package GenSA. Generalized simmulated
annealing is generic probabilistic heuristic optimization algorithm. See ?GenSA and the references
contained therein for more information.
5.5 ROI
The ROI package serves as an interface to the Rglpk package and the quadprog package to solve
linear and quadratic programming problems. The interface to the ROI package solves a limited
type of convex optimization problems:
1. Maxmimize portfolio return subject leverage, box, group, position limit, target mean return,
and/or factor exposure constraints on weights.
2. Minimize portfolio variance subject to leverage, box, group, turnover, and/or factor exposure
constraints (otherwise known as global minimum variance portfolio).
3. Minimize portfolio variance subject to leverage, box, group, and/or factor exposure con-
straints and a desired portfolio return.
4. 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 [Link] as an added argument to the portfolio object).
5. Minimize ETL subject to leverage, box, group, position limit, target mean return, and/or
factor exposure constraints and target portfolio return.
32
6 Optimization
The previous sections demonstrated how to specify a portfolio object, add constraints, add objec-
tives, and the solvers available. This section will demonstrate run the optimizations via [Link].
Only a small number of examples will be shown here, see the demos for several more examples.
> library(DEoptim)
> library(ROI)
> require([Link])
> require([Link])
> data(edhec)
> R <- edhec[, 1:6]
> colnames(R) <- c("CA", "CTAG", "DS", "EM", "EQMN", "ED")
> funds <- colnames(R)
> # Create an initial portfolio object with leverage and box constraints
> init <- [Link](assets=funds)
> init <- [Link](portfolio=init, type="leverage",
+ min_sum=0.99, max_sum=1.01)
> init <- [Link](portfolio=init, type="box", min=0.05, max=0.65)
***********************************
PortfolioAnalytics Optimization
***********************************
33
Call:
[Link](R = R, portfolio = maxret, optimize_method = "ROI",
trace = TRUE)
Optimal Weights:
CA CTAG DS EM EQMN ED
0.05 0.05 0.65 0.16 0.05 0.05
Objective Measure:
mean
0.006315
Chart the weights and optimal portfolio in risk-return space. The weights and a risk-reward
scatter plot can be plotted separately as shown below with the [Link] and [Link]
functions. The plot function will plot the weights and risk-reward scatter together.
Run the optimization. Note that although ’var’ is the risk metric, ’StdDev’ is returned as an
objective measure.
***********************************
PortfolioAnalytics Optimization
***********************************
Call:
[Link](R = R, portfolio = minvar, optimize_method = "ROI",
34
trace = TRUE)
Optimal Weights:
CA CTAG DS EM EQMN ED
0.0623 0.1277 0.0500 0.0500 0.6500 0.0500
Objective Measure:
StdDev
0.009046
Add mean and var objectives for quadratic utility. Note that the risk aversion parameter for
quadratic utility is specifed in the objective as shown below.
***********************************
PortfolioAnalytics Optimization
***********************************
Call:
[Link](R = R, portfolio = qu, optimize_method = "ROI",
trace = TRUE)
35
Optimal Weights:
CA CTAG DS EM EQMN ED
0.05 0.05 0.65 0.05 0.05 0.16
Objective Measure:
mean
0.006312
StdDev
0.01569
***********************************
PortfolioAnalytics Optimization
***********************************
Call:
[Link](R = R, portfolio = etl, optimize_method = "ROI",
trace = TRUE)
Optimal Weights:
36
CA CTAG DS EM EQMN ED
0.0500 0.2065 0.0500 0.0500 0.5835 0.0500
Objective Measure:
ETL
0.01839
6.6 Maximize mean return per unit ETL with random portfolios
***********************************
PortfolioAnalytics Optimization
***********************************
Call:
[Link](R = R, portfolio = meanETL, optimize_method = "random",
search_size = 2000, trace = TRUE)
Optimal Weights:
CA CTAG DS EM EQMN ED
0.066 0.340 0.050 0.054 0.422 0.068
37
Objective Measures:
mean
0.004706
ETL
0.01895
The optimization was run with trace=TRUE so that iterations and other output from random
portfolios is stored in the opt_meanETL object. The extractStats function can be used to get a
matrix of the weights and objective measures at each iteration.
[1] 1999 9
> head(stats_meanETL)
Chart the optimal weights and optimal portfolio in risk-return space. Because the optimization
was run with trace=TRUE, the chart of the optimal portfolio also includes the trace portfolios of
the optimization. This is usefule to visualize the feasible space of the portfolios. The ’neighbor’
portfolios relative to the optimal portfolio weights can be included the chart of the optimal weights.
38
> plot(opt_meanETL, [Link]="ETL", [Link]="mean",
+ main="mean-ETL Optimization", neighbors=25)
This figure shows that the Equity Market Nuetral strategy has greater than 50% risk contri-
bution. A risk budget objective can be added to limit risk contribution percentage to 40%.
6.7 Maximize mean return per unit ETL with ETL risk budgets
Add objectives to maximize mean return per unit ETL with 40% limit ETL risk budgets.
Run the optimization. Set traceDE=5 so that every fifth iteration is printed. The default is to
print every iteration.
> print(opt_rb_meanETL)
39
***********************************
PortfolioAnalytics Optimization
***********************************
Call:
[Link](R = R, portfolio = rb_meanETL, optimize_method = "DEoptim",
search_size = 2000, trace = TRUE, traceDE = 5)
Optimal Weights:
CA CTAG DS EM EQMN ED
0.000 0.336 0.006 0.018 0.354 0.294
Objective Measures:
mean
0.004919
ETL
0.01924
contribution :
CA CTAG DS EM EQMN ED
0.0000000 0.0073114 0.0001202 0.0006403 0.0044178 0.0067474
pct_contrib_MES :
CA CTAG DS EM EQMN ED
0.000000 0.380071 0.006248 0.033284 0.229648 0.350750
> [Link]()
> [Link](opt_rb_meanETL, [Link]="percentage", neighbors=25)
40
6.8 Maximize mean return per unit ETL with ETL equal contribution
to risk
Add objective to maximize mean return per unit ETL with ETL equal contribution to risk.
Run the optimization. Set traceDE=5 so that every fifth iteration is printed. The default is to
print every iteration.
> print(opt_eq_meanETL)
***********************************
PortfolioAnalytics Optimization
***********************************
Call:
[Link](R = R, portfolio = eq_meanETL, optimize_method = "DEoptim",
search_size = 2000, trace = TRUE, traceDE = 5)
Optimal Weights:
CA CTAG DS EM EQMN ED
0.076 0.314 0.170 0.100 0.266 0.074
Objective Measures:
41
mean
0.005093
ETL
0.02217
contribution :
CA CTAG DS EM EQMN ED
0.003168 0.001422 0.005544 0.005979 0.003563 0.002497
pct_contrib_MES :
CA CTAG DS EM EQMN ED
0.14288 0.06411 0.25005 0.26964 0.16069 0.11263
> [Link]()
> plot(opt_eq_meanETL, [Link]="ETL", [Link]="mean",
+ main="Risk Budget mean-ETL Optimization",
+ xlim=c(0,0.12), ylim=c(0.005,0.009))
Chart the contribution to risk in percentage terms. It is clear in this chart that the optimization
results in a near equal risk contribution portfolio.
> [Link]()
> [Link](opt_eq_meanETL, [Link]="percentage", neighbors=25)
The opt_meanETL, opt_rb_meanETL, and opt_eq_meanETL optimizations are similar and can
be easily compared.
opt_meanETL Objective to maximize mean return per unit ETL. The constraints are full investment and
box constraints such that the minimum weight of any asset is 0.05 and maximum weight of
any asset is 0.65.
opt_rb_meanETL Objective to maximize mean return per unit ETL with risk budget objective to limit maxi-
mum percent risk 40%. The constraints are full investment and long only constraints.
opt_eq_meanETL Objective to maximize mean return per unit ETL with equal contribution to risk. The
constraints are full investment and long only constraints.
42
Combine the optimizations for easy comparison.
CA CTAG DS EM EQMN ED
meanETL 0.066 0.340 0.050 0.054 0.422 0.068
rbmeanETL 0.000 0.336 0.006 0.018 0.354 0.294
eqmeanETL 0.076 0.314 0.170 0.100 0.266 0.074
> [Link]()
> [Link](opt_combine, [Link]="ETL", [Link]="mean",
+ main="ETL Optimization Comparison", xlim=c(0.018, 0.024),
+ ylim=c(0.005, 0.008))
> [Link]()
> [Link](opt_combine, [Link]="ETL", [Link]="percent",
+ ylim=c(0,1), [Link]="topright")
43