[Returnanalytics-commits] r2902 - in pkg/PortfolioAnalytics: R man sandbox

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Tue Aug 27 18:05:30 CEST 2013


Author: rossbennett34
Date: 2013-08-27 18:05:30 +0200 (Tue, 27 Aug 2013)
New Revision: 2902

Modified:
   pkg/PortfolioAnalytics/R/charts.efficient.frontier.R
   pkg/PortfolioAnalytics/man/chart.EfficientFrontier.Rd
   pkg/PortfolioAnalytics/sandbox/testing_efficient_frontier.R
Log:
Adding tangency lines to efficient frontier plots.

Modified: pkg/PortfolioAnalytics/R/charts.efficient.frontier.R
===================================================================
--- pkg/PortfolioAnalytics/R/charts.efficient.frontier.R	2013-08-27 10:30:38 UTC (rev 2901)
+++ pkg/PortfolioAnalytics/R/charts.efficient.frontier.R	2013-08-27 16:05:30 UTC (rev 2902)
@@ -28,6 +28,10 @@
 #' GenSA does not return any useable trace information for portfolios tested at 
 #' each iteration, therfore we cannot extract and chart an efficient frontier.
 #' 
+#' By default, the tangency portfolio (maximum Sharpe Ratio or modified Sharpe Ratio)
+#' will be plotted using a risk free rate of 0. Set \code{rf=NULL} to omit 
+#' this from the plot. 
+#' 
 #' @param object optimal portfolio created by \code{\link{optimize.portfolio}}
 #' @param string name of column to use for risk (horizontal axis).
 #' \code{match.col} must match the name of an objective measure in the 
@@ -36,10 +40,13 @@
 #' @param n.portfolios number of portfolios to use to plot the efficient frontier
 #' @param xlim set the x-axis limit, same as in \code{\link{plot}}
 #' @param ylim set the y-axis limit, same as in \code{\link{plot}}
-#' @param cex.axis
-#' @param element.color 
+#' @param cex.axis A numerical value giving the amount by which the axis should be magnified relative to the default.
+#' @param element.color provides the color for drawing less-important chart elements, such as the box lines, axis lines, etc.
 #' @param main a main title for the plot
 #' @param ... passthrough parameters to \code{\link{plot}}
