Skip to article frontmatterSkip to article content

The Overlapping Generations Model

This notebook is a slight modification of the one found in QuantEcon: The Overlapping Generations Model.

In this lecture we study the famous overlapping generations (OLG) model, which is used by policy makers and researchers to examine

  • fiscal policy
  • monetary policy
  • long-run growth

and many other topics.

The first rigorous version of the OLG model was developed by Paul Samuelson [Samuelson, 1958].

Our aim is to gain a good understanding of a simple version of the OLG model.

Overview

The dynamics of the OLG model are quite similar to those of the Solow-Swan growth model.

At the same time, the OLG model adds an important new feature: the choice of how much to save is endogenous.

To see why this is important, suppose, for example, that we are interested in predicting the effect of a new tax on long-run growth.

We could add a tax to the Solow-Swan model and look at the change in the steady state.

But this ignores the fact that households will change their savings and consumption behavior when they face the new tax rate.

Such changes can substantially alter the predictions of the model.

Hence, if we care about accurate predictions, we should model the decision problems of the agents.

In particular, households in the model should decide how much to save and how much to consume, given the environment that they face (technology, taxes, prices, etc.)

The OLG model takes up this challenge.

We will present a simple version of the OLG model that clarifies the decision problem of households and studies the implications for long-run growth.

Let’s start with some imports.

from collections import namedtuple

import matplotlib.pyplot as plt
import numpy as np
from scipy import optimize

Environment

We assume that time is discrete, so that t=0,1, t=0, 1, \ldots .

An individual born at time t t lives for two periods, t t and t+1 t + 1 .

We call an agent

  • “young” during the first period of their lives and
  • “old” during the second period of their lives.

Young agents work, supplying labor and earning labor income.

They also decide how much to save.

Old agents do not work, so all income is financial.

Their financial income is from interest on their savings from wage income, which is then combined with the labor of the new young generation at t+1 t+1 .

The wage and interest rates are determined in equilibrium by supply and demand.

To make the algebra slightly easier, we are going to assume a constant population size.

We normalize the constant population size in each period to 1.

We also suppose that each agent supplies one “unit” of labor hours, so total labor supply is 1.

Supply of capital

First let’s consider the household side.

Consumer’s problem

Suppose that utility for individuals born at time t t takes the form

Ut=u(ct)+βu(ct+1)(26.1) U_t = u(c_t) + \beta u(c_{t+1}) \tag{26.1}

Here

  • u:R+R u: \mathbb R_+ \to \mathbb R is called the “flow” utility function
  • β(0,1) \beta \in (0, 1) is the discount factor
  • ct c_t is time t t consumption of the individual born at time t t
  • ct+1 c_{t+1} is time t+1 t+1 consumption of the same individual

We assume that u u is strictly increasing.

Savings behavior is determined by the optimization problem

maxct,ct+1{u(ct)+βu(ct+1)}(26.2) \max_{c_t, c_{t+1}} \, \left \{ u(c_t) + \beta u(c_{t+1}) \right \} \tag{26.2}

subject to

ct+stwtandct+1Rt+1stc_t + s_t \le w_t \quad \text{and} \quad c_{t+1} \le R_{t+1} s_t

Here

  • st s_t is savings by an individual born at time t t
  • wt w_t is the wage rate at time t t
  • Rt+1 R_{t+1} is the gross interest rate on savings invested at time t t , paid at time t+1 t+1

Since u u is strictly increasing, both of these constraints will hold as equalities at the maximum.

Using this fact and substituting st s_t from the first constraint into the second we get ct+1=Rt+1(wtct) c_{t+1} = R_{t+1}(w_t - c_t) .

The first-order condition for a maximum can be obtained by plugging ct+1 c_{t+1} into the objective function, taking the derivative with respect to ct c_t , and setting it to zero.

This leads to the Euler equation of the OLG model, which describes the optimal intertemporal consumption dynamics:

u(ct)=βRt+1u(Rt+1(wtct))(26.3) u'(c_t) = \beta R_{t+1} u'( R_{t+1} (w_t - c_t)) \tag{26.3}

