Skip to article frontmatterSkip to article content
Contents
and

12. Consumption Smoothing

12.1Overview

In this lecture, we’ll study a famous model of the “consumption function” that Milton Friedman Friedman (1956) and Robert Hall Hall (1978)) proposed to fit some empirical data patterns that the original Keynesian consumption function described in this QuantEcon lecture geometric series missed.

We’ll study what is often called the “consumption-smoothing model.”

We’ll use matrix multiplication and matrix inversion, the same tools that we used in this QuantEcon lecture present values.

Formulas presented in present value formulas are at the core of the consumption-smoothing model because we shall use them to define a consumer’s “human wealth”.

The key idea that inspired Milton Friedman was that a person’s non-financial income, i.e., his or her wages from working, can be viewed as a dividend stream from ‘‘human capital’’ and that standard asset-pricing formulas can be applied to compute ‘‘non-financial wealth’’ that capitalizes that earnings stream.

It will take a while for a “present value” or asset price explicitly to appear in this lecture, but when it does it will be a key actor.

12.2Analysis

As usual, we’ll start by importing some Python modules.

import numpy as np
import matplotlib.pyplot as plt
from collections import namedtuple

The model describes a consumer who lives from time t=0,1,,Tt=0, 1, \ldots, T, receives a stream {yt}t=0T\{y_t\}_{t=0}^T of non-financial income and chooses a consumption stream {ct}t=0T\{c_t\}_{t=0}^T.

We usually think of the non-financial income stream as coming from the person’s earnings from supplying labor.

The model takes a non-financial income stream as an input, regarding it as “exogenous” in the sense that it is determined outside the model.

The consumer faces a gross interest rate of R>1R >1 that is constant over time, at which she is free to borrow or lend, up to limits that we’ll describe below.

Let

  • T2T \geq 2 be a positive integer that constitutes a time-horizon.
  • y={yt}t=0Ty = \{y_t\}_{t=0}^T be an exogenous sequence of non-negative non-financial incomes yty_t.
  • a={at}t=0T+1a = \{a_t\}_{t=0}^{T+1} be a sequence of financial wealth.
  • c={ct}t=0Tc = \{c_t\}_{t=0}^T be a sequence of non-negative consumption rates.
  • R1R \geq 1 be a fixed gross one period rate of return on financial assets.
  • β(0,1)\beta \in (0,1) be a fixed discount factor.
  • a0a_0 be a given initial level of financial assets
  • aT+10a_{T+1} \geq 0 be a terminal condition on final assets.

The sequence of financial wealth aa is to be determined by the model.

We require it to satisfy two boundary conditions:

  • it must equal an exogenous value a0a_0 at time 0
  • it must equal or exceed an exogenous value aT+1a_{T+1} at time T+1T+1.

The terminal condition aT+10a_{T+1} \geq 0 requires that the consumer not leave the model in debt.

(We’ll soon see that a utility maximizing consumer won’t want to die leaving positive assets, so she’ll arrange her affairs to make aT+1=0a_{T+1} = 0.)

The consumer faces a sequence of budget constraints that constrains sequences (y,c,a)(y, c, a)

at+1=R(at+ytct),t=0,1,Ta_{t+1} = R (a_t+ y_t - c_t), \quad t =0, 1, \ldots T

Equations (1) constitute T+1T+1 such budget constraints, one for each t=0,1,,Tt=0, 1, \ldots, T.

Given a sequence yy of non-financial incomes, a large set of pairs (a,c)(a, c) of (financial wealth, consumption) sequences satisfy the sequence of budget constraints (1).

Our model has the following logical flow.

  • start with an exogenous non-financial income sequence yy, an initial financial wealth a0a_0, and a candidate consumption path cc.

  • use the system of equations (1) for t=0,,Tt=0, \ldots, T to compute a path aa of financial wealth

  • verify that aT+1a_{T+1} satisfies the terminal wealth constraint aT+10a_{T+1} \geq 0.

    • If it does, declare that the candidate path is budget feasible.

    • if the candidate consumption path is not budget feasible, propose a less greedy consumption path and start over

Below, we’ll describe how to execute these steps using linear algebra -- matrix inversion and multiplication.

The above procedure seems like a sensible way to find “budget-feasible” consumption paths cc, i.e., paths that are consistent with the exogenous non-financial income stream yy, the initial financial asset level a0a_0, and the terminal asset level aT+1a_{T+1}.

