Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Today we code the stochastic consumption-savings model of Class 15, compare ways to compute the expectation over income, and solve the model three ways: value function iterations with a discretized choice, value function iterations with a continuous choice, and time iterations on the Euler equation. Then we measure what each solver buys, in accuracy and in time, with two checks that apply to any solution method.

The model objectΒΆ

The model of Deaton (1991), from Class 15:

V(M)=max⁑0β©½cβ©½M{log⁑(c)+β Ey V(R(Mβˆ’c)+y~)},log⁑y~∼N(0,Οƒ2)V(M) = \max_{0 \leqslant c \leqslant M} \Big\{ \log(c) + \beta\, \mathbb{E}_{y}\, V\big(R(M - c) + \tilde{y}\big) \Big\}, \qquad \log\tilde{y} \sim N(0, \sigma^2)

The model object holds the parameters, the state grid on (0,Mβ€Ύ](0, \overline{M}], the choice grid as shares of wealth, the quadrature nodes and weights for the income, and the primitives: utility and the budget constraint. Every solver below is a function of this object.

The last row of the grid is a linear extrapolation: with random income, next period wealth can exceed Mβ€Ύ\overline{M}, and np.interp would silently hold the function constant there.

Computing expectationsΒΆ

Income is log-normal, log⁑y~∼N(0,Οƒ2)\log\tilde{y} \sim N(0, \sigma^2), so y~>0\tilde{y} > 0 and Ey~=exp⁑(Οƒ2/2)\mathbb{E}\tilde{y} = \exp(\sigma^2/2). The expectation in the Bellman equation is an integral, and it has to be computed at every state and every choice on every iteration, so the method matters. There are two families: quadrature, a weighted sum over fixed nodes, and Monte Carlo integration, an average over random draws.

EyV(RA+y~)=∫V(RA+y) dF(y)β‰ˆβˆ‘k=1KΟ‰k V(RA+yk)\mathbb{E}_y V(RA + \tilde y) = \int V(RA + y)\, dF(y) \approx \sum_{k=1}^{K} \omega_k\, V(RA + y_k)

Newton–Cotes rules approximate the integrand on equally spaced nodes by a polynomial, and integrate the polynomial. With nodes spaced hh apart on [a,b][a,b], the composite trapezoid rule, linear pieces between neighboring nodes, and Simpson’s rule, quadratic pieces over pairs of intervals, have errors

βˆ’(bβˆ’a) h212fβ€²β€²(ΞΎ)andβˆ’(bβˆ’a) h4180f(4)(ΞΎ)-\frac{(b-a)\,h^2}{12} f''(\xi) \qquad\text{and}\qquad -\frac{(b-a)\,h^4}{180} f^{(4)}(\xi)

for some ξ∈[a,b]\xi \in [a,b]: the same rates as linear and cubic splines, and for the same reason.

Gaussian quadrature chooses the nodes as well as the weights, which doubles the degree of polynomials it integrates exactly. The nodes come from orthogonal polynomials.

Each weight function gives a family of rules, with nodes and weights tabulated in numpy.polynomial:

For our log-normal income, Gauss–Hermite fits exactly. With y~=eΟƒZ\tilde y = e^{\sigma Z}, Z∼N(0,1)Z \sim N(0,1), and the change of variable z=2 xz = \sqrt{2}\,x,

E g(y~)=1Ο€βˆ«βˆ’βˆžβˆžg(e2Οƒx) eβˆ’x2dxβ‰ˆβˆ‘i=1nΟ‰iπ g(e2Οƒxi)\mathbb{E}\, g(\tilde y) = \frac{1}{\sqrt{\pi}} \int_{-\infty}^{\infty} g\big(e^{\sqrt{2}\sigma x}\big)\, e^{-x^2} dx \approx \sum_{i=1}^{n} \frac{\omega_i}{\sqrt{\pi}}\, g\big(e^{\sqrt{2}\sigma x_i}\big)

with (xi,Ο‰i)(x_i, \omega_i) the Gauss–Hermite nodes and weights.