From the first constraint we get ct=wtst c_t = w_t - s_t , so the Euler equation can also be expressed as

u(wtst)=βRt+1u(Rt+1st)(26.4) u'(w_t - s_t) = \beta R_{t+1} u'( R_{t+1} s_t) \tag{26.4}

Suppose that, for each wt w_t and Rt+1 R_{t+1} , there is exactly one st s_t that solves (26.4).

Then savings can be written as a fixed function of wt w_t and Rt+1 R_{t+1} .

We write this as

st=s(wt,Rt+1)(26.5) s_t = s(w_t, R_{t+1}) \tag{26.5}

The precise form of the function s s will depend on the choice of flow utility function u u .

Together, wt w_t and Rt+1 R_{t+1} represent the prices in the economy (price of labor and rental rate of capital).

Thus, (26.5) states the quantity of savings given prices.

Example: log preferences

In the special case u(c)=logc u(c) = \log c , the Euler equation simplifies to st=β(wtst) s_t= \beta (w_t - s_t) .

Solving for saving, we get

st=s(wt,Rt+1)=β1+βwt(26.6) s_t = s(w_t, R_{t+1}) = \frac{\beta}{1+\beta} w_t \tag{26.6}

In this special case, savings does not depend on the interest rate.

Savings and investment

Since the population size is normalized to 1, st s_t is also total savings in the economy at time t t .

In our closed economy, there is no foreign investment, so net savings equals total investment, which can be understood as supply of capital to firms.

In the next section we investigate demand for capital.

Equating supply and demand will allow us to determine equilibrium in the OLG economy.

Demand for capital

First we describe the firm’s problem and then we write down an equation describing demand for capital given prices.

Firm’s problem

For each integer t0 t \geq 0 , output yt y_t in period t t is given by the Cobb-Douglas production function

yt=ktαt1α(26.7) y_t = k_t^{\alpha} \ell_t^{1-\alpha} \tag{26.7}

Here kt k_t is capital, t \ell_t is labor, and α \alpha is a parameter (sometimes called the “output elasticity of capital”).

The profit maximization problem of the firm is

maxkt,t{ktαt1αRtktwtt}(26.8) \max_{k_t, \ell_t} \{ k^{\alpha}_t \ell_t^{1-\alpha} - R_t k_t -w_t \ell_t \} \tag{26.8}

The first-order conditions are obtained by taking the derivative of the objective function with respect to capital and labor respectively and setting them to zero:

(1α)(kt/t)α=wtandα(kt/t)α1=Rt(1-\alpha)(k_t / \ell_t)^{\alpha} = w_t \quad \text{and} \quad \alpha (k_t / \ell_t)^{\alpha - 1} = R_t

Demand

Using our assumption t=1 \ell_t = 1 allows us to write

wt=(1α)ktα(26.9) w_t = (1-\alpha)k_t^\alpha \tag{26.9}

and

Rt=αktα1(26.10) R_t = \alpha k_t^{\alpha - 1} \tag{26.10}

Rearranging (26.10) gives the aggregate demand for capital at time t+1 t+1

kd(Rt+1):=(αRt+1)1/(1α)(26.11) k^d (R_{t+1}) := \left (\frac{\alpha}{R_{t+1}} \right )^{1/(1-\alpha)} \tag{26.11}

In Python code this is

def capital_demand(R, α):
    return (α / R) ** (1 / (1 - α))
def capital_supply(R, β, w):
    R = np.ones_like(R)
    return R * (β / (1 + β)) * w

The next figure plots the supply of capital, as in (26.6), as well as the demand for capital, as in (26.11), as functions of the interest rate Rt+1 R_{t+1} .

(For the special case of log utility, supply does not depend on the interest rate, so we have a constant function.)

Equilibrium

In this section we derive equilibrium conditions and investigate an example.

Equilibrium conditions

In equilibrium, savings at time t t equals investment at time t t , which equals capital supply at time t+1 t+1 .

Equilibrium is computed by equating these quantities, setting

