# Load packages
library(tidyverse)
library(tidyquant)

1 Get stock prices and convert to returns

Ra <- c("JPM", "MS", "DNB.OL", "NDA-FI.HE") %>%
    tq_get(get = "stock.prices", 
           from = "2022-01-01") %>%
    group_by(symbol) %>%  # Group by symbol to handle each stock separately
    tq_transmute(select     = adjusted, 
                 mutate_fun = periodReturn,
                 period     = "monthly",
                 col_rename = "Ra")
Ra
## # A tibble: 132 × 3
## # Groups:   symbol [4]
##    symbol date            Ra
##    <chr>  <date>       <dbl>
##  1 JPM    2022-01-31 -0.0755
##  2 JPM    2022-02-28 -0.0458
##  3 JPM    2022-03-31 -0.0386
##  4 JPM    2022-04-29 -0.118 
##  5 JPM    2022-05-31  0.108 
##  6 JPM    2022-06-30 -0.148 
##  7 JPM    2022-07-29  0.0335
##  8 JPM    2022-08-31 -0.0141
##  9 JPM    2022-09-30 -0.0812
## 10 JPM    2022-10-31  0.215 
## # ℹ 122 more rows

2 Get baseline and convert to return

Rb <- c("^IXIC") %>%
    tq_get(get = "stock.prices", 
           from = "2022-01-01") %>%
    tq_transmute(select     = adjusted, 
                 mutate_fun = periodReturn,
                 period     = "monthly",
                 col_rename = "Rb")  # Name the column "Rb" for the baseline returns
Rb
## # A tibble: 33 × 2
##    date            Rb
##    <date>       <dbl>
##  1 2022-01-31 -0.101 
##  2 2022-02-28 -0.0343
##  3 2022-03-31  0.0341
##  4 2022-04-29 -0.133 
##  5 2022-05-31 -0.0205
##  6 2022-06-30 -0.0871
##  7 2022-07-29  0.123 
##  8 2022-08-31 -0.0464
##  9 2022-09-30 -0.105 
## 10 2022-10-31  0.0390
## # ℹ 23 more rows

3 Join the two tables

RaRb <- left_join(Ra, Rb, by = c("date" = "date"))
RaRb
## # A tibble: 132 × 4
## # Groups:   symbol [4]
##    symbol date            Ra      Rb
##    <chr>  <date>       <dbl>   <dbl>
##  1 JPM    2022-01-31 -0.0755 -0.101 
##  2 JPM    2022-02-28 -0.0458 -0.0343
##  3 JPM    2022-03-31 -0.0386  0.0341
##  4 JPM    2022-04-29 -0.118  -0.133 
##  5 JPM    2022-05-31  0.108  -0.0205
##  6 JPM    2022-06-30 -0.148  -0.0871
##  7 JPM    2022-07-29  0.0335  0.123 
##  8 JPM    2022-08-31 -0.0141 -0.0464
##  9 JPM    2022-09-30 -0.0812 -0.105 
## 10 JPM    2022-10-31  0.215   0.0390
## # ℹ 122 more rows

4 Calculate CAPM

RaRb_capm <- RaRb %>% 
    tq_performance(Ra = Ra,  # This refers to the "Ra" column in RaRb (for stock returns)
                   Rb = Rb,  # This refers to the "Rb" column in RaRb (for baseline returns)
                   performance_fun = table.CAPM)
RaRb_capm
## # A tibble: 4 × 13
## # Groups:   symbol [4]
##   symbol  ActivePremium  Alpha AnnualizedAlpha  Beta `Beta-` `Beta+` Correlation
##   <chr>           <dbl>  <dbl>           <dbl> <dbl>   <dbl>   <dbl>       <dbl>
## 1 JPM            0.082  0.009           0.114  0.718   1.20   0.0523       0.588
## 2 MS             0.0015 0.003           0.0367 0.740   0.535  0.894        0.575
## 3 DNB.OL         0.0549 0.0079          0.0994 0.249   0.669  0.135        0.305
## 4 NDA-FI…        0.0312 0.006           0.0749 0.366   0.321  0.567        0.395
## # ℹ 5 more variables: `Correlationp-value` <dbl>, InformationRatio <dbl>,
## #   `R-squared` <dbl>, TrackingError <dbl>, TreynorRatio <dbl>

Which stock has a positively skewed distribution of returns?

RaRb_skewness <- RaRb %>% 
    tq_performance(Ra = Ra, 
                   Rb = NULL, 
                   performance_fun = skewness)
RaRb_skewness
## # A tibble: 4 × 2
## # Groups:   symbol [4]
##   symbol    skewness.1
##   <chr>          <dbl>
## 1 JPM            0.125
## 2 MS             0.216
## 3 DNB.OL        -0.285
## 4 NDA-FI.HE      0.124

Interpretation

JPM has a positive skewness of 0.124. MS has a positive skewness of 0.254. NDA-FI.HE has a positive skewness of 0.138. DNB.OL has a negative skewness of -0.279. Conclusion: The stocks MS (0.254), NDA-FI.HE (0.138), and JPM (0.124) all exhibit a positively skewed distribution of returns. Among these, MS has the highest positive skewness, indicating that it has the greatest potential for larger upside movements compared to the others.

DNB.OL is the only stock with a negatively skewed distribution, meaning it has a higher potential for larger downside movements.