FINANCIAL MATH 1
Stock analysis with R

1 Data Pre-Processing

2 US Stock Data

2.1 Asset prices series

symbols <- c( "AAPL", "DIS", "TSLA", "ADBE")

prices=tq_get(symbols, get = "stock.prices",from = "2015-03-12")

2.1.1 Daily Stock Price

2.1.2 Monthly Stock Price

monthly_prices=prices %>% group_by(symbol) %>%
    tq_transmute(select     = open:adjusted, 
                 mutate_fun = to.period, 
                 period     = "months")
glimpse(monthly_prices)
## Rows: 388
## Columns: 8
## Groups: symbol [4]
## $ symbol   <chr> "AAPL", "AAPL", "AAPL", "AAPL", "AAPL", "AAPL", "AAPL", "AAPL…
## $ date     <date> 2015-03-31, 2015-04-30, 2015-05-29, 2015-06-30, 2015-07-31, …
## $ open     <dbl> 31.5225, 32.1600, 32.8075, 31.3925, 30.6500, 28.0075, 27.5425…
## $ high     <dbl> 31.6225, 32.1600, 32.8625, 31.5300, 30.6600, 28.6325, 27.8850…
## $ low      <dbl> 31.0900, 31.1450, 32.4750, 31.2150, 30.2275, 28.0000, 27.1825…
## $ close    <dbl> 31.1075, 31.2875, 32.5700, 31.3575, 30.3250, 28.1900, 27.5750…
## $ volume   <dbl> 168362400, 332781600, 203538000, 177482800, 171540000, 224917…
## $ adjusted <dbl> 28.06891, 28.23132, 29.51130, 28.41268, 27.47714, 25.65826, 2…

2.1.3 Yearly Stock Price

yearly_prices=prices %>% group_by(symbol) %>%
    tq_transmute(select     = open:adjusted, 
                 mutate_fun = to.period, 
                 period     = "years")
glimpse(yearly_prices)
## Rows: 36
## Columns: 8
## Groups: symbol [4]
## $ symbol   <chr> "AAPL", "AAPL", "AAPL", "AAPL", "AAPL", "AAPL", "AAPL", "AAPL…
## $ date     <date> 2015-12-31, 2016-12-30, 2017-12-29, 2018-12-31, 2019-12-31, …
## $ open     <dbl> 26.75250, 29.16250, 42.63000, 39.63250, 72.48250, 134.08000, …
## $ high     <dbl> 26.7575, 29.3000, 42.6475, 39.8400, 73.4200, 134.7400, 179.23…
## $ low      <dbl> 26.20500, 28.85750, 42.30500, 39.12000, 72.38000, 131.72000, …
## $ close    <dbl> 26.31500, 28.95500, 42.30750, 39.43500, 73.41250, 132.69000, …
## $ volume   <dbl> 163649200, 122345200, 103999600, 140014000, 100805600, 991166…
## $ adjusted <dbl> 24.05418, 27.05623, 40.16885, 38.00368, 71.81093, 130.91617, …

2.2 Asset prices to returns

2.2.1 Daily return

prices_daily_log_returns <- prices %>%
    group_by(symbol) %>%
    tq_transmute(select     = adjusted, 
                 mutate_fun = periodReturn, 
                 period     = "daily", 
                 type       = "log",
                 col_rename = "daily.returns")

prices_daily_log_returns %>% ggplot(aes(x=date, y=daily.returns, col=symbol))+geom_line()+facet_wrap(symbol~.)

t=prices_daily_log_returns %>%
    ggplot(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

t=prices_daily_log_returns %>%
    ggplot(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

### Monthly returns

prices_monthly_log_returns <- prices %>%
    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_monthly_log_returns <- prices %>%
    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)

prices_monthly_log_returns <- prices %>%
    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)

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)

prices_monthly_log_returns%>%
ggplot(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))

2.2.2 Yearly returns

(prices_yearly_log_returns <- prices %>%
    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 AAPL   2015-12-31       -0.155  
##  2 AAPL   2016-12-30        0.118  
##  3 AAPL   2017-12-29        0.395  
##  4 AAPL   2018-12-31       -0.0554 
##  5 AAPL   2019-12-31        0.636  
##  6 AAPL   2020-12-31        0.601  
##  7 AAPL   2021-12-31        0.297  
##  8 AAPL   2022-12-30       -0.307  
##  9 AAPL   2023-03-17        0.178  
## 10 DIS    2015-12-31       -0.00751
## # … with 26 more rows
prices_yearly_log_returns %>% ggplot(aes(x=date, y=yearly.returns, col=symbol))+geom_line()+facet_wrap(symbol~.)

2.3 Mean return for the whole period

2.3.1 Daily mean return for the whole period

prices_daily_log_returns %>% group_by(symbol) %>% 
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)
## # A tibble: 4 × 5
##   symbol mean_return median_return maximum_return minimum_return
##   <chr>        <dbl>         <dbl>          <dbl>          <dbl>
## 1 AAPL          0.08          0.08           11.3          -13.8
## 2 ADBE          0.08          0.16           16.3          -18.4
## 3 DIS           0             0.01           13.5          -14.1
## 4 TSLA          0.13          0.13           18.1          -23.6
prices_daily_log_returns %>% ggplot(aes(x=date, y=daily.returns, col=symbol))+geom_line()+facet_wrap(symbol~.)

