What P/E says about priced-in growth

The P/E of a stock is the share price divided by the EPS. By convention, the TTM EPS will be used here, but a different one could also be used if wanted. The P/E can be thought of as the number of years required for earnings to ‘make back’ the initial investment (paying the current share price), assuming earnings stay constant at the TTM value.

So what growth rate for EPS is implied by a given P/E ratio? To answer this, we need to know the average number of years that an investor wants to make their money back in earnings (with no growth), which we assume is unknown. So this becomes more a question of simply what growth is implied by the current market price? Thus, we need a model for the market price (e.g., a DCF - we’ll come back to this).

This can sort of be answered by considering some number of years \(N<P/E\) (e.g., sector average P/E, or simply the number of years that you as an investor would like to hold your position for), so that we can ask the general question “What rate do earnings have to grow at so that I will make my money back (in earnings) in \(N\) years?”.

\[\text{Let }S_0\text{ be the current share price.}\] \[\text{Let }E_{\text{TTM}}\text{ be the TTM EPS.}\] \[\text{Let }N\text{ be a given break-even number of years for making our money back in earnings.}\] \[\text{We want to find }g\in(0,g_{\max}]\text{ such that }S_0=\sum_{t=1}^N E_\text{TTM}(1+g)^t.\] \[\implies f(g)=0~~~\text{where}~~f(g)=E_\text{TTM}\bigg(\frac{1-(1+g)^{N+1}}{-g}-1\bigg)-S_0\]

Since typically we have \(N>4\), the roots of \(f\) must be solved numerically. This works when TTM EPS is positive, and (as we’ve already assumed) growth is positive, because then the cash flows \((-S_0,E_\text{TTM}(1+g),E_\text{TTM}(1+g)^2,\dots)\) form a pure investment project, so the coefficients in our polynomial change sign only once, and hence we will have just one positive real root (Descartes’ rule of signs). If this were not the case, we’d have to discount/accumulate accordingly to make it a pure investment project (the same procedure as the MIRR). Anyway, for growth to be positive, we require \(N\in(0,S_0/E_\text{TTM})=(0,P/E)\).

## constants (using values for NVDA at close on August 5th, 2025)
s0 <- 178.26
eps_ttm <- 3.10
pe <- s0 / eps_ttm # we need N to be less than the current P/E ratio
print(pe)
## [1] 57.50323
n <- 15
g_max <- 3

## function we need to solve for the roots of
f <- function(g) {
  fv1 <- ((1 - (1+g)^(n+1)) / (-g)) - 1 # FV of 1$ growing at g
  return(eps_ttm * fv1 - s0)
}

curve(expr = f, from = 1e-4, to = 0.25)
abline(h = 0, col = "red")

## solving for root numerically

solver1 <- uniroot(f = f, interval = c(1e-5, g_max))
root1 <- solver1$root
print(root1)
## [1] 0.1554553

Taking time value of money into account (discounting)

If we bring time value of money into the picture, this becomes more of a “what earnings growth is implied by the current market price” type of question, because now our model is actually somewhat close to a real DCF (albeit simplified) that might be used to value a stock by other investors.

\[\text{Let }r\text{ be the cost of equity.}\] \[S_0=\sum_{t=1}^N E_{\text{TTM}}(1+g)^t(1+r)^{-t}\] \[\implies S_0=E_\text{TTM}\sum_{t=1}^N \bigg[\frac{1+g}{1+r}\bigg]^t=E_\text{TTM}\bigg(\frac{1-\big[\frac{1+g}{1+r}\big]^{N+1}}{1-\big[\frac{1+g}{1+r}\big]}-1 \bigg)=E_\text{TTM}\bigg(\frac{1-\big[\frac{1+g}{1+r}\big]^{N+1}}{(r-g)/(1+r)}-1 \bigg)\] \[\implies h(g)=0~~\text{where}~~h(g)=E_\text{TTM}\bigg(\frac{1-\big[\frac{1+g}{1+r}\big]^{N+1}}{(r-g)/(1+r)}-1 \bigg)-S_0\]

## using same constants as before as well as cost of equity
r <- 0.1 # cost of equity: 10% (NOTE TO SELF: UPDATE THIS TO BE MORE REALISTIC; USE SML (CAPM) OR ANOTHER RISK PREMIUM)

