In this post we will calculate the following portfolio statistics using R.

  • Portfolio average returns
  • Portfolio standard deviation
  • Portfolio Sharpe ratio

As usual we will start with loading our libraries.

library(tidyquant)
library(timetk)

We will use the same assets from the last post to build our portfolio.

# Create the tickers and weights vector

tickers = c('BND', 'VB', 'VEA', 'VOO', 'VWO')

wts = c(0.1,0.2,0.25,0.25,0.2)

Next lets download the price data from yahoo finance.

price_data <- tq_get(tickers,
                     from = '2013-01-01',
                     to = '2018-03-01',
                     get = 'stock.prices')

Next we will calculate the daily returns for our assets.

ret_data <- price_data %>%
  group_by(symbol) %>%
  tq_transmute(select = adjusted,
               mutate_fun = periodReturn,
               period = "daily",
               col_rename = "ret")

We will use the tq_portfolio package to quickly calculate the portfolio returns.

port_ret <- ret_data %>%
  tq_portfolio(assets_col = symbol,
               returns_col = ret,
               weights = wts,
               col_rename = 'port_ret',
               geometric = FALSE)

Lets look at the total cumulative returns for our portfolio.

port_ret %>%
  mutate(cr = cumprod(1 + port_ret)) %>%
  ggplot(aes(x = date, y = cr)) +
  geom_line() +
  labs(x = 'Date',
       y = 'Cumulative Returns',
       title = 'Portfolio Cumulative Returns') +
  theme_bw() +
  scale_y_continuous(breaks = seq(1,2,0.1)) +
  scale_x_date(date_breaks = 'year',
               date_labels = '%Y')

Now lets begin by calculating the average annual portfolio returns.

average_annual_port_ret <- port_ret %>%
  tq_performance(Ra = port_ret,
                 performance_fun = Return.annualized)

cat("The average annual portfolio returns is ", round((average_annual_port_ret[[1]] * 100),2),"%", sep = "")
## The average annual portfolio returns is 9.22%

Next we will calculate the portfolio standard deviation or volatility. There are two methods to do this. We will first calculate this manually. For that we need to calculate the daily portfolio volatility.

daily_port_sd <- sd(port_ret$port_ret)

cat("The daily portfolio volatility is", round((daily_port_sd),4))
## The daily portfolio volatility is 0.0076

Now we need to annualize this to find the annual volatility.

annual_port_sd <- daily_port_sd * sqrt(252)

cat("The annual portfolio volatility is", round((annual_port_sd),4))
## The annual portfolio volatility is 0.1204

We can use the built in formula to calculate this as well, but to use that we need to convert our data into an xts format. We can do that as shown below.

annual_port_sd_xts <- StdDev.annualized(tk_xts(port_ret, silent = TRUE))

cat("The annual portfolio volatility using the xts method is", round((annual_port_sd_xts),4))
## The annual portfolio volatility using the xts method is 0.1204

We can see that we get the same answer. Use whatever method you find easier.

Next we will find the portfolio’s Sharpe ratio. We will first calculate it manually and then we will use the built in formula.

sharpe_ratio_manually <- average_annual_port_ret$AnnualizedReturn / annual_port_sd

cat("The annual portfolio sharpe ratio calculated manually is", round((sharpe_ratio_manually),4))
## The annual portfolio sharpe ratio calculated manually is 0.7658

If Risk free interest rate is 4% (as it was pre 2008 crisis), then we get the Sharpe ratio as follows.

sharpe_ratio_manually_rf_4 <- (average_annual_port_ret$AnnualizedReturn - 0.04) / annual_port_sd

cat("The annual portfolio sharpe ratio calculated manually when risk free interest rate is at 4% is", round((sharpe_ratio_manually_rf_4),4))
## The annual portfolio sharpe ratio calculated manually when risk free interest rate is at 4% is 0.4337

We could do this using the tq_performance function.

sharpe_ratio <- port_ret %>%
  tq_performance(Ra = port_ret,
                 performance_fun = SharpeRatio.annualized) %>%
  .[[1]]

cat("The annual portfolio sharpe ratio calculated using the tq_performance function is", round((sharpe_ratio),4))
## The annual portfolio sharpe ratio calculated using the tq_performance function is 0.7658

We can also change the risk free rate to 4%.

sharpe_ratio_rf_4 <- port_ret %>%
  tq_performance(Ra = port_ret,
                 performance_fun = SharpeRatio.annualized,
                 Rf = 0.04/252) %>%
  .[[1]]

cat("The annual portfolio sharpe ratio calculated using the tq_performance function when Rf is 45 is", round((sharpe_ratio_rf_4),4))
## The annual portfolio sharpe ratio calculated using the tq_performance function when Rf is 45 is 0.4103

This is slightly different that our manually calculated number. This is due to the tq_performance function calculating the daily excess returns and then annualizing it. This causes the slight difference between our manual calculation, which ignored the daily excess returns.