title: “Financial Database Management and Application 3C” author: “Student” date: “September 15, 2026” output: html_document: toc: true toc_float: true df_print: paged —————

1. Objective

This assignment downloads daily stock prices for AAPL, MSFT, GOOG, AMZN, TSM, and NVDA from January 1, 2024 through the current date, calculates daily returns, and displays the first few observations of the returns.

The data source is Yahoo Finance. The analysis uses Adjusted Close prices because adjusted prices account for stock splits and distributions and are appropriate for return calculations.

knitr::opts_chunk$set(
  echo = TRUE,
  message = FALSE,
  warning = FALSE
)

required_packages <- c(
  "quantmod",
  "dplyr",
  "tidyr",
  "knitr",
  "ggplot2"
)

installed <- rownames(installed.packages())

for (p in required_packages) {
  if (!(p %in% installed)) {
    install.packages(p, repos = "https://cloud.r-project.org")
  }
}
## package 'xts' successfully unpacked and MD5 sums checked
## package 'zoo' successfully unpacked and MD5 sums checked
## package 'TTR' successfully unpacked and MD5 sums checked
## package 'curl' successfully unpacked and MD5 sums checked
## package 'quantmod' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\Dell\AppData\Local\Temp\RtmpMbsM77\downloaded_packages
## package 'utf8' successfully unpacked and MD5 sums checked
## package 'pkgconfig' successfully unpacked and MD5 sums checked
## package 'withr' successfully unpacked and MD5 sums checked
## package 'generics' successfully unpacked and MD5 sums checked
## package 'glue' successfully unpacked and MD5 sums checked
## package 'magrittr' successfully unpacked and MD5 sums checked
## package 'pillar' successfully unpacked and MD5 sums checked
## package 'tibble' successfully unpacked and MD5 sums checked
## package 'tidyselect' successfully unpacked and MD5 sums checked
## package 'vctrs' successfully unpacked and MD5 sums checked
## package 'dplyr' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\Dell\AppData\Local\Temp\RtmpMbsM77\downloaded_packages
## package 'stringi' successfully unpacked and MD5 sums checked
## package 'purrr' successfully unpacked and MD5 sums checked
## package 'stringr' successfully unpacked and MD5 sums checked
## package 'cpp11' successfully unpacked and MD5 sums checked
## package 'tidyr' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\Dell\AppData\Local\Temp\RtmpMbsM77\downloaded_packages
## package 'farver' successfully unpacked and MD5 sums checked
## package 'labeling' successfully unpacked and MD5 sums checked
## package 'RColorBrewer' successfully unpacked and MD5 sums checked
## package 'viridisLite' successfully unpacked and MD5 sums checked
## package 'gtable' successfully unpacked and MD5 sums checked
## package 'isoband' successfully unpacked and MD5 sums checked
## package 'S7' successfully unpacked and MD5 sums checked
## package 'scales' successfully unpacked and MD5 sums checked
## package 'ggplot2' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\Dell\AppData\Local\Temp\RtmpMbsM77\downloaded_packages
library(quantmod)
library(dplyr)
library(tidyr)
library(knitr)
library(ggplot2)

tickers <- c("AAPL", "MSFT", "GOOG", "AMZN", "TSM", "NVDA")

start_date <- as.Date("2024-01-01")
end_date <- Sys.Date()

2. Download Daily Prices

The following code downloads daily historical prices from Yahoo Finance.

price_list <- lapply(tickers, function(tkr) {

  x <- getSymbols(
    tkr,
    src = "yahoo",
    from = start_date,
    to = end_date + 1,
    auto.assign = FALSE
  )

  data.frame(
    Date = index(x),
    Price = as.numeric(Ad(x)),
    Ticker = tkr,
    row.names = NULL
  )
})

prices_long <- bind_rows(price_list) %>%
  arrange(Date, Ticker)

head(prices_long, 10)
##          Date     Price Ticker
## 1  2024-01-02 183.40399   AAPL
## 2  2024-01-02 149.92999   AMZN
## 3  2024-01-02 138.25053   GOOG
## 4  2024-01-02 363.11795   MSFT
## 5  2024-01-02  48.02879   NVDA
## 6  2024-01-02  98.27405    TSM
## 7  2024-01-03 182.03078   AAPL
## 8  2024-01-03 148.47000   AMZN
## 9  2024-01-03 139.04303   GOOG
## 10 2024-01-03 362.85355   MSFT

Price Data Summary

summary_table <- prices_long %>%
  group_by(Ticker) %>%
  summarise(
    First_Date = min(Date),
    Last_Date = max(Date),
    Observations = n(),
    .groups = "drop"
  )

kable(
  summary_table,
  caption = "Daily Adjusted-Price Data Downloaded"
)
Daily Adjusted-Price Data Downloaded
Ticker First_Date Last_Date Observations
AAPL 2024-01-02 2026-09-14 677
AMZN 2024-01-02 2026-09-14 677
GOOG 2024-01-02 2026-09-14 677
MSFT 2024-01-02 2026-09-14 677
NVDA 2024-01-02 2026-09-14 677
TSM 2024-01-02 2026-09-14 677

