chart.Concentration <- function(object,
...,
return.col='mean',
risk.col='ES',
chart.assets=FALSE,
conc.type=c("weights", "pct_contrib"),
col=heat.colors(20),
element.color = "darkgray",
cex.axis=0.8,
xlim=NULL, ylim=NULL){
if(!inherits(object, "optimize.portfolio")){
stop("object must be of class 'optimize.portfolio'")
}
xtract <- try(extractStats(object), silent=TRUE)
if(inherits(xtract, "try-error")) {
message(xtract)
return(NULL)
}
conc.type <- match.arg(conc.type)
columnnames <- colnames(xtract)
R <- object$R
return.column <- pmatch(return.col, columnnames)
if(is.na(return.column)) {
return.col <- paste(return.col, return.col, sep='.')
return.column <- pmatch(return.col, columnnames)
}
risk.column <- pmatch(risk.col, columnnames)
if(is.na(risk.column)) {
risk.col <- paste(risk.col, risk.col, sep='.')
risk.column <- pmatch(risk.col, columnnames)
}
if(is.na(return.column) | is.na(risk.column)){
return.col <- gsub("\\..*", "", return.col)
risk.col <- gsub("\\..*", "", risk.col)
warning(return.col,' or ', risk.col, ' do not match extractStats output of $objective_measures slot')
wts_index <- grep("w.", columnnames)
wts <- xtract[, wts_index]
if(is.na(return.column)){
tmpret <- applyFUN(R=R, weights=wts, FUN=return.col)
xtract <- cbind(tmpret, xtract)
colnames(xtract)[which(colnames(xtract) == "tmpret")] <- return.col
}
if(is.na(risk.column)){
tmprisk <- applyFUN(R=R, weights=wts, FUN=risk.col)
xtract <- cbind(tmprisk, xtract)
colnames(xtract)[which(colnames(xtract) == "tmprisk")] <- risk.col
}
columnnames = colnames(xtract)
return.column = pmatch(return.col,columnnames)
if(is.na(return.column)) {
return.col = paste(return.col,return.col,sep='.')
return.column = pmatch(return.col,columnnames)
}
risk.column = pmatch(risk.col,columnnames)
if(is.na(risk.column)) {
risk.col = paste(risk.col,risk.col,sep='.')
risk.column = pmatch(risk.col,columnnames)
}
}
if(chart.assets){
arguments <- NULL
if(is.null(arguments)){
tmp.args <- unlist(lapply(object$portfolio$objectives, function(x) x$arguments), recursive=FALSE)
tmp.args <- tmp.args[!duplicated(names(tmp.args))]
if(!is.null(tmp.args$portfolio_method)) tmp.args$portfolio_method <- "single"
arguments <- tmp.args
}
asset_ret <- scatterFUN(R=R, FUN=return.col, arguments)
asset_risk <- scatterFUN(R=R, FUN=risk.col, arguments)
xlim <- range(c(xtract[,risk.column], asset_risk))
ylim <- range(c(xtract[,return.column], asset_ret))
} else {
asset_ret <- NULL
asset_risk <- NULL
}
if(conc.type == "weights"){
idx <- grep("w.", colnames(xtract))
if(length(idx) == 0) stop("weights not detected in output of extractStats")
tmp.x <- xtract[, idx]
} else if(conc.type == "pct_contrib"){
idx <- grep("pct_contrib", colnames(xtract))
if(length(idx) == 0) stop("pct_contrib not detected in output of extractStats")
tmp.x <- xtract[, idx]
}
x.hhi <- apply(tmp.x, MARGIN=1, FUN="HHI")
y <- (x.hhi - min(x.hhi)) / (max(x.hhi) - min(x.hhi))
op <- par(no.readonly=TRUE)
layout(matrix(c(1,2)),heights=c(4,1.25),widths=1)
par(mar=c(5,4,1,2)+.1, cex=1)
plot(xtract[order(y, decreasing=TRUE), risk.column], xtract[order(y, decreasing=TRUE), return.column], xlab=risk.col, ylab=return.col, col=col, axes=FALSE, xlim=xlim, ylim=ylim, ...)
if(chart.assets){
points(x=asset_risk, y=asset_ret)
text(x=asset_risk, y=asset_ret, labels=colnames(R), pos=4, cex=0.8)
}
axis(1, cex.axis = cex.axis, col = element.color)
axis(2, cex.axis = cex.axis, col = element.color)
box(col = element.color)
par(mar=c(5,5.5,1,3)+.1, cex=0.7)
x <- x.hhi
scale01 <- function(x, low = min(x), high = max(x)) {
return((x - low) / (high - low))
}
breaks <- seq(min(x.hhi, na.rm=TRUE), max(x.hhi, na.rm=TRUE), length=(length(col)+1))
min.raw <- min(x, na.rm = TRUE)
max.raw <- max(x, na.rm = TRUE)
z <- seq(min.raw, max.raw, length=length(col))
image(z = matrix(z, ncol=1), col=col, breaks=breaks, xaxt="n", yaxt="n")
par(usr=c(0, 1, 0, 1))
lv <- pretty(breaks)
xv <- scale01(as.numeric(lv), min.raw, max.raw)
axis(1, at=xv, labels=sprintf("%s%%", pretty(lv)))
h <- hist(x, plot=FALSE, breaks=breaks)
hx <- scale01(breaks, min(x), max(x))
hy <- c(h$counts, h$counts[length(h$counts)])
lines(hx, hy / max(hy) * 0.95, lwd=2, type="s", col="blue")
axis(2, at=pretty(hy) / max(hy) * 0.95, pretty(hy))
title(ylab="Count")
title(xlab="Degree of Concentration")
par(op)
invisible(NULL)
}