Skip to content

Commit 0c7cc5c

Browse files
committed
updates
1 parent c7ed66a commit 0c7cc5c

File tree

1 file changed

+54
-41
lines changed

1 file changed

+54
-41
lines changed

lectures/ak_aiyagari.md

Lines changed: 54 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ kernelspec:
1414

1515
# A Long-Lived, Heterogeneous Agent, Overlapping Generations Model
1616

17+
In addition to what's in Anaconda, this lecture will need the following library
18+
19+
```{code-cell} ipython3
20+
:tags: [skip-execution]
21+
22+
!pip install jax
23+
```
24+
1725
## Overview
1826

1927
This lecture describes an overlapping generations model with these features:
@@ -22,7 +30,7 @@ This lecture describes an overlapping generations model with these features:
2230
- Agents live many periods as in {cite}`auerbach1987dynamic`
2331
- Agents receive idiosyncratic labor productivity shocks that cannot be fully insured as in {cite}`Aiyagari1994`
2432
- Government fiscal policy instruments include tax rates, debt, and transfers as in chapter 2 of {cite}`auerbach1987dynamic` and {doc}`Transitions in an Overlapping Generations Model<ak2>`
25-
- Among other equilibrium objects, a competitive determines a sequence of cross-section densities of heterogeneous agents' consumptions, labor incomes, and savings
33+
- Among other equilibrium objects, a competitive equilibrium determines a sequence of cross-section densities of heterogeneous agents' consumptions, labor incomes, and savings
2634

2735

2836
We use the model to study:
@@ -40,7 +48,7 @@ As prerequisites for this lecture, we recommend two quantecon lectures:
4048

4149
as well as the optional reading {doc}`aiyagari`
4250

43-
As usual, let's start by importing some Python modules.
51+
As usual, let's start by importing some Python modules
4452

4553
```{code-cell} ipython3
4654
from collections import namedtuple
@@ -53,6 +61,8 @@ import jax
5361

5462
## Environment
5563

64+
We start by introducing the economic environment we are operating in.
65+
5666
### Demographics and time
5767

5868
We work in discrete time indexed by $t = 0, 1, 2, ...$.
@@ -75,7 +85,7 @@ An agent with productivity $\gamma_{i,j,t}$ supplies $l(j)\gamma_{i,j,t}$ effici
7585

7686
$l(j)$ is a deterministic age-specific labor efficiency units profile.
7787

78-
An agent's effective labor supply depends on a life-cycle efficiency profile and an idiosyncratic stochastic process.
88+
An agent's effective labor supply depends on a life-cycle efficiency profile and an idiosyncratic stochastic process.
7989

8090
### Initial conditions
8191

@@ -199,7 +209,7 @@ $V_{J,t}(a, \gamma) = 0$
199209

200210
## Population dynamics
201211

202-
The joint probability density function $\mu_{j,t}(a,\gamma)$ of asset holdings and idiosyncratic labor evolves according to
212+
The joint probability density function $\mu_{j,t}(a,\gamma)$ of asset holdings and idiosyncratic labor productivity evolves according to
203213

204214
- For newborns $(j=0)$:
205215

@@ -245,19 +255,19 @@ Relative to the model presented in {doc}`Transitions in an Overlapping Generati
245255

246256
## Implementation
247257

248-
Using tools in {doc}`discrete_dp`, we solve our model by combining value function iteration with equilibrium price determination.
258+
Using tools in {doc}`advanced:discrete_dp`, we solve our model by combining value function iteration with equilibrium price determination.
249259

250260
A sensible approach is to nest a discrete DP solver inside an outer loop that searches for market-clearing prices.
251261

252262
For a candidate sequence of prices interest rates $r_t$ and wages $w_t$, we can solve individual households' dynamic programming problems using either value function iteration or policy iteration to obtain optimal policy functions.
253263

254264
We then deduce associated stationary joint probability distributions of asset holdings and idiosyncratic labor efficiency units for each age cohort.
255265

256-
That will give us an aggregate capital supply (from household savings) and a labor supply (from the age-efficiency profile and productivity shocks).
266+
This will give us an aggregate capital supply (from household savings) and a labor supply (from the age-efficiency profile and productivity shocks).
257267