2.3.2 Monthly mean return for the whole period

prices_monthly_log_returns %>% group_by(symbol) %>% 
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)
## # A tibble: 4 × 5
##   symbol mean_return median_return maximum_return minimum_return
##   <chr>        <dbl>         <dbl>          <dbl>          <dbl>
## 1 AAPL          1.76          2.34           19.6          -20.0
## 2 ADBE          1.58          2.74           16.0          -30.5
## 3 DIS          -0.07         -0.31           22.2          -20.6
## 4 TSLA          2.73          1.1            55.5          -45.8
prices_monthly_log_returns %>% ggplot(aes(x=date, y=monthly.returns, col=symbol))+geom_line()+facet_wrap(symbol~.)

2.3.3 Yearly mean return for the whole period

prices_yearly_log_returns %>% group_by(symbol) %>% 
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)
## # A tibble: 4 × 5
##   symbol mean_return median_return maximum_return minimum_return
##   <chr>        <dbl>         <dbl>          <dbl>          <dbl>
## 1 AAPL         19.0          17.8            63.6          -30.7
## 2 ADBE         17.0          19.4            53.2          -52.2
## 3 DIS          -0.77          3.54           28.9          -57.8
## 4 TSLA         29.4          22.9           213.          -105.
prices_yearly_log_returns %>% ggplot(aes(x=date, y=yearly.returns, col=symbol))+geom_line()+facet_wrap(symbol~.)

2.4 Stock volatility for the whole period

2.4.1 Daily Stock volatility for the whole period

prices_daily_log_returns %>% group_by(symbol) %>% 
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)
## # A tibble: 4 × 6
##   symbol mean_return median_return volatility maximum_return minimum_return
##   <chr>        <dbl>         <dbl>      <dbl>          <dbl>          <dbl>
## 1 AAPL          0.08          0.08       1.88           11.3          -13.8
## 2 ADBE          0.08          0.16       2.1            16.3          -18.4
## 3 DIS           0             0.01       1.78           13.5          -14.1
## 4 TSLA          0.13          0.13       3.62           18.1          -23.6
prices_daily_log_returns %>%  ggplot(aes(x=daily.returns,col=symbol))+geom_boxplot()+facet_wrap(symbol~.)

2.4.2 Monthly Stock volatility for the whole period

prices_monthly_log_returns %>% group_by(symbol) %>% 
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)
## # A tibble: 4 × 6
##   symbol mean_return median_return volatility maximum_return minimum_return
##   <chr>        <dbl>         <dbl>      <dbl>          <dbl>          <dbl>
## 1 AAPL          1.76          2.34       8.26           19.6          -20.0
## 2 ADBE          1.58          2.74       8.03           16.0          -30.5
## 3 DIS          -0.07         -0.31       8.33           22.2          -20.6
## 4 TSLA          2.73          1.1       16.9            55.5          -45.8
prices_monthly_log_returns %>%  ggplot(aes(x=monthly.returns,col=symbol))+geom_boxplot()+facet_wrap(symbol~.)

2.4.3 Yearly Stock volatility for the whole period

prices_yearly_log_returns %>% group_by(symbol) %>% 
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)
## # A tibble: 4 × 6
##   symbol mean_return median_return volatility maximum_return minimum_return
##   <chr>        <dbl>         <dbl>      <dbl>          <dbl>          <dbl>
## 1 AAPL         19.0          17.8        32.6           63.6          -30.7
## 2 ADBE         17.0          19.4        30.4           53.2          -52.2
## 3 DIS          -0.77          3.54       25.0           28.9          -57.8
## 4 TSLA         29.4          22.9        82.5          213.          -105.
prices_yearly_log_returns %>%  ggplot(aes(x=yearly.returns,col=symbol))+geom_boxplot()+facet_wrap(symbol~.)

2.5 Rolling stock volatility