A second rule works for any distribution with an invertible CDF: change the variable to q=F(y)q = F(y), which is uniform on [0,1][0,1], and apply Gauss–Legendre there, with nodes yk=Fβˆ’1(qk)y_k = F^{-1}(q_k) and the weights rescaled to [0,1][0,1]. It is convenient, but the integrand in qq, g(Fβˆ’1(q))g\big(F^{-1}(q)\big), has unbounded derivatives at q=0q = 0 and q=1q = 1, so the error term of the theorem gives no fast convergence. The model object above uses this rule.

Monte Carlo integration replaces the integral by an average over NN independent draws yiy_i from FF:

E g(y~)β‰ˆ1Nβˆ‘i=1Ng(yi)\mathbb{E}\, g(\tilde y) \approx \frac{1}{N} \sum_{i=1}^{N} g(y_i)

By the law of large numbers the average converges to the expectation, and by the central limit theorem its error is approximately normal with standard deviation Οƒg/N\sigma_g/\sqrt{N}, Οƒg2=Var⁑g(y~)\sigma_g^2 = \operatorname{Var} g(\tilde y), estimated by the sample standard deviation divided by N\sqrt N. The rate 1/N1/\sqrt{N} is slow, four times as many draws for twice the precision, but it does not depend on the dimension of the integral, while the number of nodes of a product quadrature rule grows exponentially with it.

  nodes  Gauss-Hermite  Legendre on CDF   errors in E(1/y)
      3        1.4e-04          2.8e-02
      5        3.4e-08          1.2e-02
     10        2.2e-16          3.7e-03
     20        2.2e-16          1.1e-03
  draws    Monte Carlo   standard error
    100        3.2e-02          5.2e-02
   1000        1.5e-03          2.0e-02
  10000        6.8e-03          6.1e-03
 100000        2.3e-03          1.9e-03

The expectation of 1/y~1/\tilde y is computed to machine precision by Gauss–Hermite with 10 nodes. Gauss–Legendre on the CDF is still off in the third digit with 20 nodes, and Monte Carlo needs about 100 thousand draws to match it. For a one-dimensional expectation inside a solver, where it is evaluated millions of times, a Gaussian rule matched to the distribution is the right tool.

VFI with discretized choiceΒΆ

The discretized solver of Class 15, now with the expectation over income. One application of the Bellman operator works on a three-dimensional array: choices along the first axis, states along the second and quadrature nodes along the third, and the expectation is a product with the weights.

Source
<Figure size 1200x450 with 2 Axes>

The consumer eats all wealth up to a threshold and saves a part of it above. With more income risk the threshold is lower and consumption at low wealth is smaller: the consumer saves for precaution. At high wealth the order flips, because with log⁑y~∼N(0,Οƒ2)\log\tilde y \sim N(0,\sigma^2) a larger Οƒ\sigma also raises mean income exp⁑(Οƒ2/2)\exp(\sigma^2/2), which is also why the value function is higher.

  • Happy with the accuracy of the solution?

  • How would you change the model to vary the risk while keeping mean income fixed?

VFI with continuous choiceΒΆ

The second approach drops the choice grid and solves the maximization in the Bellman equation numerically in every state:

ci(Mj)=arg⁑max⁑0β©½cβ©½Mj{u(c)+Ξ²βˆ‘kΟ‰k V^iβˆ’1(R(Mjβˆ’c)+yk)}c_i(M_j) = \arg\max_{0 \leqslant c \leqslant M_j} \Big\{ u(c) + \beta \sum_k \omega_k\, \hat V_{i-1}\big(R(M_j - c) + y_k\big) \Big\}

scipy.optimize.minimize_scalar with method='bounded' runs Brent’s method on an interval, combining golden section search with parabolic interpolation, without derivatives. See the link in the bottom of the page to the visualization of the method by Oscar Fernandez.

Source
<Figure size 1200x450 with 2 Axes>
  • Happy with the accuracy of the solution?

  • What contributes to the inaccuracy of the solution now?

Time iterations on the Euler equationΒΆ

The third approach does not use the value function at all. The Euler equation holds for the optimal policy, so given a policy ciβˆ’1c_{i-1} for next period, the policy for this period solves, in every state MjM_j

uβ€²(c)=Ξ²Rβˆ‘kΟ‰k uβ€²(ciβˆ’1(R(Mjβˆ’c)+yk))u'(c) = \beta R \sum_k \omega_k\, u'\Big(c_{i-1}\big(R(M_j - c) + y_k\big)\Big)