s(wt,Rt+1)=kd(Rt+1)=(αRt+1)1/(1α)(26.12) s(w_t, R_{t+1}) = k^d(R_{t+1}) = \left (\frac{\alpha}{R_{t+1}} \right )^{1/(1-\alpha)} \tag{26.12}

In principle, we can now solve for the equilibrium price Rt+1 R_{t+1} given wt w_t .

(In practice, we first need to specify the function u u and hence s s .)

When we solve this equation, which concerns time t+1 t+1 outcomes, time t t quantities are already determined, so we can treat wt w_t as a constant.

From equilibrium Rt+1 R_{t+1} and (26.11), we can obtain the equilibrium quantity kt+1 k_{t+1} .

Example: log utility

In the case of log utility, we can use (26.12) and (26.6) to obtain

β1+βwt=(αRt+1)1/(1α)(26.13) \frac{\beta}{1+\beta} w_t = \left( \frac{\alpha}{R_{t+1}} \right)^{1/(1-\alpha)} \tag{26.13}

Solving for the equilibrium interest rate gives

Rt+1=α(β1+βwt)α1(26.14) R_{t+1} = \alpha \left( \frac{\beta}{1+\beta} w_t \right)^{\alpha-1} \tag{26.14}

In Python we can compute this via

def equilibrium_R_log_utility(α, β, w):
    R = α * ((β * w) / (1 + β)) ** (α - 1)
    return R

In the case of log utility, since capital supply does not depend on the interest rate, the equilibrium quantity is fixed by supply.

That is,

kt+1=s(wt,Rt+1)=β1+βwt(26.15) k_{t+1} = s(w_t, R_{t+1}) = \frac{\beta }{1+\beta} w_t \tag{26.15}

Let’s redo our plot above but now inserting the equilibrium quantity and price.

R_vals = np.linspace(0.3, 1)
α, β = 0.5, 0.9
w = 2.0


def plot_equilibrium(α, β, w):
    fig, ax = plt.subplots()

    ax.plot(R_vals, capital_demand(R_vals, α), label="aggregate demand")
    ax.plot(R_vals, capital_supply(R_vals, β, w), label="aggregate supply")

    R_e = equilibrium_R_log_utility(α, β, w)
    k_e = (β / (1 + β)) * w

    ax.plot(R_e, k_e, "o", label="equilibrium")

    ax.set_xlabel("$R_{t+1}$")
    ax.set_ylabel("$k_{t+1}$")
    ax.legend()
    plt.show()


plot_equilibrium(α, β, w)
<Figure size 640x480 with 1 Axes>
from ipywidgets import FloatSlider, interact

interact(
    plot_equilibrium,
    α=FloatSlider(α, min=0, max=1, step=0.01),
    β=FloatSlider(β, min=0, max=1, step=0.01),
    w=FloatSlider(w, min=0, max=10, step=0.01),
)
Loading...

Dynamics

In this section we discuss dynamics.

For now we will focus on the case of log utility, so that the equilibrium is determined by (26.15).

Evolution of capital

The discussion above shows how equilibrium kt+1 k_{t+1} is obtained given wt w_t .

From (26.9) we can translate this into kt+1 k_{t+1} as a function of kt k_t

In particular, since wt=(1α)ktα w_t = (1-\alpha)k_t^\alpha , we have

kt+1=β1+β(1α)(kt)α(26.16) k_{t+1} = \frac{\beta}{1+\beta} (1-\alpha)(k_t)^{\alpha} \tag{26.16}

If we iterate on this equation, we get a sequence for capital stock.

Let’s plot the 45-degree diagram of these dynamics, which we write as

kt+1=g(kt)where g(k):=β1+β(1α)(k)αk_{t+1} = g(k_t) \quad \text{where } g(k) := \frac{\beta}{1+\beta} (1-\alpha)(k)^{\alpha}
def k_update(k, α, β):
    return β * (1 - α) * k**α / (1 + β)
α, β = 0.5, 0.9
kmin, kmax = 0, 0.1
n = 1000
k_grid = np.linspace(kmin, kmax, n)