In general, there are many budget feasible consumption paths cc.

Among all budget-feasible consumption paths, which one should a consumer want?

To answer this question, we shall eventually evaluate alternative budget feasible consumption paths cc using the following utility functional or welfare criterion:

W=t=0Tβt(g1ctg22ct2)W = \sum_{t=0}^T \beta^t (g_1 c_t - \frac{g_2}{2} c_t^2 )

where g1>0,g2>0g_1 > 0, g_2 > 0.

When βR1\beta R \approx 1, the fact that the utility function g1ctg22ct2g_1 c_t - \frac{g_2}{2} c_t^2 has diminishing marginal utility imparts a preference for consumption that is very smooth.

Indeed, we shall see that when βR=1\beta R = 1 (a condition assumed by Milton Friedman Friedman (1956) and Robert Hall Hall (1978)), criterion (2) assigns higher welfare to smoother consumption paths.

By smoother we mean as close as possible to being constant over time.

The preference for smooth consumption paths that is built into the model gives it the name “consumption-smoothing model”.

We’ll postpone verifying our claim that a constant consumption path is optimal when βR=1\beta R=1 by comparing welfare levels that comes from a constant path with ones that involve non-constant paths.

Before doing that, let’s dive in and do some calculations that will help us understand how the model works in practice when we provide the consumer with some different streams on non-financial income.

Here we use default parameters R=1.05R = 1.05, g1=1g_1 = 1, g2=1/2g_2 = 1/2, and T=65T = 65.

We create a Python namedtuple to store these parameters with default values.

ConsumptionSmoothing = namedtuple("ConsumptionSmoothing", 
                        ["R", "g1", "g2", "β_seq", "T"])

def create_consumption_smoothing_model(R=1.05, g1=1, g2=1/2, T=65):
    β = 1/R
    β_seq = np.array([β**i for i in range(T+1)])
    return ConsumptionSmoothing(R, g1, g2, 
                                β_seq, T)

12.3Friedman-Hall consumption-smoothing model

A key object is what Milton Friedman called “human” or “non-financial” wealth at time 0:

h0t=0TRtyt=[1R1RT][y0y1yT]h_0 \equiv \sum_{t=0}^T R^{-t} y_t = \begin{bmatrix} 1 & R^{-1} & \cdots & R^{-T} \end{bmatrix} \begin{bmatrix} y_0 \cr y_1 \cr \vdots \cr y_T \end{bmatrix}

Human or non-financial wealth at time 0 is evidently just the present value of the consumer’s non-financial income stream yy.

Formally it very much resembles the asset price that we computed in this QuantEcon lecture present values.

Indeed, this is why Milton Friedman called it “human capital”.

By iterating on equation (1) and imposing the terminal condition

aT+1=0,a_{T+1} = 0,

it is possible to convert a sequence of budget constraints (1) into a single intertemporal constraint

t=0TRtct=a0+h0.\sum_{t=0}^T R^{-t} c_t = a_0 + h_0.

Equation (5) says that the present value of the consumption stream equals the sum of financial and non-financial (or human) wealth.

Robert Hall Hall (1978) showed that when βR=1\beta R = 1, a condition Milton Friedman had also assumed, it is “optimal” for a consumer to smooth consumption by setting

ct=c0t=0,1,,Tc_t = c_0 \quad t =0, 1, \ldots, T

(Later we’ll present a “variational argument” that shows that this constant path maximizes criterion (2) when βR=1\beta R =1.)

In this case, we can use the intertemporal budget constraint to write

ct=c0=(t=0TRt)1(a0+h0),t=0,1,,T.c_t = c_0 = \left(\sum_{t=0}^T R^{-t}\right)^{-1} (a_0 + h_0), \quad t= 0, 1, \ldots, T.

Equation (7) is the consumption-smoothing model in a nutshell.

12.4Mechanics of consumption-smoothing model

As promised, we’ll provide step-by-step instructions on how to use linear algebra, readily implemented in Python, to compute all objects in play in the consumption-smoothing model.

In the calculations below, we’ll set default values of R>1R > 1, e.g., R=1.05R = 1.05, and β=R1\beta = R^{-1}.

12.4.1Step 1

For a (T+1)×1(T+1) \times 1 vector yy, use matrix algebra to compute h0h_0