## function we need to solve for the roots of
h <- function(g) {
  pv_fv1 <- (1 - ((1+g)/(1+r))^(n+1)) / ((r-g)*(1+r)) - 1 # PV @ r of FV @ g
  return( eps_ttm * pv_fv1 - s0 )
}

curve(expr = h, from = 1e-5, to=0.3)
abline(h = 0, col = "red")

# note: should g_max be different now under this formulation?
solver2 <- uniroot(f = h, interval = c(1e-5, g_max))
root2 <- solver2$root
print(root2)
## [1] 0.2943524

If we change TTM EPS to instead be something like free cash flow, this really becomes more like a cash growth rate backed out of a DCF.

Considering Cash Flows in Perpetuity (letting \(n\rightarrow\infty\))

Let’s continue with the discounted approach, so that we keep the beenefits of considering time value of money.

\[\begin{aligned} S_0&=\sum_{t=1}^\infty E_{\text{TTM}}(1+g)^t(1+r)^{-t}\\ &=E_{\text{TTM}}\bigg(\sum_{t=0}^\infty \bigg[\frac{1+g}{1+r}\bigg]^{t}-1\bigg)\overset{g<r}{=}E_{\text{TTM}}\bigg(\bigg(1-\frac{1+g}{1+r} \bigg)^{-1}-1\bigg)\\ &=E_{\text{TTM}}\bigg(\bigg(\frac{r-g}{1+r} \bigg)^{-1}-1\bigg)=E_{\text{TTM}}\bigg(\frac{1+r-(r-g)}{r-g} \bigg)\\ &=E_{\text{TTM}}\bigg(\frac{1+g}{r-g} \bigg)\\ &\text{ }\\ \implies S_0r-S_0g&=E_{\text{TTM}}+E_{\text{TTM}}g\implies S_0r-E_{\text{TTM}}=(E_{\text{TTM}}+S_0)g\\ \therefore~~g&=\frac{rS_0-E_{\text{TTM}}}{S_0+E_{\text{TTM}}} \end{aligned}\]

A crucial additional assumption we have just made is that \(g<r\). In this case, we have a simple analytic solution and there’s no need to involve numerical methods for root finding.

perpetual_growth <- (r*s0 - eps_ttm) / (s0 + eps_ttm)
print(perpetual_growth)
## [1] 0.08119762

Also, notice the sensitivity (partial derivative) of this perpetual growth to our discount rate:

\[\frac{\partial g}{\partial r}=\frac{S_0}{S_0+E_{\text{TTM}}}\]

which is constant with respect to \(r\), and positive. Therefore, \(g\uparrow\) as \(r\uparrow\), and the implied perpetual growth rate has a constant sensitivity to the discount rate that does not vary with respect to our parameters (the “correct” discount rate is estimated, but the current stock price and the EPS (TTM) are known values). This is good!

In the 3D plot below, the red point shows the value of \(\frac{\partial g}{\partial r}\) evaluated at the current values for the stock price and EPS (again, continuing with NVDA example from earlier).

# create points for plotting
x <- seq(100, 250, length.out=500)
y <- seq(1, 5, length.out=500)
dg_dr <- function(x, y) {x / (x+y)}
z <- outer(x, y, dg_dr)

#install.packages("plotly")
suppressPackageStartupMessages(library(plotly)) 
## Warning: package 'plotly' was built under R version 4.4.3
# run plot
plot_ly(x = ~x, y = ~y, z = ~z, type = "surface") %>% 
  add_trace(
    x = s0, y = eps_ttm, z = dg_dr(x=s0, y=eps_ttm),
    type = "scatter3d", mode = "markers",
    marker = list(size = 7, color = "red"),
    name = "With Today's Values"
  ) %>% 
  layout(scene = list(
    xaxis = list(title = "Stock Price"),
    yaxis = list(title = "EPS (TTM)"),
    zaxis = list(title = "Derivative")
  ),
  title = "Derivative of Implied Growth Rate wrt Discount Rate")
# run marginal plots (extra variable held constant at current value)
plot(x=x, y=dg_dr(x=x, y=eps_ttm), xlab="Stock Price", ylab="Derivative", 
     main="Derivative of Implied Growth Rate wrt Discount Rate")
text(x=200, y=0.975, labels="EPS held constant at current value")

plot(x=y, y=dg_dr(x=s0, y=y), xlab="EPS (TTM)", ylab="Derivative", 
     main="Derivative of Implied Growth Rate wrt Discount Rate")
text(x=2, y=0.980, labels="Stock price held constant at current value")