English · Português

Replications

Each entry takes a paper and the calibration it publishes, and the code on this page checks a number from it. When the solved system does not reproduce something in the paper, the page says so next to the number.

dsgelab

What counts as a replication

A replication here uses the paper's equations and calibration and compares the result with a published number or a closed-form solution. Each block is executed by tools/check_site_examples.py.

Dynare's teaching examples (Collard, Pfeifer) are in the validation table on the package page. They are tutorial files, and the comparison there is against Dynare's solution, variable by variable.

Heutel (2012), Review of Economic Dynamics

Garth Heutel, How should environmental policy respond to business cycles? Optimal policy under persistent productivity shocks, Review of Economic Dynamics 15, 244–264, 10.1016/j.red.2011.05.002. The port is in dsgelab.examples.heutel and in docs/heutel.md. The solved system is the linear one in the author's MATLAB code, with the package's Klein/QZ in the place of Anderson–Moore. The nonlinear model, which would allow second order and perfect foresight, is not in this example.

Table 2 and the 1% impulse

Table 2, p. 251, gives α = 0.36, β = 0.98267, δ = 0.025, ρ = 0.95, σε = 0.007, η = 0.9979, θ₁ = 0.05607, θ₂ = 2.8 and 1 − γ = 0.696. The text on p. 250 prints β = 0.98627, and the example follows the table and the scripts. Section 4.1 simulates a 1% innovation and, in two consecutive sentences, describes consumption peaking around period 15 and capital peaking “around period 40 (year 6)”. In a quarterly model the sixth year corresponds to horizon 24. The solved series reaches its capital peak at horizon 25 and its consumption peak at 15. This system does not produce a peak at period 40, and the example does not shift the series to match it.

The scalar algebra of the port is translated from Heutel's MATLAB files, which carry no licence, so the package does not distribute it. Running heutel.fetch() once downloads the public copy from Georgia State University's repository, checks each file against the SHA-256 of the files the port was validated on, and writes the translation to a cache directory.

import numpy as np
from dsgelab.examples import heutel

heutel.fetch()    # once per machine: download, check and translate Heutel's files
p = heutel.Params()
assert p.alpha == 0.36 and p.beta == 0.98267 and p.delta == 0.025
assert p.rho == 0.95 and p.sd == 0.007 and p.eta == 0.9979
assert p.theta1 == 0.05607 and p.theta2 == 2.8
assert abs((1 - p.gamma) - 0.696) < 1e-12

ss = heutel.steady_levels("tax", p)
assert abs(ss["lambda"]) < 1e-10          # Ramsey multiplier at the steady state
assert 0 < ss["mu"] < 1 and ss["c"] > 0 and ss["e"] > 0

sol = heutel.solve("tax", p)
irf = sol.irf("eps_a", size=0.01, periods=100, percent=False)
assert np.max(np.abs(irf["a"] - 0.01 * p.rho ** np.arange(100))) < 1e-12
gap = ss["c"]*irf["c"] + ss["i"]*irf["i"] + ss["z"]*irf["z"] - ss["y"]*irf["y"]
assert np.max(np.abs(gap)) < 1e-10        # resources along the impulse
assert int(np.argmax(irf["c"])) == 15
assert int(np.argmax(irf["k"])) == 25
print(ss["k"], ss["y"], ss["mu"], int(np.argmax(irf["k"])))

Lagged information, p. 262

When the government chooses the instrument before it observes the state, the paper replaces the first-order condition with τt = d · yt−1 and qt = d · yt−1. The paper publishes d = 1.415 for the tax and 0.658 for the quota, and the scripts have 1.4151 and 0.6580. Because lagged output is still at the steady state in the period of the shock, the instrument does not move in that period.

tax = heutel.Params.source("tax_asym")
quota = heutel.Params.source("quota_asym")
assert round(tax.policy_slope, 3) == 1.415
assert round(quota.policy_slope, 3) == 0.658

