Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
braverock
GitHub Repository: braverock/portfolioanalytics
Path: blob/master/demo/demo_efficient_frontier.R
1433 views
1
#' ---
2
#' title: "Efficient Frontier Demo"
3
#' date: "7/17/2014"
4
#' ---
5
6
#' This script demonstrates how to compute and plot the efficient frontier
7
#' given different constraints and objectives.
8
9
#' Efficient frontiers can be plotted two ways
10
#' 1. Run optimize.portfolio with trace=TRUE and then chart that object.
11
#' 2. create an efficient frontier and then chart that object.
12
13
#' Load required packages
14
library(PortfolioAnalytics)
15
library(DEoptim)
16
library(ROI)
17
require(ROI.plugin.quadprog)
18
require(ROI.plugin.glpk)
19
20
#' Load the data and change the column names for better legends in plotting.
21
data(edhec)
22
R <- edhec[, 1:5]
23
colnames(R) <- c("CA", "CTAG", "DS", "EM", "EQM")
24
funds <- colnames(R)
25
26
#' Set up the initial portfolio object with some basic constraints.
27
init <- portfolio.spec(assets=funds)
28
init <- add.constraint(portfolio=init, type="full_investment")
29
init <- add.constraint(portfolio=init, type="box", min=0.15, max=0.45)
30
init <- add.constraint(portfolio=init, type="group",
31
groups=list(c(1, 3),
32
c(2, 4, 5)),
33
group_min=0.05,
34
group_max=0.7)
35
36
#' Add objectives for mean-ES (Expected Shortfall) portfolio.
37
meanetl.portf <- add.objective(portfolio=init, type="risk", name="ES")
38
meanetl.portf <- add.objective(portfolio=meanetl.portf, type="return", name="mean")
39
40
#' Add objectives for mean-variance portfolio.
41
meanvar.portf <- add.objective(portfolio=init, type="risk", name="var", risk_aversion=10)
42
meanvar.portf <- add.objective(portfolio=meanvar.portf, type="return", name="mean")
43
44
#' Compute the mean-variance efficient frontier.
45
meanvar.ef <- create.EfficientFrontier(R=R, portfolio=init, type="mean-StdDev")
46
meanvar.ef
47
summary(meanvar.ef, digits=2)
48
meanvar.ef$frontier
49
50
#' The RAR.text argument can be used for the risk-adjusted-return name on the
51
#' legend, by default it is 'Modified Sharpe Ratio'.
52
chart.EfficientFrontier(meanvar.ef, match.col="StdDev", type="l",
53
RAR.text="Sharpe Ratio", pch=4)
54
55
#' The tangency portfolio and line are plotted by default, these can be
56
#' ommitted by setting rf=NULL.
57
chart.EfficientFrontier(meanvar.ef, match.col="StdDev", type="b", rf=NULL)
58
59
#' The tangency line can be omitted with tangent.line=FALSE. The tangent
60
#' portfolio, risk-free rate and Sharpe Ratio are still included in the plot.
61
chart.EfficientFrontier(meanvar.ef, match.col="StdDev", type="l", tangent.line=FALSE)
62
63
#' The assets can be omitted with chart.assets=FALSE.
64
chart.EfficientFrontier(meanvar.ef, match.col="StdDev", type="l",
65
tangent.line=FALSE, chart.assets=FALSE)
66
67
#' Just the names of the assets can be omitted with labels.assets=FALSE and the
68
#' plotting character can be changed with pch.assets.
69
chart.EfficientFrontier(meanvar.ef, match.col="StdDev", type="l",
70
tangent.line=FALSE, labels.assets=FALSE, pch.assets=1)
71
72
#' Chart the asset weights along the efficient frontier.
73
chart.EF.Weights(meanvar.ef, colorset=bluemono, match.col="StdDev")
74
75
#' Chart the group weights along the efficient frontier.
76
chart.EF.Weights(meanvar.ef, colorset=bluemono, by.groups=TRUE, match.col="StdDev")
77
78
#' The labels for Mean, Weight, and StdDev can be increased or decreased with
79
#' the cex.lab argument. The default is cex.lab=0.8.
80
chart.EF.Weights(meanvar.ef, colorset=bluemono, match.col="StdDev", main="", cex.lab=1)
81
82
#' If you have a lot of assets and they don't fit with the default legend, you
83
#' can set legend.loc=NULL and customize the plot.
84
par(mar=c(8, 4, 4, 2)+0.1, xpd=TRUE)
85
chart.EF.Weights(meanvar.ef, colorset=bluemono, match.col="StdDev", legend.loc=NULL)
86
legend("bottom", legend=colnames(R), inset=-1, fill=bluemono, bty="n", ncol=3, cex=0.8)
87
par(mar=c(5, 4, 4, 2)+0.1, xpd=FALSE)
88
89
#' Run optimize.portfolio and chart the efficient frontier of the optimal
90
#' portfolio object.
91
opt_meanvar <- optimize.portfolio(R=R, portfolio=meanvar.portf,
92
optimize_method="ROI", trace=TRUE)
93
94
#' The efficient frontier is created from the 'opt_meanvar' object by getting.
95
#' The portfolio and returns objects and then passing those to create.EfficientFrontier.
96
chart.EfficientFrontier(opt_meanvar, match.col="StdDev", n.portfolios=25, type="l")
97
98
#' Rerun the optimization with a new risk aversion parameter to change where
99
#' the portfolio is along the efficient frontier. The 'optimal' portfolio
100
#' plotted on the efficient frontier is the optimal portfolio returned by
101
#' optimize.portfolio.
102
meanvar.portf$objectives[[2]]$risk_aversion=0.25
103
opt_meanvar <- optimize.portfolio(R=R, portfolio=meanvar.portf, optimize_method="ROI", trace=TRUE)
104
chart.EfficientFrontier(opt_meanvar, match.col="StdDev", n.portfolios=25, type="l")
105
106
#' The weights along the efficient frontier can be plotted by passing in the
107
#' optimize.portfolio output object.
108
chart.EF.Weights(opt_meanvar, match.col="StdDev")
109
110
chart.EF.Weights(opt_meanvar, match.col="StdDev", by.groups=TRUE)
111
112
#' Extract the efficient frontier and then plot it.
113
#' Note that if you want to do multiple charts of the efficient frontier from
114
#' the optimize.portfolio object, it is best to extractEfficientFrontier as
115
#' shown below.
116
ef <- extractEfficientFrontier(object=opt_meanvar, match.col="StdDev", n.portfolios=15)
117
ef
118
summary(ef, digits=5)
119
chart.EF.Weights(ef, match.col="StdDev", colorset=bluemono)
120
chart.EF.Weights(ef, match.col="StdDev", colorset=bluemono, by.groups=TRUE)
121
122
#' Compute the mean-ES efficient frontier.
123
meanetl.ef <- create.EfficientFrontier(R=R, portfolio=init, type="mean-ES")
124
meanetl.ef
125
summary(meanetl.ef)
126
meanetl.ef$frontier
127
128
#' Chart the mean-ES efficient frontier.
129
chart.EfficientFrontier(meanetl.ef, match.col="ES", main="mean-ETL Efficient Frontier", type="l", col="blue", RAR.text="STARR")
130
chart.EF.Weights(meanetl.ef, colorset=bluemono, match.col="ES")
131
chart.EF.Weights(meanetl.ef, by.groups=TRUE, colorset=bluemono, match.col="ES")
132
133
#' Compute the mean-ES efficient frontier using random portfolios to solve
134
#' the optimization problem.
135
meanetl.rp.ef <- create.EfficientFrontier(R=R, portfolio=meanetl.portf, type="random", match.col="ES")
136
chart.EfficientFrontier(meanetl.rp.ef, match.col="ES", main="mean-ETL RP Efficient Frontier", type="l", col="blue", rf=0)
137
chart.EF.Weights(meanetl.rp.ef, colorset=bluemono, match.col="ES")
138
139
# mean-etl efficient frontier with optimize.portfolio output
140
opt_meanetl <- optimize.portfolio(R=R, portfolio=meanetl.portf, optimize_method="random", search_size=2000, trace=TRUE)
141
chart.EfficientFrontier(meanetl.rp.ef, match.col="ES", main="mean-ETL RP Efficient Frontier", type="l", col="blue", rf=0, RAR.text="STARR")
142
143
#' Create a mean-var efficient frontier for multiple portfolios and overlay
144
#' the efficient frontier lines. Set up an initial portfolio with the full
145
#' investment constraint and mean and var objectives.
146
init.portf <- portfolio.spec(assets=funds)
147
init.portf <- add.constraint(portfolio=init.portf, type="full_investment")
148
149
#' Portfolio with long only constraints.
150
lo.portf <- add.constraint(portfolio=init.portf, type="long_only")
151
152
#' Portfolio with box constraints.
153
box.portf <- add.constraint(portfolio=init.portf, type="box", min=0.05, max=0.65)
154
155
#' Portfolio with group constraints (also add long only constraints to the
156
#' group portfolio).
157
group.portf <- add.constraint(portfolio=init.portf, type="group",
158
groups=list(groupA=c(1, 3),
159
groupB=c(2, 4, 5)),
160
group_min=c(0.25, 0.15),
161
group_max=c(0.75, 0.55))
162
group.portf <- add.constraint(portfolio=group.portf, type="long_only")
163
164
#' Combine the portfolios into a list.
165
portf.list <- combine.portfolios(list(lo.portf, box.portf, group.portf))
166
167
#' Plot the efficient frontier overlay of the portfolios with varying constraints.
168
legend.labels <- c("Long Only", "Box", "Group + Long Only")
169
chart.EfficientFrontierOverlay(R=R, portfolio_list=portf.list, type="mean-StdDev",
170
match.col="StdDev", legend.loc="topleft",
171
legend.labels=legend.labels, cex.legend=0.6,
172
labels.assets=FALSE, pch.assets=18)
173
174
#' Efficient frontier in mean-ES space with varying confidence leves for
175
#' ES calculation.
176
ES90 <- add.objective(portfolio=lo.portf, type="risk", name="ES",
177
arguments=list(p=0.9))
178
179
ES92 <- add.objective(portfolio=lo.portf, type="risk", name="ES",
180
arguments=list(p=0.92))
181
182
ES95 <- add.objective(portfolio=lo.portf, type="risk", name="ES",
183
arguments=list(p=0.95))
184
185
#' Combine the portfolios into a list.
186
portf.list <- combine.portfolios(list(ES.90=ES90, ES.92=ES92, ES.95=ES95))
187
188
#' Plot the efficient frontier overlay of the portfolios with varying
189
#' confidence levels fot he ES calculation.
190
legend.labels <- c("ES (p=0.9)", "ES (p=0.92)", "ES (p=0.95)")
191
chart.EfficientFrontierOverlay(R=R, portfolio_list=portf.list, type="mean-ES",
192
match.col="ES", legend.loc="topleft",
193
legend.labels=legend.labels, cex.legend=0.6,
194
labels.assets=FALSE, pch.assets=18)
195
196
197