
Volatility gets talked about constantly and calculated rarely. Ask ten traders how volatile a stock is and you’ll get ten vibes (“it’s been wild lately”). Ask for an actual number and the room goes quiet. That’s a shame, because knowing how to calculate volatility is one of the most useful pieces of math in investing – it sits underneath position sizing, risk management, and every option price you’ve ever looked at.
The good news? If you can compute an average, you can compute volatility. This guide covers what volatility actually measures, the formula step by step, a worked example small enough to check by hand, and copy-pasteable versions for Excel and Python. We’ll finish with implied volatility and what the VIX really represents, because the two get confused all the time.
What Volatility Is (and What It Isn’t)
Volatility measures how much a price moves around, not which direction it moves.
Formally, it’s the standard deviation of returns – a measure of dispersion, of how spread out the day-to-day moves are around their average. That definition sounds dry, but the distinction inside it matters. A stock that grinds steadily upward, gaining a little almost every day, can have very low volatility. A stock that whipsaws – up 4%, down 5%, up 3%, ending the month exactly where it started – has high volatility even though it went nowhere. Dispersion, not direction.
This is also why “volatility” and “risk of losing money” are related but not the same thing. Volatility tells you the range of outcomes is wide; it doesn’t tell you which side of that range you’ll land on. A low-volatility stock can still lose money slowly and politely, and a high-volatility stock can be exactly the ride you signed up for. Volatility is a genuinely useful proxy for risk – it’s the standard one for a reason – but it’s a measure of bumpiness, not a verdict.
One more piece of vocabulary before the math. Realized volatility (also called historical volatility) is computed from past returns – what actually happened. Implied volatility is derived from option prices – what the market expects to happen. We’ll take them in that order.
How to Calculate Volatility: The Historical (Realized) Method
Four steps. That’s the whole recipe.
- Get closing prices. Daily closes are the standard starting point. Make sure they’re split- and dividend-adjusted (more on why later – it matters a lot).
- Compute periodic returns. You can use simple returns,
r = (P_t / P_t-1) - 1, or log returns,r = ln(P_t / P_t-1). Either is acceptable. Log returns are the common choice because they’re additive over time, which makes the math cleaner. We’ll use log returns here. - Take the standard deviation of those returns. Standard deviation is the square root of the average squared deviation from the mean. For a sample (which your price history always is), divide by
n - 1rather thann. - Annualize. Multiply the daily standard deviation by the square root of 252 to put it on the yearly scale everyone quotes. (Why the square root? Next section.)
A worked example you can check by hand
Five closing prices, deliberately small and round so you can follow every step:
| Day | Close | Log return ln(P_t / P_t-1) |
|---|---|---|
| 1 | $100 | – |
| 2 | $102 | 0.0198 |
| 3 | $101 | -0.0099 |
| 4 | $103 | 0.0196 |
| 5 | $104 | 0.0097 |
Now the arithmetic:
- Mean return: (0.0198 – 0.0099 + 0.0196 + 0.0097) / 4 = 0.0098, or about 0.98% per day.
- Squared deviations from the mean: (0.0198 – 0.0098)² + (-0.0099 – 0.0098)² + (0.0196 – 0.0098)² + (0.0097 – 0.0098)² ≈ 0.000100 + 0.000388 + 0.000096 + 0.000000 = 0.000584.
- Sample variance: divide by n – 1 = 3, giving 0.000195.
- Daily volatility: the square root, about 0.0139, or 1.39% per day.
- Annualized volatility: 0.0139 x sqrt(252) ≈ 0.0139 x 15.87 ≈ 0.22, or roughly 22% per year.
That’s it. That 22% is the number people mean when they say “this stock runs about 22 vol.”
An honest caveat: nobody estimates real volatility from four returns – this example is tiny on purpose so you can verify every step with a calculator. In practice you’d use a much longer window of returns. The mechanics are identical; only the length of the column changes.
Annualizing, and Why the Square Root of Time Shows Up
The sqrt(252) step trips people up, so let’s demystify it.
Variance – the squared version of volatility – scales linearly with time. Two days of independent returns carry twice the variance of one day. But volatility is the square root of variance, and the square root of “twice as much” is not “twice as big.” So when variance grows linearly with time, standard deviation grows with the square root of time.
Concretely: annualized vol = daily vol x sqrt(252), because 252 is the usual count of trading days in a year. Working with weekly returns instead? Use sqrt(52). Monthly? sqrt(12). Same idea, different clock.
This is also why volatility quoted “per year” is not 252 times the daily number – it’s about 15.87 times. A 1% daily vol annualizes to roughly 16%, not 252%. If your spreadsheet ever spits out a volatility over 100% for a sleepy large-cap, check this step first.
How to Calculate Volatility in Excel and Python
Excel
Suppose your closing prices live in column B, starting at B2.
- In C3, compute the first log return:
=LN(B3/B2). Fill down. - Daily volatility:
=STDEV.S(C3:C253). UseSTDEV.S– it’s the sample standard deviation that divides by n – 1. (STDEV.Pis the population version.) - Annualize:
=STDEV.S(C3:C253)*SQRT(252).
One cell of formula, one honest number. We strive for beautiful minimalism here at Tiingo, and this qualifies.
Python
Here’s the whole calculation against our end-of-day endpoint, using numpy:
import requests
import numpy as np
url = "https://api.tiingo.com/tiingo/daily/aapl/prices"
data = requests.get(url, params={"token": "YOUR_TOKEN"}).json()
closes = np.array([bar["adjClose"] for bar in data])
returns = np.diff(np.log(closes))
annualized_vol = returns.std(ddof=1) * np.sqrt(252)
Three things worth noticing. The response is a list of daily bars, and adjClose is the split- and dividend-adjusted close – the field you want for return math. np.diff(np.log(closes)) is the log-return step in one line. And ddof=1 is numpy’s way of saying “divide by n – 1,” matching STDEV.S in Excel.
Implied Volatility: The Market’s Forecast
Everything above looks backward. Implied volatility looks forward, and that flip changes what the number means.
Implied volatility is backed out of option prices, not price history, using an option-pricing model – Black-Scholes being the classic example. The logic runs in reverse: an option’s fair value depends on how volatile the underlying is expected to be, so if you observe the price the market is actually paying for an option, you can solve for the volatility that price implies. Hence the name.
So the two numbers answer different questions. Realized volatility says “here’s how much this stock actually moved.” Implied volatility says “here’s how much the options market expects it to move.” They frequently disagree, and the disagreement is not a bug – it’s information. When implied sits well above realized, option buyers are paying up for protection or anticipation; when it sits below, the market is pricing in calm. Context in markets is everything, and the gap between what happened and what’s expected is some of the best context there is.
What the VIX Actually Is
The VIX is the most famous volatility number in the world, and also one of the most misread. It’s the CBOE Volatility Index, and it estimates the market’s expected volatility of the S&P 500 over the next 30 days, calculated from SPX index option prices.
Note what that sentence does and doesn’t say. The VIX is an implied number – an expectation extracted from option prices – not a measurement of what the market has been doing. A calm-looking tape with a high VIX simply means option markets are braced for movement that hasn’t shown up yet.
The press calls it the “fear gauge” or “fear index,” and the nickname is earned – it tends to jump when investors get nervous and pay up for protection. Just remember it gauges expected fear about the next 30 days, not damage already done. Forecast, not history.
Getting the Price Data
Every calculation in this article is only as good as the closing prices you feed it, and there’s one silent killer: unadjusted data.
If your price series doesn’t account for splits and dividends, your returns will lie to you. A 2-for-1 split shows up as a fake -50% “return” in raw prices, and a single point like that will blow up a volatility estimate completely. You need split- and dividend-adjusted closes – it’s exactly why the Python snippet above reads adjClose and not the raw close.
This is the part we care about deeply at Tiingo. We’ve been making high-end market data accessible and affordable since 2014, because we don’t believe in holding good data hostage – clean inputs shouldn’t be a luxury. Our end-of-day price data covers 80,000+ assets with history back to 1962, every price split- and dividend-adjusted and error-checked. The free tier ($0 – 500 unique symbols a month and 30+ years of price history) covers everything in this article with room to spare. The end-of-day API docs will get you from token to first request in a few minutes.
The Bottom Line
Volatility is just the standard deviation of returns. Compute periodic returns, take the sample standard deviation, multiply by sqrt(252), and you have the annualized number the pros quote. Realized volatility tells you what happened; implied volatility (and the VIX) tells you what the market expects; the gap between them is worth watching.
Sound unglamorous? Good – the best risk math usually is. Pick a stock you own, pull a year of adjusted closes, and run the calculation yourself. Once you’ve computed volatility by hand even once, you’ll never read a vol number – or a VIX headline – the same way again.
If you want clean data to run it on, grab a free API token and start counting. We’d love to see what you build.