S&P 500 daily returns 2015 - 2018
Data
This plot uses the sp500 data frame of the gcubed package. Rows 250, 500, 750 and 1000 of the data frame are shown below.
library(gcubed)
sp500[c(250,500,750,1000),]
## # A tibble: 4 x 12
## Month Day Year Open High Low Close `Adj Close` Volume PrevClose
## <int> <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 12 29 2015 2061. 2082. 2061. 2078. 2078. 2.54e9 2056.
## 2 12 23 2016 2260. 2264. 2259. 2264. 2264. 2.02e9 2261.
## 3 12 21 2017 2683. 2693. 2682. 2685. 2685. 3.27e9 2679.
## 4 12 20 2018 2497. 2510. 2441. 2467. 2467. 5.59e9 2507.
## # … with 2 more variables: daily_return <dbl>, abs_ret <dbl>
First, we will restrict the data to only those entries from the year 2018. Then we will create a new column, updown that will simply say whether or not each day’s return represented a gain or a loss. This will be used later to colour the bars of the plot.
## # A tibble: 4 x 13
## Month Day Year Open High Low Close `Adj Close` Volume PrevClose
## <int> <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 12 29 2015 2061. 2082. 2061. 2078. 2078. 2.54e9 2056.
## 2 12 23 2016 2260. 2264. 2259. 2264. 2264. 2.02e9 2261.
## 3 12 21 2017 2683. 2693. 2682. 2685. 2685. 3.27e9 2679.
## 4 5 27 2015 2105. 2126. 2105. 2123. 2123. 3.13e9 2104.
## # … with 3 more variables: daily_return <dbl>, abs_ret <dbl>,
## # MonthDay <chr>
Code for plot
We will use the geom_bar geometry to create this plot. The fill aesthetic_ will be used to colour the bars appropriately for positive and negative daily returns.
library(ggplot2)
sp_plt <- ggplot(data = df, aes(x = MonthDay, y = daily_return)) +
geom_bar(stat = "identity") +
facet_wrap(~Year) +
ylab("Daily Returns (% of Prev Close)") +
ggtitle("S&P 500 Daily Returns (2015 - 2018)")
sp_plt
At present the x-axis labels are from a categorical variable, MonthDay. The hundreds of overlapping values being displayed can be removed to de-clutter the lower portion of the plot.
sp_plt <- sp_plt +
theme(plot.title = element_text(size = 16, face = "bold", hjust = 0.5),
panel.background = element_blank(), axis.title.x=element_blank(),
axis.text.x = element_blank(), axis.ticks.x = element_blank())
sp_plt
To add bands representing 95th and 99th percentile moves, first we use determine what the 95th and 99th percentile moves are.
df$abs_return <- abs(df$daily_return)
head(df)
## # A tibble: 6 x 14
## Month Day Year Open High Low Close `Adj Close` Volume PrevClose
## <int> <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 2 2015 2059. 2072. 2046. 2058. 2058. 2.71e9 2059.
## 2 1 5 2015 2054. 2054. 2017. 2021. 2021. 3.80e9 2058.
## 3 1 6 2015 2022. 2030. 1992. 2003. 2003. 4.46e9 2021.
## 4 1 7 2015 2006. 2030. 2006. 2026. 2026. 3.81e9 2003.
## 5 1 8 2015 2031. 2064. 2031. 2062. 2062. 3.93e9 2026.
## 6 1 9 2015 2063. 2064. 2038. 2045. 2045. 3.36e9 2062.
## # … with 4 more variables: daily_return <dbl>, abs_ret <dbl>,
## # MonthDay <chr>, abs_return <dbl>
pct95 <- quantile(df$abs_return, .95)
pct95
## 95%
## 1.817147
pct99 <- quantile(df$abs_return, .99)
pct99
## 99%
## 2.945549
The bands can be added using annotate to create the ribbons.
sp_plt <- sp_plt +
annotate("ribbon", ymin = pct95, ymax = pct99, x = c(-Inf,Inf), alpha = 0.3, fill = "95") +
annotate("ribbon", ymin = pct99, ymax = Inf, x = c(-Inf, Inf), alpha = 0.3, fill = "99") +
annotate("ribbon", ymax = -pct95, ymin = -pct99, x = c(-Inf,Inf), alpha = 0.3, fill = "95") +
annotate("ribbon", ymax = -pct99, ymin = -Inf, x = c(-Inf, Inf), alpha = 0.3, fill = "99")
sp_plt
To add the text, annotate can be used again. This time with the geom argument set to “text”.
sp_plt <- sp_plt +
annotate("text", label = "95th percentile", y = (pct95+pct99)/2, x = "06-01" ) +
annotate("text", label = "99th percentile", y = pct99 + (pct99-pct95)/2, x = "06-01")
sp_plt
The complete code for the plot
sp_plt <- ggplot(data = df, aes(x = MonthDay, y = daily_return)) +
geom_bar(stat = "identity") +
facet_wrap(~Year) +
ylab("Daily Returns (% of Prev Close)") +
ggtitle("S&P 500 Daily Returns (2015 - 2018)") +
theme(plot.title = element_text(size = 16, face = "bold", hjust = 0.5),
panel.background = element_blank(), axis.title.x=element_blank(),
axis.text.x = element_blank(), axis.ticks.x = element_blank()) +
annotate("ribbon", ymin = pct95, ymax = pct99, x = c(-Inf,Inf), alpha = 0.3, fill = "95") +
annotate("ribbon", ymin = pct99, ymax = Inf, x = c(-Inf, Inf), alpha = 0.3, fill = "99") +
annotate("ribbon", ymax = -pct95, ymin = -pct99, x = c(-Inf,Inf), alpha = 0.3, fill = "95") +
annotate("ribbon", ymax = -pct99, ymin = -Inf, x = c(-Inf, Inf), alpha = 0.3, fill = "99") +
annotate("text", label = "95th percentile", y = (pct95+pct99)/2, x = "06-01" ) +
annotate("text", label = "99th percentile", y = pct99 + (pct99-pct95)/2, x = "06-01")
sp_plt