h0=t=0TRtyt=[1R1RT][y0y1yT]h_0 = \sum_{t=0}^T R^{-t} y_t = \begin{bmatrix} 1 & R^{-1} & \cdots & R^{-T} \end{bmatrix} \begin{bmatrix} y_0 \cr y_1 \cr \vdots \cr y_T \end{bmatrix}

12.4.2Step 2

Compute an time 0 consumption c0c_0 :

ct=c0=(1R11R(T+1))(a0+t=0TRtyt),t=0,1,,Tc_t = c_0 = \left( \frac{1 - R^{-1}}{1 - R^{-(T+1)}} \right) (a_0 + \sum_{t=0}^T R^{-t} y_t ) , \quad t = 0, 1, \ldots, T

12.4.3Step 3

Use the system of equations (1) for t=0,,Tt=0, \ldots, T to compute a path aa of financial wealth.

To do this, we translate that system of difference equations into a single matrix equation as follows:

[100000R100000R1000000R100000R1][a1a2a3aTaT+1]=R[y0+a0c0y1c0y2c0yT1c0yTc0]\begin{bmatrix} 1 & 0 & 0 & \cdots & 0 & 0 & 0 \cr -R & 1 & 0 & \cdots & 0 & 0 & 0 \cr 0 & -R & 1 & \cdots & 0 & 0 & 0 \cr \vdots &\vdots & \vdots & \cdots & \vdots & \vdots & \vdots \cr 0 & 0 & 0 & \cdots & -R & 1 & 0 \cr 0 & 0 & 0 & \cdots & 0 & -R & 1 \end{bmatrix} \begin{bmatrix} a_1 \cr a_2 \cr a_3 \cr \vdots \cr a_T \cr a_{T+1} \end{bmatrix} = R \begin{bmatrix} y_0 + a_0 - c_0 \cr y_1 - c_0 \cr y_2 - c_0 \cr \vdots\cr y_{T-1} - c_0 \cr y_T - c_0 \end{bmatrix}

Multiply both sides by the inverse of the matrix on the left side to compute

[a1a2a3aTaT+1]\begin{bmatrix} a_1 \cr a_2 \cr a_3 \cr \vdots \cr a_T \cr a_{T+1} \end{bmatrix}

Because we have built into our calculations that the consumer leaves the model with exactly zero assets, just barely satisfying the terminal condition that aT+10a_{T+1} \geq 0, it should turn out that

aT+1=0.a_{T+1} = 0.

Let’s verify this with Python code.

First we implement the model with compute_optimal

def compute_optimal(model, a0, y_seq):
    R, T = model.R, model.T

    # non-financial wealth
    h0 = model.β_seq @ y_seq     # since β = 1/R

    # c0
    c0 = (1 - 1/R) / (1 - (1/R)**(T+1)) * (a0 + h0)
    c_seq = c0*np.ones(T+1)

    # verify
    A = np.diag(-R*np.ones(T), k=-1) + np.eye(T+1)
    b = y_seq - c_seq
    b[0] = b[0] + a0

    a_seq = np.linalg.inv(A) @ b
    a_seq = np.concatenate([[a0], a_seq])

    return c_seq, a_seq, h0

We use an example where the consumer inherits a0<0a_0<0.

This can be interpreted as student debt with which the consumer begins his or her working life.

The non-financial process {yt}t=0T\{y_t\}_{t=0}^{T} is constant and positive up to t=45t=45 and then becomes zero afterward.

The drop in non-financial income late in life reflects retirement from work.

# Financial wealth
a0 = -2     # such as "student debt"

# non-financial Income process
y_seq = np.concatenate([np.ones(46), np.zeros(20)])

cs_model = create_consumption_smoothing_model()
c_seq, a_seq, h0 = compute_optimal(cs_model, a0, y_seq)

print('check a_T+1=0:', 
      np.abs(a_seq[-1] - 0) <= 1e-8)
check a_T+1=0: True

The graphs below show paths of non-financial income, consumption, and financial assets.

# Sequence length
T = cs_model.T

fig, axes = plt.subplots(1, 2, figsize=(12,5))

axes[0].plot(range(T+1), y_seq, label='non-financial income', lw=2)
axes[0].plot(range(T+1), c_seq, label='consumption', lw=2)
axes[1].plot(range(T+2), a_seq, label='financial wealth', color='green', lw=2)
axes[0].set_ylabel(r'$c_t,y_t$')
axes[1].set_ylabel(r'$a_t$')

