Suppose that you consider investing in two stocks: S&P500 and NASDAQ. As a prudent investor, you analyze the historical performance of the stocks for the past 20 years.
library(tidyquant)
library(tidyverse)
Hint: Add group_by(symbol) at the end of the code so that calculations below will be done per stock.
# Import stock prices
from = today() - years(20)
Stocks <-
tq_get(c("^GSPC", "^IXIC"), get = "stock.prices", from = from) %>%
group_by(symbol)
Stocks
## # A tibble: 5,031 x 8
## # Groups: symbol [1]
## symbol date open high low close volume adjusted
## <chr> <date> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 ^IXIC 1999-10-29 2919. 2979. 2919. 2966. 1441380000 2966.
## 2 ^IXIC 1999-11-01 2971. 2998. 2968. 2968. 1076080000 2968.
## 3 ^IXIC 1999-11-02 2984. 3015. 2972. 2982. 1248540000 2982.
## 4 ^IXIC 1999-11-03 3022. 3041. 3012. 3029. 1339050000 3029.
## 5 ^IXIC 1999-11-04 3067. 3077. 3030. 3056. 1364610000 3056.
## 6 ^IXIC 1999-11-05 3100. 3118. 3081. 3102. 1346320000 3102.
## 7 ^IXIC 1999-11-08 3072. 3148. 3069. 3144. 1300800000 3144.
## 8 ^IXIC 1999-11-09 3173. 3175. 3099. 3125. 1470420000 3125.
## 9 ^IXIC 1999-11-10 3126. 3187. 3122. 3156. 1433250000 3156.
## 10 ^IXIC 1999-11-11 3186. 3201. 3169. 3197. 1382840000 3197.
## # … with 5,021 more rows
Hint: Take the adjusted variable from Stocks, and calculate monthly returns using ***tq_transmute().
# Calculate returns.
returns_monthly <-
Stocks %>%
tq_transmute(select = adjusted, mutate_fun = periodReturn, period = "monthly")
returns_monthly
## # A tibble: 241 x 3
## # Groups: symbol [1]
## symbol date monthly.returns
## <chr> <date> <dbl>
## 1 ^IXIC 1999-10-29 0
## 2 ^IXIC 1999-11-30 0.125
## 3 ^IXIC 1999-12-31 0.220
## 4 ^IXIC 2000-01-31 -0.0317
## 5 ^IXIC 2000-02-29 0.192
## 6 ^IXIC 2000-03-31 -0.0264
## 7 ^IXIC 2000-04-28 -0.156
## 8 ^IXIC 2000-05-31 -0.119
## 9 ^IXIC 2000-06-30 0.166
## 10 ^IXIC 2000-07-31 -0.0502
## # … with 231 more rows
Hint: Refer to the ggplot2 cheatsheet. Look for geom_density under One Variable. Use the fill argument to create the plot per each stock.
# density plot
returns_monthly %>%
ggplot(aes(x = monthly.returns, fill = symbol)) +
geom_density(alpha = 0.3)
Hint: Take returns_monthly and pipe it to summarise. Calculate the mean monthly returns.
^IXIC has a higher return. ^IXIC has a return of .64% where ^GSPC has a return of .42%
returns_monthly %>%
summarise(returns_avg = mean(monthly.returns))
## # A tibble: 1 x 2
## symbol returns_avg
## <chr> <dbl>
## 1 ^IXIC 0.00642
Hint: Discuss your answer in terms of standard deviation. Take returns_monthly and pipe it to tidyquant::tq_performance. Use the performance_fun argument to compute sd (standard deviation).
^IXIC is the riskier of the two stocks. They have a standard deviation of 6.5% where ^GSPC has a standard deviation of 4.2%. ^IXIC has a larger standard deviation than ^GSPC.
# Compute standard deviation
returns_monthly %>%
tq_performance(Ra = monthly.returns,
Rb = NULL, # Calculataing downside risk measures doesn't require Rb
performance_fun = sd)
## # A tibble: 1 x 2
## # Groups: symbol [1]
## symbol sd.1
## <chr> <dbl>
## 1 ^IXIC 0.0648
# See options for the `performance_fun` argument
#tq_performance_fun_options()
Hint: when the return distribution is not normal, the standard deviation is not an appropriate measure of risk. One can use skewness and kurtosis to detect non-normal returns. Take returns_monthly and pipe it to tidyquant::tq_performance. Use the performance_fun argument to compute skewness. Do the same for kurtosis.
Both S&P500 and NASDAQ have a negative skewness, long tail to the left, and a positive kurtusis, meaning thick tails, indicating a large negative return is likelier than a large positive return.
# Compute skewness
returns_monthly %>%
tq_performance(Ra = monthly.returns,
Rb = NULL, # Calculataing downside risk measures doesn't require Rb
performance_fun = skewness)
## # A tibble: 1 x 2
## # Groups: symbol [1]
## symbol skewness.1
## <chr> <dbl>
## 1 ^IXIC -0.365
# Compute kurtosis
returns_monthly %>%
tq_performance(Ra = monthly.returns,
Rb = NULL, # Calculataing downside risk measures doesn't require Rb
performance_fun = kurtosis)
## # A tibble: 1 x 2
## # Groups: symbol [1]
## symbol kurtosis.1
## <chr> <dbl>
## 1 ^IXIC 1.56
The return distribution is often not normal. Three additional risk measures are historical ES, expected shortfall, historical VaR, and Semi-deviation. Semi-deviation of .0218 means that the standard deviation of returns below the mean return is .0318. VaR of -.0748 means that -7.48% is the largest loss one could expect with 95% confidence. There is a 5% odd that you could lose more than 7.48%. VaR tells the you the largest loss you expect but there is 5% error that your loss could be larger than posted. ES of -.0949 means that -9.49 is the average of the 5% most negative returns. It shows the worst 5% returns. Var is the skew to the left shows the negative point. ES is to the left of VaR. ES will always be greater than VaR. if VaR is larger than ES you did something wrong.
Hint: Take returns_monthly and pipe it to tidyquant::tq_performance. Use the performance_fun argument to compute table.DownsideRisk.
# Retrieve performance metrics
returns_monthly %>%
tq_performance(Ra = monthly.returns,
Rb = NULL, # Calculataing downside risk measures doesn't require Rb
performance_fun = table.DownsideRisk) %>%
t()
## [,1]
## symbol "^IXIC"
## DownsideDeviation(0%) "0.0449"
## DownsideDeviation(MAR=10%) "0.0489"
## DownsideDeviation(Rf=0%) "0.0449"
## GainDeviation "0.0396"
## HistoricalES(95%) "-0.1456"
## HistoricalVaR(95%) "-0.1047"
## LossDeviation "0.0482"
## MaximumDrawdown "0.7504"
## ModifiedES(95%) "-0.1571"
## ModifiedVaR(95%) "-0.1044"
## SemiDeviation "0.048"
Hint: Discuss your answer in terms of risk and reward.
Based on the return ^IXIC came out on top but when we calculated risk ^GSPC came on top. Since they both came out on top for two different sections. Per unit of risk, the sharpe ratio, measures resturns per unit of risk. Main return divided by standard deviation. Youre underestimating downside risk.