Advanced Quantitative Economics with Python
Rosen Schooling Model
23. Rosen Schooling Model¶
This lecture is yet another part of a suite of lectures that use the quantecon DLE class to instantiate models within the [HS13] class of models described in detail in Recursive Models of Dynamic Linear Economies.
In addition to what’s included in Anaconda, this lecture uses the quantecon library
!pip install --upgrade quantecon
Collecting quantecon
Downloading quantecon-0.5.0-py3-none-any.whl (229 kB)
?25l
|█▍ | 10 kB 27.1 MB/s eta 0:00:01
|██▉ | 20 kB 24.1 MB/s eta 0:00:01
|████▎ | 30 kB 10.9 MB/s eta 0:00:01
|█████▊ | 40 kB 5.5 MB/s eta 0:00:01
|███████▏ | 51 kB 6.7 MB/s eta 0:00:01
|████████▌ | 61 kB 6.7 MB/s eta 0:00:01
|██████████ | 71 kB 7.5 MB/s eta 0:00:01
|███████████▍ | 81 kB 7.4 MB/s eta 0:00:01
|████████████▉ | 92 kB 7.7 MB/s eta 0:00:01
|██████████████▎ | 102 kB 6.5 MB/s eta 0:00:01
|███████████████▊ | 112 kB 6.5 MB/s eta 0:00:01
|█████████████████ | 122 kB 6.5 MB/s eta 0:00:01
|██████████████████▌ | 133 kB 6.5 MB/s eta 0:00:01
|████████████████████ | 143 kB 6.5 MB/s eta 0:00:01
|█████████████████████▍ | 153 kB 6.5 MB/s eta 0:00:01
|██████████████████████▉ | 163 kB 6.5 MB/s eta 0:00:01
|████████████████████████▏ | 174 kB 6.5 MB/s eta 0:00:01
|█████████████████████████▋ | 184 kB 6.5 MB/s eta 0:00:01
|███████████████████████████ | 194 kB 6.5 MB/s eta 0:00:01
|████████████████████████████▌ | 204 kB 6.5 MB/s eta 0:00:01
|██████████████████████████████ | 215 kB 6.5 MB/s eta 0:00:01
|███████████████████████████████▍| 225 kB 6.5 MB/s eta 0:00:01
|████████████████████████████████| 229 kB 6.5 MB/s
?25hRequirement already satisfied, skipping upgrade: numpy in /usr/share/miniconda3/envs/quantecon/lib/python3.8/site-packages (from quantecon) (1.19.2)
Requirement already satisfied, skipping upgrade: scipy>=1.0.0 in /usr/share/miniconda3/envs/quantecon/lib/python3.8/site-packages (from quantecon) (1.5.2)
Requirement already satisfied, skipping upgrade: numba>=0.38 in /usr/share/miniconda3/envs/quantecon/lib/python3.8/site-packages (from quantecon) (0.51.2)
Requirement already satisfied, skipping upgrade: requests in /usr/share/miniconda3/envs/quantecon/lib/python3.8/site-packages (from quantecon) (2.24.0)
Requirement already satisfied, skipping upgrade: sympy in /usr/share/miniconda3/envs/quantecon/lib/python3.8/site-packages (from quantecon) (1.6.2)
Requirement already satisfied, skipping upgrade: setuptools in /usr/share/miniconda3/envs/quantecon/lib/python3.8/site-packages (from numba>=0.38->quantecon) (50.3.1.post20201107)
Requirement already satisfied, skipping upgrade: llvmlite<0.35,>=0.34.0.dev0 in /usr/share/miniconda3/envs/quantecon/lib/python3.8/site-packages (from numba>=0.38->quantecon) (0.34.0)
Requirement already satisfied, skipping upgrade: idna<3,>=2.5 in /usr/share/miniconda3/envs/quantecon/lib/python3.8/site-packages (from requests->quantecon) (2.10)
Requirement already satisfied, skipping upgrade: certifi>=2017.4.17 in /usr/share/miniconda3/envs/quantecon/lib/python3.8/site-packages (from requests->quantecon) (2020.6.20)
Requirement already satisfied, skipping upgrade: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/share/miniconda3/envs/quantecon/lib/python3.8/site-packages (from requests->quantecon) (1.25.11)
Requirement already satisfied, skipping upgrade: chardet<4,>=3.0.2 in /usr/share/miniconda3/envs/quantecon/lib/python3.8/site-packages (from requests->quantecon) (3.0.4)
Requirement already satisfied, skipping upgrade: mpmath>=0.19 in /usr/share/miniconda3/envs/quantecon/lib/python3.8/site-packages (from sympy->quantecon) (1.1.0)
Installing collected packages: quantecon
Successfully installed quantecon-0.5.0
We’ll also need the following imports:
import numpy as np
import matplotlib.pyplot as plt
from quantecon import LQ
from collections import namedtuple
from quantecon import DLE
from math import sqrt
%matplotlib inline
23.1. A One-Occupation Model¶
Ryoo and Rosen’s (2004) [RR04] partial equilibrium model determines
a stock of “Engineers” \(N_t\)
a number of new entrants in engineering school, \(n_t\)
the wage rate of engineers, \(w_t\)
It takes k periods of schooling to become an engineer.
The model consists of the following equations:
a demand curve for engineers:
a time-to-build structure of the education process:
a definition of the discounted present value of each new engineering student:
a supply curve of new students driven by present value \(v_t\):
23.2. Mapping into HS2013 Framework¶
We represent this model in the [HS13] framework by
sweeping the time-to-build structure and the demand for engineers into the household technology, and
putting the supply of engineers into the technology for producing goods
23.2.1. Preferences¶
where \(\Lambda\) is a k+1 x 1 matrix, \(\Delta_h\) is a k_1 x k+1 matrix, and \(\Theta_h\) is a k+1 x 1 matrix.
This specification sets \(N_t = h_{1t-1}\), \(n_t = c_t\), \(h_{\tau+1,t-1} = n_{t-(k-\tau)}\) for \(\tau = 1,...,k\).
Below we set things up so that the number of years of education, \(k\), can be varied.
23.2.2. Technology¶
To capture Ryoo and Rosen’s [RR04] supply curve, we use the physical technology:
where \(\psi_1\) is inversely proportional to \(\alpha_s\).
23.2.3. Information¶
Because we want \(b_t = \epsilon_{dt}\) and \(d_{1t} =\epsilon_{st}\), we set
where \(\rho_s\) and \(\rho_d\) describe the persistence of the supply and demand shocks
Information = namedtuple('Information', ['a22', 'c2','ub','ud'])
Technology = namedtuple('Technology', ['ϕ_c', 'ϕ_g', 'ϕ_i', 'γ', 'δ_k', 'θ_k'])
Preferences = namedtuple('Preferences', ['β', 'l_λ', 'π_h', 'δ_h', 'θ_h'])
23.2.4. Effects of Changes in Education Technology and Demand¶
We now study how changing
the number of years of education required to become an engineer and
the slope of the demand curve
affects responses to demand shocks.
To begin, we set \(k = 4\) and \(\alpha_d = 0.1\)
k = 4 # Number of periods of schooling required to become an engineer
β = np.array([[1 / 1.05]])
α_d = np.array([[0.1]])
α_s = 1
ε_1 = 1e-7
λ_1 = np.ones((1, k)) * ε_1
# Use of ε_1 is trick to aquire detectability, see HS2013 p. 228 footnote 4
l_λ = np.hstack((α_d, λ_1))
π_h = np.array([[0]])
δ_n = np.array([[0.95]])
d1 = np.vstack((δ_n, np.zeros((k - 1, 1))))
d2 = np.hstack((d1, np.eye(k)))
δ_h = np.vstack((d2, np.zeros((1, k + 1))))
θ_h = np.vstack((np.zeros((k, 1)),
np.ones((1, 1))))
ψ_1 = 1 / α_s
ϕ_c = np.array([[1], [0]])
ϕ_g = np.array([[0], [-1]])
ϕ_i = np.array([[-1], [ψ_1]])
γ = np.array([[0], [0]])
δ_k = np.array([[0]])
θ_k = np.array([[0]])
ρ_s = 0.8
ρ_d = 0.8
a22 = np.array([[1, 0, 0],
[0, ρ_s, 0],
[0, 0, ρ_d]])
c2 = np.array([[0, 0], [10, 0], [0, 10]])
ub = np.array([[30, 0, 1]])
ud = np.array([[10, 1, 0], [0, 0, 0]])
info1 = Information(a22, c2, ub, ud)
tech1 = Technology(ϕ_c, ϕ_g, ϕ_i, γ, δ_k, θ_k)
pref1 = Preferences(β, l_λ, π_h, δ_h, θ_h)
econ1 = DLE(info1, tech1, pref1)
We create three other instances by:
Raising \(\alpha_d\) to 2
Raising \(k\) to 7
Raising \(k\) to 10
α_d = np.array([[2]])
l_λ = np.hstack((α_d, λ_1))
pref2 = Preferences(β, l_λ, π_h, δ_h, θ_h)
econ2 = DLE(info1, tech1, pref2)
α_d = np.array([[0.1]])
k = 7
λ_1 = np.ones((1, k)) * ε_1
l_λ = np.hstack((α_d, λ_1))
d1 = np.vstack((δ_n, np.zeros((k - 1, 1))))
d2 = np.hstack((d1, np.eye(k)))
δ_h = np.vstack((d2, np.zeros((1, k+1))))
θ_h = np.vstack((np.zeros((k, 1)),
np.ones((1, 1))))
Pref3 = Preferences(β, l_λ, π_h, δ_h, θ_h)
econ3 = DLE(info1, tech1, Pref3)
k = 10
λ_1 = np.ones((1, k)) * ε_1
l_λ = np.hstack((α_d, λ_1))
d1 = np.vstack((δ_n, np.zeros((k - 1, 1))))
d2 = np.hstack((d1, np.eye(k)))
δ_h = np.vstack((d2, np.zeros((1, k + 1))))
θ_h = np.vstack((np.zeros((k, 1)),
np.ones((1, 1))))
pref4 = Preferences(β, l_λ, π_h, δ_h, θ_h)
econ4 = DLE(info1, tech1, pref4)
shock_demand = np.array([[0], [1]])
econ1.irf(ts_length=25, shock=shock_demand)
econ2.irf(ts_length=25, shock=shock_demand)
econ3.irf(ts_length=25, shock=shock_demand)
econ4.irf(ts_length=25, shock=shock_demand)
The first figure plots the impulse response of \(n_t\) (on the left) and \(N_t\) (on the right) to a positive demand shock, for \(\alpha_d = 0.1\) and \(\alpha_d = 2\).
When \(\alpha_d = 2\), the number of new students \(n_t\) rises initially, but the response then turns negative.
A positive demand shock raises wages, drawing new students into the profession.
However, these new students raise \(N_t\).
The higher is \(\alpha_d\), the larger the effect of this rise in \(N_t\) on wages.
This counteracts the demand shock’s positive effect on wages, reducing the number of new students in subsequent periods.
Consequently, when \(\alpha_d\) is lower, the effect of a demand shock on \(N_t\) is larger
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))
ax1.plot(econ1.c_irf,label='$\\alpha_d = 0.1$')
ax1.plot(econ2.c_irf,label='$\\alpha_d = 2$')
ax1.legend()
ax1.set_title('Response of $n_t$ to a demand shock')
ax2.plot(econ1.h_irf[:, 0], label='$\\alpha_d = 0.1$')
ax2.plot(econ2.h_irf[:, 0], label='$\\alpha_d = 24$')
ax2.legend()
ax2.set_title('Response of $N_t$ to a demand shock')
plt.show()
The next figure plots the impulse response of \(n_t\) (on the left) and \(N_t\) (on the right) to a positive demand shock, for \(k=4\), \(k=7\) and \(k=10\) (with \(\alpha_d = 0.1\))
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))
ax1.plot(econ1.c_irf, label='$k=4$')
ax1.plot(econ3.c_irf, label='$k=7$')
ax1.plot(econ4.c_irf, label='$k=10$')
ax1.legend()
ax1.set_title('Response of $n_t$ to a demand shock')
ax2.plot(econ1.h_irf[:,0], label='$k=4$')
ax2.plot(econ3.h_irf[:,0], label='$k=7$')
ax2.plot(econ4.h_irf[:,0], label='$k=10$')
ax2.legend()
ax2.set_title('Response of $N_t$ to a demand shock')
plt.show()
Both panels in the above figure show that raising \(k\) lowers the effect of a positive demand shock on entry into the engineering profession.
Increasing the number of periods of schooling lowers the number of new students in response to a demand shock.
This occurs because with longer required schooling, new students ultimately benefit less from the impact of that shock on wages.