for ax in axes:
    ax.plot(range(T+2), np.zeros(T+2), '--', lw=1, color='black')
    ax.legend()
    ax.set_xlabel(r'$t$')

plt.show()
<Figure size 1200x500 with 2 Axes>

Note that aT+1=0a_{T+1} = 0, as anticipated.

We can evaluate welfare criterion (2)

def welfare(model, c_seq):
    β_seq, g1, g2 = model.β_seq, model.g1, model.g2

    u_seq = g1 * c_seq - g2/2 * c_seq**2
    return β_seq @ u_seq

print('Welfare:', welfare(cs_model, c_seq))
Welfare: 13.285050962183433

12.4.4Experiments

In this section we describe how a consumption sequence would optimally respond to different sequences sequences of non-financial income.

First we create a function plot_cs that generates graphs for different instances of the consumption-smoothing model cs_model.

This will help us avoid rewriting code to plot outcomes for different non-financial income sequences.

def plot_cs(model,    # consumption-smoothing model      
            a0,       # initial financial wealth
            y_seq     # non-financial income process
           ):
    
    # Compute optimal consumption
    c_seq, a_seq, h0 = compute_optimal(model, a0, y_seq)
    
    # Sequence length
    T = cs_model.T
    
    fig, axes = plt.subplots(1, 2, figsize=(12,5))
    
    axes[0].plot(range(T+1), y_seq, label='non-financial income', lw=2)
    axes[0].plot(range(T+1), c_seq, label='consumption', lw=2)
    axes[1].plot(range(T+2), a_seq, label='financial wealth', color='green', lw=2)
    axes[0].set_ylabel(r'$c_t,y_t$')
    axes[1].set_ylabel(r'$a_t$')
    
    for ax in axes:
        ax.plot(range(T+2), np.zeros(T+2), '--', lw=1, color='black')
        ax.legend()
        ax.set_xlabel(r'$t$')
    
    plt.show()

In the experiments below, please study how consumption and financial asset sequences vary across different sequences for non-financial income.

12.4.4.1Experiment 1: one-time gain/loss

We first assume a one-time windfall of W0W_0 in year 21 of the income sequence yy.

We’ll make W0W_0 big - positive to indicate a one-time windfall, and negative to indicate a one-time “disaster”.

# Windfall W_0 = 2.5
y_seq_pos = np.concatenate([np.ones(21), np.array([2.5]), np.ones(24), np.zeros(20)])

plot_cs(cs_model, a0, y_seq_pos)
<Figure size 1200x500 with 2 Axes>
# Disaster W_0 = -2.5
y_seq_neg = np.concatenate([np.ones(21), np.array([-2.5]), np.ones(24), np.zeros(20)])

plot_cs(cs_model, a0, y_seq_neg)
<Figure size 1200x500 with 2 Axes>

12.4.4.2Experiment 2: permanent wage gain/loss

Now we assume a permanent increase in income of WW in year 21 of the yy-sequence.

Again we can study positive and negative cases

# Positive permanent income change W = 0.5 when t >= 21
y_seq_pos = np.concatenate(
    [np.ones(21), 1.5*np.ones(25), np.zeros(20)])

plot_cs(cs_model, a0, y_seq_pos)
<Figure size 1200x500 with 2 Axes>
# Negative permanent income change W = -0.5 when t >= 21
y_seq_neg = np.concatenate(
    [np.ones(21), .5*np.ones(25), np.zeros(20)])

plot_cs(cs_model, a0, y_seq_neg)
<Figure size 1200x500 with 2 Axes>

12.4.4.3Experiment 3: a late starter

Now we simulate a yy sequence in which a person gets zero for 46 years, and then works and gets 1 for the last 20 years of life (a “late starter”)

# Late starter
y_seq_late = np.concatenate(
    [np.ones(46), 2*np.ones(20)])

plot_cs(cs_model, a0, y_seq_late)
<Figure size 1200x500 with 2 Axes>

12.4.4.4Experiment 4: geometric earner

Now we simulate a geometric yy sequence in which a person gets yt=λty0y_t = \lambda^t y_0 in first 46 years.

We first experiment with λ=1.05\lambda = 1.05

# Geometric earner parameters where λ = 1.05
λ = 1.05
y_0 = 1
t_max = 46

# Generate geometric y sequence
geo_seq = λ ** np.arange(t_max) * y_0 
y_seq_geo = np.concatenate(
            [geo_seq, np.zeros(20)])