3. Daily Returns

Daily simple return is calculated as:

\[ R_t = \frac{P_t}{P_{t-1}} - 1 \]

where \(P_t\) is the adjusted closing price on day \(t\).

returns_long <- prices_long %>%
  group_by(Ticker) %>%
  arrange(Date, .by_group = TRUE) %>%
  mutate(
    Return = Price / lag(Price) - 1
  ) %>%
  ungroup()

returns_wide <- returns_long %>%
  select(Date, Ticker, Return) %>%
  pivot_wider(
    names_from = Ticker,
    values_from = Return
  ) %>%
  arrange(Date)

4. First Few Daily Returns for All Stocks

The first observation for each stock is NA because a previous trading-day price is not available. Therefore, the table below displays the first five non-missing daily returns for each stock.

first_returns <- returns_long %>%
  filter(!is.na(Return)) %>%
  group_by(Ticker) %>%
  slice_head(n = 5) %>%
  ungroup() %>%
  select(Date, Ticker, Return) %>%
  mutate(
    Return = sprintf("%.4f%%", Return * 100)
  ) %>%
  pivot_wider(
    names_from = Ticker,
    values_from = Return
  )

kable(
  first_returns,
  caption = "First Five Non-Missing Daily Returns"
)
First Five Non-Missing Daily Returns
Date AAPL AMZN GOOG MSFT NVDA TSM
2024-01-03 -0.7487% -0.9738% 0.5732% -0.0728% -1.2436% -1.3395%
2024-01-04 -1.2700% -2.6268% -1.6529% -0.7178% 0.9019% -1.0382%
2024-01-05 -0.4013% 0.4634% -0.4709% -0.0516% 2.2897% 0.4842%
2024-01-08 2.4175% 2.6577% 2.2855% 1.8871% 6.4281% 2.6403%
2024-01-09 -0.2263% 1.5225% 1.4445% 0.2936% 1.6975% -0.3423%

5. Daily Returns in Wide Format

returns_wide_display <- returns_wide %>%
  slice_head(n = 10) %>%
  mutate(
    across(
      all_of(tickers),
      ~ sprintf("%.4f%%", .x * 100)
    )
  )

kable(
  returns_wide_display,
  caption = "First Ten Rows of Daily Returns"
)
First Ten Rows of Daily Returns
Date AAPL AMZN GOOG MSFT NVDA TSM
2024-01-02 NA% NA% NA% NA% NA% NA%
2024-01-03 -0.7487% -0.9738% 0.5732% -0.0728% -1.2436% -1.3395%
2024-01-04 -1.2700% -2.6268% -1.6529% -0.7178% 0.9019% -1.0382%
2024-01-05 -0.4013% 0.4634% -0.4709% -0.0516% 2.2897% 0.4842%
2024-01-08 2.4175% 2.6577% 2.2855% 1.8871% 6.4281% 2.6403%
2024-01-09 -0.2263% 1.5225% 1.4445% 0.2936% 1.6975% -0.3423%
2024-01-10 0.5671% 1.5591% 0.8698% 1.8574% 2.2770% -1.0698%
2024-01-11 -0.3222% 0.9432% -0.0904% 0.4859% 0.8684% 0.4167%
2024-01-12 0.1778% -0.3609% 0.3967% 0.9984% -0.2043% 0.0197%
2024-01-16 -1.2317% -0.9442% -0.1109% 0.4633% 3.0561% 0.4248%

6. Price Visualization

The following graph normalizes each stock’s adjusted price to 100 at its first available observation. This makes it easier to compare the relative performance of stocks with different initial prices.

prices_plot <- prices_long %>%
  group_by(Ticker) %>%
  mutate(
    Normalized_Price = Price / first(Price) * 100
  ) %>%
  ungroup()

ggplot(
  prices_plot,
  aes(
    x = Date,
    y = Normalized_Price,
    group = Ticker
  )
) +
  geom_line() +
  facet_wrap(
    ~ Ticker,
    scales = "free_y"
  ) +
  labs(
    title = "Normalized Adjusted Closing Prices",
    subtitle = "January 2024 to Present; First Observation = 100",
    x = "Date",
    y = "Normalized Price"
  ) +
  theme_minimal()

7. Conclusion

This analysis downloaded daily adjusted closing prices for AAPL, MSFT, GOOG, AMZN, TSM, and NVDA from January 2024 to the present date. Daily simple returns were then calculated using the percentage change in adjusted closing prices.

Using adjusted closing prices is useful for return analysis because the price series is adjusted for corporate actions such as stock splits and distributions.

The resulting return dataset can be used for further financial analysis, including volatility, correlation, portfolio analysis, and risk measurement.

8. Reproducibility Note

The code intentionally uses Sys.Date() for the end date. Therefore, when the document is knitted again, it will automatically update the dataset through the latest date available from Yahoo Finance.

Data source: Yahoo Finance via the R quantmod package.