Returns, Volatility, and Time Series Basics
Last lesson you ended with a clean, sorted price series. That series is raw material, not an input. A trading rule never says "buy when the price is above 420"; it says "buy when the price rose 2% this week". So this lesson turns prices into returns, then into volatility, and then into the three warnings every beginner needs before trusting a number computed from market data.
By the end you should be able to:
- Convert a price column into simple returns and log returns.
- Decide which return type fits a given job.
- Measure daily volatility and annualize it correctly.
- Name the time series properties that break naive i.i.d. statistics.
- Run all of this on the price data you cleaned for your capstone asset.
From a price column to a return column
A price tells you where the market is. A return tells you what an owner of the asset actually earned. Almost everything you compute later, from volatility to drawdown to signal strength, is built on returns.
The simple return (also called the arithmetic or percentage return) is the percentage change from one period to the next:
$$ r_t = \frac{P_t}{P_{t-1}} - 1 $$
If SPY closes at 420.00 then 424.20, the simple return is 0.01, or 1%.
Why not model prices directly? Two reasons. First, prices are not comparable across assets: a 5 dollar move on a 20 dollar stock is enormous, while the same 5 dollars on a share priced at 2,000 is noise. Returns are already scaled, so you can compare them. Second, prices are non-stationary: they trend for decades, so the average price of a series carries no useful information. The average return does.
Note: In pandas, the whole conversion is one line:
df["ret"] = df["close"].pct_change(). The first row comes back asNaNby design, because there is no previous price to divide by.
Practice (capstone thread). Your cleaned SPY series shows 420.00 then 424.20. Compute the simple return, then explain in one sentence why you cannot compare that 1% to a 1% move in a different asset without checking its price.
Click to reveal the answer
$424.20 / 420.00 - 1 = 0.01$, so 1%. You can compare it: a return is already price-scaled, which is exactly why the comparison works and why raw price changes do not.
Log returns and when to reach for them
The log return is the natural logarithm of the price ratio:
$$ r_t^{\log} = \ln\left(\frac{P_t}{P_{t-1}}\right) = \ln(1 + r_t) $$
For small moves the two are nearly identical: a 1% simple return is a 0.995% log return. They separate on large moves. A 50% loss is a log return near -0.693, and a 100% gain is +0.693, so the log scale is symmetric around zero.
The property that matters is that log returns add over time. Simple returns compound by multiplication, so a +2% day followed by a -2% day leaves you at $1.02 \times 0.98 = 0.9996$, a small loss, not flat. The log returns simply sum.
| Job | Use |
|---|---|
| Reporting performance to a person | Simple return |
| Summing returns across many periods | Log return |
| Feeding a model or a regression | Log return |
| Comparing one asset to another | Either (both are scaled) |
Practice. A price walks 100, then 105, then 110. Compute both daily log returns and confirm they sum to $\ln(110/100)$.
Click to reveal the answer
$\ln(1.05) = 0.04879$ on both days, summing to 0.09758. And $\ln(110/100) = 0.09758$. The sum of log returns is the total log return, always.
Volatility: how wide the returns scatter
Volatility is the _____ of returns. It says nothing about direction, only about the size of the wobble. A daily volatility of 0.01 means a typical day moves about 1%.
Two practical details. Use the sample standard deviation (ddof=1, which pandas .std() does by default). Then annualize, because a daily number is hard to reason about:
$$ \sigma_{\text{annual}} = \sigma_{\text{daily}} \times \sqrt{252} $$
The square root is not decoration. Variance grows linearly with time, so standard deviation grows with the square root of time. $\sqrt{252} \approx 15.87$, so 1% daily becomes roughly 15.9% annual.
Practice. Your SPY returns show a daily standard deviation of 0.0095. Annualize it, then sanity-check the answer against a typical equity volatility of 15% to 20%.
Click to reveal the answer
$0.0095 \times 15.87 \approx 0.151$, about 15.1% annualized. That sits comfortably inside the normal equity range, which is a good sign your data cleaning did not mangle anything.
Time series properties that break naive statistics
Most textbook formulas assume independent observations drawn from one fixed distribution. Returns violate that in specific, well-known ways, and each violation has a practical consequence.
- Non-stationarity in prices. Prices drift and have unit roots. Regressing one price on another produces impressive-looking relationships that are pure coincidence (spurious regression). Model returns instead.
- Volatility clustering. Large moves follow large moves. Volatility is autocorrelated even when returns are close to uncorrelated, so a single full-sample average volatility describes no actual period. Plot a rolling 20-day volatility and you will see calm stretches and violent ones.
- Fat tails. Equity returns produce far more 3-sigma and 5-sigma days than a normal distribution predicts. Anything that sizes risk using normality will understate bad days.
- Autocorrelation and stale prices. Illiquid assets print prices that lag reality, which creates positive autocorrelation and makes a naive backtest look better than the trade would have been.
The habit that protects you: before trusting any metric, plot the returns, plot rolling volatility, and put a histogram against a normal curve.
Practice. You compute one volatility number for SPY over twenty years and size every position with it. Which property did you ignore, and what goes wrong in practice?
Click to reveal the answer
Volatility clustering. A single average will be too high for calm periods (you under-trade) and far too low during a crisis (you take too much risk exactly when it hurts). Use a rolling or exponentially weighted estimate.
Rules of thumb that save beginners rework
- Compute returns once, in one place, and check that you have one fewer return than prices.
- Use
.pct_change()for simple returns andnp.log1p(...)on simple returns for log returns, avoiding alog(0)surprise. - Check for
NaNand infinities right after conversion. A single bad price poisons two returns. - Express volatility per year when you talk about it. "1% daily" and "16% annual" are the same fact.
- Never describe a strategy's risk with one volatility number for a twenty-year window. Look at the rolling series first.
- If your data has multi-day gaps, do not treat the returns as consecutive days: the volatility annualization silently lies.
Log returns are _____ across time, while simple returns compound by multiplication. Annualizing a daily volatility multiplies it by the square root of _____, roughly 15.87. The tendency of violent days to follow violent days is called _____. Equity returns producing more extreme days than a normal curve predicts is known as _____.
Front: Why compute returns instead of using prices? Back: Returns are scaled across assets and are close to stationary, while prices trend and are not comparable in raw units.
Front: Simple return formula? Back: P_t / P_(t-1) - 1
Front: Log return formula? Back: ln(P_t / P_(t-1)), which equals ln(1 + simple return)
Front: When are simple and log returns nearly equal? Back: When the move is small, roughly a few percent or less.
Front: What is the key advantage of log returns? Back: They add across time, so the sum of log returns is the total log return.
Front: A +2% day then a -2% day leaves a simple-return portfolio where? Back: Slightly below flat, at 0.9996, because simple returns compound by multiplication.
Front: Volatility is measured as what? Back: The standard deviation of returns, using the sample version with ddof=1.
Front: How do you annualize daily volatility? Back: Multiply by the square root of 252, about 15.87.
Front: Why the square root and not 252? Back: Variance scales linearly with time, so standard deviation scales with the square root of time.
Front: What does volatility clustering mean? Back: Large moves follow large moves, so volatility is autocorrelated and a single average hides calm and crisis periods.
Front: What are fat tails? Back: Far more 3-sigma and 5-sigma days than a normal distribution implies.
Front: Why is regressing one price on another dangerous? Back: Prices are non-stationary, so the regression can be spurious: a strong fit with no real relationship.
Front: How do stale prices distort a naive backtest? Back: They create positive autocorrelation, making a slow-moving signal look predictive when it is only lagging reality.
What to carry into the checkpoint
You now have the three tools this module is built on: a clean price series, a return column derived from it, and a volatility number you can defend. Remember the chain: returns make assets comparable, log returns make time aggregation trivial, annualized volatility makes risk readable, and the time series warnings keep you from trusting a metric that the data does not support.
Next up is the module checkpoint, where you will load, clean, convert, and describe a real price series from start to finish, then explain each number you produce.