plot_cs(cs_model, a0, y_seq_geo)
<Figure size 1200x500 with 2 Axes>

Now we show the behavior when λ=0.95\lambda = 0.95

λ = 0.95

geo_seq = λ ** np.arange(t_max) * y_0 
y_seq_geo = np.concatenate(
            [geo_seq, np.zeros(20)])

plot_cs(cs_model, a0, y_seq_geo)
<Figure size 1200x500 with 2 Axes>

What happens when λ is negative

λ = -0.95

geo_seq = λ ** np.arange(t_max) * y_0 + 1
y_seq_geo = np.concatenate(
            [geo_seq, np.ones(20)])

plot_cs(cs_model, a0, y_seq_geo)
<Figure size 1200x500 with 2 Axes>

12.4.5Feasible consumption variations

We promised to justify our claim that when βR=1\beta R =1 as Friedman assumed, a constant consumption play ct=c0c_t = c_0 for all tt is optimal.

Let’s do that now.

The approach we’ll take is an elementary example of the “calculus of variations”.

Let’s dive in and see what the key idea is.

To explore what types of consumption paths are welfare-improving, we shall create an admissible consumption path variation sequence {vt}t=0T\{v_t\}_{t=0}^T that satisfies

t=0TRtvt=0\sum_{t=0}^T R^{-t} v_t = 0

This equation says that the present value of admissible consumption path variations must be zero.

So once again, we encounter a formula for the present value of an “asset”:

  • we require that the present value of consumption path variations be zero.

Here we’ll restrict ourselves to a two-parameter class of admissible consumption path variations of the form

vt=ξ1ϕtξ0v_t = \xi_1 \phi^t - \xi_0

We say two and not three-parameter class because ξ0\xi_0 will be a function of (ϕ,ξ1;R)(\phi, \xi_1; R) that guarantees that the variation sequence is feasible.

Let’s compute that function.

We require

t=0TRt[ξ1ϕtξ0]=0\sum_{t=0}^T R^{-t}\left[ \xi_1 \phi^t - \xi_0 \right] = 0

which implies that

ξ1t=0TϕtRtξ0t=0TRt=0\xi_1 \sum_{t=0}^T \phi_t R^{-t} - \xi_0 \sum_{t=0}^T R^{-t} = 0

which implies that

ξ11(ϕR1)T+11ϕR1ξ01R(T+1)1R1=0\xi_1 \frac{1 - (\phi R^{-1})^{T+1}}{1 - \phi R^{-1}} - \xi_0 \frac{1 - R^{-(T+1)}}{1-R^{-1} } =0

which implies that

ξ0=ξ0(ϕ,ξ1;R)=ξ1(1R11R(T+1))(1(ϕR1)T+11ϕR1)\xi_0 = \xi_0(\phi, \xi_1; R) = \xi_1 \left(\frac{1 - R^{-1}}{1 - R^{-(T+1)}}\right) \left(\frac{1 - (\phi R^{-1})^{T+1}}{1 - \phi R^{-1}}\right)

This is our formula for ξ0\xi_0.

Key Idea: if coc^o is a budget-feasible consumption path, then so is co+vc^o + v, where vv is a budget-feasible variation.

Given RR, we thus have a two parameter class of budget feasible variations vv that we can use to compute alternative consumption paths, then evaluate their welfare.

Now let’s compute and plot consumption path variations

def compute_variation(model, ξ1, ϕ, a0, y_seq, verbose=1):
    R, T, β_seq = model.R, model.T, model.β_seq

    ξ0 = ξ1*((1 - 1/R) / (1 - (1/R)**(T+1))) * ((1 - (ϕ/R)**(T+1)) / (1 - ϕ/R))
    v_seq = np.array([(ξ1*ϕ**t - ξ0) for t in range(T+1)])
    
    if verbose == 1:
        print('check feasible:', np.isclose(β_seq @ v_seq, 0))     # since β = 1/R

    c_opt, _, _ = compute_optimal(model, a0, y_seq)
    cvar_seq = c_opt + v_seq

    return cvar_seq

We visualize variations for ξ1{.01,.05}\xi_1 \in \{.01, .05\} and ϕ{.95,1.02}\phi \in \{.95, 1.02\}

fig, ax = plt.subplots()

ξ1s = [.01, .05]
ϕs= [.95, 1.02]
colors = {.01: 'tab:blue', .05: 'tab:green'}

params = np.array(np.meshgrid(ξ1s, ϕs)).T.reshape(-1, 2)