+#' @param rf risk free rate. If \code{rf} is not null, the maximum Sharpe Ratio or modified Sharpe Ratio tangency portfolio will be plotted
+#' @param cex.legend A numerical value giving the amount by which the legend should be magnified relative to the default.
+#' @param RAR.text Risk Adjusted Return ratio text to plot in the legend
 #' @author Ross Bennett
 #' @export
 chart.EfficientFrontier <- function(object, match.col="ES", n.portfolios=25, xlim=NULL, ylim=NULL, cex.axis=0.8, element.color="darkgray", main="Efficient Frontier", ...){
@@ -48,7 +55,7 @@
 
 #' @rdname chart.EfficientFrontier
 #' @export
-chart.EfficientFrontier.optimize.portfolio.ROI <- function(object, match.col="ES", n.portfolios=25, xlim=NULL, ylim=NULL, cex.axis=0.8, element.color="darkgray", main="Efficient Frontier", ...){
+chart.EfficientFrontier.optimize.portfolio.ROI <- function(object, match.col="ES", n.portfolios=25, xlim=NULL, ylim=NULL, cex.axis=0.8, element.color="darkgray", main="Efficient Frontier", ..., rf=0, cex.legend=0.8){
   if(!inherits(object, "optimize.portfolio.ROI")) stop("object must be of class optimize.portfolio.ROI")
   
   portf <- object$portfolio
@@ -86,14 +93,23 @@
   
   if(match.col %in% c("ETL", "ES", "CVaR")){
     frontier <- meanetl.efficient.frontier(portfolio=portf, R=R, n.portfolios=n.portfolios)
+    rar <- "STARR"
   }
   if(match.col == "StdDev"){
     frontier <- meanvar.efficient.frontier(portfolio=portf, R=R, n.portfolios=n.portfolios)
+    rar <- "Sharpe Ratio"
   }
   # data points to plot the frontier
   x.f <- frontier[, match.col]
   y.f <- frontier[, "mean"]
   
+  # Points for the Sharpe Ratio ((mu - rf) / StdDev) or STARR ((mu - rf) / ETL)
+  if(!is.null(rf)){
+    sr <- (y.f - rf) / (x.f)
+    idx.maxsr <- which.max(sr)
+    srmax <- sr[idx.maxsr]
+  }
+  
   # set the x and y limits
   if(is.null(xlim)){
     xlim <- range(c(x.f, asset_risk))
@@ -110,6 +126,15 @@
   # plot the optimal portfolio
   points(opt_risk, opt_ret, col="blue", pch=16) # optimal
   text(x=opt_risk, y=opt_ret, labels="Optimal",col="blue", pos=4, cex=0.8)
+  if(!is.null(rf)){
+    # Plot tangency line and points at risk-free rate and tangency portfolio
+    abline(rf, srmax, lty=2)
+    points(0, rf, pch=16)
+    points(x.f[idx.maxsr], y.f[idx.maxsr], pch=16)
+    # Add lengend with max Sharpe Ratio and risk-free rate
+    legend("topleft", paste("Max ", rar, " = ", signif(srmax,3), sep = ""), bty = "n", cex=cex.legend)
+    legend("topleft", inset = c(0,0.05), paste("rf = ", signif(rf,3), sep = ""), bty = "n", cex=cex.legend)
+  }
   axis(1, cex.axis = cex.axis, col = element.color)
   axis(2, cex.axis = cex.axis, col = element.color)
   box(col = element.color)
@@ -117,7 +142,7 @@
 
 #' @rdname chart.EfficientFrontier
 #' @export
-chart.EfficientFrontier.optimize.portfolio <- function(object, match.col="ES", n.portfolios=25, xlim=NULL, ylim=NULL, cex.axis=0.8, element.color="darkgray", main="Efficient Frontier", ...){
+chart.EfficientFrontier.optimize.portfolio <- function(object, match.col="ES", n.portfolios=25, xlim=NULL, ylim=NULL, cex.axis=0.8, element.color="darkgray", main="Efficient Frontier", ..., RAR.text="Modified Sharpe", rf=0, cex.legend=0.8){
   # This function will work with objects of class optimize.portfolio.DEoptim,
   # optimize.portfolio.random, and optimize.portfolio.pso
   
@@ -163,6 +188,13 @@
   x.f <- frontier[, match.col]
   y.f <- frontier[, "mean"]
   
+  # Points for the Sharpe or Modified Sharpe Ratio
+  if(!is.null(rf)){
+    sr <- (y.f - rf) / (x.f)
+    idx.maxsr <- which.max(sr)
+    srmax <- sr[idx.maxsr]
+  }
+  
   # set the x and y limits
   if(is.null(xlim)){
     xlim <- range(c(x.f, asset_risk))
@@ -179,6 +211,15 @@
   # plot the optimal portfolio
   points(opt_risk, opt_ret, col="blue", pch=16) # optimal
   text(x=opt_risk, y=opt_ret, labels="Optimal",col="blue", pos=4, cex=0.8)
+  if(!is.null(rf)){
+    # Plot tangency line and points at risk-free rate and tangency portfolio
+    abline(rf, srmax, lty=2)
+    points(0, rf, pch=16)
+    points(x.f[idx.maxsr], y.f[idx.maxsr], pch=16)
+    # Add lengend with max Sharpe Ratio and risk-free rate
+    legend("topleft", paste("Max ", RAR.text, " = ", signif(srmax,3), sep = ""), bty = "n", cex=cex.legend)
+    legend("topleft", inset = c(0,0.05), paste("rf = ", signif(rf,3), sep = ""), bty = "n", cex=cex.legend)
+  }
   axis(1, cex.axis = cex.axis, col = element.color)
   axis(2, cex.axis = cex.axis, col = element.color)
   box(col = element.color)
@@ -315,7 +356,7 @@
 
 #' @rdname chart.EfficientFrontier
 #' @export
-chart.EfficientFrontier.efficient.frontier <- function(object, chart.assets=TRUE, match.col="ES", n.portfolios=NULL, xlim=NULL, ylim=NULL, cex.axis=0.8, element.color="darkgray", main="Efficient Frontier", ...){
+chart.EfficientFrontier.efficient.frontier <- function(object, chart.assets=TRUE, match.col="ES", n.portfolios=NULL, xlim=NULL, ylim=NULL, cex.axis=0.8, element.color="darkgray", main="Efficient Frontier", ..., RAR.text="Modified Sharpe", rf=0, cex.legend=0.8){
   if(!inherits(object, "efficient.frontier")) stop("object must be of class 'efficient.frontier'")
   
   # get the returns and efficient frontier object
@@ -354,6 +395,12 @@
     }
   }
   
+  if(!is.null(rf)){
+    sr <- (frontier[, mean.mtc] - rf) / (frontier[, mtc])
+    idx.maxsr <- which.max(sr)
+    srmax <- sr[idx.maxsr]
+  }
+  
   # plot the efficient frontier line
   plot(x=frontier[, mtc], y=frontier[, mean.mtc], ylab="mean", xlab=match.col, main=main, xlim=xlim, ylim=ylim, pch=5, axes=FALSE, ...)
   if(chart.assets){
@@ -361,6 +408,15 @@
     points(x=asset_risk, y=asset_ret)
     text(x=asset_risk, y=asset_ret, labels=rnames, pos=4, cex=0.8)
   }
+  if(!is.null(rf)){
+    # Plot tangency line and points at risk-free rate and tangency portfolio
+    abline(rf, srmax, lty=2)
+    points(0, rf, pch=16)
+    points(frontier[idx.maxsr, mtc], frontier[idx.maxsr, mean.mtc], pch=16)
+    # Add legend with max Risk adjusted Return ratio and risk-free rate
+    legend("topleft", paste("Max ", RAR.text, " = ", signif(srmax,3), sep = ""), bty = "n", cex=cex.legend)
+    legend("topleft", inset = c(0,0.05), paste("rf = ", signif(rf,3), sep = ""), bty = "n", cex=cex.legend)
+  }
   axis(1, cex.axis = cex.axis, col = element.color)
   axis(2, cex.axis = cex.axis, col = element.color)
   box(col = element.color)

Modified: pkg/PortfolioAnalytics/man/chart.EfficientFrontier.Rd
===================================================================
--- pkg/PortfolioAnalytics/man/chart.EfficientFrontier.Rd	2013-08-27 10:30:38 UTC (rev 2901)
+++ pkg/PortfolioAnalytics/man/chart.EfficientFrontier.Rd	2013-08-27 16:05:30 UTC (rev 2902)
@@ -14,19 +14,22 @@
     match.col = "ES", n.portfolios = 25, xlim = NULL,
     ylim = NULL, cex.axis = 0.8,
     element.color = "darkgray",
-    main = "Efficient Frontier", ...)
+    main = "Efficient Frontier", ..., rf = 0,
+    cex.legend = 0.8)
 
   chart.EfficientFrontier.optimize.portfolio(object,
     match.col = "ES", n.portfolios = 25, xlim = NULL,
     ylim = NULL, cex.axis = 0.8,
     element.color = "darkgray",
-    main = "Efficient Frontier", ...)
+    main = "Efficient Frontier", ...,
+    RAR.text = "Modified Sharpe", rf = 0, cex.legend = 0.8)
 
   chart.EfficientFrontier.efficient.frontier(object,
     chart.assets = TRUE, match.col = "ES",
     n.portfolios = NULL, xlim = NULL, ylim = NULL,
     cex.axis = 0.8, element.color = "darkgray",
-    main = "Efficient Frontier", ...)
+    main = "Efficient Frontier", ...,
+    RAR.text = "Modified Sharpe", rf = 0, cex.legend = 0.8)
 }
 \arguments{
   \item{object}{optimal portfolio created by
@@ -47,13 +50,28 @@
   \item{ylim}{set the y-axis limit, same as in
   \code{\link{plot}}}
 
-  \item{cex.axis}{}
+  \item{cex.axis}{A numerical value giving the amount by
+  which the axis should be magnified relative to the
+  default.}
 
-  \item{element.color}{}
+  \item{element.color}{provides the color for drawing
+  less-important chart elements, such as the box lines,
+  axis lines, etc.}
 
   \item{main}{a main title for the plot}
 
   \item{...}{passthrough parameters to \code{\link{plot}}}
+
+  \item{rf}{risk free rate. If \code{rf} is not null, the
+  maximum Sharpe Ratio or modified Sharpe Ratio tangency
+  portfolio will be plotted}
+
+  \item{cex.legend}{A numerical value giving the amount by
+  which the legend should be magnified relative to the
+  default.}
+
+  \item{RAR.text}{Risk Adjusted Return ratio text to plot
+  in the legend}
 }
 \description{
   This function charts the efficient frontier and
@@ -86,6 +104,11 @@
   GenSA does not return any useable trace information for
   portfolios tested at each iteration, therfore we cannot
   extract and chart an efficient frontier.
+
+  By default, the tangency portfolio (maximum Sharpe Ratio
+  or modified Sharpe Ratio) will be plotted using a risk
+  free rate of 0. Set \code{rf=NULL} to omit this from the
+  plot.
 }
 \author{
   Ross Bennett

Modified: pkg/PortfolioAnalytics/sandbox/testing_efficient_frontier.R
===================================================================
--- pkg/PortfolioAnalytics/sandbox/testing_efficient_frontier.R	2013-08-27 10:30:38 UTC (rev 2901)
+++ pkg/PortfolioAnalytics/sandbox/testing_efficient_frontier.R	2013-08-27 16:05:30 UTC (rev 2902)
@@ -38,6 +38,7 @@
 # mean-var efficient frontier
 meanvar.ef <- create.EfficientFrontier(R=R, portfolio=meanvar.portf, type="mean-StdDev")
 chart.EfficientFrontier(meanvar.ef, match.col="StdDev", type="b")
+chart.EfficientFrontier(meanvar.ef, match.col="StdDev", type="l", rf=0)
 chart.Weights.EF(meanvar.ef, colorset=bluemono, match.col="StdDev")
 
 # run optimize.portfolio and chart the efficient frontier for that object
@@ -48,7 +49,7 @@
 chart.Weights.EF(opt_meanvar, match.col="StdDev")
 # or we can extract the efficient frontier and then plot it
 ef <- extractEfficientFrontier(object=opt_meanvar, match.col="StdDev", n.portfolios=15)
-chart.Weights.EF(ef, match.col="var", colorset=bluemono)
+chart.Weights.EF(ef, match.col="StdDev", colorset=bluemono)
 
 # mean-etl efficient frontier
 meanetl.ef <- create.EfficientFrontier(R=R, portfolio=meanetl.portf, type="mean-ES")
@@ -57,9 +58,12 @@
 
 # mean-etl efficient frontier using random portfolios
 meanetl.rp.ef <- create.EfficientFrontier(R=R, portfolio=meanetl.portf, type="random", match.col="ES")
-chart.EfficientFrontier(meanetl.rp.ef, match.col="ES", main="mean-ETL RP Efficient Frontier", type="l", col="blue")
+chart.EfficientFrontier(meanetl.rp.ef, match.col="ES", main="mean-ETL RP Efficient Frontier", type="l", col="blue", rf=0)
 chart.Weights.EF(meanetl.rp.ef, colorset=bluemono, match.col="ES")
 
+# mean-etl efficient frontier with optimize.portfolio output
+opt_meanetl <- optimize.portfolio(R=R, portfolio=meanetl.portf, optimize_method="random", search_size=2000, trace=TRUE)
+chart.EfficientFrontier(meanetl.rp.ef, match.col="ES", main="mean-ETL RP Efficient Frontier", type="l", col="blue", rf=0, RAR.text="STARR")
 
 ##### overlay efficient frontiers of multiple portfolios #####
 # Create a mean-var efficient frontier for multiple portfolios and overlay the efficient frontier lines



More information about the Returnanalytics-commits mailing list