Brody DeMasi
2025-05-21
# Load packages
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ✔ purrr 1.0.4
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(tidyquant)
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
## ── Attaching core tidyquant packages ─────────────────────── tidyquant 1.0.10 ──
## ✔ PerformanceAnalytics 2.0.8 ✔ TTR 0.24.4
## ✔ quantmod 0.4.26 ✔ xts 0.14.1── Conflicts ────────────────────────────────────────── tidyquant_conflicts() ──
## ✖ zoo::as.Date() masks base::as.Date()
## ✖ zoo::as.Date.numeric() masks base::as.Date.numeric()
## ✖ dplyr::filter() masks stats::filter()
## ✖ xts::first() masks dplyr::first()
## ✖ dplyr::lag() masks stats::lag()
## ✖ xts::last() masks dplyr::last()
## ✖ PerformanceAnalytics::legend() masks graphics::legend()
## ✖ quantmod::summary() masks base::summary()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
1 Get stock prices and convert to returns
Ra <- c("NVDA", "SHOP", "TTD") %>%
tq_get(get = "stock.prices",
from = "2025-01-01") %>%
group_by(symbol) %>%
tq_transmute(select = adjusted,
mutate_fun = periodReturn,
period = "monthly",
col_rename = "Ra")
Ra
## # A tibble: 15 × 3
## # Groups: symbol [3]
## symbol date Ra
## <chr> <date> <dbl>
## 1 NVDA 2025-01-31 -0.132
## 2 NVDA 2025-02-28 0.0404
## 3 NVDA 2025-03-31 -0.132
## 4 NVDA 2025-04-30 0.00498
## 5 NVDA 2025-05-20 0.234
## 6 SHOP 2025-01-31 0.0862
## 7 SHOP 2025-02-28 -0.0411
## 8 SHOP 2025-03-31 -0.147
## 9 SHOP 2025-04-30 -0.00503
## 10 SHOP 2025-05-20 0.120
## 11 TTD 2025-01-31 0.00807
## 12 TTD 2025-02-28 -0.407
## 13 TTD 2025-03-31 -0.222
## 14 TTD 2025-04-30 -0.0199
## 15 TTD 2025-05-20 0.437
2 Get baseline and convert to returns
Rb <- "^IXIC" %>%
tq_get(get = "stock.prices",
from = "2024-01-01") %>%
tq_transmute(select = adjusted,
mutate_fun = periodReturn,
period = "monthly",
col_rename = "Rb")
Rb
## # A tibble: 17 × 2
## date Rb
## <date> <dbl>
## 1 2024-01-31 0.0270
## 2 2024-02-29 0.0612
## 3 2024-03-28 0.0179
## 4 2024-04-30 -0.0441
## 5 2024-05-31 0.0688
## 6 2024-06-28 0.0596
## 7 2024-07-31 -0.00751
## 8 2024-08-30 0.00649
## 9 2024-09-30 0.0268
## 10 2024-10-31 -0.00517
## 11 2024-11-29 0.0621
## 12 2024-12-31 0.00482
## 13 2025-01-31 0.0164
## 14 2025-02-28 -0.0397
## 15 2025-03-31 -0.0821
## 16 2025-04-30 0.00850
## 17 2025-05-20 0.0972
3 Join the two data tables
RaRb <- left_join(Ra, Rb, by = c("date" = "date"))
RaRb
## # A tibble: 15 × 4
## # Groups: symbol [3]
## symbol date Ra Rb
## <chr> <date> <dbl> <dbl>
## 1 NVDA 2025-01-31 -0.132 0.0164
## 2 NVDA 2025-02-28 0.0404 -0.0397
## 3 NVDA 2025-03-31 -0.132 -0.0821
## 4 NVDA 2025-04-30 0.00498 0.00850
## 5 NVDA 2025-05-20 0.234 0.0972
## 6 SHOP 2025-01-31 0.0862 0.0164
## 7 SHOP 2025-02-28 -0.0411 -0.0397
## 8 SHOP 2025-03-31 -0.147 -0.0821
## 9 SHOP 2025-04-30 -0.00503 0.00850
## 10 SHOP 2025-05-20 0.120 0.0972
## 11 TTD 2025-01-31 0.00807 0.0164
## 12 TTD 2025-02-28 -0.407 -0.0397
## 13 TTD 2025-03-31 -0.222 -0.0821
## 14 TTD 2025-04-30 -0.0199 0.00850
## 15 TTD 2025-05-20 0.437 0.0972
4 Calculate CAPM
Which stock has a positively skewed distrobution of returns?
RaRb_skewness <- RaRb %>%
tq_performance(Ra = Ra,
Rb = NULL,
performance_fun = skewness)
RaRb_skewness
## # A tibble: 3 × 2
## # Groups: symbol [3]
## symbol skewness.1
## <chr> <dbl>
## 1 NVDA 0.602
## 2 SHOP -0.289
## 3 TTD 0.480