for cc, a root-finding problem in one variable.

If the residual uβ€²(c)βˆ’Ξ²R E uβ€²(cβ€²)u'(c) - \beta R\, \mathbb{E}\, u'(c') is still positive at c=Mjc = M_j, the borrowing constraint binds and c=Mjc = M_j.

Iterating this operator, the time iterations, converges to the optimal policy.

Source
<Figure size 1200x450 with 2 Axes>
  • Happy with the accuracy of the solution?

  • What contributes to it now?

Accuracy: the Euler equation residualsΒΆ

The Euler equation residual of Class 15 measures the error of a numerical solution at an arbitrary point, now with the expectation over income computed by quadrature:

Ξ΅(M)=uβ€²(c(M))βˆ’Ξ²R Ey uβ€²(c(R(Mβˆ’c(M))+y~))uβ€²(c(M))\varepsilon(M) = \frac{u'\big(c(M)\big) - \beta R\, \mathbb{E}_y\, u'\Big(c\big(R(M - c(M)) + \tilde y\big)\Big)}{u'\big(c(M)\big)}

The residual is relative, so it reads as a fraction of the marginal utility. It is evaluated on a dense grid, ten times finer than the solver’s, with the policy interpolated, and only where the constraint does not bind.

Time iterations are the most accurate, because they solve the very equation the residual measures, up to the interpolation of next period’s policy. VFI with continuous choice comes next and VFI with discretized choice last.

Where it breaks: the definition of a corner solution. The bounded optimizer of bellman_continuous cannot land exactly on the bound c=Mc = M, it stops a hair below. A corner test with an absolute tolerance, c < M - 1e-10, then counts the corners as interior points, where the residual is large by construction, and the measured error of the continuous solver is twenty times too big. The relative tolerance rtol in the code below removes them. Every accuracy measure needs this kind of care.

Simulation and Keane’s testΒΆ

The simulator draws income from its true distribution, not from the quadrature nodes, and applies the interpolated policy, capped at the available wealth.

Keane’s test needs the deterministic model with Ξ²R=1\beta R = 1. A log-normal income with a tiny Οƒ\sigma puts all quadrature nodes at y=1y = 1, so the same code covers it. Consumption simulated from M0=5M_0 = 5 should stay at c⋆=((Rβˆ’1)M0+1)/Rc^\star = ((R-1) M_0 + 1)/R forever.

Source
VFI, discretized choice   max |c_t / c* - 1| = 1.4e-02
VFI, continuous choice    max |c_t / c* - 1| = 5.3e-08
time iterations           max |c_t / c* - 1| = 2.7e-09
<Figure size 1000x400 with 1 Axes>

The discretized solver fails the test, with consumption off by about one percent and drifting, while the other two keep it flat to seven digits or better.

Speed and accuracy comparedΒΆ

The Euler residual of a policy, on a dense grid and at the interior points only:

Each solver now runs for the three values of Οƒ\sigma and for a growing state grid, with the choice grid of the discretized solver fixed at 250 points. The solvers stop at a tight tolerance, 10-8, so that what we measure is the error of the grid and not of the stopping rule. For Οƒ\sigma near zero the model is set to Ξ²R=1\beta R = 1, where Keane’s test applies; for the other two values of Οƒ\sigma it does not.

Source
<Figure size 1500x1200 with 9 Axes>

Time iterations are the best of the three: as accurate as VFI with continuous choice or better, and several times faster. A root of the Euler equation is easier to find than a maximum of the Bellman equation, and the Euler equation needs no value function.

Important idea: not using value function is beneficial! (See next lecture)

  • Why do time iterations not need a value function, and what is lost without one?

  • Which of the three solvers would still work if the utility function were not concave, or if there were a discrete choice on top of consumption?

ReferencesΒΆ
  1. Deaton, A. (1991). Saving and Liquidity Constraints. Econometrica, 59(5), 1221–1248. 10.2307/2938366
  2. Judd, K. L. (1998). Numerical Methods in Economics (p. 633). MIT Press. https://mitpress.mit.edu/9780262100717/numerical-methods-in-economics/