Skip to Content
Course content

86: Financial Time Series Analysis in R

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Financial time series aren't like your standard data frames. They have a specific rhythm—a temporal dependency where today's price is heavily influenced by yesterday's. In R, we don't just use lists or tables for this; we use xts (extensible time series) objects. They're essentially matrices with a time-index, and they make slicing data by date incredibly intuitive.

For this lesson, I want to show you how to analyze the volatility of a high-growth stock—let's use NVIDIA (NVDA)—relative to the S&P 500 (SPY). We're looking for the "noise" in the price movements, not just the direction.

Grabbing live data with quantmod

I always start with the quantmod package. It's the gold standard because it hooks directly into Yahoo Finance. I'm going to pull the adjusted closing prices. I prefer adjusted prices because they account for dividends and stock splits, which would otherwise look like massive, fake crashes in your data.

library(quantmod)

# Pulling NVDA and SPY
getSymbols(c("NVDA", "SPY"), src = "yahoo", from = "2023-01-01")

# I'll extract just the Adjusted Close columns to keep things clean
nvda_adj <- Ad(NVDA)
spy_adj <- Ad(SPY)

Turning prices into percentage returns

Raw prices are misleading. A $10 move on a $100 stock is huge; a $10 move on a $1,000 stock is a rounding error. To compare the two, we need "log returns." I use log returns instead of simple percentage changes because they are additive over time, which makes the math much easier when we start aggregating daily data into monthly or yearly views.

# Calculate daily log returns
nvda_ret <- diff(log(nvda_adj))
spy_ret <- diff(log(spy_adj))

Dealing with the first-row NA glitch

Here is where I usually trip up if I'm rushing. If you try to run a calculation or a plot on nvda_ret right now, you'll notice something weird. Because diff() subtracts the previous value from the current one, the very first entry in your time series is now NA (since there was no "day zero" to subtract from).

I just tried to calculate the mean return, and R gave me NA. Frustrating, right? You have to explicitly strip that first empty row out before the xts object becomes useful for analysis.

# The mistake: mean(nvda_ret) -> returns NA
# The fix: use na.omit() to clean the series
nvda_ret <- na.omit(nvda_ret)
spy_ret <- na.omit(spy_ret)

# Now this actually works
mean(nvda_ret)

Measuring the 'shake' with rolling volatility

To see how "wild" the stock is, we look at the rolling standard deviation. I'm going to use a 20-day window. This essentially tells us: "Over the last trading month, how much has the daily return deviated from the average?"

I'll use the runSD function from the TTR package (which loads with quantmod). This gives us a dynamic view of risk rather than one static number for the whole year.

# Calculate 20-day rolling volatility (standard deviation)
nvda_vol <- runSD(nvda_ret, n = 20)
spy_vol <- runSD(spy_ret, n = 20)

# Let's plot them together to see the contrast
plot(nvda_vol, col = "blue", main = "Rolling Volatility: NVDA vs SPY")
lines(spy_vol, col = "red")
addLegend("topleft", legend.text = c("NVDA", "SPY"), col.col = c("blue", "red"), lty = 1)

When you look at that chart, the gap between the blue and red lines represents the "volatility premium." NVDA is significantly more volatile, which is exactly what you'd expect from a chip maker during an AI boom compared to a diversified index of 500 companies.




📋 Practical Task

Exercise: Calculating the Beta of Apple (AAPL)

In finance, "Beta" measures a stock's volatility in relation to the overall market. A Beta of 1.0 means the stock moves with the market; higher than 1.0 means it's more volatile.

Write an R script to perform the following:

  • Download adjusted closing prices for Apple (AAPL) and the S&P 500 (SPY) for the year 2023.
  • Convert both series into log returns and remove the resulting NA values.
  • Calculate the Beta of AAPL relative to SPY. You can do this by calculating the covariance of the two returns and dividing it by the variance of the SPY returns: Beta = cov(AAPL, SPY) / var(SPY).
  • Print the final Beta value to the console.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.