###############################################################################1# R (https://r-project.org/) Numeric Methods for Optimization of Portfolios2#3# Copyright (c) 2022-2032 Xinran Zhao4#5# This library is distributed under the terms of the GNU Public License (GPL)6# for full details see the file COPYING7#8# $Id$9#10###############################################################################1112#' Generate efficient frontiers plot by providing frontiers.13#'14#' @details15#' This function provides the ability to plot frontiers based on the result of16#' `meanvar.efficient.frontier`, `meanetl.efficient.frontier` or `meancsm.efficient.frontier`.17#'18#' When using \code{meanvar.efficient.frontier}, \code{meanetl.efficient.frontier}19#' and \code{meancsm.efficient.frontier}, the result will be frontiers data,20#' including the weights for each point on the mean-risk efficient frontiers.21#' Before using this function, user should declare which risk that they want to22#' compare, and what parameters that they want to use to calculate the risk,23#' e.g. \code{ES_alpha} for ES, \code{moment_setting} for var. Then this function24#' will calculate back mean and risk based on the weight, and draw a plot.25#'26#' Default settings use colors and line types to differentiate portfolios, and set27#' the portfolio name as 'Portfolio 1' and so on. Users could customize col, lty,28#' lwd and legend.labels to better the plot.29#'30#' @param R an xts object of asset returns31#' @param frontiers a list of frontiers, for example, list(ef1=meanvar.efficient.frontier(), ef2=meanvar.efficient.frontier())32#' @param risk type of risk that you want to compare, could be 'StdDev', 'ES', 'CSM'33#' @param ES_alpha the default value is 0.05, but could be specified as any value between 0 and 134#' @param CSM_alpha the default value is 0.05, but could be specified as any value between 0 and 135#' @param moment_setting the default is NULL, if customize momentFUN please provide moment_setting=list(mu=, sigma=)36#' @param main title used in the plot.37#' @param plot_type define the plot_type, default is "l"38#' @param cex.axis the magnification to be used for sizing the axis text relative to the current setting of 'cex', similar to \code{\link{plot}}.39#' @param element.color provides the color for drawing less-important chart elements, such as the box lines, axis lines, etc.40#' @param legend.loc location of the legend; NULL, "bottomright", "bottom", "bottomleft", "left", "topleft", "top", "topright", "right" and "center".41#' @param legend.labels character vector to use for the legend labels.42#' @param cex.legend The magnification to be used for sizing the legend relative to the current setting of 'cex', similar to \code{\link{plot}}.43#' @param xlim set the x-axis limit, same as in \code{\link{plot}}.44#' @param ylim set the y-axis limit, same as in \code{\link{plot}}.45#' @param \dots passthrough parameters to \code{\link{plot}}.46#' @param labels.assets TRUE/FALSE to include the asset names in the plot.47#' @param pch.assets plotting character of the assets, same as in \code{\link{plot}}.48#' @param cex.assets A numerical value giving the amount by which the asset points and labels should be magnified relative to the default.49#' @param col vector of colors with length equal to the number of portfolios in \code{frontiers}.50#' @param lty vector of line types with length equal to the number of portfolios in \code{frontiers}.51#' @param lwd vector of line widths with length equal to the number of portfolios in \code{frontiers}.52#' @author Xinran Zhao53#' @export plotFrontiers54#'55plotFrontiers <- function(R, frontiers, risk, ES_alpha = 0.05, CSM_alpha = 0.05, moment_setting = NULL, main="Efficient Frontiers", plot_type = "l", cex.axis=0.5, element.color="darkgray", legend.loc=NULL, legend.labels=NULL, cex.legend=0.8, xlim=NULL, ylim=NULL, ..., labels.assets=TRUE, pch.assets=21, cex.assets=0.8, col=NULL, lty=NULL, lwd=NULL){56if(risk %in% c('StdDev', 'var', 'stdDev')){57risk = 'StdDev'58} else if(risk %in% c('etl', 'ES', 'es')){59risk = 'ES'60} else if(risk %in% c('CSM', 'csm')){61risk = 'CSM'62} else {print('please give the right risk type')}6364wname = paste0('w.', colnames(R))65n = length(frontiers)66mean_list = list()67risk_list = list()68mean_scale = list('max' = c(), 'min' = c())69risk_scale = list('max' = c(), 'min' = c())7071for(i in 1:n){72w = frontiers[[i]][, wname]73mean_value = c()74risk_value = c()75for(j in 1:dim(w)[1]){76risk_measures = extract_risk(R, w[j,], ES_alpha = ES_alpha, CSM_alpha = CSM_alpha, moment_setting = moment_setting)77mean_value = append(mean_value, risk_measures$mean)78risk_value = append(risk_value, risk_measures[risk])79}80if(is.list(risk_value)) risk_value = unlist(risk_value)81if(is.list(mean_value)) mean_value = unlist(mean_value)82mean_list = c(mean_list, list(mean_value))83risk_list = c(risk_list, list(risk_value))84mean_scale$max = append(mean_scale$max, max(mean_value))85mean_scale$min = append(mean_scale$min, min(mean_value))86risk_scale$max = append(risk_scale$max, max(risk_value))87risk_scale$min = append(risk_scale$min, min(risk_value))88}8990# set the x and y limits91if(is.null(xlim)){92xlim <- c(0, 0)93xlim[1] <- min(risk_scale$min) * 0.994xlim[2] <- max(risk_scale$max) * 1.195}96if(is.null(ylim)){97ylim <- c(0, 0)98ylim[1] <- min(mean_scale$min) * 0.799ylim[2] <- max(mean_scale$max) * 1.1100}101102# plot the assets103plot(x=1, y=1, xlab=risk, ylab="Mean", main=main, xlim=xlim, ylim=ylim, axes=FALSE, type="n", ...)104axis(1, cex.axis = cex.axis, col = element.color)105axis(2, cex.axis = cex.axis, col = element.color)106box(col = element.color)107108# set some basic plot parameters109if(is.null(col)) col <- 1:n110if(is.null(lty)) lty <- 1:n111if(is.null(lwd)) lwd <- rep(1, n)112113for(i in 1:n){114lines(x=risk_list[[i]], y=mean_list[[i]], col=col[i], lty=lty[i], lwd=lwd[i], type = plot_type, ...)115}116117# legend118if(!is.null(legend.loc)){119legend.loc = "bottomright"120}121if(is.null(legend.labels)){122legend.labels <- paste("Portfolio", 1:n)123}124legend("bottomright", legend=legend.labels, col=col, lty=lty, lwd=lwd, cex=cex.legend, bty="n")125out = list(mean = mean_list, risk = risk_list)126return(invisible(out))127}128129130131