Path: blob/master/demo/demo_efficient_frontier.R
1433 views
#' ---1#' title: "Efficient Frontier Demo"2#' date: "7/17/2014"3#' ---45#' This script demonstrates how to compute and plot the efficient frontier6#' given different constraints and objectives.78#' Efficient frontiers can be plotted two ways9#' 1. Run optimize.portfolio with trace=TRUE and then chart that object.10#' 2. create an efficient frontier and then chart that object.1112#' Load required packages13library(PortfolioAnalytics)14library(DEoptim)15library(ROI)16require(ROI.plugin.quadprog)17require(ROI.plugin.glpk)1819#' Load the data and change the column names for better legends in plotting.20data(edhec)21R <- edhec[, 1:5]22colnames(R) <- c("CA", "CTAG", "DS", "EM", "EQM")23funds <- colnames(R)2425#' Set up the initial portfolio object with some basic constraints.26init <- portfolio.spec(assets=funds)27init <- add.constraint(portfolio=init, type="full_investment")28init <- add.constraint(portfolio=init, type="box", min=0.15, max=0.45)29init <- add.constraint(portfolio=init, type="group",30groups=list(c(1, 3),31c(2, 4, 5)),32group_min=0.05,33group_max=0.7)3435#' Add objectives for mean-ES (Expected Shortfall) portfolio.36meanetl.portf <- add.objective(portfolio=init, type="risk", name="ES")37meanetl.portf <- add.objective(portfolio=meanetl.portf, type="return", name="mean")3839#' Add objectives for mean-variance portfolio.40meanvar.portf <- add.objective(portfolio=init, type="risk", name="var", risk_aversion=10)41meanvar.portf <- add.objective(portfolio=meanvar.portf, type="return", name="mean")4243#' Compute the mean-variance efficient frontier.44meanvar.ef <- create.EfficientFrontier(R=R, portfolio=init, type="mean-StdDev")45meanvar.ef46summary(meanvar.ef, digits=2)47meanvar.ef$frontier4849#' The RAR.text argument can be used for the risk-adjusted-return name on the50#' legend, by default it is 'Modified Sharpe Ratio'.51chart.EfficientFrontier(meanvar.ef, match.col="StdDev", type="l",52RAR.text="Sharpe Ratio", pch=4)5354#' The tangency portfolio and line are plotted by default, these can be55#' ommitted by setting rf=NULL.56chart.EfficientFrontier(meanvar.ef, match.col="StdDev", type="b", rf=NULL)5758#' The tangency line can be omitted with tangent.line=FALSE. The tangent59#' portfolio, risk-free rate and Sharpe Ratio are still included in the plot.60chart.EfficientFrontier(meanvar.ef, match.col="StdDev", type="l", tangent.line=FALSE)6162#' The assets can be omitted with chart.assets=FALSE.63chart.EfficientFrontier(meanvar.ef, match.col="StdDev", type="l",64tangent.line=FALSE, chart.assets=FALSE)6566#' Just the names of the assets can be omitted with labels.assets=FALSE and the67#' plotting character can be changed with pch.assets.68chart.EfficientFrontier(meanvar.ef, match.col="StdDev", type="l",69tangent.line=FALSE, labels.assets=FALSE, pch.assets=1)7071#' Chart the asset weights along the efficient frontier.72chart.EF.Weights(meanvar.ef, colorset=bluemono, match.col="StdDev")7374#' Chart the group weights along the efficient frontier.75chart.EF.Weights(meanvar.ef, colorset=bluemono, by.groups=TRUE, match.col="StdDev")7677#' The labels for Mean, Weight, and StdDev can be increased or decreased with78#' the cex.lab argument. The default is cex.lab=0.8.79chart.EF.Weights(meanvar.ef, colorset=bluemono, match.col="StdDev", main="", cex.lab=1)8081#' If you have a lot of assets and they don't fit with the default legend, you82#' can set legend.loc=NULL and customize the plot.83par(mar=c(8, 4, 4, 2)+0.1, xpd=TRUE)84chart.EF.Weights(meanvar.ef, colorset=bluemono, match.col="StdDev", legend.loc=NULL)85legend("bottom", legend=colnames(R), inset=-1, fill=bluemono, bty="n", ncol=3, cex=0.8)86par(mar=c(5, 4, 4, 2)+0.1, xpd=FALSE)8788#' Run optimize.portfolio and chart the efficient frontier of the optimal89#' portfolio object.90opt_meanvar <- optimize.portfolio(R=R, portfolio=meanvar.portf,91optimize_method="ROI", trace=TRUE)9293#' The efficient frontier is created from the 'opt_meanvar' object by getting.94#' The portfolio and returns objects and then passing those to create.EfficientFrontier.95chart.EfficientFrontier(opt_meanvar, match.col="StdDev", n.portfolios=25, type="l")9697#' Rerun the optimization with a new risk aversion parameter to change where98#' the portfolio is along the efficient frontier. The 'optimal' portfolio99#' plotted on the efficient frontier is the optimal portfolio returned by100#' optimize.portfolio.101meanvar.portf$objectives[[2]]$risk_aversion=0.25102opt_meanvar <- optimize.portfolio(R=R, portfolio=meanvar.portf, optimize_method="ROI", trace=TRUE)103chart.EfficientFrontier(opt_meanvar, match.col="StdDev", n.portfolios=25, type="l")104105#' The weights along the efficient frontier can be plotted by passing in the106#' optimize.portfolio output object.107chart.EF.Weights(opt_meanvar, match.col="StdDev")108109chart.EF.Weights(opt_meanvar, match.col="StdDev", by.groups=TRUE)110111#' Extract the efficient frontier and then plot it.112#' Note that if you want to do multiple charts of the efficient frontier from113#' the optimize.portfolio object, it is best to extractEfficientFrontier as114#' shown below.115ef <- extractEfficientFrontier(object=opt_meanvar, match.col="StdDev", n.portfolios=15)116ef117summary(ef, digits=5)118chart.EF.Weights(ef, match.col="StdDev", colorset=bluemono)119chart.EF.Weights(ef, match.col="StdDev", colorset=bluemono, by.groups=TRUE)120121#' Compute the mean-ES efficient frontier.122meanetl.ef <- create.EfficientFrontier(R=R, portfolio=init, type="mean-ES")123meanetl.ef124summary(meanetl.ef)125meanetl.ef$frontier126127#' Chart the mean-ES efficient frontier.128chart.EfficientFrontier(meanetl.ef, match.col="ES", main="mean-ETL Efficient Frontier", type="l", col="blue", RAR.text="STARR")129chart.EF.Weights(meanetl.ef, colorset=bluemono, match.col="ES")130chart.EF.Weights(meanetl.ef, by.groups=TRUE, colorset=bluemono, match.col="ES")131132#' Compute the mean-ES efficient frontier using random portfolios to solve133#' the optimization problem.134meanetl.rp.ef <- create.EfficientFrontier(R=R, portfolio=meanetl.portf, type="random", match.col="ES")135chart.EfficientFrontier(meanetl.rp.ef, match.col="ES", main="mean-ETL RP Efficient Frontier", type="l", col="blue", rf=0)136chart.EF.Weights(meanetl.rp.ef, colorset=bluemono, match.col="ES")137138# mean-etl efficient frontier with optimize.portfolio output139opt_meanetl <- optimize.portfolio(R=R, portfolio=meanetl.portf, optimize_method="random", search_size=2000, trace=TRUE)140chart.EfficientFrontier(meanetl.rp.ef, match.col="ES", main="mean-ETL RP Efficient Frontier", type="l", col="blue", rf=0, RAR.text="STARR")141142#' Create a mean-var efficient frontier for multiple portfolios and overlay143#' the efficient frontier lines. Set up an initial portfolio with the full144#' investment constraint and mean and var objectives.145init.portf <- portfolio.spec(assets=funds)146init.portf <- add.constraint(portfolio=init.portf, type="full_investment")147148#' Portfolio with long only constraints.149lo.portf <- add.constraint(portfolio=init.portf, type="long_only")150151#' Portfolio with box constraints.152box.portf <- add.constraint(portfolio=init.portf, type="box", min=0.05, max=0.65)153154#' Portfolio with group constraints (also add long only constraints to the155#' group portfolio).156group.portf <- add.constraint(portfolio=init.portf, type="group",157groups=list(groupA=c(1, 3),158groupB=c(2, 4, 5)),159group_min=c(0.25, 0.15),160group_max=c(0.75, 0.55))161group.portf <- add.constraint(portfolio=group.portf, type="long_only")162163#' Combine the portfolios into a list.164portf.list <- combine.portfolios(list(lo.portf, box.portf, group.portf))165166#' Plot the efficient frontier overlay of the portfolios with varying constraints.167legend.labels <- c("Long Only", "Box", "Group + Long Only")168chart.EfficientFrontierOverlay(R=R, portfolio_list=portf.list, type="mean-StdDev",169match.col="StdDev", legend.loc="topleft",170legend.labels=legend.labels, cex.legend=0.6,171labels.assets=FALSE, pch.assets=18)172173#' Efficient frontier in mean-ES space with varying confidence leves for174#' ES calculation.175ES90 <- add.objective(portfolio=lo.portf, type="risk", name="ES",176arguments=list(p=0.9))177178ES92 <- add.objective(portfolio=lo.portf, type="risk", name="ES",179arguments=list(p=0.92))180181ES95 <- add.objective(portfolio=lo.portf, type="risk", name="ES",182arguments=list(p=0.95))183184#' Combine the portfolios into a list.185portf.list <- combine.portfolios(list(ES.90=ES90, ES.92=ES92, ES.95=ES95))186187#' Plot the efficient frontier overlay of the portfolios with varying188#' confidence levels fot he ES calculation.189legend.labels <- c("ES (p=0.9)", "ES (p=0.92)", "ES (p=0.95)")190chart.EfficientFrontierOverlay(R=R, portfolio_list=portf.list, type="mean-ES",191match.col="ES", legend.loc="topleft",192legend.labels=legend.labels, cex.legend=0.6,193labels.assets=FALSE, pch.assets=18)194195196197