irf_tax = heutel.solve("tax_asym", tax).irf("eps_a", size=0.01, periods=100, percent=False)
assert abs(irf_tax["tau"][0]) < 1e-10
assert np.max(np.abs(irf_tax["tau"][1:] - tax.policy_slope * irf_tax["y"][:-1])) < 1e-10

irf_q = heutel.solve("quota_asym", quota).irf("eps_a", size=0.01, periods=100, percent=False)
assert abs(irf_q["q"][0]) < 1e-10
assert np.max(np.abs(irf_q["q"][1:] - quota.policy_slope * irf_q["y"][:-1])) < 1e-10
assert np.max(np.abs(irf_q["e"] - irf_q["q"])) < 1e-10
print(tax.policy_slope, quota.policy_slope)

The planner's literal calibration in the scripts, θ₂ = 0.1 and γ = 0.8, is the sensitivity case of p. 258, and it does not produce an admissible steady state, so heutel.solve("planner") raises heutel.SteadyStateError, which is defined in dsgelab.examples.heutel and differs from dsgelab.SteadyStateError. For the Table 2 baseline, call heutel.solve("planner", heutel.Params()).

Stochastic growth with a closed-form solution

Brock and Mirman (1972, Journal of Economic Theory) set up optimal growth under uncertainty. With log utility and full depreciation the one-sector rule is exact, k′ = αβ a kα, and the log-linear solution is P = [[α, 1], [0, ρ]], F = [α, 1]. Long and Plosser (1983, Journal of Political Economy) wrote the multisector version, with the same utility and the same depreciation, and the example is the one-sector case.

For the process log a′ = ρ log a + ε, the second-order coefficient on technology, hσσ, equals σ², and the correction it adds to the rule, σ²/2, is the Jensen term that the approximation of Schmitt-Grohé and Uribe (2004, Journal of Economic Dynamics and Control) must return. Because capital follows the exact rule in every state, its coefficient is zero. The numerical tables of that paper belong to a different model.

import numpy as np
import dsgelab as dsg
from dsgelab.examples import rbc

model, params, guess = rbc.build()
sol = dsg.solve(model, params, guess=guess)
exact = rbc.closed_form(params)
assert np.allclose(sol.P, exact["P"]) and np.allclose(sol.F, exact["F"])

sigma = 0.007
so = dsg.solve_second_order(sol, cov={"eps_a": sigma})
i_a = model.states.index("a")
i_k = model.states.index("k")
assert abs(so.h_ss[i_a] - sigma ** 2) < 1e-8
assert abs(so.h_ss[i_k]) < 1e-8
print(sol.P, so.h_ss[i_a])

Taylor principle

Clarida, Galí and Gertler (2000, Quarterly Journal of Economics 115, 147–180) show that, under a forward-looking interest-rate rule, a determinate equilibrium requires the response to expected inflation to exceed one. The example uses a contemporaneous version of the rule, i = φπ π + φx x, in the three-equation model with φπ = 1.5, φx = 0.125 and β = 0.99, for which the equilibrium is determinate. With φπ = 0.8 the same system is rejected with BlanchardKahnError. In this version a positive φx puts the boundary slightly below 1, at about 0.9875, and 0.8 lies on the indeterminate side of it. The check is on this threshold, and the paper's table of estimated coefficients is not reproduced.

from dataclasses import replace
import dsgelab as dsg
from dsgelab.examples import nk

model, params, guess = nk.build()
assert params.phi_pi == 1.5 and params.phi_x == 0.125 and params.beta == 0.99
sol_nk = dsg.solve(model, params, guess=guess)
assert sol_nk.klein.n_stable == model.n_states

below = replace(params, phi_pi=0.8)
try:
    dsg.solve(model, below, guess=guess)
    raised = False
except dsg.BlanchardKahnError:
    raised = True
assert raised
print(sol_nk.klein.n_stable, raised)

Not on this page

PaperWhy it is not here
Smets and Wouters (2007), American Economic Review The package has the likelihood, the Kalman filter and Bayesian estimation, and the replication has not been done yet.
Schmitt-Grohé and Uribe (2003), small open economy The model is not in the package yet. The 2004 paper appears on this page only through the σ² term of the lognormal AR(1).