How to read this lecture...

Code should execute sequentially if run in a Jupyter notebook

Uncertainty Traps

Overview

In this lecture we study a simplified version of an uncertainty traps model of Fajgelbaum, Schaal and Taschereau-Dumouchel [FSTD15]

The model features self-reinforcing uncertainty that has big impacts on economic activity

In the model,

  • Fundamentals vary stochastically and are not fully observable
  • At any moment there are both active and inactive entrepreneurs; only active entrepreneurs produce
  • Agents – active and inactive entrepreuneurs – have beliefs about the fundamentals expressed as probability distributions
  • Greater uncertainty means greater dispersions of these distributions
  • Entrepreneurs are risk averse and hence less inclined to be active when uncertainty is high
  • The output of active entrepreneurs is observable, supplying a noisy signal that helps everyone inside the model infer fundamentals
  • Entrepreneurs update their beliefs about fundamentals using Bayes’ Law, implemented via Kalman filtering

Uncertainty traps emerge because:

  • High uncertainty discourages entrepreneurs from becoming active
  • A low level of participation – i.e., a smaller number of active entrepreneurs – diminishes the flow of information about fundamentals
  • Less information translates to higher uncertainty, further discouraging entrepreneurs from choosing to be active, and so on

Uncertainty traps stem from a positive externality: high aggregate economic activity levels generates valuable information

The Model

The original model described in [FSTD15] has many interesting moving parts

Here we examine a simplified version that nonetheless captures many of the key ideas

Fundamentals

The evolution of the fundamental process \(\{\theta_t\}\) is given by

\[\theta_{t+1} = \rho \theta_t + \sigma_{\theta} w_{t+1}\]

where

  • \(\sigma_\theta > 0\) and \(0 < \rho < 1\)
  • \(\{w_t\}\) is IID and standard normal

The random variable \(\theta_t\) is not observable at any time

Output

There is a total \(\bar M\) of risk averse entrepreneurs

Output of the \(m\)-th entrepreneur, conditional on being active in the market at time \(t\), is equal to

(1)\[x_m = \theta + \epsilon_m \quad \text{where} \quad \epsilon_m \sim N \left(0, \gamma_x^{-1} \right)\]

Here the time subscript has been dropped to simplify notation

The inverse of the shock variance, \(\gamma_x\), is called the shock’s precision

The higher is the precision, the more informative \(x_m\) is about the fundamental

Output shocks are independent across time and firms

Information and Beliefs

All entrepreneurs start with identical beliefs about \(\theta_0\)

Signals are publicly observable and hence all agents have identical beliefs always

Dropping time subscripts, beliefs for current \(\theta\) are represented by the normal distribution \(N(\mu, \gamma^{-1})\)

Here \(\gamma\) is the precision of beliefs; its inverse is the degree of uncertainty

These parameters are updated by Kalman filtering

Let

  • \(\mathbb M \subset \{1, \ldots, \bar M\}\) denote the set of currently active firms
  • \(M := |\mathbb M|\) denote the number of currently active firms
  • \(X\) be the average output \(\frac{1}{M} \sum_{m \in \mathbb M} x_m\) of the active firms

With this notation and primes for next period values, we can write the updating of the mean and precision via

