Performanceanalytics Charts and Tables Overview: Peter Carl & Brian G. Peterson February 5, 2020
Performanceanalytics Charts and Tables Overview: Peter Carl & Brian G. Peterson February 5, 2020
Abstract
This vignette gives a brief overview of (some of) the graphics and display wrapper
functionality contained in PerformanceAnalytics including most of the charts and
tables . For a more complete overview of the package’s functionality and extensibility
see the manual pages. We develop the examples using data for six (hypothetical)
managers, a peer index, and an asset class index.
Contents
1 Introduction 2
2 Set up PerformanceAnalytics 2
2.1 Install PerformanceAnalytics . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.2 Load and review data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.3 Create charts and tables for presentation . . . . . . . . . . . . . . . . . . . 5
4 Conclusion 26
1
1 Introduction
PerformanceAnalytics is a library of functions designed for evaluating the performance
and risk characteristics of financial assets or funds. In particular, we have focused on
functions that have appeared in the academic literature over the past several years, but
had no functional equivalent in R.
Our goal for PerformanceAnalytics is to make it simple for someone to ask and
answer questions about performance and risk as part of a broader investment decision-
making process. There is no magic bullet here – there won’t be one right answer delivered
in these metrics and charts. Investments must be made in context of investment objectives.
But what this library aspires to do is help the decision-maker accrete evidence organized
to answer a specific question that is pertinent to the decision at hand. Our hope is that
using such tools to uncover information and ask better questions will, in turn, create a
more informed investor and help them ask better quality decisions.
This vignette provides a demonstration of some of the capabilities of PerformanceAn-
alytics. We focus on the graphs and tables, but comment on some other metrics along
the way. These examples are not intended to be complete, but they should provide an
indication of the kinds of analysis that can be done. Other examples are available in the
help pages of the functions described in the main page of PerformanceAnalytics.
2 Set up PerformanceAnalytics
These examples assume the reader has basic knowledge of R and understands how to in-
stall R, read and manipulate data, and create basic calculations. For further assistance,
please see http://cran.r-project.org/doc/manuals/R-intro.pdf and other available
materials at http://cran.r-project.org. This section will begin with installation, dis-
cuss the example data set, and provide an overview of charts attributes that will be used
in the examples that follow.
2
Figure 1: First Lines of the managers Object
> data(managers)
> #managers=read.csv("/home/peter/dev/R/managers.csv",row.names=1)
> head(managers)
3
Figure 2: Assess and Organize the Data
> dim(managers)
[1] 132 10
> manager.col = 1
> peers.cols = c(2,3,4,5,6)
> indexes.cols = c(7,8)
> Rf.col = 10
> #factors.cols = NA
> trailing12.rows = ((managers.length - 11):managers.length)
> trailing12.rows
[1] 121 122 123 124 125 126 127 128 129 130 131 132
4
2.3 Create charts and tables for presentation
Graphs and charts help to organize information visually. Our goals in creating these func-
tions were to simplify the process of creating well-formatted charts that are frequently used
for portfolio analysis and to create print-quality graphics that may be used in documents
for broader consumption. R’s graphics capabilities are substantial, but the simplicity of
the output of R’s default graphics functions such as plot does not always compare well
against graphics delivered with commercial asset or portfolio analysis software from places
such as MorningStar or PerTrac.
Color Palettes
We have set up some specific color palattes designed to create readable line and bar graphs
with specific objectives. We use this approach (rather than generating them on the fly) for
two reasons: first, there are fewer dependencies on libraries that don’t need to be called
dynamically; and second, to guarantee the color used for the n-th column of data. Figure
3 shows some examples of the different palates.
The first category of colorsets are designed to provide focus to the data graphed as
the first element, and include redfocus, bluefocus, and greenfocus. These palettes
are best used when there is an important data set for the viewer to focus on. The other
data provide some context, so they are graphed in diminishing values of gray. These were
generated with RColorBrewer, using the 8 level ”grays” palette and replacing the darkest
gray with the focus color. To coordinate these colorsets with the equal-weighted colors
below, replace the highlight color with the first color of the equal weighted palette from
below. This will coordinate charts with different purposes.
The second category is sets of equal-weighted colors. These colorsets are useful for
when all of the data should be observed and distinguishable on a line graph. The different
numbers in the name indicate the number of colors generated (six colors is probably the
maximum for a readable linegraph, but we provide as many as twelve). Examples include
rainbow12equal through rainbow4equal, in steps of two. These colorsets were gener-
ated with rainbow(12,s = 0.6,v = 0.75). The rich12equal and other corresponding
colorsets were generated with with package gplots function rich.colors(12). Simi-
larly tim12equal and similar colorsets were generated with with package fields func-
tion tim.colors(12), a function said to emulate the Matlab colorset. The dark8equal,
dark6equal, set8equal, and set6equal colorsets were created with package RColor-
Brewer, e.g., brewer.pal(8,"Dark2"). A third category is a set of monochrome colorsets,
including greenmono , bluemono, redmono, and gray8mono and gray6mono.
To see what these lists contain, just type the name.
> tim12equal
5
[1] "#00008F" "#0000EA" "#0047FF" "#00A2FF" "#00FEFF" "#5AFFA5" "#B5FF4A"
[8] "#FFED00" "#FF9200" "#FF3700" "#DB0000" "#800000"
These are just lists of strings that contain the RGB codes of each color. You can easily
create your own if you have a particular palate that you like to use. Alternatively, you can
use the R default colors. For more information, see:
HTTP://research.stowers-institute.org/efg/R/Color/Chart/index.htm
Symbols
Similarly, there are a few sets of grouped symbols for scatter charts . These include
opensymbols, closedsymbols, fillsymbols, linesymbols, and allsymbols.
Legend locations
In the single charts the legend can be moved around on the plot. There are nine locations
that can be specified by keyword: ”bottomright”, ”bottom”, ”bottomleft”, ”left”, ”topleft”,
”top”, ”topright”, ”right” and ”center”. This places the legend on the inside of the plot frame
at the given location. Further information can be found in xy.coord. Most compound
charts have fixed legend locations.
Other Parameters
We have tried to leave access to all of the extensive list of parameters available in R’s
traditional graphics. For more information, see plot.default and par. In the example
above, we passed lwd the value of 2, which affects the line width. We might also alter the
line type or other parameter.
6
Figure 3: Examples of Color Palettes
default
1996−01−31 / 2006−12−31 redfocus
1996−01−31 / 2006−12−31
HAM1 HAM1
4 HAM2 4 HAM2
HAM3 HAM3
HAM4 HAM4
3 HAM5 3 HAM5
HAM6 HAM6
2 2
1 1
Jan Jul Jan Jul Jan Jan Jul Jan Jul Jan
1996 1998 2001 2003 2006 1996 1998 2001 2003 2006
rainbow6equal
1996−01−31 / 2006−12−31 tim6equal
1996−01−31 / 2006−12−31
HAM1 HAM1
4 HAM2 4 HAM2
HAM3 HAM3
HAM4 HAM4
3 HAM5 3 HAM5
HAM6 HAM6
2 2
1 1
Jan Jul Jan Jul Jan Jan Jul Jan Jul Jan
1996 1998 2001 2003 2006 1996 1998 2001 2003 2006
7
Figure 4: Draw a Performance Summary Chart
HAM1 Performance
3.0
2.5
2.0
1.5
Monthly Return
0.05
0.00
−0.05
Drawdown
−0.1
−0.2
−0.3
−0.4
Jan Jan Jan Jan Jan Jan Jan Jan Jan Jan Jan
1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006
8
begin = "first", which starts the wealth index of each column at the wealth index value
attained by the first column of data specified. The second of these settings, which is the
default, allows the reader to see how the two indexes would compare had they started at
the same time regardless of the starting period. In addition, the y-axis can be set to a
logarithmic value so that growth can be compared over long periods. This chart can be
generated independently using chart.CumReturns.
The second chart shows the individual monthly returns overlaid with a rolling measure
of tail risk referred to as Cornish Fisher Value-at-Risk (VaR) or Modified VaR. Alternative
risk measures, including standard deviation (specified as StdDev) and traditional Value-
at-Risk (VaR), can be specified using the method parameter. Note that StdDev and VaR are
symmetric calculations, so a high and low measure will be plotted. ModifiedVaR, on the
other hand, is asymmetric and only a lower bound is drawn. These risk calculations are
made on a rolling basis from inception, or can be calculated on a rolling window by setting
width to a value of the number of periods. These calculations should help the reader to
identify events or periods when estimates of tail risk may have changed suddenly, or to
help evaluate whether the assumptions underlying the calculation seem to hold . The risk
calculations can be generated for all of the columns provided by using the all parameter.
When set to TRUE, the function calculates risk lines for each column given and may help
the reader assess relative risk levels through time. This chart can be generated using
chart.BarVaR.
The third chart in the series is a drawdown or underwater chart, which shows the level
of losses from the last value of peak equity attained. Any time the cumulative returns
dips below the maximum cumulative returns, it’s a drawdown. This chart helps the reader
assess the synchronicity of the loss periods and their comparative severity. As you might
expect, this chart can also be created using chart.Drawdown.
9
Figure 5: Create a Table of Calendar Returns
> t(table.CalendarReturns(managers[,c(manager.col,indexes.cols)]))
1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006
Jan 0.7 2.1 0.6 -0.9 -1.0 0.8 1.4 -4.1 0.5 0.0 6.9
Feb 1.9 0.2 4.3 0.9 1.2 0.8 -1.2 -2.5 0.0 2.1 1.5
Mar 1.6 0.9 3.6 4.6 5.8 -1.1 0.6 3.6 0.9 -2.1 4.0
Apr -0.9 1.3 0.8 5.1 2.0 3.5 0.5 6.5 -0.4 -2.1 -0.1
May 0.8 4.4 -2.3 1.6 3.4 5.8 -0.2 3.4 0.8 0.4 -2.7
Jun -0.4 2.3 1.2 3.3 1.2 0.2 -2.4 3.1 2.6 1.6 2.2
Jul -2.3 1.5 -2.1 1.0 0.5 2.1 -7.5 1.8 0.0 0.9 -1.4
Aug 4.0 2.4 -9.4 -1.7 3.9 1.6 0.8 0.0 0.5 1.1 1.6
Sep 1.5 2.2 2.5 -0.4 0.1 -3.1 -5.8 0.9 0.9 2.6 0.7
Oct 2.9 -2.1 5.6 -0.1 -0.8 0.1 3.0 4.8 -0.1 -1.9 4.3
Nov 1.6 2.5 1.3 0.4 1.0 3.4 6.6 1.7 3.9 2.3 1.2
Dec 1.8 1.1 1.0 1.5 -0.7 6.8 -3.2 2.8 4.4 2.6 1.1
HAM1 13.6 20.4 6.1 16.1 17.7 22.4 -8.0 23.7 14.9 7.8 20.5
EDHEC LS EQ NA 21.4 14.6 31.4 12.0 -1.2 -6.4 19.3 8.6 11.3 11.7
SP500 TR 23.0 33.4 28.6 21.0 -9.1 -11.9 -22.1 28.7 10.9 4.9 15.8
10
Figure 6: Create a Table of Statistics
> table.Stats(managers[,c(manager.col,peers.cols)])
11
3.4 Compare distributions
For distributional analysis, a few graphics may be useful. The result of chart.Boxplot,
shown in Figure 7, is an example of a graphic that is difficult to create in Excel and is
under-utilized as a result. A boxplot of returns is, however, a very useful way to observe
the shape of large collections of asset returns in a manner that makes them easy to compare
to one another.
It is often valuable when evaluating an investment to know whether the instrument that
you are examining follows a normal distribution. One of the first methods to determine
how close the asset is to a normal or log-normal distribution is to visually look at your
data. Both chart.QQPlot and chart.Histogram will quickly give you a feel for whether
or not you are looking at a normally distributed return history. Figure 8 shows a histogram
generated for HAM1 with different display options.
Look back at the results generated by table.Stats. Differences between var and
SemiVariance will help you identify [fBasics]skewness in the returns. Skewness mea-
sures the degree of asymmetry in the return distribution. Positive skewness indicates that
more of the returns are positive, negative skewness indicates that more of the returns are
negative. An investor should in most cases prefer a positively skewed asset to a similar
(style, industry, region) asset that has a negative skewness. Kurtosis measures the con-
centration of the returns in any given part of the distribution (as you should see visually
in a histogram). The [fBasics]kurtosis function will by default return what is referred
to as “excess kurtosis”, where zero is a normal distribution, other methods of calculating
kurtosis than method="excess" will set the normal distribution at a value of 3. In general
a rational investor should prefer an asset with a low to negative excess kurtosis, as this will
indicate more predictable returns. If you find yourself needing to analyze the distribution
of complex or non-smooth asset distributions, the nortest package has several advanced
statistical tests for analyzing the normality of a distribution.
12
Figure 7: Create a Boxplot
HAM1 ● ●
HAM4 ●
HAM6 ●
SP500 TR ●
EDHEC LS EQ ●
HAM3 ● ●
HAM5 ●
HAM2 ● ●
Return
13
Figure 8: Create a Histogram of Returns
> layout(rbind(c(1,2),c(3,4)))
> chart.Histogram(managers[,1,drop=F], main = "Plain", methods = NULL)
> chart.Histogram(managers[,1,drop=F], main = "Density", breaks=40,
+ methods = c("add.density", "add.normal"))
> chart.Histogram(managers[,1,drop=F], main = "Skew and Kurt", methods = c
+ ("add.centered", "add.rug"))
> chart.Histogram(managers[,1,drop=F], main = "Risk Measures", methods = c
+ ("add.risk"))
Plain Density
30
30
Frequency
Density
20
20
10
5 10
5
0
Returns Returns
30
20
Frequency
Density
20
15
10
10
5
5
0
Returns Returns
14
Figure 9: Show Relative Risk and Return
● HAM1
● HAM6 ● HAM4
Annualized Return
● EDHEC LS EQTR
● SP500
0.10
● HAM3
● HAM5
● HAM2
0.05
0.00
Annualized Risk
15
the appropriate Sharpe ratio level. Lines should be removed where not appropriate (e.g.,
sharpe.ratio = NULL). With a large number of assets (or columns), the names may get in
the way. To remove them, set add.names = NULL. A box plot may be added to the margins
to help identify the relative performance quartile by setting add.boxplots = TRUE.
16
Figure 10: Examine Rolling Performance
0.8
0.6
0.4
0.2
0.0
−0.2
Annualized Standard Deviation
0.30
0.25
0.20
0.15
0.10
0.05
Annualized Sharpe Ratio
6
4
2
0
−2
Jan Jan Jan Jan Jan Jan Jan Jan Jan Jan Jan
1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006
17
Figure 11: Examine Relative Performance of Assets
HAM1.HAM2
HAM1.HAM3
1.6 HAM1.HAM4
HAM1.HAM5
HAM1.HAM6
HAM1.EDHEC.LS.EQ
1.4
1.2
1.0
0.8
0.6
0.4
Jan Jan Jan Jan Jan Jan Jan Jan Jan Jan Jan
1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006
18
Figure 12: Examine Performance Relative to a Benchmark
HAM1.SP500.TR
HAM2.SP500.TR
HAM3.SP500.TR
2.5 HAM4.SP500.TR
HAM5.SP500.TR
HAM6.SP500.TR
2.0
1.5
1.0
Jan Jan Jan Jan Jan Jan Jan Jan Jan Jan Jan
1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006
19
Model (CAPM), the efficient market hypothesis, and all forms of quantitative portfolio
construction and optimization. CAPM provides a justification for passive or index invest-
ing by positing that assets that are not on the efficient frontier will either rise or lower in
price until they are on the efficient frontier of the market portfolio.
The performance premium provided by an investment over a passive strategy (the
benchmark) is provided by ActivePremium, which is the investment’s annualized return
minus the benchmark’s annualized return. A closely related measure is the TrackingEr-
ror, which measures the unexplained portion of the investment’s performance relative to
a benchmark. The InformationRatio of an Investment in a MPT or CAPM framework
is the ActivePremium divided by the TrackingError. InformationRatio may be used
to rank investments in a relative fashion.
The code in Figure 13 creates a table of CAPM-related statistics that we can review
and compare across managers. Note that we focus on the trailing-36 month period. There
are, in addition to those listed, a wide variety of other CAPM-related metrics available.
The CAPM.RiskPremium on an investment is the measure of how much the asset’s perfor-
mance differs from the risk free rate. Negative Risk Premium generally indicates that the
investment is a bad investment, and the money should be allocated to the risk free asset
or to a different asset with a higher risk premium. CAPM.alpha is the degree to which the
assets returns are not due to the return that could be captured from the market. Con-
versely, CAPM.beta describes the portions of the returns of the asset that could be directly
attributed to the returns of a passive investment in the benchmark asset. The Capital
Market Line CAPM.CML relates the excess expected return on an efficient market portfolio
to its risk (represented in CAPM by StdDev). The slope of the CML, CAPM.CML.slope,
is the Sharpe Ratio for the market portfolio. The Security Market Line is constructed by
calculating the line of CAPM.RiskPremium over CAPM.beta. For the benchmark asset this
will be 1 over the risk premium of the benchmark asset. The slope of the SML, primarily
for plotting purposes, is given by CAPM.SML.slope. CAPM is a market equilibrium model
or a general equilibrium theory of the relation of prices to risk, but it is usually applied to
partial equilibrium portfolios which can create (sometimes serious) problems in valuation.
In a similar fashion to the rolling performance we displayed earlier, we can look at the
stability of a linear model’s parameters through time. Figure 14 shows a three panel chart
for the alpha, beta, and r-squared measures through time across a rolling window. Each
chart calls chart.RollingRegression with a different method parameter.
Likewise, we can assess whether the correlation between two time series is constant
through time. Figure 15 shows the rolling 12-month correlation between each of the peer
group and the S&P500. To look at the relationships over time and take a snapshot of the
statistical relevance of the measure, use table.Correlation, as shown in Figure 16.
20
Figure 13: Create a Table of CAPM-Related Measures
21
Figure 14: Create a Rolling Regression
> #source("PerformanceAnalytics/R/Return.excess.R")
> charts.RollingRegression(managers[, c(manager.col, peers.cols), drop = FALSE], m
0.8
0.6
0.4
0.2
0.0
Beta
1.0
0.5
0.0
R−Squared
0.8
0.6
0.4
0.2
Jan Jan Jan Jan Jan Jan Jan Jan Jan Jan Jan
1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006
22
Figure 15: Chart the Rolling Correlation
0.5
0.0
−0.5
Jan Jan Jan Jan Jan Jan Jan Jan Jan Jan Jan
1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006
23
Figure 16: Calculate Correlations
24
Figure 17: Create a Table of Downside Statistics
> table.DownsideRisk(managers[,1:6],Rf=.03/12)
> table.Drawdowns(managers[,1,drop=F])
25
4 Conclusion
With that short overview of a few of the capabilities provided by PerformanceAnalytics,
we hope that the accompanying package and documentation will partially fill a hole in the
tools available to a financial engineer or analyst. If you think there’s an important gap or
possible improvement to be made, please don’t hesitate to contact us.
26