For this assignment, I plan to use a time-series dataset containing daily prices for multiple stocks. I will organize the data by stock and date so that each stock is analyzed separately.
Using R and dplyr, I will calculate the year-to-date average price for each stock and a six-day moving average. I will then compare the original daily prices with the calculated averages and create a visualization to better understand how the prices change over time.
Some challenges I expect are making sure the dates are in the correct order, keeping the calculations separate for each stock, and understanding how the six-day moving average changes as new daily prices are added.
In this assignment, I will use time-series data containing daily stock prices for 10 companies. The goal is to use window functions in R to calculate the year-to-date average and the six-day moving average for each stock.
The year-to-date average will show the average stock price from the beginning of the year through each date. The six-day moving average will show the average price over the current day and the previous five trading days.
I will use Apple, Microsoft, Alphabet, Amazon, NVIDIA, Meta, Tesla, JPMorgan Chase, Walmart, and Coca-Cola. Using multiple stocks will allow me to apply the calculations separately to each company and compare how their prices change over time.
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
## ── Attaching core tidyquant packages ─────────────────────── tidyquant 1.0.12 ──
## ✔ PerformanceAnalytics 2.1.0 ✔ TTR 0.24.4
## ✔ quantmod 0.4.29 ✔ xts 0.14.3
## ── Conflicts ────────────────────────────────────────── tidyquant_conflicts() ──
## ✖ zoo::as.Date() masks base::as.Date()
## ✖ zoo::as.Date.numeric() masks base::as.Date.numeric()
## ✖ 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
##
## ######################### Warning from 'xts' package ##########################
## # #
## # The dplyr lag() function breaks how base R's lag() function is supposed to #
## # work, which breaks lag(my_xts). Calls to lag(my_xts) that you type or #
## # source() into this session won't work correctly. #
## # #
## # Use stats::lag() to make sure you're not using dplyr::lag(), or you can add #
## # conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop #
## # dplyr from breaking base R's lag() function. #
## # #
## # Code in packages is not affected. It's protected by R's namespace mechanism #
## # Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning. #
## # #
## ###############################################################################
##
## Attaching package: 'dplyr'
##
## The following objects are masked from 'package:xts':
##
## first, last
##
## The following objects are masked from 'package:stats':
##
## filter, lag
##
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
For this assignment, I will use daily historical stock prices from 2020 through 2025 for 10 companies. The stocks include Apple, Microsoft, Alphabet, Amazon, NVIDIA, Meta, Tesla, JPMorgan Chase, Walmart, and Coca-Cola.
Using multiple years of data will allow me to calculate the year-to-date average separately for each stock and each year.
## [1] "AAPL" "MSFT" "GOOGL" "AMZN" "NVDA" "META" "TSLA" "JPM" "WMT"
## [10] "KO"
stock_data <- tq_get(
stocks,
from = "2020-01-01",
to = "2026-01-01",
get = "stock.prices"
)
head(stock_data)## # A tibble: 6 × 8
## symbol date open high low close volume adjusted
## <chr> <date> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 AAPL 2020-01-02 74.1 75.2 73.8 75.1 135480400 72.3
## 2 AAPL 2020-01-03 74.3 75.1 74.1 74.4 146322800 71.6
## 3 AAPL 2020-01-06 73.4 75.0 73.2 74.9 118387200 72.1
## 4 AAPL 2020-01-07 75.0 75.2 74.4 74.6 108872000 71.8
## 5 AAPL 2020-01-08 74.3 76.1 74.3 75.8 132079200 73.0
## 6 AAPL 2020-01-09 76.8 77.6 76.6 77.4 170108400 74.5
## # A tibble: 6 × 3
## symbol date close
## <chr> <date> <dbl>
## 1 AAPL 2020-01-02 75.1
## 2 AAPL 2020-01-03 74.4
## 3 AAPL 2020-01-06 74.9
## 4 AAPL 2020-01-07 74.6
## 5 AAPL 2020-01-08 75.8
## 6 AAPL 2020-01-09 77.4
The year-to-date average calculates the average closing price from the beginning of each year through each trading day. The calculation will be performed separately for each stock and will reset when a new year begins.
##
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
##
## date, intersect, setdiff, union
stock_prices <- stock_prices %>%
mutate(year = year(date)) %>%
arrange(symbol, date) %>%
group_by(symbol, year) %>%
mutate(
ytd_average = cummean(close)
) %>%
ungroup()
head(stock_prices, 10)## # A tibble: 10 × 5
## symbol date close year ytd_average
## <chr> <date> <dbl> <dbl> <dbl>
## 1 AAPL 2020-01-02 75.1 2020 75.1
## 2 AAPL 2020-01-03 74.4 2020 74.7
## 3 AAPL 2020-01-06 74.9 2020 74.8
## 4 AAPL 2020-01-07 74.6 2020 74.7
## 5 AAPL 2020-01-08 75.8 2020 75.0
## 6 AAPL 2020-01-09 77.4 2020 75.4
## 7 AAPL 2020-01-10 77.6 2020 75.7
## 8 AAPL 2020-01-13 79.2 2020 76.1
## 9 AAPL 2020-01-14 78.2 2020 76.4
## 10 AAPL 2020-01-15 77.8 2020 76.5
Next, I will calculate the six-day moving average for each stock. The six-day moving average uses the current trading day’s closing price and the previous five trading days. This helps smooth short-term changes in the stock price.
The calculation will be performed separately for each stock so that prices from different companies are not combined.
library(slider)
stock_prices <- stock_prices %>%
group_by(symbol) %>%
arrange(date, .by_group = TRUE) %>%
mutate(
six_day_average = slide_dbl(
close,
mean,
.before = 5,
.complete = TRUE
)
) %>%
ungroup()
head(stock_prices, 10)## # A tibble: 10 × 6
## symbol date close year ytd_average six_day_average
## <chr> <date> <dbl> <dbl> <dbl> <dbl>
## 1 AAPL 2020-01-02 75.1 2020 75.1 NA
## 2 AAPL 2020-01-03 74.4 2020 74.7 NA
## 3 AAPL 2020-01-06 74.9 2020 74.8 NA
## 4 AAPL 2020-01-07 74.6 2020 74.7 NA
## 5 AAPL 2020-01-08 75.8 2020 75.0 NA
## 6 AAPL 2020-01-09 77.4 2020 75.4 75.4
## 7 AAPL 2020-01-10 77.6 2020 75.7 75.8
## 8 AAPL 2020-01-13 79.2 2020 76.1 76.6
## 9 AAPL 2020-01-14 78.2 2020 76.4 77.1
## 10 AAPL 2020-01-15 77.8 2020 76.5 77.7
To verify the calculation, I will manually calculate the average of the first six closing prices for Apple and compare it with the six-day moving average calculated by R.
stock_prices %>%
filter(symbol == "AAPL") %>%
slice(1:6) %>%
summarise(
manual_average = mean(close)
)## # A tibble: 1 × 1
## manual_average
## <dbl>
## 1 75.4
To better understand the window calculations, I will visualize Apple’s stock price during 2025. The graph compares the daily closing price with the year-to-date average and the six-day moving average.
apple_2025 <- stock_prices %>%
filter(symbol == "AAPL", year == 2025)
ggplot(apple_2025, aes(x = date)) +
geom_line(aes(y = close, color = "Closing Price")) +
geom_line(aes(y = ytd_average, color = "YTD Average")) +
geom_line(aes(y = six_day_average, color = "6-Day Moving Average")) +
labs(
title = "Apple Stock Price and Moving Averages - 2025",
x = "Date",
y = "Price ($)",
color = "Measure"
) +
theme_minimal()The visualization shows the difference between the daily closing price, the six-day moving average, and the year-to-date average. The six-day moving average stays close to the daily closing price because it only uses the most recent six trading days. The year-to-date average changes more slowly because it includes all trading days from the beginning of the year through each date.
For Apple in 2025, the stock price decreased during the first part of the year and then increased later in the year. The six-day moving average follows these changes closely, while the year-to-date average shows the longer-term trend.
The previous visualization focused on Apple. Since the dataset contains 10 stocks, I will also visualize the 2025 closing prices for all 10 companies. Each stock will be displayed separately so that the price movements are easier to compare.
stocks_2025 <- stock_prices %>%
filter(year == 2025)
ggplot(stocks_2025, aes(x = date, y = close, color = symbol)) +
geom_line(linewidth = 0.7) +
facet_wrap(~ symbol, scales = "free_y") +
labs(
title = "Daily Closing Prices for 10 Stocks - 2025",
x = "Date",
y = "Closing Price ($)"
) +
theme_minimal() +
theme(
legend.position = "none"
)The visualization compares the daily closing prices of all 10 stocks during 2025. Each stock is displayed in a separate panel because the companies have different stock price ranges.
The graphs show that the stocks followed different price patterns throughout the year. Some stocks experienced larger changes in price, while others were more stable. Using separate panels makes it easier to see the movement of each stock without combining all 10 stocks into one graph.
In this assignment, I used daily stock price data for 10 companies from 2020 through 2025. I used R to organize the data by stock and date and calculate two window-based measures: the year-to-date average and the six-day moving average.
The year-to-date average calculates the average closing price from the beginning of each year through each trading day. The six-day moving average uses the current closing price and the previous five trading days. I also manually checked the first six-day moving average for Apple and confirmed that the calculation matched the result produced by R.
The visualizations helped show the difference between daily prices and the calculated averages. The six-day moving average follows short-term price changes more closely, while the year-to-date average shows a smoother, longer-term trend. This assignment helped me understand how window calculations can be used to analyze time-series data separately for multiple stocks.