1 Import library
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.0 ✔ readr 2.1.4
## ✔ forcats 1.0.0 ✔ stringr 1.5.0
## ✔ ggplot2 3.4.1 ✔ tibble 3.1.8
## ✔ lubridate 1.9.2 ✔ tidyr 1.3.0
## ✔ purrr 1.0.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(lubridate)
library(readxl)
library(highcharter)
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
library(tidyquant)
## Loading required package: PerformanceAnalytics
## Loading required package: xts
## Loading required package: zoo
##
## Attaching package: 'zoo'
##
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
##
##
## ################################### WARNING ###################################
## # We noticed you have dplyr installed. The dplyr lag() function breaks how #
## # base R's lag() function is supposed to work, which breaks lag(my_xts). #
## # #
## # Calls to lag(my_xts) that you enter or source() into this session won't #
## # work correctly. #
## # #
## # All package code is unaffected because it is protected by the R namespace #
## # mechanism. #
## # #
## # Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning. #
## # #
## # You can use stats::lag() to make sure you're not using dplyr::lag(), or you #
## # can add conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop #
## # dplyr from breaking base R's lag() function. #
## ################################### WARNING ###################################
##
## Attaching package: 'xts'
##
## The following objects are masked from 'package:dplyr':
##
## first, last
##
##
## Attaching package: 'PerformanceAnalytics'
##
## The following object is masked from 'package:graphics':
##
## legend
##
## Loading required package: quantmod
## Loading required package: TTR
library(timetk)
library(tibbletime)
##
## Attaching package: 'tibbletime'
##
## The following object is masked from 'package:stats':
##
## filter
library(quantmod)
library(PerformanceAnalytics)
library(scales)
##
## Attaching package: 'scales'
##
## The following object is masked from 'package:purrr':
##
## discard
##
## The following object is masked from 'package:readr':
##
## col_factor
library(plotly)
##
## Attaching package: 'plotly'
##
## The following object is masked from 'package:ggplot2':
##
## last_plot
##
## The following object is masked from 'package:stats':
##
## filter
##
## The following object is masked from 'package:graphics':
##
## layout
library(rvest)
##
## Attaching package: 'rvest'
##
## The following object is masked from 'package:readr':
##
## guess_encoding
library(xml2)
library(tibble)
library(httr)
##
## Attaching package: 'httr'
##
## The following object is masked from 'package:plotly':
##
## config
library(purrr)
library(dplyr)
2 US Stock Data
2.1 Asset prices series
<- c( "JPM", "DIS", "^GSPC", "BAC")
symbols
=tq_get(symbols, get = "stock.prices",from = "2015-03-12") prices
2.1.1 Daily Stock Price
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
2.1.2 Monthly Stock Price
=prices %>% group_by(symbol) %>%
monthly_pricestq_transmute(select = open:adjusted,
mutate_fun = to.period,
period = "months")
glimpse(monthly_prices)
## Rows: 388
## Columns: 8
## Groups: symbol [4]
## $ symbol <chr> "JPM", "JPM", "JPM", "JPM", "JPM", "JPM", "JPM", "JPM", "JPM"…
## $ date <date> 2015-03-31, 2015-04-30, 2015-05-29, 2015-06-30, 2015-07-31, …
## $ open <dbl> 60.72, 63.58, 66.18, 67.89, 69.01, 63.61, 60.70, 65.30, 67.28…
## $ high <dbl> 60.94, 63.88, 66.22, 68.11, 69.04, 64.35, 61.00, 65.34, 67.52…
## $ low <dbl> 60.42, 62.92, 65.36, 67.16, 68.40, 63.47, 60.11, 64.13, 66.68…
## $ close <dbl> 60.58, 63.26, 65.78, 67.76, 68.53, 64.10, 60.97, 64.25, 66.68…
## $ volume <dbl> 17346700, 16840900, 14310700, 20677400, 11911800, 14223400, 1…
## $ adjusted <dbl> 48.41022, 50.88782, 52.91498, 54.50774, 55.48743, 51.90055, 4…
2.1.3 Yearly Stock Price
=prices %>% group_by(symbol) %>%
yearly_pricestq_transmute(select = open:adjusted,
mutate_fun = to.period,
period = "years")
glimpse(yearly_prices)
## Rows: 36
## Columns: 8
## Groups: symbol [4]
## $ symbol <chr> "JPM", "JPM", "JPM", "JPM", "JPM", "JPM", "JPM", "JPM", "JPM"…
## $ date <date> 2015-12-31, 2016-12-30, 2017-12-29, 2018-12-31, 2019-12-31, …
## $ open <dbl> 66.19, 86.10, 108.09, 97.59, 138.51, 125.09, 158.45, 132.81, …
## $ high <dbl> 66.78, 86.42, 108.28, 98.81, 139.48, 127.33, 159.29, 134.33, …
## $ low <dbl> 66.00, 85.66, 106.94, 96.77, 138.29, 124.82, 157.96, 132.44, …
## $ close <dbl> 66.03, 86.29, 106.94, 97.62, 139.40, 127.07, 158.35, 134.10, …
## $ volume <dbl> 14654300, 13617800, 8925700, 13237200, 7201600, 8580200, 5805…
## $ adjusted <dbl> 53.84901, 72.44651, 91.83227, 85.74950, 126.27217, 119.28329,…
2.2 Asset prices to returns
2.2.1 Daily return
<- prices %>%
prices_daily_log_returns group_by(symbol) %>%
tq_transmute(select = adjusted,
mutate_fun = periodReturn,
period = "daily",
type = "log",
col_rename = "daily.returns")
%>% ggplot(aes(x=date, y=daily.returns, col=symbol))+geom_line()+facet_wrap(symbol~.) prices_daily_log_returns
=prices_daily_log_returns %>%
tggplot(aes(x =daily.returns)) +
geom_density( aes(y=..density..)) +
labs(title = "Density of the Daily Log Returns",
x = "Daily Returns", y = "Density") +
theme_tq() +
scale_fill_tq() + scale_x_continuous(limits = c(-0.2, 0.2)) +
facet_wrap(~ symbol, ncol = 2)+stat_function(fun = dnorm,
args = list(mean = mean(prices_daily_log_returns$daily.returns),
sd = sd(prices_daily_log_returns$daily.returns)),
col = "red",
size = 0.2)
t
## Warning: The dot-dot notation (`..density..`) was deprecated in ggplot2 3.4.0.
## ℹ Please use `after_stat(density)` instead.
=prices_daily_log_returns %>%
tggplot(aes(x =daily.returns)) +
geom_density( aes(y=..density..)) +
labs(title = "Charting the Daily Log Returns",
x = "Daily Returns", y = "Density") +
theme_tq() +
scale_fill_tq() + scale_x_continuous(limits = c(0.05,0.2 )) +
facet_wrap(~ symbol, ncol = 2)+stat_function(fun = dnorm,
args = list(mean = mean(prices_daily_log_returns$daily.returns),
sd = sd(prices_daily_log_returns$daily.returns)),
col = "red",
size = 0.2)
t
## Warning: Removed 8001 rows containing non-finite values (`stat_density()`).
### Monthly returns
<- prices %>%
prices_monthly_log_returns group_by(symbol) %>%
tq_transmute(select = adjusted,
mutate_fun = periodReturn,
period = "monthly",
type = "log",
col_rename = "monthly.returns")
%>%
prices_monthly_log_returns ggplot(aes(x = monthly.returns)) +
geom_density( aes(y=..density..)) +
labs(title = "Charting the Monthly Log Returns",
x = "Monthly Returns", y = "Density") +
theme_tq() +
scale_fill_tq() + scale_x_continuous(limits = c(-0.5, 0.5)) +
facet_wrap(~ symbol, ncol = 2)+stat_function(fun = dnorm,
args = list(mean = mean(prices_monthly_log_returns$monthly.returns),
sd = sd(prices_monthly_log_returns$monthly.returns)),
col = "#1b98e0",
size = 0.3)
<- prices %>%
prices_monthly_log_returns group_by(symbol) %>%
tq_transmute(select = adjusted,
mutate_fun = periodReturn,
period = "monthly",
type = "log",
col_rename = "monthly.returns")
%>%
prices_monthly_log_returns ggplot(aes(x = monthly.returns)) +
geom_density( aes(y=..density..)) +
labs(title = "Charting the Monthly Log Returns",
x = "Monthly Returns", y = "Density") +
theme_tq() +
scale_fill_tq() + scale_x_continuous(limits = c(-0.5, -0.05)) +
facet_wrap(~ symbol, ncol = 2)+stat_function(fun = dnorm,
args = list(mean = mean(prices_monthly_log_returns$monthly.returns),
sd = sd(prices_monthly_log_returns$monthly.returns)),
col = "#1b98e0",
size = 0.3)
## Warning: Removed 314 rows containing non-finite values (`stat_density()`).
<- prices %>%
prices_monthly_log_returns group_by(symbol) %>%
tq_transmute(select = adjusted,
mutate_fun = periodReturn,
period = "monthly",
type = "log",
col_rename = "monthly.returns")
%>%
prices_monthly_log_returns ggplot(aes(x = monthly.returns)) +
geom_density( aes(y=..density..)) +
labs(title = "Charting the Monthly Log Returns",
x = "Monthly Returns", y = "Density") +
theme_tq() +
scale_fill_tq() + scale_x_continuous(limits = c(0.05, 0.5)) +
facet_wrap(~ symbol, ncol = 2)+stat_function(fun = dnorm,
args = list(mean = mean(prices_monthly_log_returns$monthly.returns),
sd = sd(prices_monthly_log_returns$monthly.returns)),
col = "#1b98e0",
size = 0.3)
## Warning: Removed 292 rows containing non-finite values (`stat_density()`).
%>%
prices_monthly_log_returns ggplot(aes(x = monthly.returns, fill = symbol)) +
geom_histogram(alpha = 0.5) +
labs(title = "Charting the Monthly Log Returns",
x = "Monthly Returns", y = "Density") +
theme_tq() +
scale_fill_tq() +
facet_wrap(~ symbol, ncol = 2)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
%>%
prices_monthly_log_returnsggplot(aes(x = monthly.returns)) +
geom_density(aes(color =symbol), alpha = 1) +
geom_histogram(aes(fill = symbol), alpha = 0.45, binwidth = .01) +
guides(fill = FALSE) +
facet_wrap(~symbol) +
ggtitle("Monthly Returns") +
xlab("monthly returns") +
ylab("distribution") +
theme_update(plot.title = element_text(hjust = 0.5))
## Warning: The `<scale>` argument of `guides()` cannot be `FALSE`. Use "none" instead as
## of ggplot2 3.3.4.
2.2.2 Yearly returns
<- prices %>%
(prices_yearly_log_returns group_by(symbol) %>%
tq_transmute(select = adjusted,
mutate_fun = periodReturn,
period = "yearly",
type = "log",
col_rename = "yearly.returns"))
## # A tibble: 36 × 3
## # Groups: symbol [4]
## symbol date yearly.returns
## <chr> <date> <dbl>
## 1 JPM 2015-12-31 0.0935
## 2 JPM 2016-12-30 0.297
## 3 JPM 2017-12-29 0.237
## 4 JPM 2018-12-31 -0.0685
## 5 JPM 2019-12-31 0.387
## 6 JPM 2020-12-31 -0.0569
## 7 JPM 2021-12-31 0.245
## 8 JPM 2022-12-30 -0.135
## 9 JPM 2023-03-16 -0.0179
## 10 DIS 2015-12-31 -0.00751
## # … with 26 more rows
%>% ggplot(aes(x=date, y=yearly.returns, col=symbol))+geom_line()+facet_wrap(symbol~.) prices_yearly_log_returns
2.3 Mean return for the whole period
2.3.1 Daily mean return for the whole period
%>% group_by(symbol) %>%
prices_daily_log_returns tq_performance(Ra = daily.returns,
Rb = NULL,
performance_fun = table.Stats) %>%
select(ArithmeticMean,Median, Maximum, Minimum) %>%
group_by(symbol) %>%
summarize(mean_return = round(ArithmeticMean, 4) * 100,
median_return = round(Median, 4) * 100,
maximum_return = round(Maximum, 4) * 100,
minimum_return = round(Minimum, 4) * 100)
## Adding missing grouping variables: `symbol`
## # A tibble: 4 × 5
## symbol mean_return median_return maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 BAC 0.04 0.04 16.4 -16.7
## 2 DIS 0 0.01 13.5 -14.1
## 3 JPM 0.05 0.02 16.6 -16.2
## 4 ^GSPC 0.03 0.06 8.97 -12.8
%>% ggplot(aes(x=date, y=daily.returns, col=symbol))+geom_line()+facet_wrap(symbol~.) prices_daily_log_returns
2.3.2 Monthly mean return for the whole period
%>% group_by(symbol) %>%
prices_monthly_log_returns tq_performance(Ra = monthly.returns,
Rb = NULL,
performance_fun = table.Stats) %>%
select(ArithmeticMean,Median, Maximum, Minimum) %>%
group_by(symbol) %>%
summarize(mean_return = round(ArithmeticMean, 4) * 100,
median_return = round(Median, 4) * 100,
maximum_return = round(Maximum, 4) * 100,
minimum_return = round(Minimum, 4) * 100)
## Adding missing grouping variables: `symbol`
## # A tibble: 4 × 5
## symbol mean_return median_return maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 BAC 0.77 2.41 25.1 -28.8
## 2 DIS -0.06 -0.31 22.2 -20.6
## 3 JPM 1.01 1.97 19.5 -25.4
## 4 ^GSPC 0.67 1.15 11.9 -13.4
%>% ggplot(aes(x=date, y=monthly.returns, col=symbol))+geom_line()+facet_wrap(symbol~.) prices_monthly_log_returns
2.3.3 Yearly mean return for the whole period
%>% group_by(symbol) %>%
prices_yearly_log_returns tq_performance(Ra = yearly.returns,
Rb = NULL,
performance_fun = table.Stats) %>%
select(ArithmeticMean,Median, Maximum, Minimum) %>%
group_by(symbol) %>%
summarize(mean_return = round(ArithmeticMean, 4) * 100,
median_return = round(Median, 4) * 100,
maximum_return = round(Maximum, 4) * 100,
minimum_return = round(Minimum, 4) * 100)
## Adding missing grouping variables: `symbol`
## # A tibble: 4 × 5
## symbol mean_return median_return maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 BAC 8.27 5.4 40.3 -27.2
## 2 DIS -0.64 3.54 28.9 -57.8
## 3 JPM 10.9 9.35 38.7 -13.5
## 4 ^GSPC 7.23 9.11 25.4 -21.6
%>% ggplot(aes(x=date, y=yearly.returns, col=symbol))+geom_line()+facet_wrap(symbol~.) prices_yearly_log_returns
2.4 Stock volatility for the whole period
2.4.1 Daily Stock volatility for the whole period
%>% group_by(symbol) %>%
prices_daily_log_returns tq_performance(Ra = daily.returns,
Rb = NULL,
performance_fun = table.Stats) %>%
select(ArithmeticMean,Median,Stdev, Maximum, Minimum) %>%
group_by(symbol) %>%
summarize(mean_return = round(ArithmeticMean, 4) * 100,
median_return = round(Median, 4) * 100,
volatility=round(Stdev, 4) * 100,
maximum_return = round(Maximum, 4) * 100,
minimum_return = round(Minimum, 4) * 100)
## Adding missing grouping variables: `symbol`
## # A tibble: 4 × 6
## symbol mean_return median_return volatility maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 BAC 0.04 0.04 2.04 16.4 -16.7
## 2 DIS 0 0.01 1.78 13.5 -14.1
## 3 JPM 0.05 0.02 1.79 16.6 -16.2
## 4 ^GSPC 0.03 0.06 1.2 8.97 -12.8
%>% ggplot(aes(x=daily.returns,col=symbol))+geom_boxplot()+facet_wrap(symbol~.) prices_daily_log_returns
2.4.2 Monthly Stock volatility for the whole period
%>% group_by(symbol) %>%
prices_monthly_log_returns tq_performance(Ra = monthly.returns,
Rb = NULL,
performance_fun = table.Stats) %>%
select(ArithmeticMean,Median,Stdev, Maximum, Minimum) %>%
group_by(symbol) %>%
summarize(mean_return = round(ArithmeticMean, 4) * 100,
median_return = round(Median, 4) * 100,
volatility=round(Stdev, 4) * 100,
maximum_return = round(Maximum, 4) * 100,
minimum_return = round(Minimum, 4) * 100)
## Adding missing grouping variables: `symbol`
## # A tibble: 4 × 6
## symbol mean_return median_return volatility maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 BAC 0.77 2.41 8.84 25.1 -28.8
## 2 DIS -0.06 -0.31 8.32 22.2 -20.6
## 3 JPM 1.01 1.97 7.14 19.5 -25.4
## 4 ^GSPC 0.67 1.15 4.59 11.9 -13.4
%>% ggplot(aes(x=monthly.returns,col=symbol))+geom_boxplot()+facet_wrap(symbol~.) prices_monthly_log_returns
2.4.3 Yearly Stock volatility for the whole period
%>% group_by(symbol) %>%
prices_yearly_log_returns tq_performance(Ra = yearly.returns,
Rb = NULL,
performance_fun = table.Stats) %>%
select(ArithmeticMean,Median,Stdev, Maximum, Minimum) %>%
group_by(symbol) %>%
summarize(mean_return = round(ArithmeticMean, 4) * 100,
median_return = round(Median, 4) * 100,
volatility=round(Stdev, 4) * 100,
maximum_return = round(Maximum, 4) * 100,
minimum_return = round(Minimum, 4) * 100)
## Adding missing grouping variables: `symbol`
## # A tibble: 4 × 6
## symbol mean_return median_return volatility maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 BAC 8.27 5.4 26.4 40.3 -27.2
## 2 DIS -0.64 3.54 25.1 28.9 -57.8
## 3 JPM 10.9 9.35 18.8 38.7 -13.5
## 4 ^GSPC 7.23 9.11 15.4 25.4 -21.6
%>% ggplot(aes(x=yearly.returns,col=symbol))+geom_boxplot()+facet_wrap(symbol~.) prices_yearly_log_returns
2.5 Rolling stock volatility
=30
daily_window=prices_daily_log_returns %>% group_by(symbol) %>%
daily_return_rollingmutate(rolling_mean_return = rollapply(daily.returns,
FUN = mean,
width = daily_window,align="right",
fill = NA),
rolling_median_return = rollapply(daily.returns,
FUN = median,
width = daily_window,
fill = NA),
rolling_max_return = rollapply(daily.returns,
FUN = max,
width = daily_window,
fill = NA),
rolling_min_return = rollapply(daily.returns,
FUN = min,
width = daily_window,
fill = NA),
rolling_volatility = rollapply(daily.returns,
FUN = sd,
width = daily_window,
fill = NA))
2.5.1 Rolling daily mean return
%>% ggplot(aes(x=date, y=rolling_mean_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.) daily_return_rolling
## Warning: Removed 116 rows containing missing values (`geom_line()`).
#### Rolling maximum daily return
%>% ggplot(aes(x=date, y=rolling_max_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.) daily_return_rolling
## Warning: Removed 116 rows containing missing values (`geom_line()`).
#### Rolling minimum daily return
%>% ggplot(aes(x=date, y=rolling_min_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.) daily_return_rolling
## Warning: Removed 116 rows containing missing values (`geom_line()`).
#### Rolling daily volatility return
%>% ggplot(aes(x=date, y=rolling_volatility*100,col=symbol))+geom_line()+facet_wrap(symbol~.) daily_return_rolling
## Warning: Removed 116 rows containing missing values (`geom_line()`).
### Rolling monthly stock volatility
=12
monthly_window=prices_monthly_log_returns %>% group_by(symbol) %>%
monthly_return_rollingmutate(rolling_mean_return = rollapply(monthly.returns,
FUN = mean,
width = monthly_window,align="right",
fill = NA),
rolling_median_return = rollapply(monthly.returns,
FUN = median,
width = monthly_window,
fill = NA),
rolling_max_return = rollapply(monthly.returns,
FUN = max,
width = monthly_window,
fill = NA),
rolling_min_return = rollapply(monthly.returns,
FUN = min,
width = monthly_window,
fill = NA),
rolling_volatility = rollapply(monthly.returns,
FUN = sd,
width = monthly_window,
fill = NA))
glimpse(monthly_return_rolling)
## Rows: 388
## Columns: 8
## Groups: symbol [4]
## $ symbol <chr> "JPM", "JPM", "JPM", "JPM", "JPM", "JPM", "JPM",…
## $ date <date> 2015-03-31, 2015-04-30, 2015-05-29, 2015-06-30,…
## $ monthly.returns <dbl> -0.012955828, 0.049912731, 0.039062736, 0.029656…
## $ rolling_mean_return <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -0.0…
## $ rolling_median_return <dbl> NA, NA, NA, NA, NA, 0.004009175, 0.023735072, 0.…
## $ rolling_max_return <dbl> NA, NA, NA, NA, NA, 0.05958916, 0.05958916, 0.07…
## $ rolling_min_return <dbl> NA, NA, NA, NA, NA, -0.09744716, -0.09744716, -0…
## $ rolling_volatility <dbl> NA, NA, NA, NA, NA, 0.05190794, 0.05420360, 0.05…
2.5.1.1 Rolling monthly mean return
%>% ggplot(aes(x=date, y=rolling_max_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.) monthly_return_rolling
## Warning: Removed 44 rows containing missing values (`geom_line()`).
2.5.1.2 Rolling minimum monthly return
%>% ggplot(aes(x=date, y=rolling_volatility*100,col=symbol))+geom_line()+facet_wrap(symbol~.) monthly_return_rolling
## Warning: Removed 44 rows containing missing values (`geom_line()`).
2.5.2 Rolling yearly stock volatility
=3
yearly_window=prices_yearly_log_returns %>% group_by(symbol) %>%
yearly_return_rollingmutate(rolling_mean_return = rollapply(yearly.returns,
FUN = mean,
width = yearly_window,align="right",
fill = NA),
rolling_median_return = rollapply(yearly.returns,
FUN = median,
width = yearly_window,
fill = NA),
rolling_max_return = rollapply(yearly.returns,
FUN = max,
width = yearly_window,
fill = NA),
rolling_min_return = rollapply(yearly.returns,
FUN = min,
width = yearly_window,
fill = NA),
rolling_volatility = rollapply(yearly.returns,
FUN = sd,
width = yearly_window,
fill = NA))
glimpse(yearly_return_rolling)
## Rows: 36
## Columns: 8
## Groups: symbol [4]
## $ symbol <chr> "JPM", "JPM", "JPM", "JPM", "JPM", "JPM", "JPM",…
## $ date <date> 2015-12-31, 2016-12-30, 2017-12-29, 2018-12-31,…
## $ yearly.returns <dbl> 0.093517296, 0.296664403, 0.237115243, -0.068533…
## $ rolling_mean_return <dbl> NA, NA, 0.20909898, 0.15508204, 0.18519706, 0.08…
## $ rolling_median_return <dbl> NA, 0.237115243, 0.237115243, 0.237115243, -0.05…
## $ rolling_max_return <dbl> NA, 0.29666440, 0.29666440, 0.38700946, 0.387009…
## $ rolling_min_return <dbl> NA, 0.093517296, -0.068533531, -0.068533531, -0.…
## $ rolling_volatility <dbl> NA, 0.10443117, 0.19593230, 0.23216692, 0.259725…
2.5.2.1 Rolling yearly mean return
%>% ggplot(aes(x=date, y=rolling_mean_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.) yearly_return_rolling
## Warning: Removed 8 rows containing missing values (`geom_line()`).
2.5.2.2 Rolling maximum yearly return
%>% ggplot(aes(x=date, y=rolling_max_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.) yearly_return_rolling
## Warning: Removed 8 rows containing missing values (`geom_line()`).
2.5.2.3 Rolling minimum yearly return
%>% ggplot(aes(x=date, y=rolling_min_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.) yearly_return_rolling
## Warning: Removed 8 rows containing missing values (`geom_line()`).
2.5.2.4 Rolling yearly volatility return
%>% ggplot(aes(x=date, y=rolling_volatility*100,col=symbol))+geom_line()+facet_wrap(symbol~.) yearly_return_rolling
## Warning: Removed 8 rows containing missing values (`geom_line()`).
2.6 Shape of return distribution
2.6.1 Skewness and kurtosis for the whole period
2.6.1.1 Daily returns
%>%
prices_daily_log_returnsggplot(aes(x = daily.returns)) +
geom_density(aes(color =symbol), alpha = 1) +
geom_histogram(aes(fill = symbol), alpha = 0.45, binwidth = .01) +
guides(fill = FALSE) +
facet_wrap(~symbol) +
ggtitle("daily Returns") +
xlab("daily returns") +
ylab("distribution") +
theme_update(plot.title = element_text(hjust = 0.5))
%>% group_by(symbol) %>%
prices_daily_log_returns tq_performance(Ra = daily.returns,
Rb = NULL,
performance_fun = table.Distributions) %>%
select(Skewness,Kurtosis)
## Adding missing grouping variables: `symbol`
## # A tibble: 4 × 3
## # Groups: symbol [4]
## symbol Skewness Kurtosis
## <chr> <dbl> <dbl>
## 1 JPM -0.0727 16.2
## 2 DIS -0.0342 14.3
## 3 ^GSPC -0.810 18.2
## 4 BAC -0.0786 12.9
2.6.1.2 Monthly returns
%>%
prices_monthly_log_returnsggplot(aes(x = monthly.returns)) +
geom_density(aes(color =symbol), alpha = 1) +
geom_histogram(aes(fill = symbol), alpha = 0.45, binwidth = .01) +
guides(fill = FALSE) +
facet_wrap(~symbol) +
ggtitle("Monthly Returns") +
xlab("monthly returns") +
ylab("distribution") +
theme_update(plot.title = element_text(hjust = 0.5))
%>% group_by(symbol) %>%
prices_monthly_log_returns tq_performance(Ra = monthly.returns,
Rb = NULL,
performance_fun = table.Distributions) %>%
select(Skewness,Kurtosis)
## Adding missing grouping variables: `symbol`
## # A tibble: 4 × 3
## # Groups: symbol [4]
## symbol Skewness Kurtosis
## <chr> <dbl> <dbl>
## 1 JPM -0.425 4.47
## 2 DIS 0.159 3.74
## 3 ^GSPC -0.514 3.57
## 4 BAC -0.404 3.64
2.6.2 Rolling monthly Skewness and Kurtosis
=12
monthly_window=prices_monthly_log_returns %>% group_by(symbol) %>%
monthly_normality_rollingmutate(rolling_skew_return = rollapply(monthly.returns,
FUN = skewness,
width = monthly_window,align="right",
fill = NA),
rolling_kurtosis_return = rollapply(monthly.returns,
FUN = kurtosis,
width = monthly_window,align="right",
fill = NA))
%>% ggplot(aes(x=date, y=rolling_skew_return,col=symbol))+geom_line()+facet_wrap(symbol~.) monthly_normality_rolling
## Warning: Removed 44 rows containing missing values (`geom_line()`).
%>% ggplot(aes(x=date, y=rolling_kurtosis_return,col=symbol))+geom_line()+facet_wrap(symbol~.) monthly_normality_rolling
## Warning: Removed 44 rows containing missing values (`geom_line()`).
2.7 Downside risk measures
%>% group_by(symbol) %>%
prices_daily_log_returns tq_performance(Ra = daily.returns,
Rb = NULL,
performance_fun = table.DownsideRisk) %>%
select(SemiDeviation,"HistoricalVaR(95%)" , "HistoricalES(95%)",MaximumDrawdown)
## Adding missing grouping variables: `symbol`
## # A tibble: 4 × 5
## # Groups: symbol [4]
## symbol SemiDeviation `HistoricalVaR(95%)` `HistoricalES(95%)` MaximumDrawdown
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 JPM 0.0127 -0.0267 -0.0411 0.473
## 2 DIS 0.0126 -0.0263 -0.0422 0.620
## 3 ^GSPC 0.0089 -0.0183 -0.03 0.361
## 4 BAC 0.0145 -0.0303 -0.0478 0.526
## From Trough To Depth Length To Trough Recovery
## 1 2020-02-20 2020-03-23 2020-09-02 -0.3610 137 23 114
## 2 2022-01-04 2022-10-12 <NA> -0.2711 302 195 NA
## 3 2018-09-21 2018-12-24 2019-07-01 -0.2025 194 65 129
## 4 2015-05-22 2016-02-11 2016-07-18 -0.1516 291 183 108
## 5 2018-01-29 2018-04-02 2018-08-27 -0.1056 147 44 103
charts.PerformanceSummary(fb_return_xts,
ylog = TRUE,
legend.loc = "topleft",
main = "Tesla stock Performance"
)
## From Trough To Depth Length To Trough Recovery
## 1 2020-01-03 2020-03-23 2021-05-05 -0.4730 337 55 282
## 2 2021-10-25 2022-10-11 <NA> -0.4115 351 243 NA
## 3 2015-07-23 2016-02-11 2016-11-09 -0.2481 330 141 189
## 4 2018-02-27 2018-12-24 2019-09-13 -0.2254 390 209 181
## 5 2017-03-02 2017-05-31 2017-07-05 -0.1205 87 63 24
charts.PerformanceSummary(fb_return_xts,
ylog = TRUE,
legend.loc = "topleft",
main = "Apple stock Performance"
)
## From Trough To Depth Length To Trough Recovery
## 1 2021-03-09 2022-12-28 <NA> -0.6195 511 457 NA
## 2 2019-11-27 2020-03-23 2020-12-11 -0.4568 263 79 184
## 3 2015-08-05 2016-02-10 2019-04-12 -0.2820 929 131 798
## 4 2019-07-30 2019-10-03 2019-11-13 -0.1293 76 47 29
## 5 2021-01-04 2021-01-27 2021-02-08 -0.1016 25 17 8
charts.PerformanceSummary(fb_return_xts,
ylog = TRUE,
legend.loc = "topleft",
main = "Disney stock Performance"
)
## From Trough To Depth Length To Trough Recovery
## 1 2020-01-03 2020-03-23 2021-05-06 -0.5255 338 55 283
## 2 2022-02-09 2023-03-15 <NA> -0.4375 277 275 NA
## 3 2015-07-23 2016-02-11 2016-11-14 -0.4101 333 141 192
## 4 2018-03-13 2018-12-24 2019-12-06 -0.3139 439 199 240
## 5 2021-06-07 2021-07-19 2021-10-05 -0.1508 85 30 55
charts.PerformanceSummary(fb_return_xts,
ylog = TRUE,
legend.loc = "topleft",
main = "Adobe stock Performance"
)
3 Vietnamese stocks
=NULL
new=c("TCB","TPB","BID","VCB")
id_listfor (j in id_list){
for (i in 1:10){
<- list(currentPage=i,id = j)
query_params <- GET("https://www.cophieu68.vn/historyprice.php", query = query_params)
parameter_response =read_html(parameter_response)
stock_share =html_nodes(stock_share, xpath="//table[@class='stock']") %>%
new1html_table(header = TRUE,fill=TRUE) %>% as.data.frame()
=new1[,2:13]
new1$symbol=j
new1=rbind(new,new1)
new }}
## Warning: NAs introduced by coercion
## Warning: NAs introduced by coercion
## Warning: NAs introduced by coercion
## Warning: NAs introduced by coercion
## Warning: NAs introduced by coercion
## Warning: NAs introduced by coercion
## Warning: NAs introduced by coercion
## Warning: NAs introduced by coercion
## Warning: NAs introduced by coercion
## Warning: NAs introduced by coercion
## Warning: NAs introduced by coercion
3.1 Asset prices series
3.1.1 Daily prices
3.1.2 Monthly stock prices
=prices %>% group_by(symbol) %>%
monthly_pricestq_transmute(select = 2:12,
mutate_fun = to.period,
period = "months")
glimpse(monthly_prices)
## Rows: 196
## Columns: 13
## Groups: symbol [4]
## $ symbol <chr> "TCB", "TCB", "TCB", "TCB", "TCB", "TCB", "TCB…
## $ date <date> 2019-03-29, 2019-04-26, 2019-05-31, 2019-06-2…
## $ Last_closed_price <dbl> 25.55, 24.15, 22.95, 20.20, 20.70, 21.35, 23.2…
## $ absolute_price_change <dbl> 0.05, 0.00, -0.35, 0.15, -0.15, 0.15, 0.15, -0…
## $ Percentage_price_change <dbl> 0.001956947, 0.000000000, -0.015250545, 0.0074…
## $ Closed_price <dbl> 25.60, 24.15, 22.60, 20.35, 20.55, 21.50, 23.3…
## $ Trading_Volume <dbl> 1656270, 898530, 1452700, 2795060, 1219550, 12…
## $ Open_price <dbl> 25.55, 24.05, 22.95, 20.35, 20.70, 21.40, 23.3…
## $ Highest_price <dbl> 25.80, 24.20, 23.00, 20.40, 20.70, 21.50, 23.5…
## $ Lowest_price <dbl> 25.55, 24.00, 22.60, 19.95, 20.55, 21.25, 23.1…
## $ Exchange_volume <dbl> 4086090, 0, 0, 12202710, 0, 20000, 0, 100000, …
## $ Foregin_buy_volume <dbl> 4105880, 0, 0, 141490, 2669990, 0, 0, 0, 0, 0,…
## $ Foreign_sell_volume <dbl> 4104580, 0, 0, 141490, 2669990, 0, 0, 0, 0, 0,…
3.1.3 Yearly stock prices
=prices %>% group_by(symbol) %>%
yearly_pricestq_transmute(select = 2:12,
mutate_fun = to.period,
period = "years")
glimpse(yearly_prices)
## Rows: 20
## Columns: 13
## Groups: symbol [4]
## $ symbol <chr> "TCB", "TCB", "TCB", "TCB", "TCB", "TPB", "TPB…
## $ date <date> 2019-12-31, 2020-12-31, 2021-12-31, 2022-12-3…
## $ Last_closed_price <dbl> 23.45, 29.90, 49.30, 25.95, 26.75, 12.79, 19.6…
## $ absolute_price_change <dbl> 0.10, 1.60, 0.70, -0.10, -0.10, -0.03, 0.19, 0…
## $ Percentage_price_change <dbl> 0.004264392, 0.053511706, 0.014198783, -0.0038…
## $ Closed_price <dbl> 23.55, 31.50, 50.00, 25.85, 26.65, 12.76, 19.8…
## $ Trading_Volume <dbl> 731740, 16486510, 9547100, 2181900, 1199600, 4…
## $ Open_price <dbl> 23.45, 29.95, 49.50, 25.95, 26.80, 12.82, 19.8…
## $ Highest_price <dbl> 23.75, 31.75, 50.50, 26.10, 27.10, 12.82, 19.9…
## $ Lowest_price <dbl> 23.45, 29.90, 49.45, 25.85, 26.60, 12.73, 19.5…
## $ Exchange_volume <dbl> 229800, 0, 391300, 3321000, 0, 0, 0, 120300, 0…
## $ Foregin_buy_volume <dbl> 0, 9030, 0, 115, 329200, 0, 10, 57700, 7340, 1…
## $ Foreign_sell_volume <dbl> 0, 50, 0, 0, 329200, 0, 0, 11000, 0, 27100, 13…
3.2 Asset prices to returns
3.2.1 Daily return
<- prices %>%
prices_daily_log_returns group_by(symbol) %>%
tq_transmute(select = Closed_price,
mutate_fun = periodReturn,
period = "daily",
type = "log",
col_rename = "daily.returns")
%>% ggplot(aes(x=date, y=daily.returns, col=symbol))+geom_line()+facet_wrap(symbol~.) prices_daily_log_returns
%>%
prices_daily_log_returns ggplot(aes(x = daily.returns, fill = symbol)) +
geom_histogram(alpha = 0.5) +
labs(title = "Charting the Daily Log Returns",
x = "Daily Returns", y = "Density") +
theme_tq() +
scale_fill_tq() +
facet_wrap(~ symbol, ncol = 2)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
3.2.2 Monthly returns
<- prices %>%
prices_monthly_log_returns group_by(symbol) %>%
tq_transmute(select = Closed_price,
mutate_fun = periodReturn,
period = "monthly",
type = "log",
col_rename = "monthly.returns")
%>%
prices_monthly_log_returnsggplot(aes(x = monthly.returns)) +
geom_density(aes(color =symbol), alpha = 1) +
geom_histogram(aes(fill = symbol), alpha = 0.45, binwidth = .01) +
guides(fill = FALSE) +
facet_wrap(~symbol) +
ggtitle("Monthly Returns") +
xlab("monthly returns") +
ylab("distribution") +
theme_update(plot.title = element_text(hjust = 0.5))
%>%
prices_monthly_log_returnsggplot(aes(x = monthly.returns)) +
geom_boxplot(aes(fill =symbol), alpha = 1) +
ggtitle("Monthly Returns") +
xlab("monthly returns") +
ylab("distribution") +
theme_update(plot.title = element_text(hjust = 0.5))
3.2.3 Yearly returns
<- prices %>%
prices_yearly_log_returns group_by(symbol) %>%
tq_transmute(select = Closed_price,
mutate_fun = periodReturn,
period = "yearly",
type = "log",
col_rename = "yearly.returns")
%>% ggplot(aes(x=date, y=yearly.returns,col=symbol))+geom_line()+facet_wrap(.~symbol) prices_yearly_log_returns
3.3 Mean return for the whole period
3.3.1 Daily mean return for the whole period
%>% group_by(symbol) %>%
prices_daily_log_returns tq_performance(Ra = daily.returns,
Rb = NULL,
performance_fun = table.Stats) %>%
select(ArithmeticMean,Median, Maximum, Minimum) %>%
group_by(symbol) %>%
summarize(mean_return = round(ArithmeticMean, 4) * 100,
median_return = round(Median, 4) * 100,
maximum_return = round(Maximum, 4) * 100,
minimum_return = round(Minimum, 4) * 100)
## Adding missing grouping variables: `symbol`
## # A tibble: 4 × 5
## symbol mean_return median_return maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 BID 0.05 0 6.77 -7.24
## 2 TCB 0 0 6.73 -7.25
## 3 TPB 0.07 0 6.74 -7.27
## 4 VCB 0.06 0 6.67 -7.24
%>% ggplot(aes(x=date, y=daily.returns, col=symbol))+geom_line()+facet_wrap(symbol~.) prices_daily_log_returns
3.3.2 Monthly mean return for the whole period
%>% group_by(symbol) %>%
prices_monthly_log_returns tq_performance(Ra = monthly.returns,
Rb = NULL,
performance_fun = table.Stats) %>%
select(ArithmeticMean,Median, Maximum, Minimum) %>%
group_by(symbol) %>%
summarize(mean_return = round(ArithmeticMean, 4) * 100,
median_return = round(Median, 4) * 100,
maximum_return = round(Maximum, 4) * 100,
minimum_return = round(Minimum, 4) * 100)
## Adding missing grouping variables: `symbol`
## # A tibble: 4 × 5
## symbol mean_return median_return maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 BID 1.05 1.26 25.6 -38.8
## 2 TCB 0 0.56 27.0 -39.4
## 3 TPB 1.38 0.22 31.2 -22.1
## 4 VCB 1.15 0.82 22.6 -28.4
%>% ggplot(aes(x=date, y=monthly.returns, col=symbol))+geom_line()+facet_wrap(symbol~.) prices_monthly_log_returns
3.3.3 Yearly mean return for the whole period
%>% group_by(symbol) %>%
prices_yearly_log_returns tq_performance(Ra = yearly.returns,
Rb = NULL,
performance_fun = table.Stats) %>%
select(ArithmeticMean,Median, Maximum, Minimum) %>%
group_by(symbol) %>%
summarize(mean_return = round(ArithmeticMean, 4) * 100,
median_return = round(Median, 4) * 100,
maximum_return = round(Maximum, 4) * 100,
minimum_return = round(Minimum, 4) * 100)
## Adding missing grouping variables: `symbol`
## # A tibble: 4 × 5
## symbol mean_return median_return maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 BID 10.3 5.39 26.2 -2.16
## 2 TCB 0.04 3.05 46.2 -66.0
## 3 TPB 13.6 18.4 72.7 -66.8
## 4 VCB 11.2 9 31.1 1.51
%>% ggplot(aes(x=date, y=yearly.returns, col=symbol))+geom_line()+facet_wrap(symbol~.) prices_yearly_log_returns
3.4 Stock volatility for the whole period
3.4.1 Daily Stock volatility for the whole period
%>% group_by(symbol) %>%
prices_daily_log_returns tq_performance(Ra = daily.returns,
Rb = NULL,
performance_fun = table.Stats) %>%
select(ArithmeticMean,Median,Stdev, Maximum, Minimum) %>%
group_by(symbol) %>%
summarize(mean_return = round(ArithmeticMean, 4) * 100,
median_return = round(Median, 4) * 100,
volatility=round(Stdev, 4) * 100,
maximum_return = round(Maximum, 4) * 100,
minimum_return = round(Minimum, 4) * 100)
## Adding missing grouping variables: `symbol`
## # A tibble: 4 × 6
## symbol mean_return median_return volatility maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 BID 0.05 0 2.31 6.77 -7.24
## 2 TCB 0 0 2.25 6.73 -7.25
## 3 TPB 0.07 0 2.26 6.74 -7.27
## 4 VCB 0.06 0 1.78 6.67 -7.24
%>% ggplot(aes(x=daily.returns,col=symbol))+geom_boxplot()+facet_wrap(symbol~.) prices_daily_log_returns
3.4.2 Monthly Stock volatility for the whole period
%>% group_by(symbol) %>%
prices_monthly_log_returns tq_performance(Ra = monthly.returns,
Rb = NULL,
performance_fun = table.Stats) %>%
select(ArithmeticMean,Median,Stdev, Maximum, Minimum) %>%
group_by(symbol) %>%
summarize(mean_return = round(ArithmeticMean, 4) * 100,
median_return = round(Median, 4) * 100,
volatility=round(Stdev, 4) * 100,
maximum_return = round(Maximum, 4) * 100,
minimum_return = round(Minimum, 4) * 100)
## Adding missing grouping variables: `symbol`
## # A tibble: 4 × 6
## symbol mean_return median_return volatility maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 BID 1.05 1.26 11.4 25.6 -38.8
## 2 TCB 0 0.56 12.0 27.0 -39.4
## 3 TPB 1.38 0.22 10.5 31.2 -22.1
## 4 VCB 1.15 0.82 8.62 22.6 -28.4
%>% ggplot(aes(x=monthly.returns,col=symbol))+geom_boxplot()+facet_wrap(symbol~.) prices_monthly_log_returns
3.4.3 Yearly Stock volatility for the whole period
%>% group_by(symbol) %>%
prices_yearly_log_returns tq_performance(Ra = yearly.returns,
Rb = NULL,
performance_fun = table.Stats) %>%
select(ArithmeticMean,Median,Stdev, Maximum, Minimum) %>%
group_by(symbol) %>%
summarize(mean_return = round(ArithmeticMean, 4) * 100,
median_return = round(Median, 4) * 100,
volatility=round(Stdev, 4) * 100,
maximum_return = round(Maximum, 4) * 100,
minimum_return = round(Minimum, 4) * 100)
## Adding missing grouping variables: `symbol`
## # A tibble: 4 × 6
## symbol mean_return median_return volatility maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 BID 10.3 5.39 11.6 26.2 -2.16
## 2 TCB 0.04 3.05 43.3 46.2 -66.0
## 3 TPB 13.6 18.4 52.7 72.7 -66.8
## 4 VCB 11.2 9 11.7 31.1 1.51
%>% ggplot(aes(x=yearly.returns,col=symbol))+geom_boxplot()+facet_wrap(symbol~.) prices_yearly_log_returns
3.5 Rolling stock volatility
3.5.1 Rolling daily stock volatility
=30
daily_window=prices_daily_log_returns %>% group_by(symbol) %>%
daily_return_rollingmutate(rolling_mean_return = rollapply(daily.returns,
FUN = mean,
width = daily_window,align="right",
fill = NA),
rolling_median_return = rollapply(daily.returns,
FUN = median,
width = daily_window,
fill = NA),
rolling_max_return = rollapply(daily.returns,
FUN = max,
width = daily_window,
fill = NA),
rolling_min_return = rollapply(daily.returns,
FUN = min,
width = daily_window,
fill = NA),
rolling_volatility = rollapply(daily.returns,
FUN = sd,
width = daily_window,
fill = NA))
3.5.1.1 Rolling daily mean return
%>% ggplot(aes(x=date, y=rolling_mean_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.) daily_return_rolling
## Warning: Removed 116 rows containing missing values (`geom_line()`).
3.5.1.2 Rolling maximum daily return
%>% ggplot(aes(x=date, y=rolling_max_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.) daily_return_rolling
## Warning: Removed 116 rows containing missing values (`geom_line()`).
3.5.1.3 Rolling minimum daily return
%>% ggplot(aes(x=date, y=rolling_min_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.) daily_return_rolling
## Warning: Removed 116 rows containing missing values (`geom_line()`).
3.5.1.4 Rolling daily volatility return
%>% ggplot(aes(x=date, y=rolling_volatility*100,col=symbol))+geom_line()+facet_wrap(symbol~.) daily_return_rolling
## Warning: Removed 116 rows containing missing values (`geom_line()`).
3.5.2 Rolling monthly stock volatility
=12
monthly_window=prices_monthly_log_returns %>% group_by(symbol) %>%
monthly_return_rollingmutate(rolling_mean_return = rollapply(monthly.returns,
FUN = mean,
width = monthly_window,align="right",
fill = NA),
rolling_median_return = rollapply(monthly.returns,
FUN = median,
width = monthly_window,
fill = NA),
rolling_max_return = rollapply(monthly.returns,
FUN = max,
width = monthly_window,
fill = NA),
rolling_min_return = rollapply(monthly.returns,
FUN = min,
width = monthly_window,
fill = NA),
rolling_volatility = rollapply(monthly.returns,
FUN = sd,
width = monthly_window,
fill = NA))
3.5.2.1 Rolling monthly mean return
%>% ggplot(aes(x=date, y=rolling_mean_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.) monthly_return_rolling
## Warning: Removed 44 rows containing missing values (`geom_line()`).
3.5.2.2 Rolling maximum monthly return
%>% ggplot(aes(x=date, y=rolling_max_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.) monthly_return_rolling
## Warning: Removed 44 rows containing missing values (`geom_line()`).
3.5.2.3 Rolling minimum monthly return
%>% ggplot(aes(x=date, y=rolling_min_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.) monthly_return_rolling
## Warning: Removed 44 rows containing missing values (`geom_line()`).
3.5.2.4 Rolling monthly volatility return
%>% ggplot(aes(x=date, y=rolling_volatility*100,col=symbol))+geom_line()+facet_wrap(symbol~.) monthly_return_rolling
## Warning: Removed 44 rows containing missing values (`geom_line()`).
3.5.3 Rolling yearly stock volatility
=3
yearly_window=prices_yearly_log_returns %>% group_by(symbol) %>%
yearly_return_rollingmutate(rolling_mean_return = rollapply(yearly.returns,
FUN = mean,
width = yearly_window,align="right",
fill = NA),
rolling_median_return = rollapply(yearly.returns,
FUN = median,
width = yearly_window,
fill = NA),
rolling_max_return = rollapply(yearly.returns,
FUN = max,
width = yearly_window,
fill = NA),
rolling_min_return = rollapply(yearly.returns,
FUN = min,
width = yearly_window,
fill = NA),
rolling_volatility = rollapply(yearly.returns,
FUN = sd,
width = yearly_window,
fill = NA))
glimpse(yearly_return_rolling)
## Rows: 20
## Columns: 8
## Groups: symbol [4]
## $ symbol <chr> "TCB", "TCB", "TCB", "TCB", "TCB", "TPB", "TPB",…
## $ date <date> 2019-12-31, 2020-12-31, 2021-12-31, 2022-12-30,…
## $ yearly.returns <dbl> -0.121785395, 0.290861725, 0.462035460, -0.65971…
## $ rolling_mean_return <dbl> NA, NA, 0.21037060, 0.03106159, -0.05573280, NA,…
## $ rolling_median_return <dbl> NA, 0.29086173, 0.29086173, 0.03047855, NA, NA, …
## $ rolling_max_return <dbl> NA, 0.46203546, 0.46203546, 0.46203546, NA, NA, …
## $ rolling_min_return <dbl> NA, -0.121785395, -0.659712404, -0.659712404, NA…
## $ rolling_volatility <dbl> NA, 0.30011800, 0.60431916, 0.56582141, NA, NA, …
3.5.3.1 Rolling yearly mean return
%>% ggplot(aes(x=date, y=rolling_mean_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.) yearly_return_rolling
## Warning: Removed 8 rows containing missing values (`geom_line()`).
3.5.3.2 Rolling maximum yearly return
%>% ggplot(aes(x=date, y=rolling_max_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.) yearly_return_rolling
## Warning: Removed 8 rows containing missing values (`geom_line()`).
3.5.3.3 Rolling minimum yearly return
%>% ggplot(aes(x=date, y=rolling_min_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.) yearly_return_rolling
## Warning: Removed 8 rows containing missing values (`geom_line()`).
3.5.3.4 Rolling yearly volatility return
%>% ggplot(aes(x=date, y=rolling_volatility*100,col=symbol))+geom_line()+facet_wrap(symbol~.) yearly_return_rolling
## Warning: Removed 8 rows containing missing values (`geom_line()`).
3.6 Shape of return distribution
3.6.1 Skewness and kurtosis for the whole period
3.6.1.1 Daily returns
%>%
prices_daily_log_returnsggplot(aes(x = daily.returns)) +
geom_density(aes(color =symbol), alpha = 1) +
geom_histogram(aes(fill = symbol), alpha = 0.45, binwidth = .01) +
guides(fill = FALSE) +
facet_wrap(~symbol) +
ggtitle("daily Returns") +
xlab("daily returns") +
ylab("distribution") +
theme_update(plot.title = element_text(hjust = 0.5))
%>% group_by(symbol) %>%
prices_daily_log_returns tq_performance(Ra = daily.returns,
Rb = NULL,
performance_fun = table.Distributions) %>%
select(Skewness,Kurtosis)
## Adding missing grouping variables: `symbol`
## # A tibble: 4 × 3
## # Groups: symbol [4]
## symbol Skewness Kurtosis
## <chr> <dbl> <dbl>
## 1 TCB -0.384 5.25
## 2 TPB -0.174 4.86
## 3 BID -0.326 4.63
## 4 VCB -0.210 5.23
3.6.1.2 Monthly returns
%>%
prices_monthly_log_returnsggplot(aes(x = monthly.returns)) +
geom_density(aes(color =symbol), alpha = 1) +
geom_histogram(aes(fill = symbol), alpha = 0.45, binwidth = .01) +
guides(fill = FALSE) +
facet_wrap(~symbol) +
ggtitle("Monthly Returns") +
xlab("monthly returns") +
ylab("distribution") +
theme_update(plot.title = element_text(hjust = 0.5))
%>% group_by(symbol) %>%
prices_monthly_log_returns tq_performance(Ra = monthly.returns,
Rb = NULL,
performance_fun = table.Distributions) %>%
select(Skewness,Kurtosis)
## Adding missing grouping variables: `symbol`
## # A tibble: 4 × 3
## # Groups: symbol [4]
## symbol Skewness Kurtosis
## <chr> <dbl> <dbl>
## 1 TCB -0.414 4.84
## 2 TPB 0.358 3.66
## 3 BID -0.717 4.63
## 4 VCB -0.496 5.06
3.6.2 Rolling monthly Skewness and Kurtosis
=12
monthly_window=prices_monthly_log_returns %>% group_by(symbol) %>%
monthly_normality_rollingmutate(rolling_skew_return = rollapply(monthly.returns,
FUN = skewness,
width = monthly_window,align="right",
fill = NA),
rolling_kurtosis_return = rollapply(monthly.returns,
FUN = kurtosis,
width = monthly_window,align="right",
fill = NA))
%>% ggplot(aes(x=date, y=rolling_skew_return,col=symbol))+geom_line()+facet_wrap(symbol~.) monthly_normality_rolling
## Warning: Removed 44 rows containing missing values (`geom_line()`).
%>% ggplot(aes(x=date, y=rolling_kurtosis_return,col=symbol))+geom_line()+facet_wrap(symbol~.) monthly_normality_rolling
## Warning: Removed 44 rows containing missing values (`geom_line()`).
3.7 Downside risk measures
%>% group_by(symbol) %>%
prices_daily_log_returns tq_performance(Ra = daily.returns,
Rb = NULL,
performance_fun = table.DownsideRisk) %>%
select(SemiDeviation,"HistoricalVaR(95%)" , "HistoricalES(95%)",MaximumDrawdown)
## Adding missing grouping variables: `symbol`
## # A tibble: 4 × 5
## # Groups: symbol [4]
## symbol SemiDeviation `HistoricalVaR(95%)` `HistoricalES(95%)` MaximumDrawdown
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 TCB 0.0165 -0.0398 -0.0598 0.675
## 2 TPB 0.0162 -0.0387 -0.0567 0.578
## 3 BID 0.0169 -0.0395 -0.0587 0.462
## 4 VCB 0.0127 -0.0266 -0.0424 0.405
3.7.1 TCB stock performance
=prices %>% filter(symbol=='TCB') %>% select(symbol, date, open=Open_price,high=Highest_price, low=Lowest_price,close=Closed_price, volume=Exchange_volume)
fbglimpse(fb)
## Rows: 1,000
## Columns: 7
## $ symbol <chr> "TCB", "TCB", "TCB", "TCB", "TCB", "TCB", "TCB", "TCB", "TCB", …
## $ date <date> 2023-03-17, 2023-03-16, 2023-03-15, 2023-03-14, 2023-03-13, 20…
## $ open <dbl> 26.80, 26.90, 26.80, 26.65, 26.55, 27.50, 27.50, 26.90, 27.20, …
## $ high <dbl> 27.10, 26.95, 27.40, 26.75, 26.95, 27.60, 27.85, 27.40, 27.50, …
## $ low <dbl> 26.60, 26.60, 26.80, 26.30, 26.55, 27.00, 27.20, 26.80, 27.05, …
## $ close <dbl> 26.65, 26.70, 27.20, 26.30, 26.75, 27.15, 27.80, 27.30, 27.10, …
## $ volume <dbl> 0, 0, 2406200, 1571600, 41232600, 0, 1529500, 720000, 54000, 45…
=xts(fb[,3:7], order.by = fb$date)
fb_xts%>%
fb_xtschartSeries(
# Add Bollinger Bands, Volume, Moving Average Convergence/Divergence
TA = 'addBBands();
addVo();
addRSI();
'
, theme = chartTheme("white.mono"),
name = "TCB Stock Prices Evolution",
minor.ticks = FALSE,
up.col = "seagreen3",
dn.col = "indianred2",
colov.vol = c("indianred2", "seagreen2")
)
=prices_daily_log_returns %>% filter(symbol=="TCB")
fb_r=xts(fb_r[,3],order.by=fb_r$date)
fb_return_xtstable.Drawdowns(fb_return_xts)
## From Trough To Depth Length To Trough Recovery
## 1 2021-07-06 2022-11-15 <NA> -0.6753 426 343 NA
## 2 2019-03-21 2020-03-30 2020-12-18 -0.4642 442 257 185
## 3 2021-01-18 2021-01-28 2021-02-17 -0.1598 18 9 9
## 4 2021-06-04 2021-06-08 2021-07-05 -0.0990 22 3 19
## 5 2021-04-08 2021-04-26 2021-05-04 -0.0672 16 12 4
# Plot of drawdowns
chart.Drawdown(fb_return_xts)
charts.PerformanceSummary(fb_return_xts,
ylog = TRUE,
legend.loc = "topleft",
main = "TCB stock Performance"
)
3.7.2 TPB stock performance
=prices %>% filter(symbol=='TPB') %>% select(symbol, date, open=Open_price,high=Highest_price, low=Lowest_price,close=Closed_price, volume=Exchange_volume)
fbglimpse(fb)
## Rows: 1,000
## Columns: 7
## $ symbol <chr> "TPB", "TPB", "TPB", "TPB", "TPB", "TPB", "TPB", "TPB", "TPB", …
## $ date <date> 2023-03-17, 2023-03-16, 2023-03-15, 2023-03-14, 2023-03-13, 20…
## $ open <dbl> 24.65, 24.55, 24.60, 24.45, 23.70, 24.20, 24.00, 23.40, 23.70, …
## $ high <dbl> 25.50, 24.60, 25.10, 24.45, 24.60, 24.45, 24.55, 24.00, 23.80, …
## $ low <dbl> 24.65, 24.35, 24.30, 23.85, 23.65, 23.90, 23.90, 23.30, 23.40, …
## $ close <dbl> 25.30, 24.35, 24.65, 24.20, 24.30, 24.00, 24.50, 23.95, 23.50, …
## $ volume <dbl> 0, 0, 0, 0, 0, 0, 0, 20191, 0, 0, 0, 0, 0, 110000, 0, 0, 800000…
=xts(fb[,3:7], order.by = fb$date)
fb_xts%>%
fb_xtschartSeries(
# Add Bollinger Bands, Volume, Moving Average Convergence/Divergence
TA = 'addBBands();
addVo();
addRSI();
'
, theme = chartTheme("white.mono"),
name = "TPB Stock Prices Evolution",
minor.ticks = FALSE,
up.col = "seagreen3",
dn.col = "indianred2",
colov.vol = c("indianred2", "seagreen2")
)
=prices_daily_log_returns %>% filter(symbol=="TPB")
fb_r=xts(fb_r[,3],order.by=fb_r$date)
fb_return_xtstable.Drawdowns(fb_return_xts)
## From Trough To Depth Length To Trough Recovery
## 1 2022-01-13 2022-10-11 <NA> -0.5776 292 184 NA
## 2 2019-06-12 2020-04-01 2020-11-30 -0.3814 373 204 169
## 3 2021-07-06 2021-07-19 2021-09-17 -0.2046 52 10 42
## 4 2021-01-19 2021-01-28 2021-03-02 -0.1939 26 8 18
## 5 2021-06-07 2021-06-08 2021-07-05 -0.1052 21 2 19
# Plot of drawdowns
chart.Drawdown(fb_return_xts)
charts.PerformanceSummary(fb_return_xts,
ylog = TRUE,
legend.loc = "topleft",
main = "TPB stock Performance"
)