The formula
The data
- Prices:
adjusted_closefrom the Historical Stock Prices listing, one row per security per day. SPY stands in for the S&P 500 here. - CPI: FRED’s
CPIAUCSL, the Consumer Price Index for All Urban Consumers, seasonally adjusted, monthly. Each observation is dated the first of the month it measures.
The query
Don’t have prices or CPI in Snowflake yet? How to Get Historical Stock Prices into Snowflake and How to Get FRED Data into Snowflake (3 Ways) cover the ways to load each. Take the last adjusted close of each month, join it to that month’s CPI, then compare each month with the same month a year earlier:Real results
SPY by calendar year, December to December, and the latest 12 months:
2022 is the year inflation mattered most: an 18% loss became a 23% loss in
real terms. Over the full 10 years from September 2016 to September 2026:
$10,000 in SPY in September 2016 grew to about $41,300, worth about $29,600
in September 2016 dollars.
The last 10 years were unusually strong. Over longer periods, the same query
gives about 8% a year after inflation:
SPY started trading in January 1993, so that’s as far back as its prices go.
For earlier decades you need an index series instead of the ETF.
The missing-month trap
FRED has no CPI observation for October 2025. The release was never published because of the government shutdown that fall. Any query that compares “12 rows back” with a window function, such aslag(price, 12) over (order by month), silently compares with the wrong
month once the joined series is missing a row. In our first version of the
query above, that turned SPY’s 2025 return from 17.72% into 14.89%.
The fix is to join on the date itself, b.month = dateadd('month', -12, e.month), as the query does. A missing month then drops out instead of
shifting every comparison after it. Core CPI (CPILFESL) has the same gap; the
PCE price index (PCEPI), from a different agency, has an October 2025
value. The same fix applies to any monthly or quarterly FRED series with a
gap.
Other things to get right
- Same months on both sides. CPI is monthly, so use month-end prices, not daily prices joined to the nearest CPI value.
- CPI lags the calendar. September’s CPI is published in mid-October, so the latest month you can calculate trails today by about six weeks.
- Pick the right index.
CPIAUCSLis the headline index. Core CPI, without food and energy, isCPILFESL, and the Fed’s preferred PCE price index isPCEPI. - Revisions. Seasonally adjusted CPI is revised each February. The FRED Series listing also has vintage observations if you need CPI as it was first published.
F.A.Q.
What's the difference between real and nominal returns?
What's the difference between real and nominal returns?
A nominal return is the change in price, including dividends when you use adjusted prices. A real return removes inflation, so it measures the change in purchasing power.
What's the average S&P 500 return after inflation?
What's the average S&P 500 return after inflation?
About 8% a year for SPY, from its launch in January 1993 to September 2026: 10.81% a year nominal, less 2.58% a year of inflation, compounded. The last 10 years were higher, at 11.47% a year real.
Can I just subtract inflation from the return?
Can I just subtract inflation from the return?
Only as a rough estimate over short periods. Over 10 years SPY’s nominal return minus inflation is 273.5 points, while the true real return is 196.1%. Divide the growth factors instead.
Which FRED series should I use for inflation?
Which FRED series should I use for inflation?
CPIAUCSL (headline CPI, seasonally adjusted) is the standard choice. Use CPILFESL for core CPI or PCEPI for the PCE price index.Can I do this for a mutual fund?
Can I do this for a mutual fund?
Yes. Mutual funds are in the same price table with daily NAV and adjusted history, so replace SPY with the fund’s ticker. For ready-made nominal returns, the Fund Returns listing has them for about 32,000 funds and ETFs.