Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
braverock
GitHub Repository: braverock/portfolioanalytics
Path: blob/master/R/plotFrontiers.R
1433 views
1
###############################################################################
2
# R (https://r-project.org/) Numeric Methods for Optimization of Portfolios
3
#
4
# Copyright (c) 2022-2032 Xinran Zhao
5
#
6
# This library is distributed under the terms of the GNU Public License (GPL)
7
# for full details see the file COPYING
8
#
9
# $Id$
10
#
11
###############################################################################
12
13
#' Generate efficient frontiers plot by providing frontiers.
14
#'
15
#' @details
16
#' This function provides the ability to plot frontiers based on the result of
17
#' `meanvar.efficient.frontier`, `meanetl.efficient.frontier` or `meancsm.efficient.frontier`.
18
#'
19
#' When using \code{meanvar.efficient.frontier}, \code{meanetl.efficient.frontier}
20
#' and \code{meancsm.efficient.frontier}, the result will be frontiers data,
21
#' including the weights for each point on the mean-risk efficient frontiers.
22
#' Before using this function, user should declare which risk that they want to
23
#' compare, and what parameters that they want to use to calculate the risk,
24
#' e.g. \code{ES_alpha} for ES, \code{moment_setting} for var. Then this function
25
#' will calculate back mean and risk based on the weight, and draw a plot.
26
#'
27
#' Default settings use colors and line types to differentiate portfolios, and set
28
#' the portfolio name as 'Portfolio 1' and so on. Users could customize col, lty,
29
#' lwd and legend.labels to better the plot.
30
#'
31
#' @param R an xts object of asset returns
32
#' @param frontiers a list of frontiers, for example, list(ef1=meanvar.efficient.frontier(), ef2=meanvar.efficient.frontier())
33
#' @param risk type of risk that you want to compare, could be 'StdDev', 'ES', 'CSM'
34
#' @param ES_alpha the default value is 0.05, but could be specified as any value between 0 and 1
35
#' @param CSM_alpha the default value is 0.05, but could be specified as any value between 0 and 1
36
#' @param moment_setting the default is NULL, if customize momentFUN please provide moment_setting=list(mu=, sigma=)
37
#' @param main title used in the plot.
38
#' @param plot_type define the plot_type, default is "l"
39
#' @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}}.
40
#' @param element.color provides the color for drawing less-important chart elements, such as the box lines, axis lines, etc.
41
#' @param legend.loc location of the legend; NULL, "bottomright", "bottom", "bottomleft", "left", "topleft", "top", "topright", "right" and "center".
42
#' @param legend.labels character vector to use for the legend labels.
43
#' @param cex.legend The magnification to be used for sizing the legend relative to the current setting of 'cex', similar to \code{\link{plot}}.
44
#' @param xlim set the x-axis limit, same as in \code{\link{plot}}.
45
#' @param ylim set the y-axis limit, same as in \code{\link{plot}}.
46
#' @param \dots passthrough parameters to \code{\link{plot}}.
47
#' @param labels.assets TRUE/FALSE to include the asset names in the plot.
48
#' @param pch.assets plotting character of the assets, same as in \code{\link{plot}}.
49
#' @param cex.assets A numerical value giving the amount by which the asset points and labels should be magnified relative to the default.
50
#' @param col vector of colors with length equal to the number of portfolios in \code{frontiers}.
51
#' @param lty vector of line types with length equal to the number of portfolios in \code{frontiers}.
52
#' @param lwd vector of line widths with length equal to the number of portfolios in \code{frontiers}.
53
#' @author Xinran Zhao
54
#' @export plotFrontiers
55
#'
56
plotFrontiers <- 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){
57
if(risk %in% c('StdDev', 'var', 'stdDev')){
58
risk = 'StdDev'
59
} else if(risk %in% c('etl', 'ES', 'es')){
60
risk = 'ES'
61
} else if(risk %in% c('CSM', 'csm')){
62
risk = 'CSM'
63
} else {print('please give the right risk type')}
64
65
wname = paste0('w.', colnames(R))
66
n = length(frontiers)
67
mean_list = list()
68
risk_list = list()
69
mean_scale = list('max' = c(), 'min' = c())
70
risk_scale = list('max' = c(), 'min' = c())
71
72
for(i in 1:n){
73
w = frontiers[[i]][, wname]
74
mean_value = c()
75
risk_value = c()
76
for(j in 1:dim(w)[1]){
77
risk_measures = extract_risk(R, w[j,], ES_alpha = ES_alpha, CSM_alpha = CSM_alpha, moment_setting = moment_setting)
78
mean_value = append(mean_value, risk_measures$mean)
79
risk_value = append(risk_value, risk_measures[risk])
80
}
81
if(is.list(risk_value)) risk_value = unlist(risk_value)
82
if(is.list(mean_value)) mean_value = unlist(mean_value)
83
mean_list = c(mean_list, list(mean_value))
84
risk_list = c(risk_list, list(risk_value))
85
mean_scale$max = append(mean_scale$max, max(mean_value))
86
mean_scale$min = append(mean_scale$min, min(mean_value))
87
risk_scale$max = append(risk_scale$max, max(risk_value))
88
risk_scale$min = append(risk_scale$min, min(risk_value))
89
}
90
91
# set the x and y limits
92
if(is.null(xlim)){
93
xlim <- c(0, 0)
94
xlim[1] <- min(risk_scale$min) * 0.9
95
xlim[2] <- max(risk_scale$max) * 1.1
96
}
97
if(is.null(ylim)){
98
ylim <- c(0, 0)
99
ylim[1] <- min(mean_scale$min) * 0.7
100
ylim[2] <- max(mean_scale$max) * 1.1
101
}
102
103
# plot the assets
104
plot(x=1, y=1, xlab=risk, ylab="Mean", main=main, xlim=xlim, ylim=ylim, axes=FALSE, type="n", ...)
105
axis(1, cex.axis = cex.axis, col = element.color)
106
axis(2, cex.axis = cex.axis, col = element.color)
107
box(col = element.color)
108
109
# set some basic plot parameters
110
if(is.null(col)) col <- 1:n
111
if(is.null(lty)) lty <- 1:n
112
if(is.null(lwd)) lwd <- rep(1, n)
113
114
for(i in 1:n){
115
lines(x=risk_list[[i]], y=mean_list[[i]], col=col[i], lty=lty[i], lwd=lwd[i], type = plot_type, ...)
116
}
117
118
# legend
119
if(!is.null(legend.loc)){
120
legend.loc = "bottomright"
121
}
122
if(is.null(legend.labels)){
123
legend.labels <- paste("Portfolio", 1:n)
124
}
125
legend("bottomright", legend=legend.labels, col=col, lty=lty, lwd=lwd, cex=cex.legend, bty="n")
126
out = list(mean = mean_list, risk = risk_list)
127
return(invisible(out))
128
}
129
130
131