# Load packages
library(tidyquant)
## Warning: package 'tidyquant' was built under R version 4.0.3
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.0.3
# Import stock prices and calculate returns
returns_quarterly <- c("^DJI", "^GSPC", "^IXIC") %>%
tq_get(get = "stock.prices",
from = "1990-01-01",
to = "2020-11-01") %>%
group_by(symbol) %>%
tq_transmute(select = adjusted,
mutate_fun = quarterlyReturn)
returns_quarterly
## # A tibble: 372 x 3
## # Groups: symbol [3]
## symbol date quarterly.returns
## <chr> <date> <dbl>
## 1 ^DJI 1990-03-30 -0.0366
## 2 ^DJI 1990-06-29 0.0641
## 3 ^DJI 1990-09-28 -0.149
## 4 ^DJI 1990-12-31 0.0739
## 5 ^DJI 1991-03-28 0.106
## 6 ^DJI 1991-06-28 -0.00244
## 7 ^DJI 1991-09-30 0.0378
## 8 ^DJI 1991-12-31 0.0504
## 9 ^DJI 1992-03-31 0.0210
## 10 ^DJI 1992-06-30 0.0257
## # ... with 362 more rows
# See options for the `performance_fun` argument
tq_performance_fun_options()
## $table.funs
## [1] "table.AnnualizedReturns" "table.Arbitrary"
## [3] "table.Autocorrelation" "table.CAPM"
## [5] "table.CaptureRatios" "table.Correlation"
## [7] "table.Distributions" "table.DownsideRisk"
## [9] "table.DownsideRiskRatio" "table.DrawdownsRatio"
## [11] "table.HigherMoments" "table.InformationRatio"
## [13] "table.RollingPeriods" "table.SFM"
## [15] "table.SpecificRisk" "table.Stats"
## [17] "table.TrailingPeriods" "table.UpDownRatios"
## [19] "table.Variability"
##
## $CAPM.funs
## [1] "CAPM.alpha" "CAPM.beta" "CAPM.beta.bear" "CAPM.beta.bull"
## [5] "CAPM.CML" "CAPM.CML.slope" "CAPM.dynamic" "CAPM.epsilon"
## [9] "CAPM.jensenAlpha" "CAPM.RiskPremium" "CAPM.SML.slope" "TimingRatio"
## [13] "MarketTiming"
##
## $SFM.funs
## [1] "SFM.alpha" "SFM.beta" "SFM.CML" "SFM.CML.slope"
## [5] "SFM.dynamic" "SFM.epsilon" "SFM.jensenAlpha"
##
## $descriptive.funs
## [1] "mean" "sd" "min" "max"
## [5] "cor" "mean.geometric" "mean.stderr" "mean.LCL"
## [9] "mean.UCL"
##
## $annualized.funs
## [1] "Return.annualized" "Return.annualized.excess"
## [3] "sd.annualized" "SharpeRatio.annualized"
##
## $VaR.funs
## [1] "VaR" "ES" "ETL" "CDD" "CVaR"
##
## $moment.funs
## [1] "var" "cov" "skewness" "kurtosis"
## [5] "CoVariance" "CoSkewness" "CoSkewnessMatrix" "CoKurtosis"
## [9] "CoKurtosisMatrix" "M3.MM" "M4.MM" "BetaCoVariance"
## [13] "BetaCoSkewness" "BetaCoKurtosis"
##
## $drawdown.funs
## [1] "AverageDrawdown" "AverageLength" "AverageRecovery"
## [4] "DrawdownDeviation" "DrawdownPeak" "maxDrawdown"
##
## $Bacon.risk.funs
## [1] "MeanAbsoluteDeviation" "Frequency" "SharpeRatio"
## [4] "MSquared" "MSquaredExcess" "HurstIndex"
##
## $Bacon.regression.funs
## [1] "CAPM.alpha" "CAPM.beta" "CAPM.epsilon" "CAPM.jensenAlpha"
## [5] "SystematicRisk" "SpecificRisk" "TotalRisk" "TreynorRatio"
## [9] "AppraisalRatio" "FamaBeta" "Selectivity" "NetSelectivity"
##
## $Bacon.relative.risk.funs
## [1] "ActivePremium" "ActiveReturn" "TrackingError" "InformationRatio"
##
## $Bacon.drawdown.funs
## [1] "PainIndex" "PainRatio" "CalmarRatio" "SterlingRatio"
## [5] "BurkeRatio" "MartinRatio" "UlcerIndex"
##
## $Bacon.downside.risk.funs
## [1] "DownsideDeviation" "DownsidePotential" "DownsideFrequency"
## [4] "SemiDeviation" "SemiVariance" "UpsideRisk"
## [7] "UpsidePotentialRatio" "UpsideFrequency" "BernardoLedoitRatio"
## [10] "DRatio" "Omega" "OmegaSharpeRatio"
## [13] "OmegaExcessReturn" "SortinoRatio" "M2Sortino"
## [16] "Kappa" "VolatilitySkewness" "AdjustedSharpeRatio"
## [19] "SkewnessKurtosisRatio" "ProspectRatio"
##
## $misc.funs
## [1] "KellyRatio" "Modigliani" "UpDownRatios"
Hint: Refer to the ggplot2 cheatsheet. Look for geom_density under One Variable. Use the fill argument to create the plot per each stock.
ggplot(returns_quarterly, aes(x = quarterly.returns, fill = symbol)) +
geom_density(alpha = .3)
Hint: Discuss your answer in terms of the mean. Take returns_quarterly and pipe it to tidyquant::tq_performance. Use the performance_fun argument to compute the mean.
returns_quarterly %>%
tq_performance(
Ra = quarterly.returns,
Rb = NULL, #baseline returns (Rb) is not required for this calculation
performance_fun = mean
)
## # A tibble: 3 x 2
## # Groups: symbol [3]
## symbol mean.1
## <chr> <dbl>
## 1 ^DJI 0.0212
## 2 ^GSPC 0.0212
## 3 ^IXIC 0.0333
NASDAQ has the larger returns on average and also the highest returns.
Hint: Discuss your answer in terms of the standard deviation. Take returns_quarterly and pipe it to tidyquant::tq_performance. Use the performance_fun argument to compute sd (standard deviation).
returns_quarterly %>%
tq_performance(
Ra = quarterly.returns,
Rb = NULL, #baseline returns (Rb) is not required for this calculation
performance_fun = sd
)
## # A tibble: 3 x 2
## # Groups: symbol [3]
## symbol sd.1
## <chr> <dbl>
## 1 ^DJI 0.0762
## 2 ^GSPC 0.0794
## 3 ^IXIC 0.122
NASDAQ is the riskiest stock because it tends to undergo the most change.
Hint: Discuss your answer in terms of the skewness and the kurtosis. Take returns_quarterly and pipe it to tidyquant::tq_performance. Use the performance_fun argument to compute the skewness. Do the same for the kurtosis.
returns_quarterly %>%
tq_performance(
Ra = quarterly.returns,
Rb = NULL, #baseline returns (Rb) is not required for this calculation
performance_fun = skewness
)
## # A tibble: 3 x 2
## # Groups: symbol [3]
## symbol skewness.1
## <chr> <dbl>
## 1 ^DJI -0.734
## 2 ^GSPC -0.601
## 3 ^IXIC -0.106
if you are to account for skewness you are more likely to have large losses rather than large gains.
returns_quarterly %>%
tq_performance(
Ra = quarterly.returns,
Rb = NULL, #baseline returns (Rb) is not required for this calculation
performance_fun = kurtosis
)
## # A tibble: 3 x 2
## # Groups: symbol [3]
## symbol kurtosis.1
## <chr> <dbl>
## 1 ^DJI 0.811
## 2 ^GSPC 0.770
## 3 ^IXIC 1.81
NasDAQ has the larger tail because its total is bigger than 1.
Hint: Take returns_quarterly and pipe it to tidyquant::tq_performance. Use the performance_fun argument to compute table.DownsideRisk.
returns_quarterly %>%
tq_performance(
Ra = quarterly.returns,
Rb = NULL, #baseline returns (Rb) is not required for this calculation
performance_fun = table.DownsideRisk
) %>%
t()
## [,1] [,2] [,3]
## symbol "^DJI" "^GSPC" "^IXIC"
## DownsideDeviation(0%) "0.0492" "0.0512" "0.0734"
## DownsideDeviation(MAR=3.33333333333333%) "0.0528" "0.0548" "0.0770"
## DownsideDeviation(Rf=0%) "0.0492" "0.0512" "0.0734"
## GainDeviation "0.0428" "0.0463" "0.0814"
## HistoricalES(95%) "-0.1664" "-0.1686" "-0.2565"
## HistoricalVaR(95%) "-0.1235" "-0.1394" "-0.1954"
## LossDeviation "0.0596" "0.0621" "0.0882"
## MaximumDrawdown "0.4524" "0.4774" "0.7437"
## ModifiedES(95%) "-0.1658" "-0.1724" "-0.2550"
## ModifiedVaR(95%) "-0.1175" "-0.1207" "-0.1658"
## SemiDeviation "0.0587" "0.0607" "0.0885"
Because of expected shortfall NASDAQ is the greatest downside risk, this is the highest of the three.
Hint: Assume that the risk free rate is zero and 95% confidence level. Note that the Sharpe Ratios are calculated using different risk measures: ES, VaR and semideviation. Make your argument based on all three Sharpe Ratios.
returns_quarterly %>%
tq_performance(
Ra = quarterly.returns,
Rb = NULL, #baseline returns (Rb) is not required for this calculation
performance_fun = SharpeRatio
)
## # A tibble: 3 x 4
## # Groups: symbol [3]
## symbol `ESSharpe(Rf=0%,p=95%~ `StdDevSharpe(Rf=0%,p=95~ `VaRSharpe(Rf=0%,p=95~
## <chr> <dbl> <dbl> <dbl>
## 1 ^DJI 0.128 0.278 0.181
## 2 ^GSPC 0.123 0.266 0.175
## 3 ^IXIC 0.131 0.273 0.201
The highest Sharpe Ratio is also held by NASDAQ, but it has the lowest if you use standard deviation
Hint: Google tq_performance(). Discuss in terms of ES, VaR and semideviation and their differences between 95% and 99%.
returns_quarterly %>%
tq_performance(
Ra = quarterly.returns,
Rb = NULL, #baseline returns (Rb) is not required for this calculation
performance_fun = SharpeRatio,
p = 0.99
)
## # A tibble: 3 x 4
## # Groups: symbol [3]
## symbol `ESSharpe(Rf=0%,p=99%~ `StdDevSharpe(Rf=0%,p=99~ `VaRSharpe(Rf=0%,p=99~
## <chr> <dbl> <dbl> <dbl>
## 1 ^DJI 0.0784 0.278 0.109
## 2 ^GSPC 0.0799 0.266 0.105
## 3 ^IXIC 0.0814 0.273 0.108
NASDAQ is still number 1. The smartest bet is to go for another stock because there is less of a risk and still come out with profit.
Hint: Use message, echo and results in the chunk options. Refer to the RMarkdown Reference Guide.