Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
braverock
GitHub Repository: braverock/portfolioanalytics
Path: blob/master/vignettes/ROI_vignette.Rnw
1433 views
1
\documentclass[12pt,letterpaper,english]{article}
2
\usepackage[OT1]{fontenc}
3
\usepackage{Sweave}
4
\usepackage{verbatim}
5
\usepackage{Rd}
6
\usepackage{amsmath}
7
8
\begin{document}
9
\SweaveOpts{concordance=TRUE}
10
11
% \VignetteIndexEntry{Portfolio Optimization with ROI in PortfolioAnalytics}
12
13
\title{Portfolio Optimization with ROI in PortfolioAnalytics}
14
\author{Ross Bennett}
15
16
\date{May 17, 2018}
17
\maketitle
18
19
\begin{abstract}
20
The purpose of this vignette is to demonstrate a sample of the optimzation problems that can be solved in PortfolioAnalytics with the ROI solvers. See \code{demo(demo\_ROI)} for a more complete set of examples.
21
\end{abstract}
22
23
\tableofcontents
24
25
\section{Getting Started}
26
\subsection{Load Packages}
27
Load the necessary packages.
28
<<>>=
29
suppressMessages(library(PortfolioAnalytics))
30
suppressMessages(library(foreach))
31
suppressMessages(library(iterators))
32
suppressMessages(library(ROI))
33
suppressMessages(library(ROI.plugin.quadprog))
34
suppressMessages(library(ROI.plugin.glpk))
35
@
36
37
\subsection{Data}
38
The edhec data set from the PerformanceAnalytics package will be used as example data.
39
<<>>=
40
data(edhec)
41
42
# Use the first 4 columns in edhec for a returns object
43
returns <- edhec[, 1:4]
44
colnames(returns) <- c("CA", "CTAG", "DS", "EM")
45
print(head(returns, 5))
46
47
# Get a character vector of the fund names
48
funds <- colnames(returns)
49
@
50
51
52
\section{Maximizing Mean Return}
53
The objective to maximize mean return is a linear problem of the form:
54
\begin{equation*}
55
\begin{aligned}
56
& \underset{\boldsymbol{w}}{\text{maximize}}
57
& & \hat{\boldsymbol{\mu}}' \boldsymbol{w} \\
58
\end{aligned}
59
\end{equation*}
60
61
Where $\hat{\boldsymbol{\mu}}$ is the estimated mean asset returns and $\boldsymbol{w}$ is the set of weights. Because this is a linear problem, it is well suited to be solved using a linear programming solver. For these types of problems, PortfolioAnalytics uses the ROI package with the glpk plugin.
62
63
\subsection{Portfolio Object}
64
65
The first step is to create the portfolio object. Then add constraints and a return objective.
66
<<tidy=FALSE>>=
67
# Create portfolio object
68
portf_maxret <- portfolio.spec(assets=funds)
69
70
# Add constraints to the portfolio object
71
portf_maxret <- add.constraint(portfolio=portf_maxret, type="full_investment")
72
portf_maxret <- add.constraint(portfolio=portf_maxret, type="box",
73
min=c(0.02, 0.05, 0.03, 0.02),
74
max=c(0.55, 0.6, 0.65, 0.5))
75
76
# Add objective to the portfolio object
77
portf_maxret <- add.objective(portfolio=portf_maxret, type="return", name="mean")
78
@
79
80
The print method for the portfolio object shows a high level overview while the summary method shows much more detail of the assets, constraints, and objectives that are specified in the portfolio object.
81
<<>>=
82
print(portf_maxret)
83
summary(portf_maxret)
84
@
85
86
\subsection{Optimization}
87
The next step is to run the optimization. Note that \code{optimize\_method="ROI"} is specified in the call to \code{optimize.portfolio} to select the solver used for the optimization.
88
<<tidy=FALSE>>=
89
# Run the optimization
90
opt_maxret <- optimize.portfolio(R=returns, portfolio=portf_maxret,
91
optimize_method="ROI", trace=TRUE)
92
@
93
94
The print method for the \code{opt\_maxret} object shows the call, optimal weights, and the objective measure
95
<<>>=
96
print(opt_maxret)
97
@
98
99
The sumary method for the \code{opt\_maxret} object shows details of the object with constraints, objectives, and other portfolio statistics.
100
<<>>=
101
summary(opt_maxret)
102
@
103
104
105
The \code{opt\_maxret} object is of class \code{optimize.portfolio.ROI} and contains the following elements. Objects of class \code{optimize.portfolio.ROI} are S3 objects and elements can be accessed with the \code{\$} operator.
106
<<>>=
107
names(opt_maxret)
108
@
109
110
The optimal weights and value of the objective function at the optimum can be accessed with the \code{extractStats} function.
111
<<>>=
112
extractStats(opt_maxret)
113
@
114
115
The optimal weights can be accessed with the \code{extractWeights} function.
116
<<>>=
117
extractWeights(opt_maxret)
118
@
119
120
\subsection{Visualization}
121
The \code{plot} method charts of the optimal weights with the box constraints along with the optimal portfolio in risk-return space. The blue dots are the optimal weights and the gray triangles are the \code{min} and \code{max} of the box constraints.
122
<<>>=
123
plot(opt_maxret, chart.assets=TRUE, xlim=c(0.02, 0.18))
124
@
125
126
The optimal portfolio can be plotted in risk-return space along with other feasible portfolios. The return metric is defined in the \code{return.col} argument and the risk metric is defined in the \code{risk.col} argument. The scatter chart includes the optimal portfolio (blue dot) and other feasible portfolios (gray circles) to show the overall feasible space given the constraints. By default, if \code{rp} is not passed in, the feasible portfolios are generated with \code{random\_portfolios} to satisfy the constraints of the portfolio object.
127
128
Volatility as the risk metric
129
<<tidy=FALSE, fig.align='center',fig.height=5, fig.width=5>>=
130
chart.RiskReward(opt_maxret,return.col="mean", risk.col="sd",
131
chart.assets=TRUE, xlim=c(0.01, 0.05), main="Maximum Return")
132
@
133
134
\subsection{Backtesting}
135
An out of sample backtest is run with \code{optimize.portfolio.rebalancing}. In this example, an initial training period of 36 months is used and the portfolio is rebalanced quarterly.
136
<<tidy=FALSE>>=
137
bt_maxret <- optimize.portfolio.rebalancing(R=returns, portfolio=portf_maxret,
138
optimize_method="ROI",
139
rebalance_on="quarters",
140
training_period=36)
141
@
142
143
The \code{bt\_maxret} object is a list containing the optimal weights and objective measure at each rebalance period.
144
145
\section{Minimizing Portfolio Variance}
146
The objective to minimize portfolio variance is a quadratic problem of the form:
147
\begin{equation*}
148
\begin{aligned}
149
& \underset{\boldsymbol{w}}{\text{minimize}}
150
& & \boldsymbol{w}' \boldsymbol{\Sigma} \boldsymbol{w} \\
151
\end{aligned}
152
\end{equation*}
153
154
Where $\boldsymbol{\Sigma}$ is the estimated covariance matrix of asset returns and $\boldsymbol{w}$ is the set of weights. Because this is a quadratic problem, it is well suited to be solved using a quadratic programming solver. For these types of problems, PortfolioAnalytics uses the ROI package with the quadprog plugin.
155
156
\subsection{Global Minimum Variance Portfolio}
157
\subsubsection{Portfolio Object}
158
<<>>=
159
# Create portfolio object
160
portf_minvar <- portfolio.spec(assets=funds)
161
162
# Add full investment constraint to the portfolio object
163
portf_minvar <- add.constraint(portfolio=portf_minvar, type="full_investment")
164
165
# Add objective to minimize variance
166
portf_minvar <- add.objective(portfolio=portf_minvar, type="risk", name="var")
167
@
168
169
The only constraint specified is the full investment constraint, therefore the optimization problem is solving for the global minimum variance portfolio.
170
171
\subsubsection{Optimization}
172
<<tidy=FALSE>>=
173
# Run the optimization
174
opt_gmv <- optimize.portfolio(R=returns, portfolio=portf_minvar,
175
optimize_method="ROI", trace=TRUE)
176
print(opt_gmv)
177
@
178
179
\subsubsection{Backtesting}
180
<<tidy=FALSE>>=
181
bt_gmv <- optimize.portfolio.rebalancing(R=returns, portfolio=portf_minvar,
182
optimize_method="ROI",
183
rebalance_on="quarters",
184
training_period=36)
185
@
186
187
188
\subsection{Constrained Minimum Variance Portfolio}
189
190
\subsubsection{Portfolio Object}
191
Constraints can be added to the \code{portf\_minvar} portfolio object previously created.
192
<<tidy=FALSE>>=
193
# Add long only constraints
194
portf_minvar <- add.constraint(portfolio=portf_minvar, type="box",
195
min=0, max=1)
196
197
# Add group constraints
198
portf_minvar <- add.constraint(portfolio=portf_minvar,
199
type="group",
200
groups=list(groupA=1,
201
groupB=c(2, 3),
202
groupC=4),
203
group_min=c(0, 0.25, 0.10),
204
group_max=c(0.45, 0.6, 0.5))
205
@
206
207
\subsubsection{Optimization}
208
<<tidy=FALSE>>=
209
# Run the optimization
210
opt_minvar <- optimize.portfolio(R=returns, portfolio=portf_minvar,
211
optimize_method="ROI", trace=TRUE)
212
print(opt_minvar)
213
@
214
215
\subsubsection{Backtesting}
216
<<tidy=FALSE>>=
217
bt_minvar <- optimize.portfolio.rebalancing(R=returns, portfolio=portf_minvar,
218
optimize_method="ROI",
219
rebalance_on="quarters",
220
training_period=36)
221
@
222
223
\section{Maximizing Quadratic Utility}
224
The objective to maximize quadratic utility is a quadratic problem of the form:
225
\begin{equation*}
226
\begin{aligned}
227
& \underset{\boldsymbol{w}}{\text{maximize}}
228
& & \boldsymbol{w}' \boldsymbol{\mu} - \frac{\lambda}{2}\boldsymbol{w}' \boldsymbol{\Sigma} \boldsymbol{w} \\
229
\end{aligned}
230
\end{equation*}
231
232
Where $\mu$ is the estimated mean asset returns, $\lambda$ is the risk aversion parameter, $\boldsymbol{\Sigma}$ is the estimated covariance matrix of asset returns and $\boldsymbol{w}$ is the set of weights. Quadratic utility maximizes return while penalizing variance. The $\lambda$ risk aversion parameter controls how much portfolio variance is penalized. Because this is a quadratic problem, it is well suited to be solved using a quadratic programming solver. For these types of problems, PortfolioAnalytics uses the ROI package with the quadprog plugin.
233
234
\subsection{Portfolio Object}
235
The portfolio object is specified, and constraints and objectives are created separately. The constraints and objectives are created separately as an alternative example and could also have been added directly to the portfolio object as in the previous sections.
236
<<>>=
237
# Create initial portfolio object
238
init_portf <- portfolio.spec(assets=funds)
239
240
# Create full investment constraint
241
fi_constr <- weight_sum_constraint(type="full_investment")
242
243
# Create long only constraint
244
lo_constr <- box_constraint(type="long_only", assets=init_portf$assets)
245
246
# Combine the constraints in a list
247
qu_constr <- list(fi_constr, lo_constr)
248
249
# Create return objective
250
ret_obj <- return_objective(name="mean")
251
252
# Create variance objective specifying a risk_aversion parameter which controls
253
# how much the variance is penalized
254
var_obj <- portfolio_risk_objective(name="var", risk_aversion=0.25)
255
256
# Combine the objectives into a list
257
qu_obj <- list(ret_obj, var_obj)
258
@
259
260
\subsection{Optimization}
261
Note how the constraints and objectives are passed to optimize.portfolio.
262
<<tidy=FALSE>>=
263
# Run the optimization
264
opt_qu <- optimize.portfolio(R=returns, portfolio=init_portf,
265
constraints=qu_constr,
266
objectives=qu_obj,
267
optimize_method="ROI",
268
trace=TRUE)
269
@
270
271
\subsection{Backtesting}
272
<<tidy=FALSE>>=
273
bt_qu <- optimize.portfolio.rebalancing(R=returns, portfolio=init_portf,
274
constraints=qu_constr,
275
objectives=qu_obj,
276
optimize_method="ROI",
277
rebalance_on="quarters",
278
training_period=36)
279
@
280
281
\section{Minimizing Expected Tail Loss}
282
TODO
283
284
\end{document}
285