def plot45(α, β):
    k_grid_next = k_update(k_grid, α, β)

    fig, ax = plt.subplots(figsize=(6, 6))

    ymin, ymax = np.min(k_grid_next), np.max(k_grid_next)

    ax.plot(k_grid, k_grid_next, lw=2, alpha=0.6, label="$g$")
    ax.plot(k_grid, k_grid, "k-", lw=1, alpha=0.7, label=r"$45^{\circ}$")

    ax.legend(loc="upper left", frameon=False, fontsize=12)
    ax.set_xlabel("$k_t$", fontsize=12)
    ax.set_ylabel("$k_{t+1}$", fontsize=12)

    plt.show()


plot45(α, β)
<Figure size 600x600 with 1 Axes>
interact(
    plot45,
    α=FloatSlider(α, min=0, max=1, step=0.01),
    β=FloatSlider(β, min=0, max=1, step=0.01),
)
Loading...

Steady state (log case)

The diagram shows that the model has a unique positive steady state, which we denote by k k^* .

We can solve for k k^* by setting k=g(k) k^* = g(k^*) , or

k=β(1α)(k)α(1+β)(26.17) k^* = \frac{\beta (1-\alpha) (k^*)^{\alpha}}{(1+\beta)} \tag{26.17}

Solving this equation yields

k=(β(1α)1+β)1/(1α)(26.18) k^* = \left (\frac{\beta (1-\alpha)}{1+\beta} \right )^{1/(1-\alpha)} \tag{26.18}

We can get the steady state interest rate from (26.10), which yields

R=α(k)α1=α1α1+ββR^* = \alpha (k^*)^{\alpha - 1} = \frac{\alpha}{1 - \alpha} \frac{1 + \beta}{\beta}

In Python we have

k_star = ((β * (1 - α)) / (1 + β)) ** (1 / (1 - α))
R_star = (α / (1 - α)) * ((1 + β) / β)

Time series

The 45-degree diagram above shows that time series of capital with positive initial conditions converge to this steady state.

Let’s plot some time series that visualize this.

ts_length = 25
k_series = np.empty(ts_length)
k_series[0] = 0.02
for t in range(ts_length - 1):
    k_series[t + 1] = k_update(k_series[t], α, β)

fig, ax = plt.subplots()
ax.plot(k_series, label="capital series")
ax.plot(range(ts_length), np.full(ts_length, k_star), "k--", label="$k^*$")
ax.set_ylim(0, 0.1)
ax.set_ylabel("capital")
ax.set_xlabel("$t$")
ax.legend()
plt.show()
<Figure size 640x480 with 1 Axes>

If you experiment with different positive initial conditions, you will see that the series always converges to k k^* .

Below we also plot the gross interest rate over time.

R_series = α * k_series ** (α - 1)

fig, ax = plt.subplots()
ax.plot(R_series, label="gross interest rate")
ax.plot(range(ts_length), np.full(ts_length, R_star), "k--", label="$R^*$")
ax.set_ylim(0, 4)
ax.set_ylabel("gross interest rate")
ax.set_xlabel("$t$")
ax.legend()
plt.show()
<Figure size 640x480 with 1 Axes>

The interest rate reflects the marginal product of capital, which is high when capital stock is low.

CRRA preferences

Previously, in our examples, we looked at the case of log utility.

Log utility is a rather special case of CRRA utility with γ1 \gamma \to 1 .

In this section, we are going to assume that u(c)=c1γ11γ u(c) = \frac{ c^{1- \gamma}-1}{1-\gamma} , where γ>0,γ1 \gamma >0, \gamma\neq 1 .

This function is called the CRRA utility function.

In other respects, the model is the same.

Below we define the utility function in Python and construct a namedtuple to store the parameters.

def crra(c, γ):
    return c ** (1 - γ) / (1 - γ)


Model = namedtuple(
    "Model",
    [
        "α",  # Cobb-Douglas parameter
        "β",  # discount factor
        "γ",
    ],  # parameter in CRRA utility
)