258268
We can then compare these with capital and labor demand from firms, compute deviations between factor market supplies and demands, then update price guesses until we find market-clearing prices.
259269

260-
To construct transition dynamics, we can compute sequences of time-varying prices by using _backward induction_ to compute value and policy functions, and _forward iteration_ for the distributions of agents across states.
270+
To construct transition dynamics, we can compute sequences of time-varying prices by using _backward induction_ to compute value and policy functions, and _forward iteration_ for the distributions of agents across states:
261271

262272
1. Outer loop (market clearing)
263273
* Guess initial prices ($r_t, w_t$)
@@ -319,7 +329,7 @@ def l(j):
319329
return l1 + l2 * j + l3 * j ** 2
320330
```
321331

322-
Let's define a `Firm` namedtuple that contains parameters governing the production technology.
332+
Let's define a `Firm` namedtuple that contains parameters governing the production technology.
323333

324334
```{code-cell} ipython3
325335
Firm = namedtuple("Firm", ("α", "Z"))
@@ -333,7 +343,7 @@ def create_firm(α=0.3, Z=1):
333343
firm = create_firm()
334344
```
335345

336-
The following helper functions link aggregates ($K, L$) and prices ($w, r$) that emerge from the representative firm's first-order necessary conditions.
346+
The following helper functions link aggregates ($K, L$) and prices ($w, r$) that emerge from the representative firm's first-order necessary conditions.
337347

338348
```{code-cell} ipython3
339349
@jax.jit
@@ -351,7 +361,7 @@ def KL_to_w(K, L, firm):
351361
return Z * (1 - α) * (K / L) ** α
352362
```
353363

354-
We use a function `find_τ` to find flat tax rates that balance the government budget constraint given other policy variables that include debt levels, government spending, and transfers.
364+
We use a function `find_τ` to find flat tax rates that balance the government budget constraint given other policy variables that include debt levels, government spending, and transfers.
355365

356366
```{code-cell} ipython3
357367
@jax.jit
@@ -367,7 +377,7 @@ def find_τ(policy, price, aggs):
367377
return num / denom
368378
```
369379

370-
We use a namedtuple `Household` to store parameters that characterize households' problems.
380+
We use a namedtuple `Household` to store parameters that characterize households' problems.
371381

372382
```{code-cell} ipython3
373383
Household = namedtuple("Household", ("j_grid", "a_grid", "γ_grid",
@@ -408,7 +418,7 @@ def create_household(
408418
hh = create_household()
409419
```
410420

411-
We apply discrete state dynamic programming tools.
421+
We apply discrete state dynamic programming tools.
412422

413423
Initial steps involve preparing rewards and transition matrices $R$ and $Q$ for our discretized Bellman equations.
414424

@@ -446,11 +456,11 @@ def populate_R(j, r, w, τ, δ, household):
446456

447457
## Computing a steady state
448458

449-
We first compute steady state.
459+
We first compute a steady state.
450460

451461
Given guesses of prices and taxes, we can use backwards induction to solve for value functions and optimal consumption and saving policies at all ages.
452462

453-
The function `backwards_opt` solve for optimal values by applying the discretized bellman operator backwards.
463+
The function `backwards_opt` solves for optimal values by applying the discretized bellman operator backwards.
454464

455465
We use `jax.lax.scan` to facilitate sequential and recurrent computations efficiently.
456466

@@ -500,11 +510,13 @@ Q = populate_Q(hh)
500510
V, σ = backwards_opt([r, w], [τ, δ], hh, Q)
501511
```
502512

513+
Let's time the computation with `block_until_ready()` to ensure that all JAX operations are complete
514+
503515
```{code-cell} ipython3
504-
%time backwards_opt([r, w], [τ, δ], hh, Q).block_until_ready()
516+
%time backwards_opt([r, w], [τ, δ], hh, Q)[0].block_until_ready();
505517
```
506518

507-
From optimal consumption and saving choices by each cohort, we can compute a joint probability distribution of asset levels and idiosyncratic productivity levels in a steady state.
519+
From the optimal consumption and saving choices by each cohort, we can compute a joint probability distribution of asset levels and idiosyncratic productivity levels in a steady state.
508520

509521
```{code-cell} ipython3
510522
@jax.jit
@@ -536,8 +548,10 @@ def popu_dist(σ, household, Q):
536548
μ = popu_dist(σ, hh, Q)
537549
```
538550

551+
Let's time the computation
552+
539553
```{code-cell} ipython3
540-
%time popu_dist(σ, hh, Q).block_until_ready()
554+
%time popu_dist(σ, hh, Q)[0].block_until_ready();
541555
```
542556

543557
Below we plot the marginal distribution of savings for each age group.
@@ -558,11 +572,11 @@ plt.show()
558572
```
559573

560574

561-
These marginal distributions confirm that new agents enter the economy with no asset holdings.
575+
These marginal distributions confirm that new agents enter the economy with no asset holdings.
562576

563-
* the blue $j=0$ distribution has mass only at $a=0$.
577+
* the blue $j=0$ distribution has mass only at $a=0$.
564578

565-
As agents age, at first they gradually accumulate assets.
579+
As agents age, at first they gradually accumulate assets.
566580

567581
* the orange $j=5$ distribution puts positive mass on positive but low asset levels
568582
* the green $j=20$ distribution puts positive mass on a much wider range of asset levels.
@@ -643,9 +657,9 @@ The firm's optimality conditions imply interest rate $r$ and wage rate $w$.
643657
KL_to_r(K, L, firm), KL_to_w(K, L, firm)
644658
```
645659

646-
The implied prices $(r,w)$ differ from our guesses, so we must update our guesses and iterate until we find a fixed point.
660+
The implied prices $(r,w)$ differ from our guesses, so we must update our guesses and iterate until we find a fixed point.
647661

648-
This is our outer loop.
662+
This is our outer loop.
649663

650664
```{code-cell} ipython3
651665
@jax.jit
@@ -758,7 +772,7 @@ r_ss1, w_ss1
758772

759773
## Transition dynamics
760774

761-
We compute transition dynamics using a function `path_iteration`.
775+
We compute transition dynamics using a function `path_iteration`.
762776

763777
In an outer loop, we iterate over guesses of prices and taxes.
764778

@@ -908,10 +922,10 @@ The following algorithm describes the path iteration procedure:
908922
1. Initialize from steady states:
909923
- $(V_1, \sigma_1, \mu_1) \leftarrow ss_1$ *(Initial steady state)*
910924
- $(V_2, \sigma_2, \mu_2) \leftarrow ss_2$ *(Final steady state)*
911-
- $(r, w, \tau) \leftarrow \text{initialize\_prices}(T)$ *(Linear interpolation)*
925+
- $(r, w, \tau) \leftarrow \text{initialize_prices}(T)$ *(Linear interpolation)*
912926
- $\text{error} \leftarrow \infty$, $i \leftarrow 0$
913927
914-
2. **While** $\text{error} > \varepsilon$ or $i \leq \text{max\_iter}$:
928+
2. **While** $\text{error} > \varepsilon$ or $i \leq \text{max_iter}$:
915929
916930
1. $i \leftarrow i + 1$
917931
2. $(r_{\text{old}}, w_{\text{old}}, \tau_{\text{old}}) \leftarrow (r, w, \tau)$
@@ -927,8 +941,8 @@ The following algorithm describes the path iteration procedure:
927941
- $L[t] \leftarrow \int l(j)\gamma \, d\mu[t]$ *(Aggregate labor)*
928942
- $r[t] \leftarrow \alpha Z(K[t]/L[t])^{\alpha-1}$ *(Interest rate)*
929943
- $w[t] \leftarrow (1-\alpha)Z(K[t]/L[t])^{\alpha}$ *(Wage rate)*
930-
- $\tau[t] \leftarrow \text{solve\_budget}(r[t],w[t],K[t],L[t],D[t],G[t])$
931-
944+
- $\tau[t] \leftarrow \text{solve_budget}(r[t],w[t],K[t],L[t],D[t],G[t])$
945+
932946
5. Compute convergence metric:
933947
- $\text{error} \leftarrow \|r - r_{\text{old}}\| + \|w - w_{\text{old}}\| + \|\tau - \tau_{\text{old}}\|$
934948
@@ -1032,23 +1046,23 @@ We can now compute equilibrium transitions that are ignited by fiscal policy
10321046

10331047
## Experiment 1: Immediate tax cut
10341048

1035-
Assume that the government cuts the tax rate immediately balances its budget by issuing debt.
1049+
Assume that the government cuts the tax rate and immediately balances its budget by issuing debt.
10361050

10371051
At $t=0$, the government unexpectedly announces an immediate tax cut.
10381052

10391053
From $t=0$ to $19$, the government issues debt, so debt $D_{t+1}$ increases linearly for $20$ periods.
10401054

1041-
The government sets a target for its new debt level $D_{20} =D_0 + 1 = \bar{D} + 1$.
1055+
The government sets a target for its new debt level $D_{20} =D_0 + 1 = \bar{D} + 1$.
10421056

10431057
Government spending $\bar{G}$ and transfers $\bar{\delta}_j$ remain constant.
10441058

10451059
The government adjusts $\tau_t$ to balance the budget along the transition.
10461060

1047-
We want to compute the equilibrium transition path.
1061+
We want to compute the equilibrium transition path.
10481062

10491063
Our first step is to prepare appropriate policy variable arrays `D_seq`, `G_seq`, `δ_seq`
10501064

1051-
We'll compute a `τ_seq` that balances government budgets.
1065+
We'll compute a `τ_seq` that balances government budgets.
10521066

10531067
```{code-cell} ipython3
10541068
T = 150
@@ -1068,9 +1082,9 @@ In order to iterate the path, we need to first find its destination, which is th
10681082
ss2 = find_ss(hh, firm, [D_seq[-1], G_seq[-1], δ_seq[-1]], Q)
10691083
```
10701084

1071-
We can use `path_iteration` to find equilibrium transition dynamics.
1085+
We can use `path_iteration` to find equilibrium transition dynamics.
10721086

1073-
Setting the key argument `verbose=True` tells the function `path_iteration` to display convergence information.
1087+
Setting the key argument `verbose=True` tells the function `path_iteration` to display convergence information.
10741088

10751089
```{code-cell} ipython3
10761090
paths = path_iteration(ss1, ss2, [D_seq, G_seq, δ_seq], hh, firm, Q, verbose=True)
@@ -1138,11 +1152,11 @@ To summarize the transition, we can plot paths as we did in {doc}`ak2`.
11381152

11391153
But unlike the setup in that two-period lived overlapping generations model, we no longer have representative old and young agents.
11401154

1141-
* now we have 50 cohorts of different ages at each time
1155+
* now we have 50 cohorts of different ages at each time
11421156

1143-
To proceed, we construct two age groups of equal size -- young and old.
1157+
To proceed, we construct two age groups of equal size -- young and old.
11441158

1145-
* at age 25, someone moves from being young to become old
1159+
* at age 25, someone moves from being young to becoming old
11461160

11471161
```{code-cell} ipython3
11481162
ap = hh.a_grid[σ_ss1]
@@ -1255,12 +1269,11 @@ plt.show()
12551269

12561270
## Experiment 2: Preannounced tax cut
12571271

1258-
1259-
Now the government announces a permanent tax rate cut at time $0$ but implements it only after 20 periods.
1272+
Now the government announces a permanent tax rate cut at time $0$ but implements it only after 20 periods.
12601273

12611274
We will use the same key toolkit `path_iteration`.
12621275

1263-
We must specify `D_seq` appropriately.
1276+
We must specify `D_seq` appropriately.
12641277

12651278
```{code-cell} ipython3
12661279
T = 150
@@ -1363,7 +1376,7 @@ plt.title("K")
13631376
plt.xlabel("t")
13641377
```
13651378

1366-
After the tax cut policy is implemented after $t=20$, the aggregate capital will decrease because of the crowding out effect.
1379+
After the tax cut policy is implemented at $t=20$, the aggregate capital will decrease because of the crowding out effect.
13671380

13681381
Having foreseen an increase in the interest rate, individuals a few periods before $t=20$ start saving more.
13691382

@@ -1373,7 +1386,7 @@ For agents living in much earlier periods, that lower interest rate causes them
13731386

13741387

13751388

1376-
We can also plot evolutions of means and variances of consumption by different cohorts along a transition path.
1389+
We can also plot evolutions of means and variances of consumption by different cohorts along a transition path.
13771390

13781391
```{code-cell} ipython3
13791392
Cmean_seq = np.empty((T, J))

0 commit comments

Comments
 (0)