(2)\[\mu' = \rho \frac{\gamma \mu + M \gamma_x X}{\gamma + M \gamma_x}\]
(3)\[\gamma' = \left( \frac{\rho^2}{\gamma + M \gamma_x} + \sigma_\theta^2 \right)^{-1}\]

These are standard Kalman filtering results applied to the current setting

Exercise 1 provides more details on how (2) and (3) are derived, and then asks you to fill in remaining steps

The next figure plots the law of motion for the precision in (3) as a 45 degree diagram, with one curve for each \(M \in \{0, \ldots, 6\}\)

The other parameter values are \(\rho = 0.99, \gamma_x = 0.5, \sigma_\theta =0.5\)

../_images/uncertainty_traps_45.png

Points where the curves hit the 45 degree lines are long run steady states for precision for different values of \(M\)

Thus, if one of these values for \(M\) remains fixed, a corresponding steady state is the equilibrium level of precision

  • high values of \(M\) correspond to greater information about the fundamental, and hence more precision in steady state
  • low values of \(M\) correspond to less information and more uncertainty in steady state

In practice, as we’ll see, the number of active firms fluctuates stochastically

Participation

Omitting time subscripts once more, entrepreneurs enter the market in the current period if

(4)\[\mathbb E [ u(x_m - F_m) ] > c\]

Here

  • the mathematical expectation of \(x_m\) is based on (1) and beliefs \(N(\mu, \gamma^{-1})\) for \(\theta\)
  • \(F_m\) is a stochastic but previsible fixed cost, independent across time and firms
  • \(c\) is a constant reflecting opportunity costs

The statement that \(F_m\) is previsible means that it is realized at the start of the period and treated as a constant in (4)

The utility function has the constant absolute risk aversion form

(5)\[u(x) = \frac{1}{a} \left(1 - \exp(-a x) \right)\]

where \(a\) is a positive parameter

Combining (4) and (5), entrepreneur \(m\) participates in the market (or is said to be active) when

\[\frac{1}{a} \left\{ 1 - \mathbb E [ \exp \left( -a (\theta + \epsilon_m - F_m) \right) ] \right\} > c\]

Using standard formulas for expectations of lognormal random variables, this is equivalent to the condition

(6)\[\psi(\mu, \gamma, F_m) := \frac{1}{a} \left( 1 - \exp \left( -a \mu + a F_m + \frac{a^2 \left( \frac{1}{\gamma} + \frac{1}{\gamma_x} \right)}{2} \right) \right) - c > 0\]

Implementation

We want to simulate this economy

As a first step, let’s put together a class that bundles

  • the parameters, the current value of \(\theta\) and the current values of the two belief parameters \(\mu\) and \(\gamma\)
  • methods to update \(\theta\), \(\mu\) and \(\gamma\), as well as to determine the number of active firms and their outputs

The updating methods follow the laws of motion for \(\theta\), \(\mu\) and \(\gamma\) given above

The method to evaluate the number of active firms generates \(F_1, \ldots, F_{\bar M}\) and tests condition (6) for each firm

The function UncertaintyTrapEcon encodes as default values the parameters we’ll use in the simulations below

Here’s the code, which can be obtained from GitHub

type UncertaintyTrapEcon
    a::Float64          # Risk aversion
    gx::Float64         # Production shock precision
    rho::Float64        # Correlation coefficient for theta
    sig_theta::Float64  # Std dev of theta shock
    num_firms::Int      # Number of firms
    sig_F::Float64      # Std dev of fixed costs
    c::Float64          # External opportunity cost
    mu::Float64         # Initial value for mu
    gamma::Float64      # Initial value for gamma
    theta::Float64      # Initial value for theta
    sd_x::Float64       # standard deviation of shock
end

function UncertaintyTrapEcon(;a::Real=1.5, gx::Real=0.5, rho::Real=0.99,
                             sig_theta::Real=0.5, num_firms::Int=100,
                             sig_F::Real=1.5, c::Real=-420, mu_init::Real=0,
                             gamma_init::Real=4 , theta_init::Real=0)
    sd_x = sqrt(a/gx)
    UncertaintyTrapEcon(a, gx, rho, sig_theta, num_firms, sig_F, c, mu_init,
                        gamma_init, theta_init, sd_x)

end

function psi(uc::UncertaintyTrapEcon, F)
    temp1 = -uc.a * (uc.mu - F)
    temp2 = 0.5 * uc.a^2 * (1/uc.gamma + 1/uc.gx)
    return (1/uc.a) * (1 - exp(temp1 + temp2)) - uc.c
end

"""
Update beliefs (mu, gamma) based on aggregates X and M.
"""
function update_beliefs!(uc::UncertaintyTrapEcon, X, M)
    # Simplify names
    gx, rho, sig_theta = uc.gx, uc.rho, uc.sig_theta

    # Update mu
    temp1 = rho * (uc.gamma*uc.mu + M*gx*X)
    temp2 = uc.gamma + M*gx
    uc.mu =  temp1 / temp2

    # Update gamma
    uc.gamma = 1 / (rho^2 / (uc.gamma + M * gx) + sig_theta^2)
end

update_theta!(uc::UncertaintyTrapEcon, w) =
    (uc.theta = uc.rho*uc.theta + uc.sig_theta*w)

"""
Generate aggregates based on current beliefs (mu, gamma).  This
is a simulation step that depends on the draws for F.
"""
function gen_aggregates(uc::UncertaintyTrapEcon)
    F_vals = uc.sig_F * randn(uc.num_firms)

    M = sum(psi(uc, F_vals) .> 0)::Int  # Counts number of active firms
    if M > 0
        x_vals = uc.theta + uc.sd_x * randn(M)
        X = mean(x_vals)
    else
        X = 0.0
    end
    return X, M
end

In the results below we use this code to simulate time series for the major variables

Results

Let’s look first at the dynamics of \(\mu\), which the agents use to track \(\theta\)

../_images/uncertainty_traps_mu.png

We see that \(\mu\) tracks \(\theta\) well when there are sufficient firms in the market

However, there are times when \(\mu\) tracks \(\theta\) poorly due to insufficient information

These are episodes where the uncertainty traps take hold

During these episodes

  • precision is low and uncertainty is high
  • few firms are in the market

To get a clearer idea of the dynamics, let’s look at all the main time series at once, for a given set of shocks

../_images/uncertainty_traps_sim.png

Notice how the traps only take hold after a sequence of bad draws for the fundamental

Thus, the model gives us a propagation mechanism that maps bad random draws into long downturns in economic activity

Exercises

Exercise 1

Fill in the details behind (2) and (3) based on the following standard result (see, e.g., p. 24 of [YS05])

Fact Let \(\mathbf x = (x_1, \ldots, x_M)\) be a vector of IID draws from common distribution \(N(\theta, 1/\gamma_x)\) and let \(\bar x\) be the sample mean. If \(\gamma_x\) is known and the prior for \(\theta\) is \(N(\mu, 1/\gamma)\), then the posterior distribution of \(\theta\) given \(\mathbf x\) is

\[\pi(\theta \,|\, \mathbf x) = N(\mu_0, 1/\gamma_0)\]

where

\[\mu_0 = \frac{\mu \gamma + M \bar x \gamma_x}{\gamma + M \gamma_x} \quad \text{and} \quad \gamma_0 = \gamma + M \gamma_x\]

Exercise 2

Modulo randomness, replicate the simulation figures shown above

  • Use the parameter values listed as defaults in the function UncertaintyTrapEcon

Solutions

Exercise 1

This exercise asked you to validate the laws of motion for \(\gamma\) and \(\mu\) given in the lecture, based on the stated result about Bayesian updating in a scalar Gaussian setting. The stated result tells us that after observing average output \(X\) of the \(M\) firms, our posterior beliefs will be

\[N(\mu_0, 1/\gamma_0)\]

where

\[\mu_0 = \frac{\mu \gamma + M X \gamma_x}{\gamma + M \gamma_x} \quad \text{and} \quad \gamma_0 = \gamma + M \gamma_x\]

If we take a random variable \(\theta\) with this distribution and then evaluate the distribution of \(\rho \theta + \sigma_\theta w\) where \(w\) is independent and standard normal, we get the expressions for \(\mu'\) and \(\gamma'\) given in the lecture.

Exercise 2

First let’s replicate the plot that illustrates the law of motion for precision, which is

\[\gamma_{t+1} = \left( \frac{\rho^2}{\gamma_t + M \gamma_x} + \sigma_\theta^2 \right)^{-1}\]

Here \(M\) is the number of active firms. The next figure plots \(\gamma_{t+1}\) against \(\gamma_t\) on a 45 degree diagram for different values of \(M\)

using QuantEcon
using Gadfly, DataFrames, LaTeXStrings
econ = UncertaintyTrapEcon()
rho, sig_theta, gx = econ.rho, econ.sig_theta, econ.gx # simplify names

# grid for gamma and gamma_{t+1}
γ = linspace(1e-10, 3, 200)
M_range = 0:6
γp = 1 ./ (rho^2 ./ (γ .+ gx.*M_range') + sig_theta^2)

p1=plot(x=repeat(collect(γ), outer=[length(M_range)+1]),
     y=vec([γ γp]),
     color=repeat(["45 Degree"; map(string, M_range)], inner=[length(γ)]),
     Geom.line, Guide.colorkey("M"), Guide.xlabel("Gamma"), Guide.ylabel("Gamma'"))
../_images/uncertainty_traps_solutions_ex2_1_jl.png

The points where the curves hit the 45 degree lines are the long run steady states corresponding to each \(M\), if that value of \(M\) was to remain fixed. As the number of firms falls, so does the long run steady state of precision.

Next let’s generate time series for beliefs and the aggregates – that is, the number of active firms and average output.

function QuantEcon.simulate(uc::UncertaintyTrapEcon, capT::Int=2000)
    # allocate memory
    μ_vec = Array{Float64}(capT)
    θ_vec = Array{Float64}(capT)
    γ_vec = Array{Float64}(capT)
    X_vec = Array{Float64}(capT)
    M_vec = Array{Int}(capT)

    # set initial using fields from object
    μ_vec[1] = uc.mu
    γ_vec[1] = uc.gamma
    θ_vec[1] = 0

    # draw standard normal shocks
    w_shocks = randn(capT)

    for t=1:capT-1
        X, M = gen_aggregates(uc)
        X_vec[t] = X
        M_vec[t] = M

        update_beliefs!(uc, X, M)
        update_theta!(uc, w_shocks[t])

        μ_vec[t+1] = uc.mu
        γ_vec[t+1] = uc.gamma
        θ_vec[t+1] = uc.theta
    end

    # Record final values of aggregates
    X, M = gen_aggregates(uc)
    X_vec[end] = X
    M_vec[end] = M

    return μ_vec, γ_vec, θ_vec, X_vec, M_vec
end

First let’s see how well \(\mu\) tracks \(\theta\) in these simulations

srand(42)  # set random seed for reproducible results
μ_vec, γ_vec, θ_vec, X_vec, M_vec = simulate(econ)

p2=plot(x=repeat(collect(1:length(μ_vec)), outer=[2]),
     y=[μ_vec; θ_vec],
     color=repeat(["Mu", "Theta"], inner=[length(μ_vec)]),
     Geom.line, Guide.colorkey("Variable"))
../_images/uncertainty_traps_solutions_ex2_2_jl.png

Now let’s plot the whole thing together

mdf = DataFrame(t=1:length(θ_vec), θ=θ_vec, μ=μ_vec, γ=γ_vec, M=M_vec)
p3=plot(stack(mdf, collect(2:5)), x="t",
     ygroup="variable",
     y="value",
     Geom.subplot_grid(Geom.line, free_y_axis=true))
../_images/uncertainty_traps_solutions_ex2_3_jl.png