def create_olg_model(α=0.4, β=0.9, γ=0.5):
    return Model(α=α, β=β, γ=γ)

Let’s also redefine the capital demand function to work with this namedtuple.

def capital_demand_model(R, model):
    return (model.α / R) ** (1 / (1 - model.α))

Supply

For households, the Euler equation becomes

(wtst)γ=βRt+11γ(st)γ(26.19) (w_t - s_t)^{-\gamma} = \beta R^{1-\gamma}_{t+1} (s_t)^{-\gamma} \tag{26.19}

Solving for savings, we have

st=s(wt,Rt+1)=wt[1+β1/γRt+1(γ1)/γ]1(26.20) s_t = s(w_t, R_{t+1}) = w_t \left [ 1 + \beta^{-1/\gamma} R_{t+1}^{(\gamma-1)/\gamma} \right ]^{-1} \tag{26.20}

Notice how, unlike the log case, savings now depends on the interest rate.

def savings_crra(w, R, model):
    α, β, γ = model
    return w / (1 + β ** (-1 / γ) * R ** ((γ - 1) / γ))
model = create_olg_model()
w = 2.0

fig, ax = plt.subplots()

ax.plot(R_vals, capital_demand_model(R_vals, model), label="aggregate demand")
ax.plot(R_vals, savings_crra(w, R_vals, model), label="aggregate supply")

ax.set_xlabel("$R_{t+1}$")
ax.set_ylabel("$k_{t+1}$")
ax.legend()
plt.show()
<Figure size 640x480 with 1 Axes>

Equilibrium

Equating aggregate demand for capital (see (26.11)) with our new aggregate supply function yields equilibrium capital.

Thus, we set

wt[1+β1/γRt+1(γ1)/γ]1=(Rt+1α)1/(α1)(26.21) w_t \left [ 1 + \beta^{-1/\gamma} R_{t+1}^{(\gamma-1)/\gamma} \right ]^{-1} = \left (\frac{R_{t+1}}{\alpha} \right )^{1/(\alpha - 1)} \tag{26.21}

This expression is quite complex and we cannot solve for Rt+1 R_{t+1} analytically.

Combining (26.10) and (26.21) yields

kt+1=[1+β1/γ(αkt+1α1)(γ1)/γ]1(1α)(kt)α(26.22) k_{t+1} = \left [ 1 + \beta^{-1/\gamma} (\alpha k^{\alpha - 1}_{t+1})^{(\gamma-1)/\gamma} \right ]^{-1} (1-\alpha)(k_t)^{\alpha} \tag{26.22}

Again, with this equation and kt k_t as given, we cannot solve for kt+1 k_{t+1} by pencil and paper.

In the exercise below, you will be asked to solve these equations numerically.

Exercises

Exercise 26.1

Solve for the dynamics of equilibrium capital stock in the CRRA case numerically using (26.22).

Visualize the dynamics using a 45-degree diagram.

Solution toExercise 26.1

To solve for kt+1 k_{t+1} given kt k_t we use Newton’s method.

Let

f(kt+1,kt)=kt+1[1+β1/γ(αkt+1α1)(γ1)/γ](1α)ktα=0(26.23) f(k_{t+1}, k_t) = k_{t+1} \left[ 1 + \beta^{-1/\gamma} \left ( \alpha k^{\alpha-1}_{t+1} \right )^{(\gamma-1)/\gamma} \right] - (1-\alpha) k^{\alpha}_t =0 \tag{26.23}

If kt k_t is given then f f is a function of unknown kt+1 k_{t+1} .

Then we can use scipy.optimize.newton to solve f(kt+1,kt)=0 f(k_{t+1}, k_t)=0 for kt+1 k_{t+1} .

First let’s define f f .

def f(k_prime, k, model):
    α, β, γ = model.α, model.β, model.γ
    z = (1 - α) * k**α
    a = α ** (1 - 1 / γ)
    b = k_prime ** ((α * γ - α + 1) / γ)
    p = k_prime + k_prime * β ** (-1 / γ) * a * b
    return p - z

