Skip to content

Commit 9c372bd

Browse files
authored
Merge branch 'main' into greek_square
2 parents 670444d + 9e6bceb commit 9c372bd

29 files changed

+783
-118
lines changed

.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838
shell: bash -l {0}
3939
run: pip list
4040
- name: Download "build" folder (cache)
41-
uses: dawidd6/action-download-artifact@v7
41+
uses: dawidd6/action-download-artifact@v9
4242
with:
4343
workflow: cache.yml
4444
branch: main

.github/workflows/collab.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
shell: bash -l {0}
2121
run: pip list
2222
- name: Download "build" folder (cache)
23-
uses: dawidd6/action-download-artifact@v7
23+
uses: dawidd6/action-download-artifact@v9
2424
with:
2525
workflow: cache.yml
2626
branch: main

.github/workflows/linkcheck.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
environment-file: environment.yml
2828
activate-environment: quantecon
2929
- name: Download "build" folder (cache)
30-
uses: dawidd6/action-download-artifact@v7
30+
uses: dawidd6/action-download-artifact@v9
3131
with:
3232
workflow: cache.yml
3333
branch: main

.github/workflows/publish.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
shell: bash -l {0}
4040
run: pip list
4141
- name: Download "build" folder (cache)
42-
uses: dawidd6/action-download-artifact@v7
42+
uses: dawidd6/action-download-artifact@v9
4343
with:
4444
workflow: cache.yml
4545
branch: main

lectures/_config.yml

+6-6
Original file line numberDiff line numberDiff line change
@@ -84,22 +84,22 @@ sphinx:
8484
- https://intro.quantecon.org/
8585
- null
8686
dle:
87-
- https://quantecon.github.io/lecture-dle/
87+
- https://dle.quantecon.org/
8888
- null
8989
dps:
90-
- https://quantecon.github.io/lecture-dps/
90+
- https://dps.quantecon.org/
9191
- null
9292
eqm:
93-
- https://quantecon.github.io/lecture-eqm/
93+
- https://eqm.quantecon.org/
9494
- null
9595
stats:
96-
- https://quantecon.github.io/lecture-stats/
96+
- https://stats.quantecon.org/
9797
- null
9898
tools:
99-
- https://quantecon.github.io/lecture-tools-techniques/
99+
- https://tools-techniques.quantecon.org/
100100
- null
101101
dynam:
102-
- https://quantecon.github.io/lecture-dynamics/
102+
- https://dynamics.quantecon.org/
103103
- null
104104
mathjax3_config:
105105
tex:

lectures/_toc.yml

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ parts:
2525
chapters:
2626
- file: pv
2727
- file: cons_smooth
28+
- file: tax_smooth
2829
- file: equalizing_difference
2930
- file: cagan_ree
3031
- file: cagan_adaptive

lectures/ar1_processes.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ for t in range(sim_length):
180180
mu = a * mu + b
181181
v = a**2 * v + c**2
182182
ax.plot(grid, norm.pdf(grid, loc=mu, scale=np.sqrt(v)),
183-
label=f"$\psi_{t}$",
183+
label=fr"$\psi_{t}$",
184184
alpha=0.7)
185185
186186
ax.legend(bbox_to_anchor=[1.05,1],loc=2,borderaxespad=1)
@@ -267,7 +267,7 @@ plot_density_seq(ax, mu_0=4.0)
267267
mu_star = b / (1 - a)
268268
std_star = np.sqrt(c**2 / (1 - a**2)) # square root of v_star
269269
psi_star = norm.pdf(grid, loc=mu_star, scale=std_star)
270-
ax.plot(grid, psi_star, 'k-', lw=2, label="$\psi^*$")
270+
ax.plot(grid, psi_star, 'k-', lw=2, label=r"$\psi^*$")
271271
ax.legend()
272272
273273
plt.show()

lectures/cobweb.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ def plot45(model, pmin, pmax, p0, num_arrows=5):
271271
272272
ax.plot(pgrid, g(model, pgrid), 'b-',
273273
lw=2, alpha=0.6, label='g')
274-
ax.plot(pgrid, pgrid, lw=1, alpha=0.7, label='$45\degree$')
274+
ax.plot(pgrid, pgrid, lw=1, alpha=0.7, label=r'$45\degree$')
275275
276276
x = p0
277277
xticks = [pmin]

lectures/commod_price.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ The figure below shows the price of cotton in USD since the start of 2016.
6060
```{code-cell} ipython3
6161
:tags: [hide-input, hide-output]
6262
63-
s = yf.download('CT=F', '2016-1-1', '2023-4-1')['Adj Close']
63+
s = yf.download('CT=F', '2016-1-1', '2023-4-1')['Close']
6464
```
6565