daily_window=30
daily_return_rolling=prices_daily_log_returns %>% group_by(symbol) %>% 
mutate(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

daily_return_rolling %>% ggplot(aes(x=date, y=rolling_mean_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

#### Rolling maximum daily return

daily_return_rolling %>% ggplot(aes(x=date, y=rolling_max_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

#### Rolling minimum daily return

daily_return_rolling %>% ggplot(aes(x=date, y=rolling_min_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

#### Rolling daily volatility return

daily_return_rolling %>% ggplot(aes(x=date, y=rolling_volatility*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

### Rolling monthly stock volatility

monthly_window=12
monthly_return_rolling=prices_monthly_log_returns %>% group_by(symbol) %>% 
mutate(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> "AAPL", "AAPL", "AAPL", "AAPL", "AAPL", "AAPL", …
## $ date                  <date> 2015-03-31, 2015-04-30, 2015-05-29, 2015-06-30,…
## $ monthly.returns       <dbl> -1.605562e-04, 5.769513e-03, 4.434131e-02, -3.79…
## $ 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.013939498, -0.013939498, …
## $ rolling_max_return    <dbl> NA, NA, NA, NA, NA, 0.08011253, 0.11974583, 0.11…
## $ rolling_min_return    <dbl> NA, NA, NA, NA, NA, -0.11679010, -0.11679010, -0…
## $ rolling_volatility    <dbl> NA, NA, NA, NA, NA, 0.05341556, 0.06688065, 0.07…

2.5.1.1 Rolling monthly mean return

monthly_return_rolling %>% ggplot(aes(x=date, y=rolling_max_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

2.5.1.2 Rolling minimum monthly return

monthly_return_rolling %>% ggplot(aes(x=date, y=rolling_volatility*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

2.5.2 Rolling yearly stock volatility

yearly_window=3
yearly_return_rolling=prices_yearly_log_returns %>% group_by(symbol) %>% 
mutate(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> "AAPL", "AAPL", "AAPL", "AAPL", "AAPL", "AAPL", …
## $ date                  <date> 2015-12-31, 2016-12-30, 2017-12-29, 2018-12-31,…
## $ yearly.returns        <dbl> -0.154514293, 0.117608655, 0.395174478, -0.05540…
## $ rolling_mean_return   <dbl> NA, NA, 0.11942295, 0.15245804, 0.32537307, 0.39…
## $ rolling_median_return <dbl> NA, 0.117608655, 0.117608655, 0.395174478, 0.600…
## $ rolling_max_return    <dbl> NA, 0.39517448, 0.39517448, 0.63635375, 0.636353…
## $ rolling_min_return    <dbl> NA, -0.154514293, -0.055409001, -0.055409001, -0…
## $ rolling_volatility    <dbl> NA, 0.27484888, 0.22730426, 0.35112405, 0.389457…

2.5.2.1 Rolling yearly mean return

yearly_return_rolling %>% ggplot(aes(x=date, y=rolling_mean_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

2.5.2.2 Rolling maximum yearly return

yearly_return_rolling %>% ggplot(aes(x=date, y=rolling_max_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

2.5.2.3 Rolling minimum yearly return

yearly_return_rolling %>% ggplot(aes(x=date, y=rolling_min_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

2.5.2.4 Rolling yearly volatility return

yearly_return_rolling %>% ggplot(aes(x=date, y=rolling_volatility*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

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_returns%>%
ggplot(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))

prices_daily_log_returns %>% group_by(symbol) %>% 
tq_performance(Ra = daily.returns,
Rb = NULL,
performance_fun = table.Distributions) %>%
  select(Skewness,Kurtosis) 
## # A tibble: 4 × 3
## # Groups:   symbol [4]
##   symbol Skewness Kurtosis
##   <chr>     <dbl>    <dbl>
## 1 AAPL    -0.229      8.27
## 2 DIS     -0.0334    14.3 
## 3 TSLA    -0.163      7.56
## 4 ADBE    -0.584     12.3

2.6.1.2 Monthly returns

prices_monthly_log_returns%>%
ggplot(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_returns %>% group_by(symbol) %>% 
tq_performance(Ra = monthly.returns,
Rb = NULL,
performance_fun = table.Distributions) %>%
  select(Skewness,Kurtosis) 
## # A tibble: 4 × 3
## # Groups:   symbol [4]
##   symbol Skewness Kurtosis
##   <chr>     <dbl>    <dbl>
## 1 AAPL     -0.229     2.52
## 2 DIS       0.160     3.72
## 3 TSLA      0.44      3.68
## 4 ADBE     -0.903     4.54

2.6.2 Rolling monthly Skewness and Kurtosis

monthly_window=12
monthly_normality_rolling=prices_monthly_log_returns %>% group_by(symbol) %>% 
mutate(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))

monthly_normality_rolling %>% ggplot(aes(x=date, y=rolling_skew_return,col=symbol))+geom_line()+facet_wrap(symbol~.)

monthly_normality_rolling %>% ggplot(aes(x=date, y=rolling_kurtosis_return,col=symbol))+geom_line()+facet_wrap(symbol~.)

2.7 Downside risk measures

prices_daily_log_returns %>% group_by(symbol) %>% 
tq_performance(Ra = daily.returns,
Rb = NULL,
performance_fun = table.DownsideRisk) %>%
  select(SemiDeviation,"HistoricalVaR(95%)" , "HistoricalES(95%)",MaximumDrawdown) 
## # A tibble: 4 × 5
## # Groups:   symbol [4]
##   symbol SemiDeviation `HistoricalVaR(95%)` `HistoricalES(95%)` MaximumDrawdown
##   <chr>          <dbl>                <dbl>               <dbl>           <dbl>
## 1 AAPL          0.0136              -0.0291             -0.0442           0.402
## 2 DIS           0.0126              -0.0263             -0.0422           0.620
## 3 TSLA          0.0259              -0.054              -0.0852           0.799
## 4 ADBE          0.0156              -0.0329             -0.0519           0.640

##         From     Trough         To   Depth Length To Trough Recovery
## 1 2021-11-05 2023-01-03       <NA> -0.7988    343       291       NA
## 2 2020-02-20 2020-03-18 2020-07-01 -0.6388     93        20       73
## 3 2017-06-26 2019-06-03 2020-01-14 -0.6377    643       487      156
## 4 2015-07-21 2016-02-10 2017-05-30 -0.5231    469       142      327
## 5 2021-01-11 2021-05-19 2021-10-25 -0.4044    200        90      110

charts.PerformanceSummary(fb_return_xts, 
 ylog       = TRUE,
 legend.loc = "topleft",
 main       = "Tesla stock Performance"
 )

##         From     Trough         To   Depth Length To Trough Recovery
## 1 2018-10-04 2019-01-03 2019-10-23 -0.4016    265        62      203
## 2 2022-01-04 2023-01-05       <NA> -0.3518    303       253       NA
## 3 2020-02-13 2020-03-23 2020-06-10 -0.3434     82        27       55
## 4 2015-05-26 2016-05-12 2017-02-14 -0.3312    436       245      191
## 5 2020-09-02 2020-09-18 2021-01-22 -0.2112     98        12       86

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    512       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 2021-11-22 2022-09-30       <NA> -0.6399    332       216       NA
## 2 2020-02-20 2020-03-16 2020-06-18 -0.2887     84        18       66
## 3 2018-10-02 2018-12-24 2019-04-30 -0.2793    144        58       86
## 4 2015-12-17 2016-02-09 2016-05-24 -0.2355    109        36       73
## 5 2020-09-03 2021-03-08 2021-06-14 -0.2336    195       127       68

charts.PerformanceSummary(fb_return_xts, 
 ylog       = TRUE,
 legend.loc = "topleft",
 main       = "Adobe stock Performance"
 )

3 Vietnamese stocks

new=NULL
id_list=c("VND","FPT","PNJ","VCB")
for (j in id_list){
for (i in 1:10){
  query_params <- list(currentPage=i,id = j)
  parameter_response <- GET("https://www.cophieu68.vn/historyprice.php", query = query_params)
  stock_share =read_html(parameter_response)
  new1=html_nodes(stock_share, xpath="//table[@class='stock']") %>%
    html_table(header = TRUE,fill=TRUE) %>% as.data.frame()
  new1=new1[,2:13]
  new1$symbol=j
  new=rbind(new,new1)
}}

3.1 Asset prices series

3.1.1 Daily prices

3.1.2 Monthly stock prices

monthly_prices=prices %>% group_by(symbol) %>%
    tq_transmute(select     = 2:12, 
                 mutate_fun = to.period, 
                 period     = "months")
glimpse(monthly_prices)
## Rows: 196
## Columns: 13
## Groups: symbol [4]
## $ symbol                  <chr> "VND", "VND", "VND", "VND", "VND", "VND", "VND…
## $ date                    <date> 2019-03-29, 2019-04-26, 2019-05-31, 2019-06-2…
## $ Last_closed_price       <dbl> 3.87, 3.65, 3.69, 3.62, 3.49, 3.31, 3.43, 3.21…
## $ absolute_price_change   <dbl> -0.02, 0.00, -0.03, 0.01, 0.00, 0.00, -0.02, 0…
## $ Percentage_price_change <dbl> -0.005167959, 0.000000000, -0.008130081, 0.002…
## $ Closed_price            <dbl> 3.84, 3.65, 3.66, 3.64, 3.49, 3.31, 3.41, 3.21…
## $ Trading_Volume          <dbl> 719420, 306440, 366210, 213130, 360560, 311890…
## $ Open_price              <dbl> 3.87, 3.65, 3.69, 3.62, 3.49, 3.31, 3.43, 3.21…
## $ Highest_price           <dbl> 3.88, 3.66, 3.69, 3.64, 3.49, 3.32, 3.48, 3.21…
## $ Lowest_price            <dbl> 3.83, 3.60, 3.54, 3.56, 3.43, 3.26, 3.41, 3.18…
## $ Exchange_volume         <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ Foregin_buy_volume      <dbl> 115160, 0, 74000, 70000, 20000, 75000, 0, 0, 5…
## $ Foreign_sell_volume     <dbl> 75500, 200, 0, 0, 0, 17460, 113230, 0, 0, 0, 2…

3.1.3 Yearly stock prices

yearly_prices=prices %>% group_by(symbol) %>%
    tq_transmute(select     = 2:12, 
                 mutate_fun = to.period, 
                 period     = "years")
glimpse(yearly_prices)
## Rows: 20
## Columns: 13
## Groups: symbol [4]
## $ symbol                  <chr> "VND", "VND", "VND", "VND", "VND", "FPT", "FPT…
## $ date                    <date> 2019-12-31, 2020-12-31, 2021-12-31, 2022-12-3…
## $ Last_closed_price       <dbl> 3.39, 7.21, 32.92, 13.50, 14.80, 34.05, 40.39,…
## $ absolute_price_change   <dbl> 0.01, 0.15, -0.32, 0.00, 0.20, -0.17, 0.70, -0…
## $ Percentage_price_change <dbl> 0.002949853, 0.020804438, -0.009720535, 0.0000…
## $ Closed_price            <dbl> 3.40, 7.36, 32.60, 13.50, 15.00, 33.87, 41.09,…
## $ Trading_Volume          <dbl> 108720, 3940730, 3670100, 12603500, 20471500, …
## $ Open_price              <dbl> 3.39, 7.21, 33.32, 13.65, 15.15, 34.05, 41.09,…
## $ Highest_price           <dbl> 3.40, 7.59, 33.32, 13.85, 15.15, 34.10, 41.15,…
## $ Lowest_price            <dbl> 3.33, 7.21, 32.36, 13.50, 14.70, 33.70, 40.32,…
## $ Exchange_volume         <dbl> 0, 0, 0, 0, 0, 0, 100000, 132300, 500000, 0, 0…
## $ Foregin_buy_volume      <dbl> 0, 53460, 352300, 3184900, 9229700, 7710, 3550…
## $ Foreign_sell_volume     <dbl> 0, 5500, 70600, 1445400, 926100, 0, 10, 200000…

3.2 Asset prices to returns

3.2.1 Daily return

prices_daily_log_returns <- prices %>%
    group_by(symbol) %>%
    tq_transmute(select     = Closed_price, 
                 mutate_fun = periodReturn, 
                 period     = "daily", 
                 type       = "log",
                 col_rename = "daily.returns")

prices_daily_log_returns %>% ggplot(aes(x=date, y=daily.returns, col=symbol))+geom_line()+facet_wrap(symbol~.)

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)

3.2.2 Monthly returns

prices_monthly_log_returns <- prices %>%
    group_by(symbol) %>%
    tq_transmute(select     = Closed_price, 
                 mutate_fun = periodReturn, 
                 period     = "monthly", 
                 type       = "log",
                 col_rename = "monthly.returns")


prices_monthly_log_returns%>%
ggplot(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_returns%>%
ggplot(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_yearly_log_returns <- prices %>%
    group_by(symbol) %>%
    tq_transmute(select     = Closed_price, 
                 mutate_fun = periodReturn, 
                 period     = "yearly", 
                 type       = "log",
                 col_rename = "yearly.returns")
prices_yearly_log_returns %>% ggplot(aes(x=date, y=yearly.returns,col=symbol))+geom_line()+facet_wrap(.~symbol)

3.3 Mean return for the whole period

3.3.1 Daily mean return for the whole period

prices_daily_log_returns %>% group_by(symbol) %>% 
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)
## # A tibble: 4 × 5
##   symbol mean_return median_return maximum_return minimum_return
##   <chr>        <dbl>         <dbl>          <dbl>          <dbl>
## 1 FPT           0.12          0.11           6.76          -7.24
## 2 PNJ           0.04          0              6.76          -7.26
## 3 VCB           0.06          0              6.67          -7.24
## 4 VND           0.13          0              9.52         -10.4
prices_daily_log_returns %>% ggplot(aes(x=date, y=daily.returns, col=symbol))+geom_line()+facet_wrap(symbol~.)

3.3.2 Monthly mean return for the whole period

prices_monthly_log_returns %>% group_by(symbol) %>% 
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)
## # A tibble: 4 × 5
##   symbol mean_return median_return maximum_return minimum_return
##   <chr>        <dbl>         <dbl>          <dbl>          <dbl>
## 1 FPT           2.51          3.04           21.2          -29.3
## 2 PNJ           0.83          1.51           21.5          -55.5
## 3 VCB           1.15          0.82           22.6          -28.4
## 4 VND           2.71          2.95           49.6          -42.0
prices_monthly_log_returns %>% ggplot(aes(x=date, y=monthly.returns, col=symbol))+geom_line()+facet_wrap(symbol~.)

3.3.3 Yearly mean return for the whole period

prices_yearly_log_returns %>% group_by(symbol) %>% 
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)
## # A tibble: 4 × 5
##   symbol mean_return median_return maximum_return minimum_return
##   <chr>        <dbl>         <dbl>          <dbl>          <dbl>
## 1 FPT          24.6           19.3           61.4           1.28
## 2 PNJ           8.15          13.4           23.8         -12.3 
## 3 VCB          11.2            9             31.1           1.51
## 4 VND          26.6           10.5          149.          -88.2
prices_yearly_log_returns %>% ggplot(aes(x=date, y=yearly.returns, col=symbol))+geom_line()+facet_wrap(symbol~.)

3.4 Stock volatility for the whole period

3.4.1 Daily Stock volatility for the whole period

prices_daily_log_returns %>% group_by(symbol) %>% 
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)
## # A tibble: 4 × 6
##   symbol mean_return median_return volatility maximum_return minimum_return
##   <chr>        <dbl>         <dbl>      <dbl>          <dbl>          <dbl>
## 1 FPT           0.12          0.11       1.81           6.76          -7.24
## 2 PNJ           0.04          0          2.08           6.76          -7.26
## 3 VCB           0.06          0          1.78           6.67          -7.24
## 4 VND           0.13          0          2.98           9.52         -10.4
prices_daily_log_returns %>%  ggplot(aes(x=daily.returns,col=symbol))+geom_boxplot()+facet_wrap(symbol~.)

3.4.2 Monthly Stock volatility for the whole period

prices_monthly_log_returns %>% group_by(symbol) %>% 
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)
## # A tibble: 4 × 6
##   symbol mean_return median_return volatility maximum_return minimum_return
##   <chr>        <dbl>         <dbl>      <dbl>          <dbl>          <dbl>
## 1 FPT           2.51          3.04       8.27           21.2          -29.3
## 2 PNJ           0.83          1.51      11.3            21.5          -55.5
## 3 VCB           1.15          0.82       8.62           22.6          -28.4
## 4 VND           2.71          2.95      17.4            49.6          -42.0
prices_monthly_log_returns %>%  ggplot(aes(x=monthly.returns,col=symbol))+geom_boxplot()+facet_wrap(symbol~.)

3.4.3 Yearly Stock volatility for the whole period

prices_yearly_log_returns %>% group_by(symbol) %>% 
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)
## # A tibble: 4 × 6
##   symbol mean_return median_return volatility maximum_return minimum_return
##   <chr>        <dbl>         <dbl>      <dbl>          <dbl>          <dbl>
## 1 FPT          24.6           19.3       25.5           61.4           1.28
## 2 PNJ           8.15          13.4       15.2           23.8         -12.3 
## 3 VCB          11.2            9         11.7           31.1           1.51
## 4 VND          26.6           10.5       90.4          149.          -88.2
prices_yearly_log_returns %>%  ggplot(aes(x=yearly.returns,col=symbol))+geom_boxplot()+facet_wrap(symbol~.)

3.5 Rolling stock volatility

3.5.1 Rolling daily stock volatility

daily_window=30
daily_return_rolling=prices_daily_log_returns %>% group_by(symbol) %>% 
mutate(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

daily_return_rolling %>% ggplot(aes(x=date, y=rolling_mean_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

3.5.1.2 Rolling maximum daily return

daily_return_rolling %>% ggplot(aes(x=date, y=rolling_max_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

3.5.1.3 Rolling minimum daily return

daily_return_rolling %>% ggplot(aes(x=date, y=rolling_min_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

3.5.1.4 Rolling daily volatility return

daily_return_rolling %>% ggplot(aes(x=date, y=rolling_volatility*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

3.5.2 Rolling monthly stock volatility

monthly_window=12
monthly_return_rolling=prices_monthly_log_returns %>% group_by(symbol) %>% 
mutate(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

monthly_return_rolling %>% ggplot(aes(x=date, y=rolling_mean_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

3.5.2.2 Rolling maximum monthly return

monthly_return_rolling %>% ggplot(aes(x=date, y=rolling_max_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

3.5.2.3 Rolling minimum monthly return

monthly_return_rolling %>% ggplot(aes(x=date, y=rolling_min_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

3.5.2.4 Rolling monthly volatility return

monthly_return_rolling %>% ggplot(aes(x=date, y=rolling_volatility*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

3.5.3 Rolling yearly stock volatility

yearly_window=3
yearly_return_rolling=prices_yearly_log_returns %>% group_by(symbol) %>% 
mutate(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> "VND", "VND", "VND", "VND", "VND", "FPT", "FPT",…
## $ date                  <date> 2019-12-31, 2020-12-31, 2021-12-31, 2022-12-30,…
## $ yearly.returns        <dbl> -0.15499066, 0.77228450, 1.48825236, -0.88162260…
## $ rolling_mean_return   <dbl> NA, NA, 0.70184873, 0.45963808, 0.23733009, NA, …
## $ rolling_median_return <dbl> NA, 0.77228450, 0.77228450, 0.10536052, NA, NA, …
## $ rolling_max_return    <dbl> NA, 1.48825236, 1.48825236, 1.48825236, NA, NA, …
## $ rolling_min_return    <dbl> NA, -0.15499066, -0.88162260, -0.88162260, NA, N…
## $ rolling_volatility    <dbl> NA, 0.82388276, 1.21547837, 1.19043639, NA, NA, …

3.5.3.1 Rolling yearly mean return

yearly_return_rolling %>% ggplot(aes(x=date, y=rolling_mean_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

3.5.3.2 Rolling maximum yearly return

yearly_return_rolling %>% ggplot(aes(x=date, y=rolling_max_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

3.5.3.3 Rolling minimum yearly return

yearly_return_rolling %>% ggplot(aes(x=date, y=rolling_min_return*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

3.5.3.4 Rolling yearly volatility return

yearly_return_rolling %>% ggplot(aes(x=date, y=rolling_volatility*100,col=symbol))+geom_line()+facet_wrap(symbol~.)

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_returns%>%
ggplot(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))

prices_daily_log_returns %>% group_by(symbol) %>% 
tq_performance(Ra = daily.returns,
Rb = NULL,
performance_fun = table.Distributions) %>%
  select(Skewness,Kurtosis) 
## # A tibble: 4 × 3
## # Groups:   symbol [4]
##   symbol Skewness Kurtosis
##   <chr>     <dbl>    <dbl>
## 1 VND     -0.0765     4.15
## 2 FPT     -0.226      6.12
## 3 PNJ     -0.306      5.43
## 4 VCB     -0.210      5.23

3.6.1.2 Monthly returns

prices_monthly_log_returns%>%
ggplot(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_returns %>% group_by(symbol) %>% 
tq_performance(Ra = monthly.returns,
Rb = NULL,
performance_fun = table.Distributions) %>%
  select(Skewness,Kurtosis) 
## # A tibble: 4 × 3
## # Groups:   symbol [4]
##   symbol Skewness Kurtosis
##   <chr>     <dbl>    <dbl>
## 1 VND     -0.0594     3.75
## 2 FPT     -0.687      6.42
## 3 PNJ     -2.46      14.0 
## 4 VCB     -0.496      5.06

3.6.2 Rolling monthly Skewness and Kurtosis

monthly_window=12
monthly_normality_rolling=prices_monthly_log_returns %>% group_by(symbol) %>% 
mutate(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))
monthly_normality_rolling %>% ggplot(aes(x=date, y=rolling_skew_return,col=symbol))+geom_line()+facet_wrap(symbol~.)

monthly_normality_rolling %>% ggplot(aes(x=date, y=rolling_kurtosis_return,col=symbol))+geom_line()+facet_wrap(symbol~.)

3.7 Downside risk measures

prices_daily_log_returns %>% group_by(symbol) %>% 
tq_performance(Ra = daily.returns,
Rb = NULL,
performance_fun = table.DownsideRisk) %>%
  select(SemiDeviation,"HistoricalVaR(95%)" , "HistoricalES(95%)",MaximumDrawdown) 
## # A tibble: 4 × 5
## # Groups:   symbol [4]
##   symbol SemiDeviation `HistoricalVaR(95%)` `HistoricalES(95%)` MaximumDrawdown
##   <chr>          <dbl>                <dbl>               <dbl>           <dbl>
## 1 VND           0.0212              -0.0584             -0.0711           0.754
## 2 FPT           0.013               -0.0252             -0.0443           0.352
## 3 PNJ           0.0151              -0.0336             -0.0524           0.503
## 4 VCB           0.0127              -0.0266             -0.0424           0.405

3.7.1 VND stock performance

fb=prices %>% filter(symbol=='VND') %>% select(symbol, date, open=Open_price,high=Highest_price, low=Lowest_price,close=Closed_price, volume=Exchange_volume)
glimpse(fb)
## Rows: 1,000
## Columns: 7
## $ symbol <chr> "VND", "VND", "VND", "VND", "VND", "VND", "VND", "VND", "VND", …
## $ date   <date> 2023-03-17, 2023-03-16, 2023-03-15, 2023-03-14, 2023-03-13, 20…
## $ open   <dbl> 15.15, 14.90, 14.60, 14.55, 14.30, 14.55, 14.75, 14.00, 14.00, …
## $ high   <dbl> 15.15, 15.10, 14.95, 14.60, 14.80, 14.80, 14.95, 14.70, 14.35, …
## $ low    <dbl> 14.70, 14.80, 14.40, 13.95, 14.30, 14.30, 14.60, 13.90, 13.90, …
## $ close  <dbl> 15.00, 14.80, 14.95, 14.00, 14.50, 14.50, 14.70, 14.70, 14.20, …
## $ volume <dbl> 0, 0, 0, 0, 0, 0, 40000, 0, 0, 0, 154900, 0, 446400, 478100, 0,…
fb_xts=xts(fb[,3:7], order.by = fb$date)
fb_xts%>% 
  chartSeries( 
    # Add Bollinger Bands, Volume, Moving Average Convergence/Divergence
    TA = 'addBBands();
          addVo();
 addRSI();
          '
, 
    theme  = chartTheme("white.mono"),                    
    name = "VND Stock Prices Evolution", 
    minor.ticks = FALSE, 
    up.col = "seagreen3", 
    dn.col = "indianred2",
    colov.vol = c("indianred2", "seagreen2")
  )  

fb_r=prices_daily_log_returns %>% filter(symbol=="VND")
fb_return_xts=xts(fb_r[,3],order.by=fb_r$date)
table.Drawdowns(fb_return_xts)
##         From     Trough         To   Depth Length To Trough Recovery
## 1 2021-12-21 2022-11-10       <NA> -0.7542    308       222       NA
## 2 2019-03-21 2020-05-05 2020-11-11 -0.3817    415       280      135
## 3 2021-01-18 2021-02-01 2021-04-05 -0.3211     51        11       40
## 4 2021-07-05 2021-07-19 2021-08-03 -0.2339     22        11       11
## 5 2021-06-04 2021-06-08 2021-06-11 -0.1486      6         3        3
# Plot of drawdowns
chart.Drawdown(fb_return_xts)

charts.PerformanceSummary(fb_return_xts, 
 ylog       = TRUE,
 legend.loc = "topleft",
 main       = "VND stock Performance"
 )

3.7.2 FPT stock performance

fb=prices %>% filter(symbol=='FPT') %>% select(symbol, date, open=Open_price,high=Highest_price, low=Lowest_price,close=Closed_price, volume=Exchange_volume)
glimpse(fb)
## Rows: 1,000
## Columns: 7
## $ symbol <chr> "FPT", "FPT", "FPT", "FPT", "FPT", "FPT", "FPT", "FPT", "FPT", …
## $ date   <date> 2023-03-17, 2023-03-16, 2023-03-15, 2023-03-14, 2023-03-13, 20…
## $ open   <dbl> 79.6, 80.0, 79.1, 79.0, 78.1, 80.2, 79.5, 78.5, 79.1, 78.1, 79.…
## $ high   <dbl> 80.0, 80.0, 80.5, 79.1, 79.4, 80.4, 80.7, 79.5, 79.9, 79.8, 80.…
## $ low    <dbl> 78.6, 79.1, 79.1, 78.5, 78.1, 79.0, 79.2, 78.5, 78.8, 78.1, 78.…
## $ close  <dbl> 79.0, 79.1, 80.5, 78.7, 78.9, 79.5, 80.6, 79.5, 78.8, 78.2, 78.…
## $ volume <dbl> 0, 0, 608400, 270000, 0, 0, 632900, 564500, 108900, 28000, 0, 1…
fb_xts=xts(fb[,3:7], order.by = fb$date)
fb_xts%>% 
  chartSeries( 
    # Add Bollinger Bands, Volume, Moving Average Convergence/Divergence
    TA = 'addBBands();
          addVo();
 addRSI();
          '
, 
    theme  = chartTheme("white.mono"),                    
    name = "FPT Stock Prices Evolution", 
    minor.ticks = FALSE, 
    up.col = "seagreen3", 
    dn.col = "indianred2",
    colov.vol = c("indianred2", "seagreen2")
  )  

fb_r=prices_daily_log_returns %>% filter(symbol=="FPT")
fb_return_xts=xts(fb_r[,3],order.by=fb_r$date)
table.Drawdowns(fb_return_xts)
##         From     Trough         To   Depth Length To Trough Recovery
## 1 2019-11-13 2020-03-30 2020-10-22 -0.3523    237        93      144
## 2 2022-04-15 2022-11-15       <NA> -0.3348    232       149       NA
## 3 2021-11-26 2022-01-24 2022-03-29 -0.1503     82        41       41
## 4 2021-01-26 2021-01-28 2021-02-03 -0.1289      7         3        4
## 5 2021-07-06 2021-07-19 2021-07-26 -0.0903     15        10        5
# Plot of drawdowns
chart.Drawdown(fb_return_xts)

charts.PerformanceSummary(fb_return_xts, 
 ylog       = TRUE,
 legend.loc = "topleft",
 main       = "FPT stock Performance"
 )