To readers of the book, there was an error in the book code where I missed a group_by(asset)
. Thanks very much to a kind reader for pointing this out! I have corrected the code below at line 265.
Skewness in the xts world
skew_xts <-
skewness(portfolio_returns_xts_rebalanced_monthly$returns)
skew_xts
## [1] -0.2319883
Skewness in the tidyverse
skew_tidy <-
portfolio_returns_tq_rebalanced_monthly %>%
summarise(skew_builtin = skewness(returns),
skew_byhand =
(sum((returns - mean(returns))^3)/length(returns))/
((sum((returns - mean(returns))^2)/length(returns)))^(3/2)) %>%
select(skew_builtin, skew_byhand)
skew_tidy %>%
mutate(xts = coredata(skew_xts)) %>%
mutate_all(funs(round(., 3)))
## # A tibble: 1 x 3
## skew_builtin skew_byhand xts
## <dbl> <dbl> <dbl>
## 1 -0.232 -0.232 -0.232
Visualizing Skewness
portfolio_returns_tq_rebalanced_monthly %>%
ggplot(aes(x = returns)) +
geom_histogram(alpha = .7,
binwidth = .003,
fill = "cornflowerblue",
color = "cornflowerblue") +
scale_x_continuous(breaks =
pretty_breaks(n = 10))
![Returns Histogram](http://d33wubrfki0l68.cloudfront.net/57b6c7ff736d855cbac23015cea6407ee7db165c/b7923/code/2018-06-08-skewness_files/figure-html/unnamed-chunk-3-1.png)
Figure 1: Returns Histogram
portfolio_returns_tq_rebalanced_monthly %>%
mutate(hist_col_red =
if_else(returns < (mean(returns) - 2*sd(returns)),
returns, as.numeric(NA)),
returns =
if_else(returns > (mean(returns) - 2*sd(returns)),
returns, as.numeric(NA))) %>%
ggplot() +
geom_histogram(aes(x = hist_col_red),
alpha = .7,
binwidth = .003,
fill = "red",
color = "red") +
geom_histogram(aes(x = returns),
alpha = .7,
binwidth = .003,
fill = "cornflowerblue",
color = "cornflowerblue") +
scale_x_continuous(breaks = pretty_breaks(n = 10)) +
xlab("monthly returns")
![Shaded Histogram Returns](http://d33wubrfki0l68.cloudfront.net/6f5015c0bd1326bec1997c0761272c6871787c2a/e8f17/code/2018-06-08-skewness_files/figure-html/unnamed-chunk-4-1.png)
Figure 2: Shaded Histogram Returns
portfolio_density_plot <-
portfolio_returns_tq_rebalanced_monthly %>%
ggplot(aes(x = returns)) +
stat_density(geom = "line",
alpha = 1,
colour = "cornflowerblue")
portfolio_density_plot
![Density Plot Skewness](http://d33wubrfki0l68.cloudfront.net/6803a8f61700a57ed4339197ebe3940a081bac35/c077c/code/2018-06-08-skewness_files/figure-html/unnamed-chunk-5-1.png)
Figure 3: Density Plot Skewness
shaded_area_data <-
ggplot_build(portfolio_density_plot)$data[[1]] %>%
filter(x <
mean(portfolio_returns_tq_rebalanced_monthly$returns))
portfolio_density_plot_shaded <-
portfolio_density_plot +
geom_area(data = shaded_area_data,
aes(x = x, y = y),
fill="pink",
alpha = 0.5)
portfolio_density_plot_shaded
![Density Plot with Shaded Area](http://d33wubrfki0l68.cloudfront.net/145e188bb0b401af36c94e260d37f0d089b87dcf/adccf/code/2018-06-08-skewness_files/figure-html/unnamed-chunk-6-1.png)
Figure 4: Density Plot with Shaded Area
median <-
median(portfolio_returns_tq_rebalanced_monthly$returns)
mean <-
mean(portfolio_returns_tq_rebalanced_monthly$returns)
median_line_data <-
ggplot_build(portfolio_density_plot)$data[[1]] %>%
filter(x <= median)
portfolio_density_plot_shaded +
geom_segment(data = shaded_area_data,
aes(x = mean,
y = 0,
xend = mean,
yend = density),
color = "red",
linetype = "dotted") +
annotate(geom = "text",
x = mean,
y = 5,
label = "mean",
color = "red",
fontface = "plain",
angle = 90,
alpha = .8,
vjust = -1.75) +
geom_segment(data = median_line_data,
aes(x = median,
y = 0,
xend = median,
yend = density),
color = "black",
linetype = "dotted") +
annotate(geom = "text",
x = median,
y = 5,
label = "median",
fontface = "plain",
angle = 90,
alpha = .8,
vjust = 1.75) +
ggtitle("Density Plot Illustrating Skewness")
![Density Plot Shaded with Lines](http://d33wubrfki0l68.cloudfront.net/201334db62e496753824b9841095d02b0588acd9/00e2c/code/2018-06-08-skewness_files/figure-html/unnamed-chunk-9-1.png)
Figure 5: Density Plot Shaded with Lines
asset_returns_long %>%
# The following line group_by(asset) is not in the book!
# It was added after a tip from a very kind reader. I will post a full explanation of why it is needed and why it was missing to begin with. Mea culpa!
group_by(asset) %>%
summarize(skew_assets = skewness(returns)) %>%
add_row(asset = "Portfolio",
skew_assets = skew_tidy$skew_byhand)%>%
ggplot(aes(x = asset,
y = skew_assets,
colour = asset)) +
geom_point() +
geom_text(
aes(x = "Portfolio",
y =
skew_tidy$skew_builtin + .04),
label = "Portfolio",
color = "cornflowerblue") +
# alternate geom_text()
# Here's a way to label all the points
# geom_text(aes(label = asset),
# nudge_y = .04)
labs(y = "skewness")
![Asset and Portfolio Skewness Comparison](http://d33wubrfki0l68.cloudfront.net/947f278eec590bd322aed015831f9ea374e5d78d/f8b95/code/2018-06-08-skewness_files/figure-html/unnamed-chunk-10-1.png)
Figure 6: Asset and Portfolio Skewness Comparison
Rolling Skewness in the xts world
window <- 24
rolling_skew_xts <-
rollapply(portfolio_returns_xts_rebalanced_monthly,
FUN = skewness,
width = window) %>%
na.omit()
Rolling Skewness in the tidyverse with tibbletime
skew_roll_24 <-
rollify(skewness, window = window)
roll_skew_tibbletime <-
portfolio_returns_tq_rebalanced_monthly %>%
as_tbl_time(index = date) %>%
mutate(skew = skew_roll_24(returns)) %>%
select(-returns) %>%
na.omit()
Rolling Skewness in the tidyquant world
rolling_skew_tq <-
portfolio_returns_tq_rebalanced_monthly %>%
tq_mutate(select = returns,
mutate_fun = rollapply,
width = window,
FUN = skewness,
col_rename = "tq") %>%
na.omit()
rolling_skew_tq %>%
select(-returns) %>%
mutate(xts = coredata(rolling_skew_xts),
tbltime = roll_skew_tibbletime$skew) %>%
mutate_if(is.numeric, funs(round(., 3))) %>%
tail(3)
## # A tibble: 3 x 4
## date tq xts tbltime
## <date> <dbl> <dbl> <dbl>
## 1 2017-10-31 0.083 0.083 0.083
## 2 2017-11-30 -0.004 -0.004 -0.004
## 3 2017-12-31 0.018 0.018 0.018
Visualizing Rolling Skewness
highchart(type = "stock") %>%
hc_title(text = "Rolling 24-Month Skewness") %>%
hc_add_series(rolling_skew_xts,
name = "Rolling skewness",
color = "cornflowerblue") %>%
hc_yAxis(title = list(text = "skewness"),
opposite = FALSE,
max = 1,
min = -1) %>%
hc_navigator(enabled = FALSE) %>%
hc_scrollbar(enabled = FALSE) %>%
hc_add_theme(hc_theme_flat()) %>%
hc_exporting(enabled = TRUE)
rolling_skew_tq %>%
ggplot(aes(x = date, y = tq)) +
geom_line(color = "cornflowerblue") +
ggtitle("Rolling 24-Month Skew ") +
ylab(paste("Rolling ", window, " month skewness",
sep = " ")) +
scale_y_continuous(limits = c(-1, 1),
breaks = pretty_breaks(n = 8)) +
scale_x_date(breaks = pretty_breaks(n = 8)) +
theme_update(plot.title = element_text(hjust = 0.5))
![Rolling Skewness ggplot](http://d33wubrfki0l68.cloudfront.net/7f3588ffdc1040ec74f2f6a4669ab103be28630d/e8bea/code/2018-06-08-skewness_files/figure-html/unnamed-chunk-17-1.png)
Figure 7: Rolling Skewness ggplot