for i, param in enumerate(params):
    ξ1, ϕ = param
    print(f'variation {i}: ξ1={ξ1}, ϕ={ϕ}')
    cvar_seq = compute_variation(model=cs_model, 
                                 ξ1=ξ1, ϕ=ϕ, a0=a0, 
                                 y_seq=y_seq)
    print(f'welfare={welfare(cs_model, cvar_seq)}')
    print('-'*64)
    if i % 2 == 0:
        ls = '-.'
    else: 
        ls = '-'  
    ax.plot(range(T+1), cvar_seq, ls=ls, 
            color=colors[ξ1], 
            label=fr'$\xi_1 = {ξ1}, \phi = {ϕ}$')

plt.plot(range(T+1), c_seq, 
         color='orange', label=r'Optimal $\vec{c}$ ')

plt.legend()
plt.xlabel(r'$t$')
plt.ylabel(r'$c_t$')
plt.show()
variation 0: ξ1=0.01, ϕ=0.95
check feasible: True
welfare=13.285009346064834
----------------------------------------------------------------
variation 1: ξ1=0.01, ϕ=1.02
check feasible: True
welfare=13.284911631015438
----------------------------------------------------------------
variation 2: ξ1=0.05, ϕ=0.95
check feasible: True
welfare=13.284010559218512
----------------------------------------------------------------
variation 3: ξ1=0.05, ϕ=1.02
check feasible: True
welfare=13.281567682983608
----------------------------------------------------------------
<Figure size 640x480 with 1 Axes>

We can even use the Python np.gradient command to compute derivatives of welfare with respect to our two parameters.

(We are actually discovering the key idea beneath the calculus of variations.)

First, we define the welfare with respect to ξ1\xi_1 and ϕ

def welfare_rel(ξ1, ϕ):
    """
    Compute welfare of variation sequence 
    for given ϕ, ξ1 with a consumption-smoothing model
    """
    
    cvar_seq = compute_variation(cs_model, ξ1=ξ1, 
                                 ϕ=ϕ, a0=a0, 
                                 y_seq=y_seq, 
                                 verbose=0)
    return welfare(cs_model, cvar_seq)

# Vectorize the function to allow array input
welfare_vec = np.vectorize(welfare_rel)

Then we can visualize the relationship between welfare and ξ1\xi_1 and compute its derivatives

ξ1_arr = np.linspace(-0.5, 0.5, 20)

plt.plot(ξ1_arr, welfare_vec(ξ1_arr, 1.02))
plt.ylabel('welfare')
plt.xlabel(r'$\xi_1$')
plt.show()

welfare_grad = welfare_vec(ξ1_arr, 1.02)
welfare_grad = np.gradient(welfare_grad)
plt.plot(ξ1_arr, welfare_grad)
plt.ylabel('derivative of welfare')
plt.xlabel(r'$\xi_1$')
plt.show()
<Figure size 640x480 with 1 Axes><Figure size 640x480 with 1 Axes>

The same can be done on ϕ

ϕ_arr = np.linspace(-0.5, 0.5, 20)

plt.plot(ξ1_arr, welfare_vec(0.05, ϕ_arr))
plt.ylabel('welfare')
plt.xlabel(r'$\phi$')
plt.show()

welfare_grad = welfare_vec(0.05, ϕ_arr)
welfare_grad = np.gradient(welfare_grad)
plt.plot(ξ1_arr, welfare_grad)
plt.ylabel('derivative of welfare')
plt.xlabel(r'$\phi$')
plt.show()
<Figure size 640x480 with 1 Axes><Figure size 640x480 with 1 Axes>

12.5Wrapping up the consumption-smoothing model

The consumption-smoothing model of Milton Friedman Friedman (1956) and Robert Hall Hall (1978)) is a cornerstone of modern economics that has important ramifications for the size of the Keynesian “fiscal policy multiplier” that we described in QuantEcon lecture geometric series.

The consumption-smoothingmodel lowers the government expenditure multiplier relative to one implied by the original Keynesian consumption function presented in geometric series.

Friedman’s work opened the door to an enlightening literature on the aggregate consumption function and associated government expenditure multipliers that remains active today.

12.6Appendix: solving difference equations with linear algebra

In the preceding sections we have used linear algebra to solve a consumption-smoothing model.

The same tools from linear algebra -- matrix multiplication and matrix inversion -- can be used to study many other dynamic models.

