CAGR

Also written compound annual growth rate, compound annualized growth rate, compounded annual growth rate

Compound annual growth rate: the single yearly rate that, compounded over the whole period, turns the starting value into the ending value — ending over starting, raised to one over the number of years, minus one. It is a geometric mean, so it sits below the average of the yearly returns whenever they vary. How a tool counts the years, and whether deposits and withdrawals are in the balances, changes the figure.

How it works

The formula is one line: CAGR = (ending value / starting value) ^ (1 / years) − 1. It answers what constant yearly rate would have produced the same end point, and it says nothing about the path — two portfolios with the same CAGR can have had entirely different drawdowns on the way.

It is the geometric mean, not the arithmetic one. Averaging yearly returns treats a 50% loss and a 50% gain as cancelling; compounding does not, because the gain is earned on a smaller base. The arithmetic average is always at or above the CAGR, and the gap widens with volatility. A tool that labels the arithmetic mean of annual returns "average annual return" and another that prints CAGR are not disagreeing about the history; they are reporting different statistics of it.

"Years" is a convention, and libraries pick different ones. Read from their source:

  • ffn measures calendar time between the first and last price, using a year of 31,557,600 seconds — 365.25 days.
  • QuantStats and empyrical-reloaded count observations instead: the number of returns divided by periods per year, 252 by default. That is right for exchange-traded daily data and wrong for a series that trades every day: a calendar year of 365 daily returns reads as 1.45 years, and a 20% gain over it comes out near 13.4% unless the caller passes 365.
  • Backtesting.py prints two annualised figures in one stats table. CAGR [%] uses the calendar duration over 365.25 days; Return (Ann.) [%] compounds the geometric mean bar return over its trading-days-per-year figure (252, or 365 when weekends are in the data). They are different clocks and need not agree.

Short periods are a trap of their own. Raising a three-month return to the fourth power produces a number nobody earned. The performance standard this industry reports against is explicit: under the 2020 GIPS standards, returns for periods of less than one year must not be annualised.

Cash flows. The formula takes two balances. If money was added in between, the end balance includes it, and the result is no longer the return on the holdings. That is what the time-weighted return page is about, and it is where the two backtesters below go opposite ways.

Why it matters here

CAGR is the headline number in most of retirement planning's backtesters, and the label does not tell you which one you are reading. Portfolio Visualizer computes it from the start and end balance and says so — contributions and withdrawals are inside it — while testfolio computes its CAGR ignoring cashflows, so it behaves like a time-weighted return. Run the same allocation with a monthly contribution through both and the two CAGRs should differ; neither is wrong. Portfolio Charts reports a real, inflation-adjusted CAGR in its Heat Map, which differs from a nominal one by roughly the inflation rate over the same years.

The other variable is the window. On the testfolio card, TQQQ over its real life from February 2010 returned 42.3% CAGR, while the simulated TQQQSIM back to 1986 returned 13.3%: one instrument, two start dates. A CAGR quoted without its first and last date is not a fact about the asset.

And not every CAGR on a card is a return at all. DivvyDiary reports dividend growth as a CAGR over 1, 3, 5 and 10 years — the growth rate of the payments, on the same formula with income in place of value. Before comparing two figures with this label, check four things: nominal or real, cashflows in or out, calendar or observation years, and the dates.

Where you will meet this

The cards where this changes a decision, then the rest that use the word.

Sources

  1. Portfolio Visualizer Documentation — Portfolio Visualizer, read
  2. Help, Methodology, and Tool Guides — testfolio, read
  3. Global Investment Performance Standards (GIPS) for Firms, 2020 edition — CFA Institute, . The current edition — it took effect on 1 January 2020 and CFA Institute has published no successor edition.
  4. quantstats/stats.py, cagr() — QuantStats (GitHub), read
  5. empyrical/stats.py, annual_return() and cagr() — empyrical-reloaded (GitHub), read
  6. ffn/core.py, calc_cagr() and year_frac() — ffn (GitHub), read
  7. backtesting/_stats.py, compute_stats() — Backtesting.py (GitHub), read

FAQ

Why is the CAGR lower than the average of the yearly returns?

Because one is a geometric mean and the other arithmetic. A year of +50% followed by a year of −50% averages 0%, but 1.5 × 0.5 leaves 75% of the money, and the rate that does that in two years is about −13.4% a year. The two agree only when every year returns the same; the more the years vary, the further the arithmetic average sits above the CAGR.

Is a CAGR with deposits in it the same as my return?

No, and tools disagree about which one they print. Portfolio Visualizer computes CAGR from the start and end balance, so contributions and withdrawals are inside it, and it points to the time-weighted and money-weighted returns instead when there are cashflows. testfolio computes its CAGR ignoring cashflows, so it behaves like a time-weighted return. Same label, opposite treatment.

Updated