This analysis examines the stock price trends of major technology companies from 2016 to 2024. The stocks analyzed include:
library(tidyverse)
library(tidyquant)
library(lubridate)
We use the tidyquant package to download historical
stock price data from Yahoo Finance.
# Define stock symbols
stock_symbols <- c("AAPL", "AMD", "MU", "NIO", "NVDA", "PRPL", "SNAP", "TSLA", "TWTR")
# Download stock prices
stock_prices <- tq_get(
stock_symbols,
from = "2016-01-01",
to = "2024-12-31",
get = "stock.prices"
)
# Display data structure
glimpse(stock_prices)
## Rows: 17,134
## Columns: 8
## $ symbol <chr> "AAPL", "AAPL", "AAPL", "AAPL", "AAPL", "AAPL", "AAPL", "AAPL…
## $ date <date> 2016-01-04, 2016-01-05, 2016-01-06, 2016-01-07, 2016-01-08, …
## $ open <dbl> 25.6525, 26.4375, 25.1400, 24.6700, 24.6375, 24.7425, 25.1375…
## $ high <dbl> 26.3425, 26.4625, 25.5925, 25.0325, 24.7775, 24.7650, 25.1725…
## $ low <dbl> 25.5000, 25.6025, 24.9675, 24.1075, 24.1900, 24.3350, 24.7100…
## $ close <dbl> 26.3375, 25.6775, 25.1750, 24.1125, 24.2400, 24.6325, 24.9900…
## $ volume <dbl> 270597600, 223164000, 273829600, 324377600, 283192000, 198957…
## $ adjusted <dbl> 23.75315, 23.15792, 22.70472, 21.74648, 21.86147, 22.21545, 2…
stock_summary <- stock_prices %>%
group_by(symbol) %>%
summarise(
Start_Date = min(date),
End_Date = max(date),
Min_Price = min(close),
Max_Price = max(close),
Avg_Price = mean(close),
Total_Days = n()
) %>%
arrange(desc(Avg_Price))
knitr::kable(stock_summary,
caption = "Summary Statistics by Stock",
digits = 2)
| symbol | Start_Date | End_Date | Min_Price | Max_Price | Avg_Price | Total_Days |
|---|---|---|---|---|---|---|
| TSLA | 2016-01-04 | 2024-12-30 | 9.58 | 479.86 | 126.73 | 2263 |
| AAPL | 2016-01-04 | 2024-12-30 | 22.58 | 259.02 | 103.68 | 2263 |
| AMD | 2016-01-04 | 2024-12-30 | 1.80 | 211.38 | 64.77 | 2263 |
| MU | 2016-01-04 | 2024-12-30 | 9.56 | 153.45 | 56.34 | 2263 |
| NVDA | 2016-01-04 | 2024-12-30 | 0.63 | 148.88 | 23.02 | 2263 |
| SNAP | 2017-03-02 | 2024-12-30 | 4.99 | 83.11 | 21.52 | 1971 |
| NIO | 2018-09-12 | 2024-12-30 | 1.32 | 62.84 | 15.37 | 1585 |
| PRPL | 2016-01-04 | 2024-12-30 | 0.56 | 40.05 | 9.82 | 2263 |
This visualization shows each stock’s closing price in separate panels, with independent y-axis scales to highlight individual trends.
plot1 <- stock_prices %>%
ggplot(aes(x = date, y = close)) +
geom_line(color = "darkblue", size = 0.5) +
facet_wrap(~ symbol, scales = "free_y", ncol = 3) +
labs(
x = "Date",
y = "Closing prices"
) +
theme_minimal() +
theme(
strip.background = element_rect(fill = "lightgray", color = "lightgray"),
strip.text = element_text(face = "bold", size = 11),
panel.grid.minor = element_blank()
)
print(plot1)
This chart normalizes all stock prices to start at $1, allowing for direct comparison of relative performance across different stocks.
# Normalize prices to start at $1
stock_normalized <- stock_prices %>%
group_by(symbol) %>%
mutate(
first_price = first(close),
normalized_price = close / first_price
) %>%
ungroup()
plot2 <- stock_normalized %>%
ggplot(aes(x = date, y = normalized_price, color = symbol)) +
geom_line(size = 0.7) +
labs(
title = "Normalized Stock Prices (2016-2024)",
x = "Date",
y = "Normalized price (base = $1)",
color = "Stock"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
legend.position = "right",
panel.grid.minor = element_blank()
) +
scale_color_manual(values = c(
"AAPL" = "red",
"AMD" = "blue",
"MU" = "green",
"NIO" = "purple",
"NVDA" = "orange",
"PRPL" = "yellow3",
"SNAP" = "brown",
"TSLA" = "pink",
"TWTR" = "gray30"
))
print(plot2)
stock_returns <- stock_normalized %>%
group_by(symbol) %>%
summarise(
Initial_Price = first(close),
Final_Price = last(close),
Total_Return = ((Final_Price - Initial_Price) / Initial_Price) * 100,
Normalized_Growth = last(normalized_price)
) %>%
arrange(desc(Total_Return))
knitr::kable(stock_returns,
caption = "Total Returns (2016-2024)",
digits = 2)
| symbol | Initial_Price | Final_Price | Total_Return | Normalized_Growth |
|---|---|---|---|---|
| NVDA | 0.81 | 137.49 | 16889.81 | 169.90 |
| AMD | 2.77 | 122.44 | 4320.22 | 44.20 |
| TSLA | 14.89 | 417.41 | 2702.54 | 28.03 |
| AAPL | 26.34 | 252.20 | 857.57 | 9.58 |
| MU | 14.33 | 85.31 | 495.32 | 5.95 |
| NIO | 6.60 | 4.38 | -33.64 | 0.66 |
| SNAP | 24.48 | 10.86 | -55.64 | 0.44 |
| PRPL | 9.66 | 0.83 | -91.36 | 0.09 |
top_3 <- stock_returns %>%
slice_max(Total_Return, n = 3)
cat("Top 3 Performing Stocks:\n")
## Top 3 Performing Stocks:
for(i in 1:nrow(top_3)) {
cat(sprintf("%d. %s: %.2f%%\n",
i,
top_3$symbol[i],
top_3$Total_Return[i]))
}
## 1. NVDA: 16889.81%
## 2. AMD: 4320.22%
## 3. TSLA: 2702.54%
Based on the normalized price chart:
This analysis reveals significant variation in stock performance across the technology sector from 2016 to 2024. The semiconductor stocks (NVDA, AMD) showed particularly strong performance, likely driven by AI and technology infrastructure demand.
sessionInfo()
## R version 4.5.1 (2025-06-13 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26200)
##
## Matrix products: default
## LAPACK version 3.12.1
##
## locale:
## [1] LC_COLLATE=English_United States.utf8
## [2] LC_CTYPE=English_United States.utf8
## [3] LC_MONETARY=English_United States.utf8
## [4] LC_NUMERIC=C
## [5] LC_TIME=English_United States.utf8
##
## time zone: Asia/Taipei
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] PerformanceAnalytics_2.0.8 quantmod_0.4.28
## [3] TTR_0.24.4 xts_0.14.1
## [5] zoo_1.8-14 tidyquant_1.0.11
## [7] lubridate_1.9.4 forcats_1.0.1
## [9] stringr_1.5.2 dplyr_1.1.4
## [11] purrr_1.1.0 readr_2.1.5
## [13] tidyr_1.3.1 tibble_3.3.0
## [15] ggplot2_4.0.0 tidyverse_2.0.0
##
## loaded via a namespace (and not attached):
## [1] gtable_0.3.6 xfun_0.53 bslib_0.9.0
## [4] recipes_1.3.1 lattice_0.22-7 tzdb_0.5.0
## [7] quadprog_1.5-8 vctrs_0.6.5 tools_4.5.1
## [10] generics_0.1.4 parallel_4.5.1 curl_7.0.0
## [13] RobStatTM_1.0.11 pkgconfig_2.0.3 Matrix_1.7-3
## [16] data.table_1.17.8 RColorBrewer_1.1-3 S7_0.2.0
## [19] lifecycle_1.0.4 compiler_4.5.1 farver_2.1.2
## [22] codetools_0.2-20 htmltools_0.5.8.1 class_7.3-23
## [25] sass_0.4.10 yaml_2.3.10 prodlim_2025.04.28
## [28] furrr_0.3.1 pillar_1.11.1 jquerylib_0.1.4
## [31] MASS_7.3-65 cachem_1.1.0 gower_1.0.2
## [34] rpart_4.1.24 parallelly_1.45.1 lava_1.8.2
## [37] tidyselect_1.2.1 digest_0.6.37 future_1.67.0
## [40] stringi_1.8.7 listenv_0.9.1 labeling_0.4.3
## [43] splines_4.5.1 fastmap_1.2.0 grid_4.5.1
## [46] cli_3.6.5 magrittr_2.0.3 survival_3.8-3
## [49] future.apply_1.20.0 withr_3.0.2 scales_1.4.0
## [52] timechange_0.3.0 rmarkdown_2.29 globals_0.18.0
## [55] nnet_7.3-20 timeDate_4051.111 hms_1.1.3
## [58] evaluate_1.0.5 knitr_1.50 timetk_2.9.1
## [61] hardhat_1.4.2 rsample_1.3.1 rlang_1.1.6
## [64] Rcpp_1.1.0 glue_1.8.0 ipred_0.9-15
## [67] rstudioapi_0.17.1 jsonlite_2.0.0 R6_2.6.1