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\deegi\AppData\Local\Temp\Rtmpeeeu7o\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\deegi\AppData\Local\Temp\Rtmpeeeu7o\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\deegi\AppData\Local\Temp\Rtmpeeeu7o\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\deegi\AppData\Local\Temp\Rtmpeeeu7o\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()
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)
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")
| 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 |
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)
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"
)
| 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.7177% | 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% |
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"
)
| 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.7177% | 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.3223% | 0.9432% | -0.0904% | 0.4859% | 0.8684% | 0.4167% |
| 2024-01-12 | 0.1778% | -0.3609% | 0.3968% | 0.9984% | -0.2043% | 0.0197% |
| 2024-01-16 | -1.2317% | -0.9442% | -0.1109% | 0.4633% | 3.0561% | 0.4247% |
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()
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.
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.