6666
```{code-cell} ipython3

lectures/cons_smooth.md

+50-47
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,38 @@ jupytext:
44
extension: .md
55
format_name: myst
66
format_version: 0.13
7-
jupytext_version: 1.16.1
7+
jupytext_version: 1.16.4
88
kernelspec:
99
display_name: Python 3 (ipykernel)
1010
language: python
1111
name: python3
1212
---
1313

14-
1514
# Consumption Smoothing
1615

1716
## Overview
1817

1918

2019
In this lecture, we'll study a famous model of the "consumption function" that Milton Friedman {cite}`Friedman1956` and Robert Hall {cite}`Hall1978`) proposed to fit some empirical data patterns that the original Keynesian consumption function described in this QuantEcon lecture {doc}`geometric series <geom_series>` missed.
2120

22-
In this lecture, we'll study what is often called the "consumption-smoothing model" using matrix multiplication and matrix inversion, the same tools that we used in this QuantEcon lecture {doc}`present values <pv>`.
21+
We'll study what is often called the "consumption-smoothing model."
22+
23+
We'll use matrix multiplication and matrix inversion, the same tools that we used in this QuantEcon lecture {doc}`present values <pv>`.
2324

2425
Formulas presented in {doc}`present value formulas<pv>` are at the core of the consumption-smoothing model because we shall use them to define a consumer's "human wealth".
2526

2627
The key idea that inspired Milton Friedman was that a person's non-financial income, i.e., his or
27-
her wages from working, could be viewed as a dividend stream from that person's ''human capital''
28-
and that standard asset-pricing formulas could be applied to compute a person's
29-
''non-financial wealth'' that capitalizes the earnings stream.
28+
her wages from working, can be viewed as a dividend stream from ''human capital''
29+
and that standard asset-pricing formulas can be applied to compute
30+
''non-financial wealth'' that capitalizes that earnings stream.
3031

3132
```{note}
3233
As we'll see in this QuantEcon lecture {doc}`equalizing difference model <equalizing_difference>`,
3334
Milton Friedman had used this idea in his PhD thesis at Columbia University,
3435
eventually published as {cite}`kuznets1939incomes` and {cite}`friedman1954incomes`.
3536
```
3637

37-
It will take a while for a "present value" or asset price explicilty to appear in this lecture, but when it does it will be a key actor.
38+
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.
3839

3940

4041
## Analysis
@@ -47,16 +48,15 @@ import matplotlib.pyplot as plt
4748
from collections import namedtuple
4849
```
4950

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

53-
We usually think of the non-financial income stream as coming from the person's salary from supplying labor.
53+
We usually think of the non-financial income stream as coming from the person's earnings from supplying labor.
5454

55-
The model takes a non-financial income stream as an input, regarding it as "exogenous" in the sense of not being determined by the model.
55+
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.
5656

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

59-
To set up the model, let
59+
Let
6060

