Vorrei creare una "versione ggplot" della funzionalità di base di charts.PerformanceSummary
disponibile nel pacchetto PerformanceAnalytics
, poiché penso che ggplot sia generalmente più bello e teoricamente più potente in termini di modifica del Immagine. Ho ragionevolmente vicino ma ho alcuni problemi su cui vorrei un po 'di aiuto. Vale a dire:versione ggplot di charts.PerformanceSummary
- riducendo la quantità di spazio che la leggenda prende, diventa orrendo/brutto quando si hanno più di 10 linee su di esso ... (solo il colore della linea e il nome è sufficiente)
- Aumentare la dimensione della faccetta Daily_Returns corrispondente a quella dei grafici.PerformanceSummary in
PerformanceAnalytics
- Avere un'opzione che specifica quale risorsa mostrare nella serie di resi giornalieri nella faccetta Daily_Returns, invece di utilizzare sempre la prima colonna, che è ciò che accade in
charts.PerformanceSummary
Se ci sono modi migliori per fare questo potenzialmente usando gridExtra
piuttosto che faccette ... Non sono contrario alle persone che mi mostrano come sarebbe meglio ...
Il problema qui è l'estetica, e il potenziale facile di manipolazione suppongo, visto che PerformanceAnalytics ha già un buon esempio di lavoro, voglio solo renderlo più bello/più professionale ...
Oltre a questo per i punti bonus, vorrei poter mostrare alcune statistiche sulle prestazioni associate con esso da qualche parte sopra o sotto o sul lato del grafico per ogni risorsa ... non troppo sicuro di dove sarebbe meglio mostrare o visualizzare queste informazioni.
Inoltre, non sono contrario a persone che suggeriscono parti che puliscono il mio codice se hanno suggerimenti per questo.
Ecco il mio esempio riproducibile ...
Prima generare dati di ritorno:
require(xts)
X.stock.rtns <- xts(rnorm(1000,0.00001,0.0003), Sys.Date()-(1000:1))
Y.stock.rtns <- xts(rnorm(1000,0.00003,0.0004), Sys.Date()-(1000:1))
Z.stock.rtns <- xts(rnorm(1000,0.00005,0.0005), Sys.Date()-(1000:1))
rtn.obj <- merge(X.stock.rtns , Y.stock.rtns, Z.stock.rtns)
colnames(rtn.obj) <- c("x.stock.rtns","y.stock.rtns","z.stock.rtns")
vorrei replicare l'immagine dal risultato di:
require(PerformanceAnalytics)
charts.PerformanceSummary(rtn.obj, geometric=TRUE)
Questo è il mio tentativo finora ...
gg.charts.PerformanceSummary <- function(rtn.obj, geometric=TRUE, main="",plot=TRUE){
# load libraries
suppressPackageStartupMessages(require(ggplot2))
suppressPackageStartupMessages(require(scales))
suppressPackageStartupMessages(require(reshape))
suppressPackageStartupMessages(require(PerformanceAnalytics))
# create function to clean returns if having NAs in data
clean.rtn.xts <- function(univ.rtn.xts.obj,na.replace=0){
univ.rtn.xts.obj[is.na(univ.rtn.xts.obj)]<- na.replace
univ.rtn.xts.obj
}
# Create cumulative return function
cum.rtn <- function(clean.xts.obj, g=TRUE){
x <- clean.xts.obj
if(g==TRUE){y <- cumprod(x+1)-1} else {y <- cumsum(x)}
y
}
# Create function to calculate drawdowns
dd.xts <- function(clean.xts.obj, g=TRUE){
x <- clean.xts.obj
if(g==TRUE){y <- Drawdowns(x)} else {y <- Drawdowns(x,geometric=FALSE)}
y
}
# create a function to create a dataframe to be usable in ggplot to replicate charts.PerformanceSummary
cps.df <- function(xts.obj,geometric){
x <- clean.rtn.xts(xts.obj)
series.name <- colnames(xts.obj)[1]
tmp <- cum.rtn(x,geometric)
tmp$rtn <- x
tmp$dd <- dd.xts(x,geometric)
colnames(tmp) <- c("Cumulative_Return","Daily_Return","Drawdown")
tmp.df <- as.data.frame(coredata(tmp))
tmp.df$Date <- as.POSIXct(index(tmp))
tmp.df.long <- melt(tmp.df,id.var="Date")
tmp.df.long$asset <- rep(series.name,nrow(tmp.df.long))
tmp.df.long
}
# A conditional statement altering the plot according to the number of assets
if(ncol(rtn.obj)==1){
# using the cps.df function
df <- cps.df(rtn.obj,geometric)
# adding in a title string if need be
if(main==""){
title.string <- paste0(df$asset[1]," Performance")
} else {
title.string <- main
}
# generating the ggplot output with all the added extras....
gg.xts <- ggplot(df, aes_string(x="Date",y="value",group="variable"))+
facet_grid(variable ~ ., scales="free", space="free")+
geom_line(data=subset(df,variable=="Cumulative_Return"))+
geom_bar(data=subset(df,variable=="Daily_Return"),stat="identity")+
geom_line(data=subset(df,variable=="Drawdown"))+
ylab("")+
geom_abline(intercept=0,slope=0,alpha=0.3)+
ggtitle(title.string)+
theme(axis.text.x = element_text(angle = 45, hjust = 1))+
scale_x_datetime(breaks = date_breaks("6 months"), labels = date_format("%d/%m/%Y"))
} else {
# a few extra bits to deal with the added rtn columns
no.of.assets <- ncol(rtn.obj)
asset.names <- colnames(rtn.obj)
df <- do.call(rbind,lapply(1:no.of.assets, function(x){cps.df(rtn.obj[,x],geometric)}))
df$asset <- ordered(df$asset, levels=asset.names)
if(main==""){
title.string <- paste0(df$asset[1]," Performance")
} else {
title.string <- main
}
if(no.of.assets>5){legend.rows <- 5} else {legend.rows <- no.of.assets}
gg.xts <- ggplot(df, aes_string(x="Date", y="value",group="asset"))+
facet_grid(variable~.,scales="free",space="free")+
geom_line(data=subset(df,variable=="Cumulative_Return"),aes(colour=factor(asset)))+
geom_bar(data=subset(df,variable=="Daily_Return"),stat="identity",aes(fill=factor(asset),colour=factor(asset)),position="dodge")+
geom_line(data=subset(df,variable=="Drawdown"),aes(colour=factor(asset)))+
ylab("")+
geom_abline(intercept=0,slope=0,alpha=0.3)+
ggtitle(title.string)+
theme(legend.title=element_blank(), legend.position=c(0,1), legend.justification=c(0,1),
axis.text.x = element_text(angle = 45, hjust = 1))+
guides(col=guide_legend(nrow=legend.rows))+
scale_x_datetime(breaks = date_breaks("6 months"), labels = date_format("%d/%m/%Y"))
}
assign("gg.xts", gg.xts,envir=.GlobalEnv)
if(plot==TRUE){
plot(gg.xts)
} else {}
}
# seeing the ggplot equivalent....
gg.charts.PerformanceSummary(rtn.obj, geometric=TRUE)
Ho usato questo come un esercizio per imparare ggplot2. Controllare le leggende era un incubo, ci sono stati molti cambiamenti nel tempo. Una parola chiave è "show_guide = FALSE". Ottenere la leggenda per mostrare sia la forma che il colore è stata dura. L'ho fatto in un modo diverso da quello suggerito dal manuale. Ciò che suggerisce il manuale produce un avvertimento.(Ho commentato il codice sopra, così puoi sperimentare e vedere se ricevi anche degli avvertimenti). C'è un modo per ottenere etichette con più parole e senza trattini o punti, ma ho rinunciato a provare prima di impazzire. Ho rimosso i giorni dall'asse del tempo. Commenti benvenuto !! – PatrickT
Probabilmente mi piacerebbe avere le etichette "Drawdown", "Return", "Index" stampate in nero su bianco anziché in grigio. E probabilmente mi piacerebbe avere il colore grigio di sfondo un po 'più leggero. Credo. Ma fermerò questo piccolo progetto ora. Forse qualcuno può fare ancora un passo avanti. – PatrickT
Ho 2 aggiornamenti che mostrano come personalizzare le etichette di testo e i colori e le griglie dello sfondo. Una cosa che sto notando è che la leggenda sarebbe probabilmente più carina senza il colore di sfondo grigio. Ho intenzione di indovinare che può essere risolto aggiungendo color = "white" all'opzione legend.background = element_rect() all'interno del tema. Ma questa è solo una supposizione ... – PatrickT