We’ll conclude this lecture by giving a couple of examples.

We’ll describe a useful way of representing and “solving” linear difference equations.

To generate some yy vectors, we’ll just write down a linear difference equation with appropriate initial conditions and then use linear algebra to solve it.

12.6.1First-order difference equation

We’ll start with a first-order linear difference equation for {yt}t=0T\{y_t\}_{t=0}^T:

yt=λyt1,t=1,2,,Ty_{t} = \lambda y_{t-1}, \quad t = 1, 2, \ldots, T

where y0y_0 is a given initial condition.

We can cast this set of TT equations as a single matrix equation

[10000λ10000λ100000λ1][y1y2y3yT]=[λy0000]\begin{bmatrix} 1 & 0 & 0 & \cdots & 0 & 0 \cr -\lambda & 1 & 0 & \cdots & 0 & 0 \cr 0 & -\lambda & 1 & \cdots & 0 & 0 \cr \vdots & \vdots & \vdots & \cdots & \vdots & \vdots \cr 0 & 0 & 0 & \cdots & -\lambda & 1 \end{bmatrix} \begin{bmatrix} y_1 \cr y_2 \cr y_3 \cr \vdots \cr y_T \end{bmatrix} = \begin{bmatrix} \lambda y_0 \cr 0 \cr 0 \cr \vdots \cr 0 \end{bmatrix}

Multiplying both sides of (20) by the inverse of the matrix on the left provides the solution

[y1y2y3yT]=[10000λ1000λ2λ100λT1λT2λT3λ1][λy0000]\begin{bmatrix} y_1 \cr y_2 \cr y_3 \cr \vdots \cr y_T \end{bmatrix} = \begin{bmatrix} 1 & 0 & 0 & \cdots & 0 & 0 \cr \lambda & 1 & 0 & \cdots & 0 & 0 \cr \lambda^2 & \lambda & 1 & \cdots & 0 & 0 \cr \vdots & \vdots & \vdots & \cdots & \vdots & \vdots \cr \lambda^{T-1} & \lambda^{T-2} & \lambda^{T-3} & \cdots & \lambda & 1 \end{bmatrix} \begin{bmatrix} \lambda y_0 \cr 0 \cr 0 \cr \vdots \cr 0 \end{bmatrix}

12.6.2Second-order difference equation

A second-order linear difference equation for {yt}t=0T\{y_t\}_{t=0}^T is

yt=λ1yt1+λ2yt2,t=1,2,,Ty_{t} = \lambda_1 y_{t-1} + \lambda_2 y_{t-2}, \quad t = 1, 2, \ldots, T

where now y0y_0 and y1y_{-1} are two given initial equations determined outside the model.

As we did with the first-order difference equation, we can cast this set of TT equations as a single matrix equation

[100000λ110000λ2λ11000000λ2λ11][y1y2y3yT]=[λ1y0+λ2y1λ2y000]\begin{bmatrix} 1 & 0 & 0 & \cdots & 0 & 0 & 0 \cr -\lambda_1 & 1 & 0 & \cdots & 0 & 0 & 0 \cr -\lambda_2 & -\lambda_1 & 1 & \cdots & 0 & 0 & 0 \cr \vdots & \vdots & \vdots & \cdots & \vdots & \vdots \cr 0 & 0 & 0 & \cdots & -\lambda_2 & -\lambda_1 & 1 \end{bmatrix} \begin{bmatrix} y_1 \cr y_2 \cr y_3 \cr \vdots \cr y_T \end{bmatrix} = \begin{bmatrix} \lambda_1 y_0 + \lambda_2 y_{-1} \cr \lambda_2 y_0 \cr 0 \cr \vdots \cr 0 \end{bmatrix}

Multiplying both sides by inverse of the matrix on the left again provides the solution.

References
  1. Friedman, M. (1956). A Theory of the Consumption Function. Princeton University Press.
  2. Hall, R. E. (1978). Stochastic Implications of the Life Cycle-Permanent Income Hypothesis: Theory and Evidence. Journal of Political Economy, 86(6), 971–987.
  3. Kuznets, S., & Friedman, M. (1939). Incomes from independent professional practice, 1929-1936. National Bureau of Economic Research Bulletin, 72–23.
  4. Friedman, M., & Kuznets, S. (1945). Income from Independent Professional Practice. National Bureau of Economic Research.
CC-BY-SA-4.0

Creative Commons License – This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International.