Now let’s define a function that finds the value of kt+1 k_{t+1} .

def k_update_opt(k, model):
    return optimize.newton(lambda k_prime: f(k_prime, k, model), 0.1)

Finally, here is the 45-degree diagram.

kmin, kmax = 0, 0.5
n = 1000
k_grid = np.linspace(kmin, kmax, n)
k_grid_next = np.empty_like(k_grid)

for i in range(n):
    k_grid_next[i] = k_update_opt(k_grid[i], model)

fig, ax = plt.subplots(figsize=(6, 6))

ymin, ymax = np.min(k_grid_next), np.max(k_grid_next)

ax.plot(k_grid, k_grid_next, lw=2, alpha=0.6, label="$g$")
ax.plot(k_grid, k_grid, "k-", lw=1, alpha=0.7, label=r"$45^{\circ}$")


ax.legend(loc="upper left", frameon=False, fontsize=12)
ax.set_xlabel("$k_t$", fontsize=12)
ax.set_ylabel("$k_{t+1}$", fontsize=12)

plt.show()
<Figure size 600x600 with 1 Axes>

Exercise 26.2

The 45-degree diagram from the last exercise shows that there is a unique positive steady state.

The positive steady state can be obtained by setting kt+1=kt=k k_{t+1} = k_t = k^* in (26.22), which yields

k=(1α)(k)α1+β1/γ(α(k)α1)(γ1)/γk^* = \frac{(1-\alpha)(k^*)^{\alpha}} {1 + \beta^{-1/\gamma} (\alpha (k^*)^{\alpha-1})^{(\gamma-1)/\gamma}}

Unlike the log preference case, the CRRA utility steady state k k^* cannot be obtained analytically.

Instead, we solve for k k^* using Newton’s method.

Solution toExercise 26.2

We introduce a function h h such that positive steady state is the root of h h .

h(k)=k[1+β1/γ(α(k)α1)(γ1)/γ](1α)(k)α(26.24) h(k^*) = k^* \left [ 1 + \beta^{-1/\gamma} (\alpha (k^*)^{\alpha-1})^{(\gamma-1)/\gamma} \right ] - (1-\alpha)(k^*)^{\alpha} \tag{26.24}

Here it is in Python

def h(k_star, model):
    α, β, γ = model.α, model.β, model.γ
    z = (1 - α) * k_star**α
    R1 = α ** (1 - 1 / γ)
    R2 = k_star ** ((α * γ - α + 1) / γ)
    p = k_star + k_star * β ** (-1 / γ) * R1 * R2
    return p - z

Let’s apply Newton’s method to find the root:

k_star = optimize.newton(h, 0.2, args=(model,))
print(f"k_star = {k_star}")
k_star = 0.25788950250843484

Exercise 26.3

Generate three time paths for capital, from three distinct initial conditions, under the parameterization listed above.

Use initial conditions for k0 k_0 of 0.001,1.2,2.6 0.001, 1.2, 2.6 and time series length 10.

Solution toExercise 26.3

Let’s define the constants and three distinct intital conditions

ts_length = 10
k0 = np.array([0.001, 1.2, 2.6])
def simulate_ts(model, k0_values, ts_length):
    fig, ax = plt.subplots()

    ts = np.zeros(ts_length)

    # simulate and plot time series
    for k_init in k0_values:
        ts[0] = k_init
        for t in range(1, ts_length):
            ts[t] = k_update_opt(ts[t - 1], model)
        ax.plot(
            np.arange(ts_length),
            ts,
            "-o",
            ms=4,
            alpha=0.6,
            label=r"$k_0=%g$" % k_init,
        )
    ax.plot(
        np.arange(ts_length),
        np.full(ts_length, k_star),
        alpha=0.6,
        color="red",
        label=r"$k^*$",
    )
    ax.legend(fontsize=10)

    ax.set_xlabel(r"$t$", fontsize=14)
    ax.set_ylabel(r"$k_t$", fontsize=14)

    plt.show()
simulate_ts(model, k0, ts_length)
<Figure size 640x480 with 1 Axes>