library(quantmod)
## Warning: package 'quantmod' was built under R version 4.5.2
## Loading required package: xts
## Warning: package 'xts' was built under R version 4.5.2
## Loading required package: zoo
## Warning: package 'zoo' was built under R version 4.5.2
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
## Loading required package: TTR
## Warning: package 'TTR' was built under R version 4.5.2
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.5.2
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.1     ✔ stringr   1.5.2
## ✔ ggplot2   4.0.0     ✔ tibble    3.3.0
## ✔ lubridate 1.9.4     ✔ tidyr     1.3.1
## ✔ purrr     1.1.0
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::first()  masks xts::first()
## ✖ dplyr::lag()    masks stats::lag()
## ✖ dplyr::last()   masks xts::last()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(patchwork)
## Warning: package 'patchwork' was built under R version 4.5.2
tickers <- c("AAPL","AMD","MU","NIO","NVDA","PRPL","SNAP","TSLA")

start_date <- "2016-01-01"
end_date   <- "2024-12-01"
getSymbols(tickers, from = start_date, to = end_date, auto.assign = TRUE)
## [1] "AAPL" "AMD"  "MU"   "NIO"  "NVDA" "PRPL" "SNAP" "TSLA"
prices <- map(tickers, ~ Ad(get(.x))) %>%
  reduce(merge) %>%
  `colnames<-`(tickers)
normalized <- prices / as.numeric(prices[1,])
df_norm <- data.frame(Date = index(normalized), coredata(normalized)) %>%
  pivot_longer(-Date, names_to = "Stock", values_to = "Price")
p1 <- ggplot(df_norm, aes(Date, Price, color = Stock)) +
  geom_line() +
  labs(title = "Normalized Stock Prices (2016–2024)",
       y = "Normalized Price (Base = 1)",
       x = "Date") +
  theme_minimal()

p1
## Warning: Removed 975 rows containing missing values or values outside the scale range
## (`geom_line()`).

df_raw <- data.frame(Date = index(prices), coredata(prices)) %>%
  pivot_longer(-Date, names_to = "Stock", values_to = "Close")

p2 <- ggplot(df_raw, aes(Date, Close)) +
  geom_line(color = "steelblue") +
  facet_wrap(~ Stock, scales = "free_y", ncol = 3) +
  labs(title = "Closing Prices of Sampled Stocks (2016–2024)",
       y = "Closing Price",
       x = "Date") +
  theme_minimal()

p2