6161
* $T \geq 2$ be a positive integer that constitutes a time-horizon.
6262
* $y = \{y_t\}_{t=0}^T$ be an exogenous sequence of non-negative non-financial incomes $y_t$.
@@ -130,7 +130,10 @@ By **smoother** we mean as close as possible to being constant over time.
130130
131131
The preference for smooth consumption paths that is built into the model gives it the name "consumption-smoothing model".
132132
133-
Let's dive in and do some calculations that will help us understand how the model works.
133+
We'll postpone verifying our claim that a constant consumption path is optimal when $\beta R=1$
134+
by comparing welfare levels that comes from a constant path with ones that involve non-constant paths.
135+
136+
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.
134137
135138
Here we use default parameters $R = 1.05$, $g_1 = 1$, $g_2 = 1/2$, and $T = 65$.
136139
@@ -147,7 +150,6 @@ def create_consumption_smoothing_model(R=1.05, g1=1, g2=1/2, T=65):
147150
β_seq, T)
148151
```
149152
150-
151153
## Friedman-Hall consumption-smoothing model
152154
153155
A key object is what Milton Friedman called "human" or "non-financial" wealth at time $0$:
@@ -285,7 +287,7 @@ def compute_optimal(model, a0, y_seq):
285287
286288
We use an example where the consumer inherits $a_0<0$.
287289
288-
This can be interpreted as a student debt.
290+
This can be interpreted as student debt with which the consumer begins his or her working life.
289291
290292
The non-financial process $\{y_t\}_{t=0}^{T}$ is constant and positive up to $t=45$ and then becomes zero afterward.
291293
@@ -308,17 +310,22 @@ print('check a_T+1=0:',
308310
The graphs below show paths of non-financial income, consumption, and financial assets.
309311
310312
```{code-cell} ipython3
311-
# Sequence Length
313+
# Sequence length
312314
T = cs_model.T
313315
314-
plt.plot(range(T+1), y_seq, label='non-financial income')
315-
plt.plot(range(T+1), c_seq, label='consumption')
316-
plt.plot(range(T+2), a_seq, label='financial wealth')
317-
plt.plot(range(T+2), np.zeros(T+2), '--')
316+
fig, axes = plt.subplots(1, 2, figsize=(12,5))
317+
318+
axes[0].plot(range(T+1), y_seq, label='non-financial income', lw=2)
319+
axes[0].plot(range(T+1), c_seq, label='consumption', lw=2)
320+
axes[1].plot(range(T+2), a_seq, label='financial wealth', color='green', lw=2)
321+
axes[0].set_ylabel(r'$c_t,y_t$')
322+
axes[1].set_ylabel(r'$a_t$')
323+
324+
for ax in axes:
325+
ax.plot(range(T+2), np.zeros(T+2), '--', lw=1, color='black')
326+
ax.legend()
327+
ax.set_xlabel(r'$t$')
318328
319-
plt.legend()
320-
plt.xlabel(r'$t$')
321-
plt.ylabel(r'$c_t,y_t,a_t$')
322329
plt.show()
323330
```
324331
@@ -356,15 +363,19 @@ def plot_cs(model, # consumption-smoothing model
356363
# Sequence length
357364
T = cs_model.T
358365
359-
# Generate plot
360-
plt.plot(range(T+1), y_seq, label='non-financial income')
361-
plt.plot(range(T+1), c_seq, label='consumption')
362-
plt.plot(range(T+2), a_seq, label='financial wealth')
363-
plt.plot(range(T+2), np.zeros(T+2), '--')
366+
fig, axes = plt.subplots(1, 2, figsize=(12,5))
367+
368+
axes[0].plot(range(T+1), y_seq, label='non-financial income', lw=2)
369+
axes[0].plot(range(T+1), c_seq, label='consumption', lw=2)
370+
axes[1].plot(range(T+2), a_seq, label='financial wealth', color='green', lw=2)
371+
axes[0].set_ylabel(r'$c_t,y_t$')
372+
axes[1].set_ylabel(r'$a_t$')
373+
374+
for ax in axes:
375+
ax.plot(range(T+2), np.zeros(T+2), '--', lw=1, color='black')
376+
ax.legend()
377+
ax.set_xlabel(r'$t$')
364378
365-
plt.legend()
366-
plt.xlabel(r'$t$')
367-
plt.ylabel(r'$c_t,y_t,a_t$')
368379
plt.show()
369380
```
370381
@@ -419,7 +430,7 @@ Now we simulate a $y$ sequence in which a person gets zero for 46 years, and the
419430
```{code-cell} ipython3
420431
# Late starter
421432
y_seq_late = np.concatenate(
422-
[np.zeros(46), np.ones(20)])
433+
[np.ones(46), 2*np.ones(20)])
423434
424435
plot_cs(cs_model, a0, y_seq_late)
425436
```
@@ -461,18 +472,16 @@ What happens when $\lambda$ is negative
461472
```{code-cell} ipython3
462473
λ = -0.95
463474
464-
geo_seq = λ ** np.arange(t_max) * y_0
475+
geo_seq = λ ** np.arange(t_max) * y_0 + 1
465476
y_seq_geo = np.concatenate(
466-
[geo_seq, np.zeros(20)])
477+
[geo_seq, np.ones(20)])
467478
468479
plot_cs(cs_model, a0, y_seq_geo)
469480
```
470481
471-
472482
### Feasible consumption variations
473483
474-
We promised to justify our claim that a constant consumption play $c_t = c_0$ for all
475-
$t$ is optimal.
484+
We promised to justify our claim that when $\beta R =1$ as Friedman assumed, a constant consumption play $c_t = c_0$ for all $t$ is optimal.
476485
477486
Let's do that now.
478487
@@ -554,7 +563,6 @@ def compute_variation(model, ξ1, ϕ, a0, y_seq, verbose=1):
554563
return cvar_seq
555564
```
556565
557-
558566
We visualize variations for $\xi_1 \in \{.01, .05\}$ and $\phi \in \{.95, 1.02\}$
559567
560568
```{code-cell} ipython3
@@ -591,10 +599,9 @@ plt.ylabel(r'$c_t$')
591599
plt.show()
592600
```
593601
594-
595602
We can even use the Python `np.gradient` command to compute derivatives of welfare with respect to our two parameters.
596603
597-
We are teaching the key idea beneath the **calculus of variations**.
604+
(We are actually discovering the key idea beneath the **calculus of variations**.)
598605
599606
First, we define the welfare with respect to $\xi_1$ and $\phi$
600607
@@ -615,7 +622,6 @@ def welfare_rel(ξ1, ϕ):
615622
welfare_vec = np.vectorize(welfare_rel)
616623
```
617624
618-
619625
Then we can visualize the relationship between welfare and $\xi_1$ and compute its derivatives
620626
621627
```{code-cell} ipython3
@@ -634,7 +640,6 @@ plt.xlabel(r'$\xi_1$')
634640
plt.show()
635641
```
636642
637-
638643
The same can be done on $\phi$
639644
640645
```{code-cell} ipython3
@@ -655,14 +660,12 @@ plt.show()
655660
656661
## Wrapping up the consumption-smoothing model
657662
658-
The consumption-smoothing model of Milton Friedman {cite}`Friedman1956` and Robert Hall {cite}`Hall1978`) is a cornerstone of modern macro that has important ramifications for the size of the Keynesian "fiscal policy multiplier" described briefly in
663+
The consumption-smoothing model of Milton Friedman {cite}`Friedman1956` and Robert Hall {cite}`Hall1978`) is a cornerstone of modern economics that has important ramifications for the size of the Keynesian "fiscal policy multiplier" that we described in
659664
QuantEcon lecture {doc}`geometric series <geom_series>`.
660665
661-
In particular, it **lowers** the government expenditure multiplier relative to one implied by
662-
the original Keynesian consumption function presented in {doc}`geometric series <geom_series>`.
666+
The consumption-smoothingmodel **lowers** the government expenditure multiplier relative to one implied by the original Keynesian consumption function presented in {doc}`geometric series <geom_series>`.
663667
664-
Friedman's work opened the door to an enlightening literature on the aggregate consumption function and associated government expenditure multipliers that
665-
remains active today.
668+
Friedman's work opened the door to an enlightening literature on the aggregate consumption function and associated government expenditure multipliers that remains active today.
666669
667670
668671
## Appendix: solving difference equations with linear algebra

lectures/eigen_I.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ def circle_transform(A=np.array([[-1, 2], [0, 1]])):
265265
ax[0].plot(x, y, color='black', zorder=1)
266266
ax[0].scatter(a_1, b_1, c=colors, alpha=1, s=60,
267267
edgecolors='black', zorder=2)
268-
ax[0].set_title("unit circle in $\mathbb{R}^2$")
268+
ax[0].set_title(r"unit circle in $\mathbb{R}^2$")
269269
270270
x1 = x.reshape(1, -1)
271271
y1 = y.reshape(1, -1)
@@ -542,15 +542,15 @@ def grid_composition_transform(A=np.array([[1, -1], [1, 1]]),
542542
543543
# Plot grid points
544544
ax[0].scatter(xygrid[0], xygrid[1], s=36, c=colors, edgecolor="none")
545-
ax[0].set_title("points $x_1, x_2, \cdots, x_k$")
545+
ax[0].set_title(r"points $x_1, x_2, \cdots, x_k$")
546546
547547
# Plot intermediate grid points
548548
ax[1].scatter(uvgrid[0], uvgrid[1], s=36, c=colors, edgecolor="none")
549-
ax[1].set_title("points $Bx_1, Bx_2, \cdots, Bx_k$")
549+
ax[1].set_title(r"points $Bx_1, Bx_2, \cdots, Bx_k$")
550550
551551
# Plot transformed grid points
552552
ax[2].scatter(abgrid[0], abgrid[1], s=36, c=colors, edgecolor="none")
553-
ax[2].set_title("points $ABx_1, ABx_2, \cdots, ABx_k$")
553+
ax[2].set_title(r"points $ABx_1, ABx_2, \cdots, ABx_k$")
554554
555555
plt.show()
556556
```

lectures/equalizing_difference.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ We'll use the Python module 'sympy' to compute partial derivatives of $\phi$ wit
374374
Define symbols
375375
376376
```{code-cell} ipython3
377-
γ_h, γ_c, w_h0, D = symbols('\gamma_h, \gamma_c, w_0^h, D', real=True)
377+
γ_h, γ_c, w_h0, D = symbols(r'\gamma_h, \gamma_c, w_0^h, D', real=True)
378378
R, T = Symbol('R', real=True), Symbol('T', integer=True)
379379
```
380380

lectures/geom_series.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,7 @@ T_max = 10
761761
T=np.arange(0, T_max+1)
762762
763763
rs, gs = (0.9, 0.5, 0.4001, 0.4), (0.4, 0.4, 0.4, 0.5),
764-
comparisons = ('$\gg$', '$>$', r'$\approx$', '$<$')
764+
comparisons = (r'$\gg$', '$>$', r'$\approx$', '$<$')
765765
for r, g, comp in zip(rs, gs, comparisons):
766766
ax.plot(finite_lease_pv_true(T, g, r, x_0), label=f'r(={r}) {comp} g(={g})')
767767

0 commit comments

Comments
 (0)