diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5e9c5e60..ffaf30d2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,6 +51,12 @@ jobs: jb build lectures --builder pdflatex --path-output ./ -n --keep-going mkdir -p _build/html/_pdf cp -u _build/latex/*.pdf _build/html/_pdf + - name: Upload Execution Reports (LaTeX) + uses: actions/upload-artifact@v4 + if: failure() + with: + name: execution-reports + path: _build/latex/reports - name: Build Download Notebooks (sphinx-tojupyter) shell: bash -l {0} run: | @@ -66,7 +72,7 @@ jobs: rm -r _build/.doctrees jb build lectures --path-output ./ -nW --keep-going - name: Upload Execution Reports (HTML) - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: failure() with: name: execution-reports diff --git a/lectures/_static/lecture_specific/long_run_growth/tooze_ch1_graph.png b/lectures/_static/lecture_specific/long_run_growth/tooze_ch1_graph.png index d8ccd582..a3833f10 100644 Binary files a/lectures/_static/lecture_specific/long_run_growth/tooze_ch1_graph.png and b/lectures/_static/lecture_specific/long_run_growth/tooze_ch1_graph.png differ diff --git a/lectures/_static/quant-econ.bib b/lectures/_static/quant-econ.bib index 9d0395f7..409748aa 100644 --- a/lectures/_static/quant-econ.bib +++ b/lectures/_static/quant-econ.bib @@ -2782,3 +2782,88 @@ @article{imampolitical year = {2023}, journal = {IMF Working Paper} } + +@article{diamond1965national, + title = {National debt in a neoclassical growth model}, + author = {Diamond, Peter A}, + journal = {The American Economic Review}, + volume = {55}, + number = {5}, + pages = {1126--1150}, + year = {1965}, + publisher = {JSTOR} +} + +@book{auerbach1987dynamic, + title = {Dynamic fiscal policy}, + author = {Auerbach, Alan J and Kotlikoff, Laurence J}, + publisher = {Cambridge University Press}, + address = {Cambridge}, + year = {1987} +} + +@article{sargent_velde1995, + title={Macroeconomic Features of the French Revolution}, + author={Sargent, Thomas J and Velde, Francois R}, + journal={Journal of Political Economy}, + volume={103}, + number={3}, + pages={474--518}, + year={1995} +} + +@article{sargent1981, + title={Some unpleasant monetarist arithmetic}, + author={Sargent, Thomas J and Wallace, Neil}, + journal={Federal reserve bank of minneapolis quarterly review}, + volume={5}, + number={3}, + pages={1--17}, + year={1981} +} + + + + +@article{sargent2009conquest, + title={The conquest of South American inflation}, + author={Sargent, Thomas and Williams, Noah and Zha, Tao}, + journal={Journal of Political Economy}, + volume={117}, + number={2}, + pages={211--256}, + year={2009}, + publisher={The University of Chicago Press} +} + +@article{marcet2003recurrent, + title={Recurrent hyperinflations and learning}, + author={Marcet, Albert and Nicolini, Juan P}, + journal={American Economic Review}, + volume={93}, + number={5}, + pages={1476--1498}, + year={2003}, + publisher={American Economic Association} +} + + +@article{bruno1990seigniorage, + title={Seigniorage, operating rules, and the high inflation trap}, + author={Bruno, Michael and Fischer, Stanley}, + journal={The Quarterly Journal of Economics}, + volume={105}, + number={2}, + pages={353--374}, + year={1990}, + publisher={MIT Press} +} + +@incollection{sargent1989least, + title={Least squares learning and the dynamics of hyperinflation}, + author={Marcet, Albert and Sargent, Thomas J}, + editor = {William Barnett, John Geweke, and Karl Shell}, + booktitle={Sunspots, Complexity, and Chaos}, + year={1989}, + publisher={Cambridge University Press} +} diff --git a/lectures/_toc.yml b/lectures/_toc.yml index 7ba84da9..91ae341f 100644 --- a/lectures/_toc.yml +++ b/lectures/_toc.yml @@ -47,6 +47,15 @@ parts: - file: cobweb - file: olg - file: commod_price +- caption: Monetary-Fiscal Policy Interactions + numbered: true + chapters: + - file: money_inflation + - file: unpleasant + - file: money_inflation_nonlinear + - file: laffer_adaptive + #- file: french_rev + #- file: ak2 - caption: Stochastic Dynamics numbered: true chapters: diff --git a/lectures/ak2.md b/lectures/ak2.md new file mode 100644 index 00000000..6f530a5c --- /dev/null +++ b/lectures/ak2.md @@ -0,0 +1,1172 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.14.1 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +--- + +# Transitions in an Overlapping Generations Model + + + +## Overview + + +This lecture presents a life-cycle model consisting of overlapping generations of two-period lived people proposed by +{cite}`diamond1965national`. + +We'll present the version that was analyzed in chapter 2 of {cite}`auerbach1987dynamic`. + +Auerbach and Kotlikoff (1987) used their two period model as a warm-up for their analysis of overlapping generation models of long-lived people that is the main topic of their book. + +Their model of two-period lived overlapping generations is a useful starting point because + +* it sets forth the structure of interactions between generations of different agents who are alive at a given date +* it activates forces and tradeoffs confronting the government and successive generations of people +* it is good laboratory for studying connections between government tax and subsidy programs and for policies for issuing and servicing government debt +* it is a good setting for introducing describing the **shooting method** for solving a system of non-linear difference equations with boundary conditions that take the form of initial and terminal conditions +* interesting experiments involving transitions from one steady state to another can be computed by hand + ```{note} +Auerbach and Kotlikoff use computer code to calculate transition paths for their models with long-lived people. +``` + +We take the liberty of extending Auerbach and Kotlikoff's chapter 2 model by adding ways to redistribute resources across generations + + * these take the form of a sequence of age-specific lump sum taxes and transfers + +We study how these additional instruments for redistributing resources across generations affect capital accumulation and government debt + + + + + + +## Setting + +Time is discrete and is indexed by $t=0, 1, 2, \ldots$. + +The economy lives forever, but the people inside it do not. + +At each time $ t \geq 0$ a representative old person and a representative young person are alive. + +Thus, at time $t$ a representative old person coexists with a representative young person who will become an old person at time $t+1$. + +We assume that the population size is constant over time. + +A young person works, saves, and consumes. + +An old person dissaves and consumes but does not work, + +There is a government that lives forever, i.e., at $t=0, 1, 2, \ldots $. + +Each period $t \geq 0$, the government taxes, spends, transfers, and borrows. + + + + +Initial conditions set from outside the model at time $t=0$ are + +* $K_0$ -- initial capital stock brought into time $t=0$ by a representative initial old person +* $D_0$ government debt falling due at $t=0$ and owned by a representative old person at time $t=0$ + +$K_0$ and $D_0$ are both measured in units of time $0$ goods. + +A government **policy** consists of five sequences $\{G_t, D_t, \tau_t, \delta_{ot}, \delta_{yt}\}_{t=0}^\infty $ whose components are + + * $\tau_t$ -- flat rate tax at time $t$ on wages and earnings from capital and government bonds + * $D_t$ -- one-period government bond principal due at time $t$, per capita + * $G_t$ -- government purchases of goods at time $t$ (`thrown into ocean'), per capita + * $\delta_{yt}$ -- a lump sum tax on each young person at time $t$ + * $\delta_{ot}$ -- a lump sum tax on each old person at time $t$ + + + +An **allocation** is a collection of sequences $\{C_{yt}, C_{ot}, K_{t+1}, L_t, Y_t, G_t\}_{t=0}^\infty $; constituents of the sequences include + + * $K_t$ -- physical capital per capita + * $L_t$ -- labor per capita + * $Y_t$ -- output per capita + +and also + +* $C_{yt}$ -- consumption of young person at time $t \geq 0$ +* $C_{ot}$ -- consumption of old person at time $t \geq 0$ +* $K_{t+1} - K_t \equiv I_t $ -- investment in physical capital at time $t \geq 0$ +* $G_t$ -- government purchases + +National income and product accounts consist of a sequence of equalities + +* $Y_t = C_{yt} + C_{ot} + (K_{t+1} - K_t) + G_t, \quad t \geq 0$ + +A **price system** is a pair of sequences $\{W_t, r_t\}_{t=0}^\infty$; constituents of the sequence include rental rates for the factors of production + +* $W_t$ -- rental rate for labor at time $t \geq 0$ +* $r_t$ -- rental rate for capital at time $t \geq 0$ + + +## Production + +There are two factors of production, physical capital $K_t$ and labor $L_t$. + +Capital does not depreciate. + +The initial capital stock $K_0$ is owned by the initial old person, who rents it to the firm at time $0$. + +The economy's net investment rate $I_t$ at time $t$ is + +$$ +I_t = K_{t+1} - K_t +$$ + +The economy's capital stock at time $t$ emerges from cumulating past rates of investment: + +$$ +K_t = K_0 + \sum_{s=0}^{t-1} I_s +$$ + +There is a Cobb-Douglas technology that converts physical capital $K_t$ and labor services $L_t$ into +output $Y_t$ + +$$ +Y_t = K_t^\alpha L_t^{1-\alpha}, \quad \alpha \in (0,1) +$$ (eq:prodfn) + + +## Government + +At time $t-1$, the government issues one-period risk-free debt that promises to pay $D_t$ time $t$ goods per capita at time $t$. + +Young people at time $t$ purchase government debt $D_{t+1}$ that matures at time $t+1$. + +Government debt issued at $t$ bears a before-tax net rate of interest rate of $r_{t}$ at time $t+1$. + +The government budget constraint at time $t \geq 0$ is + +$$ +D_{t+1} - D_t = r_t D_t + G_t - T_t +$$ + +or + + + + +$$ +D_{t+1} = (1 + r_t) D_t + G_t - T_t . +$$ (eq:govbudgetsequence) + +Here total tax collections net of transfers are given by $T_t$ satisfying + + +$$ +T_t = \tau_t W_t L_t + \tau_t r_t (D_t + K_t) + \delta_{yt} + \delta_{ot} +$$ + + + + +## Households' Activities in Factor Markets + +**Old people:** At each $t \geq 0$, an old person + + * brings $K_t$ and $D_t$ into the period, + * rents capital to a representative firm for $r_{t} K_t$, + * pays taxes $\tau_t (K_t+ D_t)$ on its rental and interest earnings, + * pays a lump sum tax $\delta_{ot}$ to the government, + * sells $K_t$ to a young person. + + + **Young people:** At each $t \geq 0$, a young person + * sells one unit of labor services to a representative firm for $W_t$ in wages, + * pays taxes $\tau_t W_t$ on its labor earnings + * pays a lump sum tax $\delta_{yt}$ to the goverment, + * spends $C_{yt}$ on consumption, + * acquires non-negative assets $A_{t+1}$ consisting of a sum of physical capital $K_{t+1}$ and one-period government bonds $D_{t+1}$ that mature at $t+1$. + +```{note} +If a lump-sum tax is negative, it means that the government pays the person a subsidy. +``` + + +## Representative firm's problem + +The firm hires labor services from young households at competitive wage rate $W_t$ and hires capital from old households at competitive rental rate +$r_t$. + +The rental rate on capital $r_t$ equals the interest rate on government one-period bonds. + +Units of the rental rates are: + +* for $W_t$, output at time $t$ per unit of labor at time $t$ +* for $r_t$, output at time $t$ per unit of capita at time $t$ + + +We take output at time $t$ as *numeraire*, so the price of output at time $t$ is one. + +The firm's profits at time $t$ are thus + +$$ +K_t^\alpha L_t^{1-\alpha} - r_t K_t - W_t L_t . +$$ + +To maximize profits a firm equates marginal products to rental rates: + +$$ +\begin{aligned} +W_t & = (1-\alpha) K_t^\alpha L_t^{-\alpha} \\ +r_t & = \alpha K_t^\alpha L_t^{1-\alpha} +\end{aligned} +$$ (eq:firmfonc) + +Output can either be consumed by old or young households, sold to young households who use it to augment the capital stock, or sold to the government for uses that do not generate utility for the people in the model (e.g., ``thrown into the ocean''). + + +The firm thus sells output to old households, young households, and the government. + + + + + + + + + +## Households' problems + +### Initial old household + +At time $t=0$, a representative initial old household is endowed with $(1 + r_0(1 - \tau_0)) A_0$ in initial assets. + +It must pay a lump sum tax to (if positive) or receive a subsidy from (if negative) +$\delta_{ot}$ the government. + +An old household's budget constraint is + + + +$$ +C_{o0} = (1 + r_0 (1 - \tau_0)) A_0 - \delta_{ot} . +$$ (eq:hbudgetold) + +An initial old household's utility function is $C_{o0}$, so the household's optimal consumption plan +is provided by equation {eq}`eq:hbudgetold`. + +### Young household + +At each $t \geq 0$, a young household inelastically supplies one unit of labor and in return +receives pre-tax labor earnings of $W_t$ units of output. + +A young-household's post-tax-and-transfer earnings are $W_t (1 - \tau_t) - \delta_{yt}$. + +At each $t \geq 0$, a young household chooses a consumption plan $C_{yt}, C_{ot+1}$ +to maximize the Cobb-Douglas utility function + +$$ +U_t = C_{yt}^\beta C_{o,t+1}^{1-\beta}, \quad \beta \in (0,1) +$$ (eq:utilfn) + +subject to the following budget constraints at times $t$ and $t+1$: + +$$ +\begin{aligned} +C_{yt} + A_{t+1} & = W_t (1 - \tau_t) - \delta_{yt} \\ +C_{ot+1} & = (1+ r_{t+1} (1 - \tau_{t+1}))A_{t+1} - \delta_{ot} +\end{aligned} +$$ (eq:twobudgetc) + + +Solving the second equation of {eq}`eq:twobudgetc` for savings $A_{t+1}$ and substituting it into the first equation implies the present value budget constraint + +$$ +C_{yt} + \frac{C_{ot+1}}{1 + r_{t+1}(1 - \tau_{t+1})} = W_t (1 - \tau_t) - \delta_{yt} - \frac{\delta_{ot}}{1 + r_{t+1}(1 - \tau_{t+1})} +$$ (eq:onebudgetc) + +To solve the young household's choice problem, form a Lagrangian + +$$ +\begin{aligned} +{\mathcal L} & = C_{yt}^\beta C_{o,t+1}^{1-\beta} \\ & + \lambda \Bigl[ C_{yt} + \frac{C_{ot+1}}{1 + r_{t+1}(1 - \tau_{t+1})} - W_t (1 - \tau_t) + \delta_{yt} + \frac{\delta_{ot}}{1 + r_{t+1}(1 - \tau_{t+1})}\Bigr], +\end{aligned} +$$ (eq:lagC) + +where $\lambda$ is a Lagrange multiplier on the intertemporal budget constraint {eq}`eq:onebudgetc`. + + +After several lines of algebra, the intertemporal budget constraint {eq}`eq:onebudgetc` and the first-order conditions for maximizing ${\mathcal L}$ with respect to $C_{yt}, C_{ot+1}$ +imply that an optimal consumption plan satisfies + +$$ +\begin{aligned} +C_{yt} & = \beta \Bigl[ W_t (1 - \tau_t) - \delta_{yt} - \frac{\delta_{ot}}{1 + r_{t+1}(1 - \tau_{t+1})}\Bigr] \\ +\frac{C_{0t+1}}{1 + r_{t+1}(1-\tau_{t+1}) } & = (1-\beta) \Bigl[ W_t (1 - \tau_t) - \delta_{yt} - \frac{\delta_{ot}}{1 + r_{t+1}(1 - \tau_{t+1})}\Bigr] +\end{aligned} +$$ (eq:optconsplan) + +The first-order condition for minimizing Lagrangian {eq}`eq:lagC` with respect to the Lagrange multipler $\lambda$ recovers the budget constraint {eq}`eq:onebudgetc`, +which, using {eq}`eq:optconsplan` gives the optimal savings plan + +$$ +A_{t+1} = (1-\beta) [ (1- \tau_t) W_t - \delta_{yt}] + \beta \frac{\delta_{ot}}{1 + r_{t+1}(1 - \tau_{t+1})} +$$ (eq:optsavingsplan) + + +(sec-equilibrium)= +## Equilbrium + +**Definition:** An equilibrium is an allocation, a government policy, and a price system with the properties that +* given the price system and the government policy, the allocation solves + * represenative firms' problems for $t \geq 0$ + * households problems for $t \geq 0$ +* given the price system and the allocation, the government budget constraint is satisfies for all $t \geq 0$. + + +## Next steps + + +To begin our analysis of equilibrium outcomes, we'll study the special case of the model with which Auerbach and +Kotlikoff (1987) {cite}`auerbach1987dynamic` began their analysis in chapter 2. + +It can be solved by hand. + +We shall do that next. + +After we derive a closed form solution, we'll pretend that we don't know and will compute equilibrium outcome paths. + +We'll do that by first formulating an equilibrium as a fixed point of a mapping from sequences of factor prices and tax rates to sequences of factor prices and tax rates. + +We'll compute an equilibrium by iterating to convergence on that mapping. + + +## Closed form solution + +To get the special chapter 2 case of Auerbach and Kotlikoff (1987) {cite}`auerbach1987dynamic`, we set both $\delta_{ot}$ and $\delta_{yt}$ to zero. + +As our special case of {eq}`eq:optconsplan`, we compute the following consumption-savings plan for a representative young person: + + +$$ +\begin{aligned} +C_{yt} & = \beta (1 - \tau_t) W_t \\ +A_{t+1} &= (1-\beta) (1- \tau_t) W_t +\end{aligned} +$$ + +Using {eq}`eq:firmfonc` and $A_t = K_t + D_t$, we obtain the following closed form transition law for capital: + +$$ +K_{t+1}=K_{t}^{\alpha}\left(1-\tau_{t}\right)\left(1-\alpha\right)\left(1-\beta\right) - D_{t}\\ +$$ (eq:Klawclosed) + +### Steady states + +From {eq}`eq:Klawclosed` and the government budget constraint {eq}`eq:govbudgetsequence`, we compute **time-invariant** or **steady state values** $\hat K, \hat D, \hat T$: + +$$ +\begin{aligned} +\hat{K} &=\hat{K}\left(1-\hat{\tau}\right)\left(1-\alpha\right)\left(1-\beta\right) - \hat{D} \\ +\hat{D} &= (1 + \hat{r}) \hat{D} + \hat{G} - \hat{T} \\ +\hat{T} &= \hat{\tau} \hat{Y} + \hat{\tau} \hat{r} \hat{D} . +\end{aligned} +$$ (eq:steadystates) + +These imply + +$$ +\begin{aligned} +\hat{K} &= \left[\left(1-\hat{\tau}\right)\left(1-\alpha\right)\left(1-\beta\right)\right]^{\frac{1}{1-\alpha}} \\ +\hat{\tau} &= \frac{\hat{G} + \hat{r} \hat{D}}{\hat{Y} + \hat{r} \hat{D}} +\end{aligned} +$$ + +Let's take an example in which + +1. there is no initial government debt, $D_t=0$, +2. government consumption $G_t$ equals $15\%$ of output $Y_t$ + +Our formulas for steady-state values tell us that + +$$ +\begin{aligned} +\hat{D} &= 0 \\ +\hat{G} &= 0.15 \hat{Y} \\ +\hat{\tau} &= 0.15 \\ +\end{aligned} +$$ + + + +## Code + + +In addition to what’s in Anaconda, this lecture will need the following libraries: + +```{code-cell} ipython3 +!pip install --upgrade quantecon +``` + +```{code-cell} ipython3 +import numpy as np +import matplotlib.pyplot as plt +from numba import jit, prange +from quantecon.optimize import brent_max +``` + + +For parameters $\alpha = 0.3$ and $\beta = 0.5$, let's compute $\hat{K}$: + +```{code-cell} ipython3 +# parameters +α = 0.3 +β = 0.5 + +# steady state ̂τ +τ_hat = 0.15 +D_hat = 0. + +# solve for steady state +K_hat = ((1 - τ_hat) * (1 - α) * (1 - β)) ** (1 / (1 - α)) +K_hat +``` +Knowing $\hat K$, we can calculate other equilibrium objects. + +Let's first define some Python helper functions. + +```{code-cell} ipython3 +@jit +def K_to_Y(K, α): + return K ** α + +@jit +def K_to_r(K, α): + return α * K ** (α - 1) + +@jit +def K_to_W(K, α): + return (1 - α) * K ** α + +@jit +def K_to_C(K, D, τ, r, α, β): + + # consumption for old + A = K + D + Co = A * (1 + r * (1 - τ)) + + # consumption for young + W = K_to_W(K, α) + Cy = β * W * (1 - τ) + + return Cy, Co +``` + +We can use these helper functions to obtain steady state values $\hat{Y}$, $\hat{r}$, and $\hat{W}$ associated with steady state values $\hat{K}$ and $\hat{r}$. + +```{code-cell} ipython3 +Y_hat, r_hat, W_hat = K_to_Y(K_hat, α), K_to_r(K_hat, α), K_to_W(K_hat, α) +Y_hat, r_hat, W_hat +``` + +Since steady state government debt $\hat{D}$ is $0$, all taxes are used to pay for government expenditures + +```{code-cell} ipython3 +G_hat = τ_hat * Y_hat +G_hat +``` + +We use the optimal consumption plans to find steady state consumption for young and old are given by the + +```{code-cell} ipython3 +Cy_hat, Co_hat = K_to_C(K_hat, D_hat, τ_hat, r_hat, α, β) +Cy_hat, Co_hat +``` + +Let's store the steady state quantities and prices using an array called `init_ss` + +```{code-cell} ipython3 +init_ss = np.array([K_hat, Y_hat, Cy_hat, Co_hat, # quantities + W_hat, r_hat, # prices + τ_hat, D_hat, G_hat # policies + ]) +``` + + +### Transitions + +%Zejin: I tried to edit the following part to describe the fiscal policy %experiment and the objects we are interested in computing. + +We have computed a steady state in which the government policy sequences are each constant over time. + + +We'll use this steady state as an initial condition at time $t=0$ for another economy in which government policy sequences are with time-varying sequences. + +To make sense of our calculation, we'll treat $t=0$ as time when a huge unanticipated shock occurs in the form of + + * a time-varying government policy sequences that disrupts an original steady state + * new government policy sequences are eventually time-invariant in the sense that after some date $T >0$, each sequence is constant over time. + * sudden revelation of a new government policy in the form of sequences starting at time $t=0$ + +We assume that everyone, including old people at time $t=0$, know the new government policy sequence and choose accordingly. + + + + +As the capital stock and other economy aggregates adjust to the fiscal policy change over time, the economy will approach a new steady state. + +We can find a transition path from an old steady state to a new steady state by employing a fixed-point algorithm in a space of sequences. + +But in our special case with its closed form solution, we have available a simpler and faster +approach. + +Here we define a Python class `ClosedFormTrans` that computes length $T$ transitional path of the economy in response to a particular fiscal policy change. + +We choose $T$ large enough so that we have gotten very close to a new steady state after $T$ periods. + +The class takes three keyword arguments, `τ_pol`, `D_pol`, and `G_pol`. + +These are sequences of tax rate, government debt level, and government purchases, respectively. + +In each policy experiment below, we will pass two out of three as inputs that fully depict a fiscal policy change. + +We'll then compute the single remaining policy variable from the government budget constraint. + +When simulating the transitional paths, it is useful to distinguish what **state variables** at time $t$ such as $K_t, Y_t, D_t, W_t, r_t$ from **control variables** including $C_{yt}, C_{ot}, \tau_{t}, G_t$. + +```{code-cell} ipython3 +class ClosedFormTrans: + """ + This class simulates length T transitional path of a economy + in response to a fiscal policy change given its initial steady + state. The simulation is based on the closed form solution when + the lump sum taxations are absent. + + """ + + def __init__(self, α, β): + + self.α, self.β = α, β + + def simulate(self, + T, # length of transitional path to simulate + init_ss, # initial steady state + τ_pol=None, # sequence of tax rates + D_pol=None, # sequence of government debt levels + G_pol=None): # sequence of government purchases + + α, β = self.α, self.β + + # unpack the steady state variables + K_hat, Y_hat, Cy_hat, Co_hat = init_ss[:4] + W_hat, r_hat = init_ss[4:6] + τ_hat, D_hat, G_hat = init_ss[6:9] + + # initialize array containers + # K, Y, Cy, Co + quant_seq = np.empty((T+1, 4)) + + # W, r + price_seq = np.empty((T+1, 2)) + + # τ, D, G + policy_seq = np.empty((T+2, 3)) + + # t=0, starting from steady state + K0, Y0 = K_hat, Y_hat + W0, r0 = W_hat, r_hat + D0 = D_hat + + # fiscal policy + if τ_pol is None: + D1 = D_pol[1] + G0 = G_pol[0] + τ0 = (G0 + (1 + r0) * D0 - D1) / (Y0 + r0 * D0) + elif D_pol is None: + τ0 = τ_pol[0] + G0 = G_pol[0] + D1 = (1 + r0) * D0 + G0 - τ0 * (Y0 + r0 * D0) + elif G_pol is None: + D1 = D_pol[1] + τ0 = τ_pol[0] + G0 = τ0 * (Y0 + r0 * D0) + D1 - (1 + r0) * D0 + + # optimal consumption plans + Cy0, Co0 = K_to_C(K0, D0, τ0, r0, α, β) + + # t=0 economy + quant_seq[0, :] = K0, Y0, Cy0, Co0 + price_seq[0, :] = W0, r0 + policy_seq[0, :] = τ0, D0, G0 + policy_seq[1, 1] = D1 + + # starting from t=1 to T + for t in range(1, T+1): + + # transition of K + K_old, τ_old = quant_seq[t-1, 0], policy_seq[t-1, 0] + D = policy_seq[t, 1] + K = K_old ** α * (1 - τ_old) * (1 - α) * (1 - β) - D + + # output, capital return, wage + Y, r, W = K_to_Y(K, α), K_to_r(K, α), K_to_W(K, α) + + # to satisfy the government budget constraint + if τ_pol is None: + D = D_pol[t] + D_next = D_pol[t+1] + G = G_pol[t] + τ = (G + (1 + r) * D - D_next) / (Y + r * D) + elif D_pol is None: + τ = τ_pol[t] + G = G_pol[t] + D = policy_seq[t, 1] + D_next = (1 + r) * D + G - τ * (Y + r * D) + elif G_pol is None: + D = D_pol[t] + D_next = D_pol[t+1] + τ = τ_pol[t] + G = τ * (Y + r * D) + D_next - (1 + r) * D + + # optimal consumption plans + Cy, Co = K_to_C(K, D, τ, r, α, β) + + # store time t economy aggregates + quant_seq[t, :] = K, Y, Cy, Co + price_seq[t, :] = W, r + policy_seq[t, 0] = τ + policy_seq[t+1, 1] = D_next + policy_seq[t, 2] = G + + self.quant_seq = quant_seq + self.price_seq = price_seq + self.policy_seq = policy_seq + + return quant_seq, price_seq, policy_seq + + def plot(self): + + quant_seq = self.quant_seq + price_seq = self.price_seq + policy_seq = self.policy_seq + + fig, axs = plt.subplots(3, 3, figsize=(14, 10)) + + # quantities + for i, name in enumerate(['K', 'Y', 'Cy', 'Co']): + ax = axs[i//3, i%3] + ax.plot(range(T+1), quant_seq[:T+1, i], label=name) + ax.hlines(init_ss[i], 0, T+1, color='r', linestyle='--') + ax.legend() + ax.set_xlabel('t') + + # prices + for i, name in enumerate(['W', 'r']): + ax = axs[(i+4)//3, (i+4)%3] + ax.plot(range(T+1), price_seq[:T+1, i], label=name) + ax.hlines(init_ss[i+4], 0, T+1, color='r', linestyle='--') + ax.legend() + ax.set_xlabel('t') + + # policies + for i, name in enumerate(['τ', 'D', 'G']): + ax = axs[(i+6)//3, (i+6)%3] + ax.plot(range(T+1), policy_seq[:T+1, i], label=name) + ax.hlines(init_ss[i+6], 0, T+1, color='r', linestyle='--') + ax.legend() + ax.set_xlabel('t') +``` + +We can create an instance `closed` given model parameters $\{\alpha, \beta\}$ and use it for various fiscal policy experiments. + + +```{code-cell} ipython3 +closed = ClosedFormTrans(α, β) +``` + +(exp-tax-cut)= +### Experiment 1: Tax cut + +To illustrate the power of `ClosedFormTrans`, let's first experiment with the following fiscal policy change: + +1. at $t=0$, the government unexpectedly announces a one-period tax cut, $\tau_0 =(1-\frac{1}{3}) \hat{\tau}$, by issuing government debt $\bar{D}$ +2. from $t=1$, the government will keep $D_t=\bar{D}$ and adjust $\tau_{t}$ to collect taxation to pay for the government consumption and interest payments on the debt +3. government consumption $G_t$ will be fixed at $0.15 \hat{Y}$ + +The following equations completely characterize the equilibrium transition path originating from the initial steady state + +$$ +\begin{aligned} +K_{t+1} &= K_{t}^{\alpha}\left(1-\tau_{t}\right)\left(1-\alpha\right)\left(1-\beta\right) - \bar{D} \\ +\tau_{0} &= (1-\frac{1}{3}) \hat{\tau} \\ +\bar{D} &= \hat{G} - \tau_0\hat{Y} \\ +\quad\tau_{t} & =\frac{\hat{G}+r_{t} \bar{D}}{\hat{Y}+r_{t} \bar{D}} +\end{aligned} +$$ + +We can simulate the transition of the economy for $20$ periods, after which the economy will be fairly close to the new steady state. + +The first step is to prepare sequences of policy variables that describe the fiscal policy change. + + In this example, we need to define sequences of government expenditure $\{G_t\}_{t=0}^{T}$ and debt level $\{D_t\}_{t=0}^{T+1}$ in advance, then pass them to the solver. + +```{code-cell} ipython3 +T = 20 + +# tax cut +τ0 = τ_hat * (1 - 1/3) + +# sequence of government purchase +G_seq = τ_hat * Y_hat * np.ones(T+1) + +# sequence of government debt +D_bar = G_hat - τ0 * Y_hat +D_seq = np.ones(T+2) * D_bar +D_seq[0] = D_hat +``` + +Let's use the `simulate` method of `closed` to obtain the dynamic transitions. + +Note that we leave `τ_pol` as `None`, since the tax rates need to be determined to satisfy the government budget constraint. + +```{code-cell} ipython3 +quant_seq1, price_seq1, policy_seq1 = closed.simulate(T, init_ss, + D_pol=D_seq, + G_pol=G_seq) +closed.plot() +``` + +We can also easily experiment with a lower tax cut rate, such as $0.2$, and compare + +```{code-cell} ipython3 +# lower tax cut rate +τ0 = 0.15 * (1 - 0.2) + +# the corresponding debt sequence +D_bar = G_hat - τ0 * Y_hat +D_seq = np.ones(T+2) * D_bar +D_seq[0] = D_hat + +quant_seq2, price_seq2, policy_seq2 = closed.simulate(T, init_ss, + D_pol=D_seq, + G_pol=G_seq) +``` + +```{code-cell} ipython3 +fig, axs = plt.subplots(3, 3, figsize=(14, 10)) + +# quantities +for i, name in enumerate(['K', 'Y', 'Cy', 'Co']): + ax = axs[i//3, i%3] + ax.plot(range(T+1), quant_seq1[:T+1, i], label=name+', 1/3') + ax.plot(range(T+1), quant_seq2[:T+1, i], label=name+', 0.2') + ax.hlines(init_ss[i], 0, T+1, color='r', linestyle='--') + ax.legend() + ax.set_xlabel('t') + +# prices +for i, name in enumerate(['W', 'r']): + ax = axs[(i+4)//3, (i+4)%3] + ax.plot(range(T+1), price_seq1[:T+1, i], label=name+', 1/3') + ax.plot(range(T+1), price_seq2[:T+1, i], label=name+', 0.2') + ax.hlines(init_ss[i+4], 0, T+1, color='r', linestyle='--') + ax.legend() + ax.set_xlabel('t') + +# policies +for i, name in enumerate(['τ', 'D', 'G']): + ax = axs[(i+6)//3, (i+6)%3] + ax.plot(range(T+1), policy_seq1[:T+1, i], label=name+', 1/3') + ax.plot(range(T+1), policy_seq2[:T+1, i], label=name+', 0.2') + ax.hlines(init_ss[i+6], 0, T+1, color='r', linestyle='--') + ax.legend() + ax.set_xlabel('t') +``` + +### Experiment 2: Government asset accumulation + +Assuming that the economy was in the same steady state, but instead of announcing a tax cut at $t=0$, the government now promises to cut its spending on services and goods by a half $\forall t \leq 0$. + +The government wants to target the same tax rate $\tau_t=\hat{\tau}$ and accumulate assets $-D_t$ over time. + +Note that in this experiment, we pass `τ_seq` and `G_seq` as inputs, and let `D_pol` be determined along the path by satisfying the government budget constraint. + +```{code-cell} ipython3 +# government expenditure cut by a half +G_seq = τ_hat * 0.5 * Y_hat * np.ones(T+1) + +# targeted tax rate +τ_seq = τ_hat * np.ones(T+1) + +closed.simulate(T, init_ss, τ_pol=τ_seq, G_pol=G_seq); +closed.plot() +``` + +It will be useful for understanding the transition paths by looking at the ratio of government asset to the output, $-\frac{D_t}{Y_t}$ + +```{code-cell} ipython3 +plt.plot(range(T+1), -closed.policy_seq[:-1, 1] / closed.quant_seq[:, 0]) +plt.xlabel('t') +plt.title('-D/Y'); +``` + +### Experiment 3: Temporary expenditure cut + +Let's now consider the case where the government also cuts its spending by half and accumulates asset. + +But this time the expenditure cut only lasts for one period at $t=0$. + +From $t \geq 1$, the government will return to the original level of consumption $\hat{G}$, and will adjust $\tau_t$ to maintain the same level of asset $-D_t = -D_1$. + +```{code-cell} ipython3 +# sequence of government purchase +G_seq = τ_hat * Y_hat * np.ones(T+1) +G_seq[0] = 0 + +# sequence of government debt +D_bar = G_seq[0] - τ_hat * Y_hat +D_seq = D_bar * np.ones(T+2) +D_seq[0] = D_hat + +closed.simulate(T, init_ss, D_pol=D_seq, G_pol=G_seq); +closed.plot() +``` + + + +## A computational strategy + +In the above illustrations, we studied dynamic transitions associated with various fiscal policy experiments. + +In these experiments, we maintained the assumption that lump sum taxes are absent ($\delta_{yt}=0, \delta_{ot}=0$). + +In this section, we investigate the transition dynamics when the lump sum taxes are present. + +The government will use lump sum taxes and transfers to redistribute resources across successive +generations. + +Including lump sum taxes will break down the closed form solution because now optimal consumption and saving plans will depend on future prices and tax rates. + +Therefore, we use a more general way of solving for equilibriunm transitional paths that involves computing them as a fixed point in a mapping from sequences to sequences. + +We elaborate on the equilibrium conditions as we define in section {ref}`sec-equilibrium`, which characterize the fixed point + +**Definition:** Given model parameters $\{\alpha$, $\beta\}$, a competitive equilibrium consists of + +* sequences of optimal consumptions $\{C_{yt}, C_{ot}\}$ +* sequences of prices $\{W_t, r_t\}$ +* sequences of capital stock and output $\{K_t, Y_t\}$ +* sequences of tax rates, government assets (debt), government purchases $\{\tau_t, D_t, G_t\, \delta_{yt}, \delta_{ot}\}$ + +with the properties that + +* given the price system and government fiscal policy, the household consumption plans are optimal +* the government budget constraints are satisfied for all $t$ + +An equilibrium transition path can be computed by "guessing and verifying" + +In our {ref}`exp-tax-cut` example, sequences $\{D_t\}_{t=0}^{T}$ and $\{G_t\}_{t=0}^{T}$ are exogenous. + +In addition, we assume that the lump sum taxes $\{\delta_{yt}, \delta_{ot}\}_{t=0}^{T}$ are given and known to the households. + +We can solve for sequences of other equilibrium objects following the steps below + +1. guesses prices $\{W_t, r_t\}_{t=0}^{T}$ and tax rates $\{\tau_t\}_{t=0}^{T}$ +2. solve for optimal consumption and saving plans $\{C_{yt}, C_{ot}\}_{t=0}^{T}$, treating the guesses of future prices and taxes as true +3. solve for transitional dynamics of the capital stock $\{K_t\}_{t=0}^{T}$ +4. update the guesses for prices and tax rates with the values implied by the equilibrium conditions +5. iterate until convergence + +Below we implement the "guess and verify" computation. + +We start by defining the Cobb-Douglas utility function + +```{code-cell} ipython3 +@jit +def U(Cy, Co, β): + + return (Cy ** β) * (Co ** (1-β)) +``` + +We use `Cy_val` to compute the lifetime value of choosing an arbitrary consumption plan, $C_y$, given the intertemporal budget constraint. + +Note that it requires knowing future prices $r_{t+1}$ and tax rate $\tau_{t+1}$. + +```{code-cell} ipython3 +@jit +def Cy_val(Cy, W, r_next, τ, τ_next, δy, δo_next, β): + + # Co given by the budget constraint + Co = (W * (1 - τ) - δy - Cy) * (1 + r_next * (1 - τ_next)) - δo_next + + return U(Cy, Co, β) +``` + +The optimal consumption plan $C_y^*$ can be found by maximizing `Cy_val`. + +Here is an example of finding the optimal consumption $C_y^*=\hat{C}_y$ in the steady state as we discussed before, with $\delta_{yt}=\delta_{ot}=0$ + +```{code-cell} ipython3 +W, r_next, τ, τ_next = W_hat, r_hat, τ_hat, τ_hat +δy, δo_next = 0, 0 + +Cy_opt, U_opt, _ = brent_max(Cy_val, # maximand + 1e-6, # lower bound + W*(1-τ)-δy-1e-6, # upper bound + args=(W, r_next, τ, τ_next, δy, δo_next, β)) + +Cy_opt, U_opt +``` + +Below we define a Python class `AK2` that solves for the transitional paths of the economy using the fixed-point algorithm. It can handle any fiscal policy experiment including nonzero lump sum taxations + +```{code-cell} ipython3 +class AK2(): + """ + This class simulates length T transitional path of a economy + in response to a fiscal policy change given its initial steady + state. The transitional path is found by employing a fixed point + algorithm that and uses equilibrium conditions. + + """ + + def __init__(self, α, β): + + self.α, self.β = α, β + + def simulate(self, + T, # length of transitional path to simulate + init_ss, # initial steady state + δy_seq, # sequence of lump sum tax for the young + δo_seq, # sequence of lump sum tax for the old + τ_pol=None, # sequence of tax rates + D_pol=None, # sequence of government debt levels + G_pol=None, # sequence of government purchases + verbose=False, + max_iter=500, + tol=1e-5): + + α, β = self.α, self.β + + # unpack the steady state variables + K_hat, Y_hat, Cy_hat, Co_hat = init_ss[:4] + W_hat, r_hat = init_ss[4:6] + τ_hat, D_hat, G_hat = init_ss[6:9] + + # K, Y, Cy, Co + quant_seq = np.empty((T+2, 4)) + + # W, r + price_seq = np.empty((T+2, 2)) + + # τ, D, G + policy_seq = np.empty((T+2, 3)) + policy_seq[:, 1] = D_pol + policy_seq[:, 2] = G_pol + + # initial guesses of prices + price_seq[:, 0] = np.ones(T+2) * W_hat + price_seq[:, 1] = np.ones(T+2) * r_hat + + # initial guesses of policies + policy_seq[:, 0] = np.ones(T+2) * τ_hat + + # t=0, starting from steady state + quant_seq[0, :2] = K_hat, Y_hat + + if verbose: + # prepare to plot iterations until convergence + fig, axs = plt.subplots(1, 3, figsize=(14, 4)) + + # containers for checking convergence + price_seq_old = np.empty_like(price_seq) + policy_seq_old = np.empty_like(policy_seq) + + # start iteration + i_iter = 0 + while True: + + if verbose: + # plot current prices at ith iteration + for i, name in enumerate(['W', 'r']): + axs[i].plot(range(T+1), price_seq[:T+1, i]) + axs[i].set_title(name) + axs[i].set_xlabel('t') + axs[2].plot(range(T+1), policy_seq[:T+1, 0]) + axs[2].set_title('τ') + axs[2].set_xlabel('t') + + # store old prices from last iteration + price_seq_old[:] = price_seq + policy_seq_old[:] = policy_seq + + # start updating quantities and prices + for t in range(T+1): + K, Y = quant_seq[t, :2] + W, r = price_seq[t, :] + r_next = price_seq[t+1, 1] + τ, D, G = policy_seq[t, :] + τ_next, D_next, G_next = policy_seq[t+1, :] + δy, δo = δy_seq[t], δo_seq[t] + δy_next, δo_next = δy_seq[t+1], δo_seq[t+1] + + # consumption for the old + Co = (1 + r * (1 - τ)) * (K + D) - δo + + # optimal consumption for the young + out = brent_max(Cy_val, 1e-6, W*(1-τ)-δy-1e-6, + args=(W, r_next, τ, τ_next, + δy, δo_next, β)) + Cy = out[0] + + quant_seq[t, 2:] = Cy, Co + τ_num = ((1 + r) * D + G - D_next - δy - δo) + τ_denom = (Y + r * D) + policy_seq[t, 0] = τ_num / τ_denom + + # saving of the young + A_next = W * (1 - τ) - δy - Cy + + # transition of K + K_next = A_next - D_next + Y_next = K_to_Y(K_next, α) + W_next, r_next = K_to_W(K_next, α), K_to_r(K_next, α) + + quant_seq[t+1, :2] = K_next, Y_next + price_seq[t+1, :] = W_next, r_next + + i_iter += 1 + + if (np.max(np.abs(price_seq_old - price_seq)) < tol) & \ + (np.max(np.abs(policy_seq_old - policy_seq)) < tol): + if verbose: + print(f"Converge using {i_iter} iterations") + break + + if i_iter > max_iter: + if verbose: + print(f"Fail to converge using {i_iter} iterations") + break + + self.quant_seq = quant_seq + self.price_seq = price_seq + self.policy_seq = policy_seq + + return quant_seq, price_seq, policy_seq + + def plot(self): + + quant_seq = self.quant_seq + price_seq = self.price_seq + policy_seq = self.policy_seq + + fig, axs = plt.subplots(3, 3, figsize=(14, 10)) + + # quantities + for i, name in enumerate(['K', 'Y', 'Cy', 'Co']): + ax = axs[i//3, i%3] + ax.plot(range(T+1), quant_seq[:T+1, i], label=name) + ax.hlines(init_ss[i], 0, T+1, color='r', linestyle='--') + ax.legend() + ax.set_xlabel('t') + + # prices + for i, name in enumerate(['W', 'r']): + ax = axs[(i+4)//3, (i+4)%3] + ax.plot(range(T+1), price_seq[:T+1, i], label=name) + ax.hlines(init_ss[i+4], 0, T+1, color='r', linestyle='--') + ax.legend() + ax.set_xlabel('t') + + # policies + for i, name in enumerate(['τ', 'D', 'G']): + ax = axs[(i+6)//3, (i+6)%3] + ax.plot(range(T+1), policy_seq[:T+1, i], label=name) + ax.hlines(init_ss[i+6], 0, T+1, color='r', linestyle='--') + ax.legend() + ax.set_xlabel('t') +``` + +We can initialize an instance of class `AK2` with model parameters $\{\alpha, \beta\}$ and then use it for various fiscal policy experiments. + +```{code-cell} ipython3 +ak2 = AK2(α, β) +``` + +We first examine that the "guess and verify" method leads to the same numerical results as we obtain with the closed form solution when lump sum taxes are muted + +```{code-cell} ipython3 +δy_seq = np.ones(T+2) * 0. +δo_seq = np.ones(T+2) * 0. + +D_pol = np.zeros(T+2) +G_pol = np.ones(T+2) * G_hat + +# tax cut +τ0 = τ_hat * (1 - 1/3) +D1 = D_hat * (1 + r_hat * (1 - τ0)) + G_hat - τ0 * Y_hat - δy_seq[0] - δo_seq[0] +D_pol[0] = D_hat +D_pol[1:] = D1 +``` + +```{code-cell} ipython3 +quant_seq3, price_seq3, policy_seq3 = ak2.simulate(T, init_ss, + δy_seq, δo_seq, + D_pol=D_pol, G_pol=G_pol, + verbose=True) +``` + +```{code-cell} ipython3 +ak2.plot() +``` + +Next, we can now try to turn on the lump sum taxes with the more general laboratory at hand. + +For example, let's try the same fiscal policy experiment in {ref}`exp-tax-cut`, but slightly modify it and assume that the government will in addition increase the lump sum taxes for both the young and old households $\delta_{yt}=\delta_{ot}=0.01, t\geq0$. + +```{code-cell} ipython3 +δy_seq = np.ones(T+2) * 0.01 +δo_seq = np.ones(T+2) * 0.01 + +D1 = D_hat * (1 + r_hat * (1 - τ0)) + G_hat - τ0 * Y_hat - δy_seq[0] - δo_seq[0] +D_pol[1:] = D1 + +quant_seq4, price_seq4, policy_seq4 = ak2.simulate(T, init_ss, + δy_seq, δo_seq, + D_pol=D_pol, G_pol=G_pol) +``` + +As a result, we see that the "crowding out" effect is mitigated. + +```{code-cell} ipython3 +fig, axs = plt.subplots(3, 3, figsize=(14, 10)) + +# quantities +for i, name in enumerate(['K', 'Y', 'Cy', 'Co']): + ax = axs[i//3, i%3] + ax.plot(range(T+1), quant_seq3[:T+1, i], label=name+', $\delta$s=0') + ax.plot(range(T+1), quant_seq4[:T+1, i], label=name+', $\delta$s=0.01') + ax.hlines(init_ss[i], 0, T+1, color='r', linestyle='--') + ax.legend() + ax.set_xlabel('t') + +# prices +for i, name in enumerate(['W', 'r']): + ax = axs[(i+4)//3, (i+4)%3] + ax.plot(range(T+1), price_seq3[:T+1, i], label=name+', $\delta$s=0') + ax.plot(range(T+1), price_seq4[:T+1, i], label=name+', $\delta$s=0.01') + ax.hlines(init_ss[i+4], 0, T+1, color='r', linestyle='--') + ax.legend() + ax.set_xlabel('t') + +# policies +for i, name in enumerate(['τ', 'D', 'G']): + ax = axs[(i+6)//3, (i+6)%3] + ax.plot(range(T+1), policy_seq3[:T+1, i], label=name+', $\delta$s=0') + ax.plot(range(T+1), policy_seq4[:T+1, i], label=name+', $\delta$s=0.01') + ax.hlines(init_ss[i+6], 0, T+1, color='r', linestyle='--') + ax.legend() + ax.set_xlabel('t') +``` diff --git a/lectures/cagan_adaptive.md b/lectures/cagan_adaptive.md index 88d13626..62743cd6 100644 --- a/lectures/cagan_adaptive.md +++ b/lectures/cagan_adaptive.md @@ -11,9 +11,9 @@ kernelspec: name: python3 --- -# A Monetarist Theory of Price Levels with Adaptive Expectations +# Monetarist Theory of Price Levels with Adaptive Expectations -## Introduction +## Overview This lecture is a sequel or prequel to the lecture {doc}`cagan_ree`. @@ -22,7 +22,7 @@ We'll use linear algebra to do some experiments with an alternative "monetarist Like the model in {doc}`cagan_ree`, the model asserts that when a government persistently spends more than it collects in taxes and prints money to finance the shortfall, it puts upward pressure on the price level and generates persistent inflation. -Instead of the "perfect foresight" or "rational expectations" version of the model in {doc}`cagan_ree`, our model in the present lecture is an "adaptive expectations" version of a model that Philip Cagan {cite}`Cagan` used to study the monetary dynamics of hyperinflations. +Instead of the "perfect foresight" or "rational expectations" version of the model in {doc}`cagan_ree`, our model in the present lecture is an "adaptive expectations" version of a model that {cite}`Cagan` used to study the monetary dynamics of hyperinflations. It combines these components: @@ -79,7 +79,7 @@ $$ $$ (eq:eqpipi) We assume that the expected rate of inflation $\pi_t^*$ is governed -by the Friedman-Cagan adaptive expectations scheme +by the following adaptive expectations scheme proposed by {cite}`Friedman1956` and {cite}`Cagan`: $$ \pi_{t+1}^* = \lambda \pi_t^* + (1 -\lambda) \pi_t diff --git a/lectures/datasets/assignat.xlsx b/lectures/datasets/assignat.xlsx new file mode 100755 index 00000000..eeb17079 Binary files /dev/null and b/lectures/datasets/assignat.xlsx differ diff --git a/lectures/datasets/caron.npy b/lectures/datasets/caron.npy new file mode 100644 index 00000000..e8b7ac6c Binary files /dev/null and b/lectures/datasets/caron.npy differ diff --git a/lectures/datasets/dette.xlsx b/lectures/datasets/dette.xlsx new file mode 100755 index 00000000..01a814d4 Binary files /dev/null and b/lectures/datasets/dette.xlsx differ diff --git a/lectures/datasets/fig_3.ods b/lectures/datasets/fig_3.ods new file mode 100644 index 00000000..5d6ae11c Binary files /dev/null and b/lectures/datasets/fig_3.ods differ diff --git a/lectures/datasets/fig_3.xlsx b/lectures/datasets/fig_3.xlsx new file mode 100644 index 00000000..7c637d4d Binary files /dev/null and b/lectures/datasets/fig_3.xlsx differ diff --git a/lectures/datasets/nom_balances.npy b/lectures/datasets/nom_balances.npy new file mode 100644 index 00000000..2c90a3f7 Binary files /dev/null and b/lectures/datasets/nom_balances.npy differ diff --git a/lectures/french_rev.md b/lectures/french_rev.md new file mode 100644 index 00000000..226f4dc5 --- /dev/null +++ b/lectures/french_rev.md @@ -0,0 +1,1031 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.1 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +--- + + +# Inflation During French Revolution + + +## Overview + +This lecture describes some monetary and fiscal features of the French Revolution +described by {cite}`sargent_velde1995`. + +We use matplotlib to replicate several of the graphs that they used to present salient patterns. + + + +## Fiscal Situation and Response of National Assembly + + +In response to a motion by Catholic Bishop Talleyrand, +the National Assembly confiscated and nationalized Church lands. + +But the National Assembly was dominated by free market advocates, not socialists. + +The National Assembly intended to use earnings from Church lands to service its national debt. + +To do this, it began to implement a ''privatization plan'' that would let it service its debt while +not raising taxes. + +Their plan involved issuing paper notes called ''assignats'' that entitled bearers to use them to purchase state lands. + +These paper notes would be ''as good as silver coins'' in the sense that both were acceptable means of payment in exchange for those (formerly) church lands. + +Finance Minister Necker and the Constituants planned +to solve the privatization problem **and** the debt problem simultaneously +by creating a new currency. + +They devised a scheme to raise revenues by auctioning +the confiscated lands, thereby withdrawing paper notes issued on the security of +the lands sold by the government. + + This ''tax-backed money'' scheme propelled the National Assembly into the domain of monetary experimentation. + +Records of their debates show +how members of the Assembly marshaled theory and evidence to assess the likely +effects of their innovation. + +They quoted David Hume and Adam Smith and cited John +Law's System of 1720 and the American experiences with paper money fifteen years +earlier as examples of how paper money schemes can go awry. + + +### Necker's plan and how it was tweaked + +Necker's original plan embodied two components: a national bank and a new +financial instrument, the ''assignat''. + + +Necker's national +bank was patterned after the Bank of England. He proposed to transform the *Caisse d'Escompte* into a national bank by granting it a monopoly on issuing +notes and marketing government debt. The *Caisse* was a +discount bank founded in 1776 whose main function was to discount commercial bills +and issue convertible notes. Although independent of the government in principle, +it had occasionally been used as a source of loans. Its notes had been declared +inconvertible in August 1788, and by the time of Necker's proposal, its reserves +were exhausted. Necker's plan placed the National Estates (as the Church lands +became known after the addition of the royal demesne) at the center of the financial +picture: a ''Bank of France'' would issue a $5\%$ security mortgaged on the prospective +receipts from the modest sale of some 400 millions' worth of National Estates in +the years 1791 to 1793. +```{note} + Only 170 million was to be used initially +to cover the deficits of 1789 and 1790. +``` + + +By mid-1790, members of the National Assembly had agreed to sell the National +Estates and to use the proceeds to service the debt in a ``tax-backed money'' scheme +```{note} +Debt service costs absorbed + over 60\% of French government expenditures. +``` + +The government would issue securities with which it would reimburse debt. + +The securities +were acceptable as payment for National Estates purchased at auctions; once received +in payment, they were to be burned. + +```{note} +The appendix to {cite}`sargent_velde1995` describes the +auction rules in detail. +``` +The Estates available for sale were thought to be worth about 2,400 +million, while the exactable debt (essentially fixed-term loans, unpaid arrears, +and liquidated offices) stood at about 2,000 million. The value of the land was +sufficient to let the Assembly retire all of the exactable debt and thereby eliminate +the interest payments on it. After lengthy debates, in August 1790, the Assembly set the denomination +and interest rate structure of the debt. + + +```{note} Two distinct +aspects of monetary theory help in thinking about the assignat plan. First, a system +beginning with a commodity standard typically has room for a once-and-for-all emission +of (an unbacked) paper currency that can replace the commodity money without generating +inflation. \citet{Sargent/Wallace:1983} describe models with this property. That +commodity money systems are wasteful underlies Milton Friedman's (1960) TOM:ADD REFERENCE preference +for a fiat money regime over a commodity money. Second, in a small country on a +commodity money system that starts with restrictions on intermediation, those restrictions +can be relaxed by letting the government issue bank notes on the security of safe +private indebtedness, while leaving bank notes convertible into gold at par. See +Adam Smith and Sargent and Wallace (1982) for expressions of this idea. TOM: ADD REFERENCES HEREAND IN BIBTEX FILE. +``` + + +```{note} +The +National Assembly debated many now classic questions in monetary economics. Under +what conditions would money creation generate inflation, with what consequences +for business conditions? Distinctions were made between issue of money to pay off +debt, on one hand, and monetization of deficits, on the other. Would *assignats* be akin +to notes emitted under a real bills regime, and cause loss of specie, or would +they circulate alongside specie, thus increasing the money stock? Would inflation +affect real wages? How would it impact foreign trade, competitiveness of French +industry and agriculture, balance of trade, foreign exchange? +``` + +## Data Sources + +This notebook uses data from three spreadsheets: + + * datasets/fig_3.ods + * datasets/dette.xlsx + * datasets/assignat.xlsx + +```{code-cell} ipython3 +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt +plt.rcParams.update({'font.size': 12}) +``` + + +## Figure 1 + + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: "Ratio of debt service to taxes, Britain and France" + name: fig1 +--- + +# Read the data from the Excel file +data1 = pd.read_excel('datasets/dette.xlsx', sheet_name='Debt', usecols='R:S', skiprows=5, nrows=99, header=None) +data1a = pd.read_excel('datasets/dette.xlsx', sheet_name='Debt', usecols='P', skiprows=89, nrows=15, header=None) + +# Plot the data +plt.figure() +plt.plot(range(1690, 1789), 100 * data1.iloc[:, 1], linewidth=0.8) + +date = np.arange(1690, 1789) +index = (date < 1774) & (data1.iloc[:, 0] > 0) +plt.plot(date[index], 100 * data1[index].iloc[:, 0], '*:', color='r', linewidth=0.8) + +# Plot the additional data +plt.plot(range(1774, 1789), 100 * data1a, '*:', color='orange') + +# Note about the data +# The French data before 1720 don't match up with the published version +# Set the plot properties +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) +plt.gca().set_facecolor('white') +plt.gca().set_xlim([1688, 1788]) +plt.ylabel('% of Taxes') + +plt.tight_layout() +plt.show() + +#plt.savefig('frfinfig1.pdf', dpi=600) +#plt.savefig('frfinfig1.jpg', dpi=600) +``` + + +TO TEACH TOM: By staring at {numref}`fig1` carefully + + +## Figure 2 + + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: "Government Expenditures and Tax Revenues in Britain" + name: fig2 +--- + +# Read the data from Excel file +data2 = pd.read_excel('datasets/dette.xlsx', sheet_name='Militspe', usecols='M:X', skiprows=7, nrows=102, header=None) + +# Plot the data +plt.figure() +plt.plot(range(1689, 1791), data2.iloc[:, 5], linewidth=0.8) +plt.plot(range(1689, 1791), data2.iloc[:, 11], linewidth=0.8, color='red') +plt.plot(range(1689, 1791), data2.iloc[:, 9], linewidth=0.8, color='orange') +plt.plot(range(1689, 1791), data2.iloc[:, 8], 'o-', markerfacecolor='none', linewidth=0.8, color='purple') + +# Customize the plot +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) +plt.gca().tick_params(labelsize=12) +plt.xlim([1689, 1790]) +plt.ylabel('millions of pounds', fontsize=12) + +# Add text annotations +plt.text(1765, 1.5, 'civil', fontsize=10) +plt.text(1760, 4.2, 'civil plus debt service', fontsize=10) +plt.text(1708, 15.5, 'total govt spending', fontsize=10) +plt.text(1759, 7.3, 'revenues', fontsize=10) + + +plt.tight_layout() +plt.show() + +# Save the figure as a PDF +#plt.savefig('frfinfig2.pdf', dpi=600) +``` + + +## Figure 3 + + + + +```{code-cell} ipython3 +# Read the data from the Excel file +data1 = pd.read_excel('datasets/fig_3.xlsx', sheet_name='Sheet1', usecols='C:F', skiprows=5, nrows=30, header=None) + +data1.replace(0, np.nan, inplace=True) +``` + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: "Government Spending and Tax Revenues in France" + name: fr_fig3 +--- +# Plot the data +plt.figure() + +plt.plot(range(1759, 1789, 1), data1.iloc[:, 0], '-x', linewidth=0.8) +plt.plot(range(1759, 1789, 1), data1.iloc[:, 1], '--*', linewidth=0.8) +plt.plot(range(1759, 1789, 1), data1.iloc[:, 2], '-o', linewidth=0.8, markerfacecolor='none') +plt.plot(range(1759, 1789, 1), data1.iloc[:, 3], '-*', linewidth=0.8) + +plt.text(1775, 610, 'total spending', fontsize=10) +plt.text(1773, 325, 'military', fontsize=10) +plt.text(1773, 220, 'civil plus debt service', fontsize=10) +plt.text(1773, 80, 'debt service', fontsize=10) +plt.text(1785, 500, 'revenues', fontsize=10) + + + +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) +plt.ylim([0, 700]) +plt.ylabel('millions of livres') + +plt.tight_layout() +plt.show() + +#plt.savefig('frfinfig3.jpg', dpi=600) +``` + + +TO TEACH TOM: By staring at {numref}`fr_fig3` carefully + +```{code-cell} ipython3 +# Plot the data +plt.figure() + +plt.plot(np.arange(1759, 1789, 1)[~np.isnan(data1.iloc[:, 0])], data1.iloc[:, 0][~np.isnan(data1.iloc[:, 0])], '-x', linewidth=0.8) +plt.plot(np.arange(1759, 1789, 1)[~np.isnan(data1.iloc[:, 1])], data1.iloc[:, 1][~np.isnan(data1.iloc[:, 1])], '--*', linewidth=0.8) +plt.plot(np.arange(1759, 1789, 1)[~np.isnan(data1.iloc[:, 2])], data1.iloc[:, 2][~np.isnan(data1.iloc[:, 2])], '-o', linewidth=0.8, markerfacecolor='none') +plt.plot(np.arange(1759, 1789, 1)[~np.isnan(data1.iloc[:, 3])], data1.iloc[:, 3][~np.isnan(data1.iloc[:, 3])], '-*', linewidth=0.8) + +plt.text(1775, 610, 'total spending', fontsize=10) +plt.text(1773, 325, 'military', fontsize=10) +plt.text(1773, 220, 'civil plus debt service', fontsize=10) +plt.text(1773, 80, 'debt service', fontsize=10) +plt.text(1785, 500, 'revenues', fontsize=10) + + +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) +plt.ylim([0, 700]) +plt.ylabel('millions of livres') + +plt.tight_layout() +plt.show() + +#plt.savefig('frfinfig3_ignore_nan.jpg', dpi=600) +``` + + +## Figure 4 + + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: "Military Spending in Britain and France" + name: fig4 +--- +# French military spending, 1685-1789, in 1726 livres +data4 = pd.read_excel('datasets/dette.xlsx', sheet_name='Militspe', usecols='D', skiprows=3, nrows=105, header=None).squeeze() +years = range(1685, 1790) + +plt.figure() +plt.plot(years, data4, '*-', linewidth=0.8) + +plt.plot(range(1689, 1791), data2.iloc[:, 4], linewidth=0.8) + +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) +plt.gca().tick_params(labelsize=12) +plt.xlim([1689, 1790]) +plt.xlabel('*: France') +plt.ylabel('Millions of livres') +plt.ylim([0, 475]) + +plt.tight_layout() +plt.show() + +#plt.savefig('frfinfig4.pdf', dpi=600) +``` + +TO TEACH TOM: By staring at {numref}`fig4` carefully + +## Figure 5 + + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: "Index of real per capital revenues, France" + name: fig5 +--- +# Read data from Excel file +data5 = pd.read_excel('datasets/dette.xlsx', sheet_name='Debt', usecols='K', skiprows=41, nrows=120, header=None) + +# Plot the data +plt.figure() +plt.plot(range(1726, 1846), data5.iloc[:, 0], linewidth=0.8) + +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) +plt.gca().set_facecolor('white') +plt.gca().tick_params(labelsize=12) +plt.xlim([1726, 1845]) +plt.ylabel('1726 = 1', fontsize=12) + +plt.tight_layout() +plt.show() + +# Save the figure as a PDF +#plt.savefig('frfinfig5.pdf', dpi=600) +``` + +TO TEACH TOM: By staring at {numref}`fig5` carefully + +## Rise and Fall of the *Assignat* + + + + We have partitioned Figures~\ref{fig:fig7}, \ref{fig:fig8}, and \ref{fig:fig9} + into three periods, corresponding +to different monetary regimes or episodes. The three clouds of points in +Figure~\ref{fig:fig7} + depict different real balance-inflation relationships. Only the cloud for the +third period has the inverse relationship familiar to us now from twentieth-century +hyperinflations. The first period ends in the late summer of 1793, and is characterized +by growing real balances and moderate inflation. The second period begins and ends +with the Terror. It is marked by high real balances, around 2,500 millions, and +roughly stable prices. The fall of Robespierre in late July 1794 begins the third +of our episodes, in which real balances decline and prices rise rapidly. We interpret +these three episodes in terms of three separate theories about money: a ``backing'' +or ''real bills'' theory (the text is Adam Smith (1776)), +a legal restrictions theory (TOM: HERE PLEASE CITE +Keynes,1940, AS WELL AS Bryant/Wallace:1984 and Villamil:1988) +and a classical hyperinflation theory.% +```{note} +According to the empirical definition of hyperinflation adopted by {cite}`Cagan`, +beginning in the month that inflation exceeds 50 percent +per month and ending in the month before inflation drops below 50 percent per month +for at least a year, the *assignat* experienced a hyperinflation from May to December +1795. +``` +We view these +theories not as competitors but as alternative collections of ``if-then'' +statements about government note issues, each of which finds its conditions more +nearly met in one of these episodes than in the other two. + + + + + +## Figure 7 + + +## To Do for Zejin + +I want to tweak and consolidate the extra lines that Zejin drew on the beautiful **Figure 7**. + +I'd like to experiment in plotting the **six** extra lines all on one graph -- a pair of lines for each of our subsamples + + * one for the $y$ on $x$ regression line + * another for the $x$ on $y$ regression line + +I'd like the $y$ on $x$ and $x$ on $y$ lines to be in separate colors. + +Once we are satisfied with this new graph with its six additional lines, we can dispense with the other graphs that add one line at a time. + +Zejin, I can explain on zoom the lessons I want to convey with this. + + + +Just to recall, to compute the regression lines, Zejin wrote a function that use standard formulas +for a and b in a least squares regression y = a + b x + residual -- i.e., b is ratio of sample covariance of y,x to sample variance of x; while a is then computed from a = sample mean of y - \hat b *sample mean of x + +We could presumably tell students how to do this with a couple of numpy lines +I'd like to create three additional versions of the following figure. + +To remind you, we focused on three subperiods: + + +* subperiod 1: ("real bills period): January 1791 to July 1793 + +* subperiod 2: ("terror:): August 1793 - July 1794 + +* subperiod 3: ("classic Cagan hyperinflation): August 1794 - March 1796 + + +I can explain what this is designed to show. + + + +```{code-cell} ipython3 +def fit(x, y): + + b = np.cov(x, y)[0, 1] / np.var(x) + a = y.mean() - b * x.mean() + + return a, b +``` + +```{code-cell} ipython3 +# load data +caron = np.load('datasets/caron.npy') +nom_balances = np.load('datasets/nom_balances.npy') + +infl = np.concatenate(([np.nan], -np.log(caron[1:63, 1] / caron[0:62, 1]))) +bal = nom_balances[14:77, 1] * caron[:, 1] / 1000 +``` + +```{code-cell} ipython3 +# fit data + +# reg y on x for three periods +a1, b1 = fit(bal[1:31], infl[1:31]) +a2, b2 = fit(bal[31:44], infl[31:44]) +a3, b3 = fit(bal[44:63], infl[44:63]) + +# reg x on y for three periods +a1_rev, b1_rev = fit(infl[1:31], bal[1:31]) +a2_rev, b2_rev = fit(infl[31:44], bal[31:44]) +a3_rev, b3_rev = fit(infl[44:63], bal[44:63]) +``` + +```{code-cell} ipython3 +plt.figure() +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +# first subsample +plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') + +# second subsample +plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') + +# third subsample +plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') + +plt.xlabel('real balances') +plt.ylabel('inflation') +plt.legend() + +plt.tight_layout() +plt.show() +#plt.savefig('frfinfig7.pdf', dpi=600) +``` + + + +```{code-cell} ipython3 +# fit data + +# reg y on x for three periods +a1, b1 = fit(bal[1:31], infl[1:31]) +a2, b2 = fit(bal[31:44], infl[31:44]) +a3, b3 = fit(bal[44:63], infl[44:63]) + +# reg x on y for three periods +a1_rev, b1_rev = fit(infl[1:31], bal[1:31]) +a2_rev, b2_rev = fit(infl[31:44], bal[31:44]) +a3_rev, b3_rev = fit(infl[44:63], bal[44:63]) +``` + +```{code-cell} ipython3 +plt.figure() +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +# first subsample +plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') + +# second subsample +plt.plot(bal[34:44], infl[34:44], '+', color='red', label='terror') + +# third subsample # Tom tinkered with subsample period +plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') + +plt.xlabel('real balances') +plt.ylabel('inflation') +plt.legend() + +plt.tight_layout() +plt.show() +#plt.savefig('frfinfig7.pdf', dpi=600) +``` + + +
The above graph is Tom's experimental lab. We'll delete it eventually.
+ +Zejin: below is the grapth with six lines in one graph. The lines generated by regressing y on x have the same color as the corresponding data points, while the lines generated by regressing x on y are all in green.
+ +```{code-cell} ipython3 +plt.figure() +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +# first subsample +plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') +plt.plot(bal[1:31], a1 + bal[1:31] * b1, color='blue', linewidth=0.8) +plt.plot(a1_rev + b1_rev * infl[1:31], infl[1:31], color='green', linewidth=0.8) + +# second subsample +plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') +plt.plot(bal[31:44], a2 + bal[31:44] * b2, color='red', linewidth=0.8) +plt.plot(a2_rev + b2_rev * infl[31:44], infl[31:44], color='green', linewidth=0.8) + +# third subsample +plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') +plt.plot(bal[44:63], a3 + bal[44:63] * b3, color='orange', linewidth=0.8) +plt.plot(a3_rev + b3_rev * infl[44:63], infl[44:63], color='green', linewidth=0.8) + +plt.xlabel('real balances') +plt.ylabel('inflation') +plt.legend() +#plt.savefig('frfinfig7.pdf', dpi=600) +``` + + + +The graph below is Tom's version of the six lines in one graph. The lines generated by regressing y on x have the same color as the corresponding data points, while the lines generated by regressing x on y are all in green.
+ +```{code-cell} ipython3 +plt.figure() +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +# first subsample +plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') +plt.plot(bal[1:31], a1 + bal[1:31] * b1, color='blue', linewidth=0.8) +plt.plot(a1_rev + b1_rev * infl[1:31], infl[1:31], color='green', linewidth=0.8) + +# second subsample +plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') +plt.plot(bal[34:44], a2 + bal[34:44] * b2, color='red', linewidth=0.8) +plt.plot(a2_rev + b2_rev * infl[34:44], infl[34:44], color='green', linewidth=0.8) + +# third subsample +plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') +plt.plot(bal[44:63], a3 + bal[44:63] * b3, color='orange', linewidth=0.8) +plt.plot(a3_rev + b3_rev * infl[44:63], infl[44:63], color='green', linewidth=0.8) + +plt.xlabel('real balances') +plt.ylabel('inflation') +plt.legend() + +plt.tight_layout() +plt.show() +#plt.savefig('frfinfig7.pdf', dpi=600) +``` + +```{code-cell} ipython3 +plt.figure() +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +# first subsample +plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') +plt.plot(bal[1:31], a1 + bal[1:31] * b1, color='blue') + +# second subsample +plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') + +# third subsample +plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') + +plt.xlabel('real balances') +plt.ylabel('inflation') +plt.legend() + +plt.tight_layout() +plt.show() +#plt.savefig('frfinfig7_line1.pdf', dpi=600) +``` + +```{code-cell} ipython3 +plt.figure() +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +# first subsample +plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') +plt.plot(a1_rev + b1_rev * infl[1:31], infl[1:31], color='blue') + +# second subsample +plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') + +# third subsample +plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') + +plt.xlabel('real balances') +plt.ylabel('inflation') +plt.legend() + +plt.tight_layout() +plt.show() +#plt.savefig('frfinfig7_line1_rev.pdf', dpi=600) +``` + +```{code-cell} ipython3 +plt.figure() +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +# first subsample +plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') + +# second subsample +plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') +plt.plot(bal[31:44], a2 + bal[31:44] * b2, color='red') + +# third subsample +plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') + +plt.xlabel('real balances') +plt.ylabel('inflation') +plt.legend() + +plt.tight_layout() +plt.show() +#plt.savefig('frfinfig7_line2.pdf', dpi=600) +``` + +```{code-cell} ipython3 +plt.figure() +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +# first subsample +plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') + +# second subsample +plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') +plt.plot(a2_rev + b2_rev * infl[31:44], infl[31:44], color='red') + +# third subsample +plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') + +plt.xlabel('real balances') +plt.ylabel('inflation') +plt.legend() + +plt.tight_layout() +plt.show() +#plt.savefig('frfinfig7_line2_rev.pdf', dpi=600) +``` + +```{code-cell} ipython3 +plt.figure() +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +# first subsample +plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') + +# second subsample +plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') + +# third subsample +plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') +plt.plot(bal[44:63], a3 + bal[44:63] * b3, color='orange') + +plt.xlabel('real balances') +plt.ylabel('inflation') +plt.legend() + +plt.tight_layout() +plt.show() +#plt.savefig('frfinfig7_line3.pdf', dpi=600) +``` + +```{code-cell} ipython3 +plt.figure() +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +# first subsample +plt.plot(bal[1:31], infl[1:31], 'o', markerfacecolor='none', color='blue', label='real bills period') + +# second subsample +plt.plot(bal[31:44], infl[31:44], '+', color='red', label='terror') + +# third subsample +plt.plot(bal[44:63], infl[44:63], '*', color='orange', label='classic Cagan hyperinflation') +plt.plot(a3_rev + b3_rev * infl[44:63], infl[44:63], color='orange') + +plt.xlabel('real balances') +plt.ylabel('inflation') +plt.legend() + +plt.tight_layout() +plt.show() +#plt.savefig('frfinfig7_line3_rev.pdf', dpi=600) +``` + + +## Figure 8 + + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: "Real balances of assignats (in gold and goods)" + name: fig8 +--- +# Read the data from Excel file +data7 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Data', usecols='P:Q', skiprows=4, nrows=80, header=None) +data7a = pd.read_excel('datasets/assignat.xlsx', sheet_name='Data', usecols='L', skiprows=4, nrows=80, header=None) + +# Create the figure and plot +plt.figure() +h = plt.plot(pd.date_range(start='1789-11-01', periods=len(data7), freq='M'), (data7a.values * [1, 1]) * data7.values, linewidth=1.) +plt.setp(h[1], linestyle='--', color='red') + +plt.vlines([pd.Timestamp('1793-07-15'), pd.Timestamp('1793-07-15')], 0, 3000, linewidth=0.8, color='orange') +plt.vlines([pd.Timestamp('1794-07-15'), pd.Timestamp('1794-07-15')], 0, 3000, linewidth=0.8, color='purple') + +plt.ylim([0, 3000]) + +# Set properties of the plot +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) +plt.gca().set_facecolor('white') +plt.gca().tick_params(labelsize=12) +plt.xlim(pd.Timestamp('1789-11-01'), pd.Timestamp('1796-06-01')) +plt.ylabel('millions of livres', fontsize=12) + +# Add text annotations +plt.text(pd.Timestamp('1793-09-01'), 200, 'Terror', fontsize=12) +plt.text(pd.Timestamp('1791-05-01'), 750, 'gold value', fontsize=12) +plt.text(pd.Timestamp('1794-10-01'), 2500, 'real value', fontsize=12) + + +plt.tight_layout() +plt.show() + +# Save the figure as a PDF +#plt.savefig('frfinfig8.pdf', dpi=600) +``` + +TO TEACH TOM: By staring at {numref}`fig8` carefully + + +## Figure 9 + + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: "Price Level and Price of Gold (log scale)" + name: fig9 +--- +# Create the figure and plot +plt.figure() +x = np.arange(1789 + 10/12, 1796 + 5/12, 1/12) +h, = plt.plot(x, 1. / data7.iloc[:, 0], linestyle='--') +h, = plt.plot(x, 1. / data7.iloc[:, 1], color='r') + +# Set properties of the plot +plt.gca().tick_params(labelsize=12) +plt.yscale('log') +plt.xlim([1789 + 10/12, 1796 + 5/12]) +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +# Add vertical lines +plt.axvline(x=1793 + 6.5/12, linestyle='-', linewidth=0.8, color='orange') +plt.axvline(x=1794 + 6.5/12, linestyle='-', linewidth=0.8, color='purple') + +# Add text +plt.text(1793.75, 120, 'Terror', fontsize=12) +plt.text(1795, 2.8, 'price level', fontsize=12) +plt.text(1794.9, 40, 'gold', fontsize=12) + + +plt.tight_layout() +plt.show() +#plt.savefig('frfinfig9.pdf', dpi=600) +``` + +TO TEACH TOM: By staring at {numref}`fig9` carefully + + +## Figure 11 + + + + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: "Spending (blue) and Revenues (orange), (real values)" + name: fig11 +--- +# Read data from Excel file +data11 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Budgets', usecols='J:K', skiprows=22, nrows=52, header=None) + +# Prepare the x-axis data +x_data = np.concatenate([ + np.arange(1791, 1794 + 8/12, 1/12), + np.arange(1794 + 9/12, 1795 + 3/12, 1/12) +]) + +# Remove NaN values from the data +data11_clean = data11.dropna() + +# Plot the data +plt.figure() +h = plt.plot(x_data, data11_clean.values[:, 0], linewidth=0.8) +h = plt.plot(x_data, data11_clean.values[:, 1], '--', linewidth=0.8) + + + +# Set plot properties +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) +plt.gca().set_facecolor('white') +plt.gca().tick_params(axis='both', which='major', labelsize=12) +plt.xlim([1791, 1795 + 3/12]) +plt.xticks(np.arange(1791, 1796)) +plt.yticks(np.arange(0, 201, 20)) + +# Set the y-axis label +plt.ylabel('millions of livres', fontsize=12) + + + +plt.tight_layout() +plt.show() + +#plt.savefig('frfinfig11.pdf', dpi=600) +``` +TO TEACH TOM: By staring at {numref}`fig11` carefully + + +## Figure 12 + + +```{code-cell} ipython3 +# Read data from Excel file +data12 = pd.read_excel('datasets/assignat.xlsx', sheet_name='seignor', usecols='F', skiprows=6, nrows=75, header=None).squeeze() + + +# Create a figure and plot the data +plt.figure() +plt.plot(pd.date_range(start='1790', periods=len(data12), freq='M'), data12, linewidth=0.8) + +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) + +plt.axhline(y=472.42/12, color='r', linestyle=':') +plt.xticks(ticks=pd.date_range(start='1790', end='1796', freq='AS'), labels=range(1790, 1797)) +plt.xlim(pd.Timestamp('1791'), pd.Timestamp('1796-02') + pd.DateOffset(months=2)) +plt.ylabel('millions of livres', fontsize=12) +plt.text(pd.Timestamp('1793-11'), 39.5, 'revenues in 1788', verticalalignment='top', fontsize=12) + + +plt.tight_layout() +plt.show() + +#plt.savefig('frfinfig12.pdf', dpi=600) +``` + + +## Figure 13 + + +```{code-cell} ipython3 +# Read data from Excel file +data13 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Exchge', usecols='P:T', skiprows=3, nrows=502, header=None) + +# Plot the last column of the data +plt.figure() +plt.plot(data13.iloc[:, -1], linewidth=0.8) + +# Set properties of the plot +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) +plt.gca().set_xlim([1, len(data13)]) + +# Set x-ticks and x-tick labels +ttt = np.arange(1, len(data13) + 1) +plt.xticks(ttt[~np.isnan(data13.iloc[:, 0])], + ['Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'Jan', 'Feb', + 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep']) + +# Add text to the plot +plt.text(1, 120, '1795', fontsize=12, ha='center') +plt.text(262, 120, '1796', fontsize=12, ha='center') + +# Draw a horizontal line and add text +plt.axhline(y=186.7, color='red', linestyle='-', linewidth=0.8) +plt.text(150, 190, 'silver parity', fontsize=12) + +# Add an annotation with an arrow +plt.annotate('end of the assignat', xy=(340, 172), xytext=(380, 160), + arrowprops=dict(facecolor='black', arrowstyle='->'), fontsize=12) + + +plt.tight_layout() +plt.show() +#plt.savefig('frfinfig13.pdf', dpi=600) +``` + + +## Figure 14 + + +```{code-cell} ipython3 +# figure 14 +data14 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Post-95', usecols='I', skiprows=9, nrows=91, header=None).squeeze() +data14a = pd.read_excel('datasets/assignat.xlsx', sheet_name='Post-95', usecols='F', skiprows=100, nrows=151, header=None).squeeze() + +plt.figure() +h = plt.plot(data14, '*-', markersize=2, linewidth=0.8) +plt.plot(np.concatenate([np.full(data14.shape, np.nan), data14a]), linewidth=0.8) +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) +plt.gca().set_xticks(range(20, 237, 36)) +plt.gca().set_xticklabels(range(1796, 1803)) +plt.xlabel('*: Before the 2/3 bankruptcy') +plt.ylabel('Francs') + +plt.tight_layout() +plt.show() +#plt.savefig('frfinfig14.pdf', dpi=600) +``` + + +## Figure 15 + + +```{code-cell} ipython3 +# figure 15 +data15 = pd.read_excel('datasets/assignat.xlsx', sheet_name='Post-95', usecols='N', skiprows=4, nrows=88, header=None).squeeze() + +plt.figure() +h = plt.plot(range(2, 90), data15, '*-', linewidth=0.8) +plt.setp(h, markersize=2) +plt.gca().spines['top'].set_visible(False) +plt.gca().spines['right'].set_visible(False) +plt.text(47.5, 11.4, '17 brumaire', horizontalalignment='left', fontsize=12) +plt.text(49.5, 14.75, '19 brumaire', horizontalalignment='left', fontsize=12) +plt.text(15, -1, 'Vendémiaire 8', fontsize=12, horizontalalignment='center') +plt.text(45, -1, 'Brumaire', fontsize=12, horizontalalignment='center') +plt.text(75, -1, 'Frimaire', fontsize=12, horizontalalignment='center') +plt.ylim([0, 25]) +plt.xticks([], []) +plt.ylabel('Francs') + +plt.tight_layout() +plt.show() +#plt.savefig('frfinfig15.pdf', dpi=600) +``` + +```{code-cell} ipython3 + +``` diff --git a/lectures/laffer_adaptive.md b/lectures/laffer_adaptive.md new file mode 100644 index 00000000..92640fc3 --- /dev/null +++ b/lectures/laffer_adaptive.md @@ -0,0 +1,465 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.14.5 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +--- + ++++ {"user_expressions": []} + +# Laffer Curves with Adaptive Expectations + +## Overview + +This lecture studies stationary and dynamic **Laffer curves** in the inflation tax rate in a non-linear version of the model studied in this lecture {doc}`money_inflation`. + +As in the lecture {doc}`money_inflation`, this lecture uses the log-linear version of the demand function for money that {cite}`Cagan` used in his classic paper in place of the linear demand function used in this lecture {doc}`money_inflation`. + +But now, instead of assuming ''rational expectations'' in the form of ''perfect foresight'', +we'll adopt the ''adaptive expectations'' assumption used by {cite}`Cagan` and {cite}`Friedman1956`. + + + +This means that instead of assuming that expected inflation $\pi_t^*$ is described by the "perfect foresight" or "rational expectations" hypothesis + +$$ +\pi_t^* = p_{t+1} - p_t +$$ + +that we adopted in lectures {doc}`money_inflation` and lectures {doc}`money_inflation_nonlinear`, we'll now assume that $\pi_t^*$ is determined by the adaptive expectations hypothesis described in equation {eq}`eq:adaptex` reported below. + + + +We shall discover that changing our hypothesis about expectations formation in this way will change some our findings and leave others intact. In particular, we shall discover that + + +* replacing rational expectations with adaptive expectations leaves the two stationary inflation rates unchanged, but that $\ldots$ +* it reverse the pervese dynamics by making the **lower** stationary inflation rate the one to which the system typically converges +* a more plausible comparative dynamic outcome emerges in which now inflation can be **reduced** by running **lower** government deficits + +These more plausible comparative dynamics underly the "old time religion" that states that +"inflation is always and everwhere caused by government deficits". + + +These issues were studyied by {cite}`bruno1990seigniorage`. + +Their purpose was to reverse what they thought were counter intuitive +predictions of their model under rational expectations (i.e., perfect foresight in this context) +by dropping rational expectations and instead assuming that people form expectations about future inflation rates according to the "adaptive expectations" scheme {eq}`eq:adaptex` described below. + +```{note} +{cite}`sargent1989least` had studied another way of selecting stationary equilibrium that involved replacing rational expectations with a model of learning via least squares regression. + {cite}`marcet2003recurrent` and {cite}`sargent2009conquest` extended that work and applied it to study recurrent high-inflation episodes in Latin America. +``` + + +## The Model + +Let + + * $m_t$ be the log of the money supply at the beginning of time $t$ + * $p_t$ be the log of the price level at time $t$ + * $\pi_t^*$ be the public's expectation of the rate of inflation between $t$ and $t+1$ + + +The law of motion of the money supply is + +$$ +\exp(m_{t+1}) - \exp(m_t) = g \exp(p_t) +$$ (eq:ada_msupply) + + +where $g$ is the part of government expenditures financed by printing money. + +Notice that equation {eq}`eq:ada_msupply` implies that + +$$ +m_{t+1} = \log[ \exp(m_t) + g \exp(p_t)] +$$ (eq:ada_msupply2) + +The demand function for money is + +$$ +m_{t+1} - p_t = -\alpha \pi_t^* +$$ (eq:ada_mdemand) + +where $\alpha \geq 0$. + + + +Expectations of inflation are governed by + +$$ +\pi_{t}^* = (1-\delta) (p_t - p_{t-1}) + \delta \pi_{t-1}^* +$$ (eq:adaptex) + +where $\delta \in (0,1)$ + + +## Computing An Equilibrium Sequence + +Equation the expressions for $m_{t+1}$ promided by {eq}`eq:ada_mdemand` and {eq}`eq:ada_msupply2` and use equation {eq}`eq:adaptex` to eliminate $\pi_t^*$ to obtain +the following equation for $p_t$: + +$$ +\log[ \exp(m_t) + g \exp(p_t)] - p_t = -\alpha [(1-\delta) (p_t - p_{t-1}) + \delta \pi_{t-1}^*] +$$ (eq:pequation) + + +**Pseudo-code** + +Here is pseudo code for our algorithm. + +Starting at time $0$ with initial conditions $(m_0, \pi_{-1}^*, p_{-1})$, for each $t \geq 0$ +deploy the following steps in order: + +* solve {eq}`eq:pequation` for $p_t$ +* solve equation {eq}`eq:adaptex` for $\pi_t^*$ +* solve equation {eq}`eq:ada_msupply2` for $m_{t+1}$ + +This completes the algorithm. + + +## Claims or Conjectures + + +It will turn out that + + * if they exist, limiting values $\overline \pi$ and $\overline \mu$ will be equal + + * if limiting values exists, there are two possible limiting values, one high, one low + + * unlike the outcome in lecture {doc}`money_inflation_nonlinear`, for almost all initial log price levels and expected inflation rates $p_0, \pi_{t}^*$, the limiting $\overline \pi = \overline \mu$ is the **lower** steady state value + + * for each of the two possible limiting values $\bar \pi$ ,there is a unique initial log price level $p_0$ that implies that $\pi_t = \mu_t = \bar \mu$ for all $t \geq 0$ + + * this unique initial log price level solves $\log(\exp(m_0) + g \exp(p_0)) - p_0 = - \alpha \bar \pi $ + + * the preceding equation for $p_0$ comes from $m_1 - p_0 = - \alpha \bar \pi$ + ++++ {"user_expressions": []} + +## Limiting Values of Inflation Rate + +As in our earlier lecture {doc}`money_inflation_nonlinear`, we can compute the two prospective limiting values for $\bar \pi$ by studying the steady-state Laffer curve. + +Thus, in a **steady state** + +$$ +m_{t+1} - m_t = p_{t+1} - p_t = x \quad \forall t , +$$ + +where $x > 0 $ is a common rate of growth of logarithms of the money supply and price level. + +A few lines of algebra yields the following equation that $x$ satisfies + +$$ +\exp(-\alpha x) - \exp(-(1 + \alpha) x) = g +$$ (eq:ada_steadypi) + +where we require that + +$$ +g \leq \max_{x: x \geq 0} \exp(-\alpha x) - \exp(-(1 + \alpha) x) , +$$ (eq:ada_revmax) + +so that it is feasible to finance $g$ by printing money. + +The left side of {eq}`eq:ada_steadypi` is steady state revenue raised by printing money. + +The right side of {eq}`eq:ada_steadypi` is the quantity of time $t$ goods that the government raises by printing money. + +Soon we'll plot the left and right sides of equation {eq}`eq:ada_steadypi`. + +But first we'll write code that computes a steady-state +$\bar \pi$. + + + +Let's start by importing some libraries + +```{code-cell} ipython3 +from collections import namedtuple +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.ticker import MaxNLocator +from matplotlib.cm import get_cmap +from matplotlib.colors import to_rgba +import matplotlib +from scipy.optimize import root, fsolve +``` + ++++ {"user_expressions": []} + +Let's create a `namedtuple` to store the parameters of the model + +```{code-cell} ipython3 +LafferAdaptive = namedtuple('LafferAdaptive', + ["m0", # log of the money supply at t=0 + "α", # sensitivity of money demand + "g", # government expenditure + "δ"]) + +# Create a Cagan Laffer model +def create_model(α=0.5, m0=np.log(100), g=0.35, δ=0.9): + return LafferAdaptive(α=α, m0=m0, g=g, δ=δ) + +model = create_model() +``` + ++++ {"user_expressions": []} + +Now we write code that computes steady-state $\bar \pi$s. + +```{code-cell} ipython3 +# Define formula for π_bar +def solve_π(x, α, g): + return np.exp(-α * x) - np.exp(-(1 + α) * x) - g + +def solve_π_bar(model, x0): + π_bar = fsolve(solve_π, x0=x0, xtol=1e-10, args=(model.α, model.g))[0] + return π_bar + +# Solve for the two steady state of π +π_l = solve_π_bar(model, x0=0.6) +π_u = solve_π_bar(model, x0=3.0) +print(f'The two steady state of π are: {π_l, π_u}') +``` + ++++ {"user_expressions": []} + +We find two steady state $\bar \pi$ values + ++++ {"user_expressions": []} + +## Steady State Laffer Curve + +The following figure plots the steady state Laffer curve together with the two stationary inflation rates. + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Seigniorage as function of steady state inflation. The dashed brown lines + indicate $\pi_l$ and $\pi_u$. + name: laffer_curve_adaptive + width: 500px +--- +def compute_seign(x, α): + return np.exp(-α * x) - np.exp(-(1 + α) * x) + +def plot_laffer(model, πs): + α, g = model.α, model.g + + # Generate π values + x_values = np.linspace(0, 5, 1000) + + # Compute corresponding seigniorage values for the function + y_values = compute_seign(x_values, α) + + # Plot the function + plt.plot(x_values, y_values, + label=f'$exp((-{α})x) - exp(- (1- {α}) x)$') + for π, label in zip(πs, ['$\pi_l$', '$\pi_u$']): + plt.text(π, plt.gca().get_ylim()[0]*2, + label, horizontalalignment='center', + color='brown', size=10) + plt.axvline(π, color='brown', linestyle='--') + plt.axhline(g, color='red', linewidth=0.5, + linestyle='--', label='g') + plt.xlabel('$\pi$') + plt.ylabel('seigniorage') + plt.legend() + plt.grid(True) + plt.show() + +# Steady state Laffer curve +plot_laffer(model, (π_l, π_u)) +``` + ++++ {"user_expressions": []} + +## Associated Initial Price Levels + + + Now that we have our hands on the two possible steady states, we can compute two initial log price levels $p_{-1}$, which as initial conditions, imply that $\pi_t = \bar \pi $ for all $t \geq 0$. + +In particular, to initiate a fixed point of the dynamic Laffer curve dynamics we set + +$$ +p_{-1} = m_0 + \alpha \pi^* +$$ + +```{code-cell} ipython3 +def solve_p_init(model, π_star): + m0, α = model.m0, model.α + return m0 + α*π_star + + +# Compute two initial price levels associated with π_l and π_u +p_l, p_u = map(lambda π: solve_p_init(model, π), (π_l, π_u)) +print('Associated initial p_{-1}s', f'are: {p_l, p_u}') +``` + ++++ {"user_expressions": []} + +### Verification + + + +To start, let's write some code to verify that if we initial $\pi_{-1}^*,p_{-1}$ appropriately, the inflation rate $\pi_t$ will be constant for all $t \geq 0$ (at either $\pi_u$ or $\pi_l$ depending on the initial condition) + + + +The following code verifies this. + +```{code-cell} ipython3 +def solve_laffer_adapt(p_init, π_init, model, num_steps): + m0, α, δ, g = model.m0, model.α, model.δ, model.g + + m_seq = np.nan * np.ones(num_steps+1) + π_seq = np.nan * np.ones(num_steps) + p_seq = np.nan * np.ones(num_steps) + μ_seq = np.nan * np.ones(num_steps) + + m_seq[1] = m0 + π_seq[0] = π_init + p_seq[0] = p_init + + for t in range(1, num_steps): + # Solve p_t + def p_t(pt): + return np.log(np.exp(m_seq[t]) + g * np.exp(pt)) \ + - pt + α * ((1-δ)*(pt - p_seq[t-1]) + δ*π_seq[t-1]) + + p_seq[t] = root(fun=p_t, x0=p_seq[t-1]).x[0] + + # Solve π_t + π_seq[t] = (1-δ) * (p_seq[t]-p_seq[t-1]) + δ*π_seq[t-1] + + # Solve m_t + m_seq[t+1] = np.log(np.exp(m_seq[t]) + g*np.exp(p_seq[t])) + + # Solve μ_t + μ_seq[t] = m_seq[t+1] - m_seq[t] + + return π_seq, μ_seq, m_seq, p_seq +``` + ++++ {"user_expressions": []} + +Compute limiting values starting from $p_{-1}$ associated with $\pi_l$ + +```{code-cell} ipython3 +π_seq, μ_seq, m_seq, p_seq = solve_laffer_adapt(p_l, π_l, model, 50) + +# Check steady state m_{t+1} - m_t and p_{t+1} - p_t +print('m_{t+1} - m_t:', m_seq[-1] - m_seq[-2]) +print('p_{t+1} - p_t:', p_seq[-1] - p_seq[-2]) + +# Check if exp(-αx) - exp(-(1 + α)x) = g +eq_g = lambda x: np.exp(-model.α * x) - np.exp(-(1 + model.α) * x) + +print('eq_g == g:', np.isclose(eq_g(m_seq[-1] - m_seq[-2]), model.g)) +``` + ++++ {"user_expressions": []} + +Compute limiting values starting from $p_{-1}$ associated with $\pi_u$ + +```{code-cell} ipython3 +π_seq, μ_seq, m_seq, p_seq = solve_laffer_adapt(p_u, π_u, model, 50) + +# Check steady state m_{t+1} - m_t and p_{t+1} - p_t +print('m_{t+1} - m_t:', m_seq[-1] - m_seq[-2]) +print('p_{t+1} - p_t:', p_seq[-1] - p_seq[-2]) + +# Check if exp(-αx) - exp(-(1 + α)x) = g +eq_g = lambda x: np.exp(-model.α * x) - np.exp(-(1 + model.α) * x) + +print('eq_g == g:', np.isclose(eq_g(m_seq[-1] - m_seq[-2]), model.g)) +``` + ++++ {"user_expressions": []} + +## Slippery Side of Laffer Curve Dynamics + + + +We are now equipped to compute time series starting from different $p_{-1}, \pi_{-1}^*$ settings, analogous to those in this lecture {doc}`money_inflation` and this lecture {doc}`money_inflation_nonlinear`. + + +Now we'll study how outcomes unfold when we start $p_{-1}, \pi_{-1}^*$ away from a stationary point of the dynamic Laffer curve, i.e., away from either $\pi_u$ or $ \pi_l$. + +To construct a perturbation pair $\check p_{-1}, \check \pi_{-1}^*$we'll implement the following pseudo code: + +* set $\check \pi_{-1}^* $ not equal to one of the stationary points $\pi_u$ or $ \pi_l$. +* set $\check p_{-1} = m_0 + \alpha \check \pi_{-1}^*$ + + + +```{code-cell} ipython3 +:tags: [hide-cell] + +def draw_iterations(π0s, model, line_params, π_bars, num_steps): + fig, axes = plt.subplots(4, 1, figsize=(8, 12), sharex=True) + + for ax in axes[:2]: + ax.set_yscale('log') + + for i, π0 in enumerate(π0s): + p0 = model.m0 + model.α*π0 + π_seq, μ_seq, m_seq, p_seq = solve_laffer_adapt(p0, π0, model, num_steps) + + axes[0].plot(np.arange(num_steps), m_seq[1:], **line_params) + axes[1].plot(np.arange(-1, num_steps-1), p_seq, **line_params) + axes[2].plot(np.arange(-1, num_steps-1), π_seq, **line_params) + axes[3].plot(np.arange(num_steps), μ_seq, **line_params) + + axes[2].axhline(y=π_bars[0], color='grey', linestyle='--', lw=1.5, alpha=0.6) + axes[2].axhline(y=π_bars[1], color='grey', linestyle='--', lw=1.5, alpha=0.6) + axes[2].text(num_steps * 1.07, π_bars[0], '$\pi_l$', verticalalignment='center', + color='grey', size=10) + axes[2].text(num_steps * 1.07, π_bars[1], '$\pi_u$', verticalalignment='center', + color='grey', size=10) + + axes[0].set_ylabel('$m_t$') + axes[1].set_ylabel('$p_t$') + axes[2].set_ylabel('$\pi_t$') + axes[3].set_ylabel('$\mu_t$') + axes[3].set_xlabel('timestep') + axes[3].xaxis.set_major_locator(MaxNLocator(integer=True)) + + plt.tight_layout() + plt.show() +``` + ++++ {"user_expressions": []} + +Let's simulate the result generated by varying the initial $\pi_{-1}$ and corresponding $p_{-1}$ + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Starting from different initial values of $\pi_0$, paths of $m_t$ (top + panel, log scale for $m$), $p_t$ (second panel, log scale for $p$), $\pi_t$ (third panel), and $\mu_t$ (bottom + panel) + name: pi0_path + width: 500px +--- +πs = np.linspace(π_l, π_u, 10) + +line_params = {'lw': 1.5, + 'marker': 'o', + 'markersize': 3} + +π_bars = (π_l, π_u) +draw_iterations(πs, model, line_params, π_bars, num_steps=80) +``` diff --git a/lectures/money_inflation.md b/lectures/money_inflation.md new file mode 100644 index 00000000..58bf93d1 --- /dev/null +++ b/lectures/money_inflation.md @@ -0,0 +1,1008 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.1 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +--- + ++++ {"user_expressions": []} + +# Money Financed Government Deficits and Price Levels + ++++ {"user_expressions": []} + +## Overview + +This lecture extends and modifies the model in this lecture {doc}`cagan_ree` by modifying the +law of motion that governed the supply of money. + +The model in this lecture consists of two components + + * a demand function for money + * a law of motion for the supply of money + +The demand function describes the public's demand for "real balances", defined as the ratio of nominal money balances to the price level + + * it assumes that the demand for real balance today varies inversely with the rate of inflation that the public forecasts to prevail between today and tomorrow + * it assumes that the public's forecast of that rate of inflation is perfect + +The law of motion for the supply of money assumes that the government prints money to finance government expenditures + +Our model equates the demand for money to the supply at each time $t \geq 0$. + +Equality between those demands and supply gives in a **dynamic** model in which money supply +and price level **sequences** are simultaneously determined by a set of simultaneous linear equations. + +These equations take the form of what are often called vector linear **difference equations**. + +In this lecture, we'll roll up our sleeves and solve those equations in two different ways. + + +(One of the methods for solving vector linear difference equations will take advantage of a decomposition of a matrix that is studied in this lecture {doc}`eigen_I`.) + +In this lecture we will encounter these concepts from macroeconomics: + +* an **inflation tax** that a government gathers by printing paper or electronic money +* a dynamic **Laffer curve** in the inflation tax rate that has two stationary equilibria +* perverse dynamics under rational expectations in which the system converges to the higher stationary inflation tax rate +* a peculiar comparative stationary-state outcome connected with that stationary inflation rate: it asserts that inflation can be **reduced** by running **higher** government deficits, i.e., by raising more resources by printing money. + +The same qualitive outcomes prevail in this lecture {doc}`money_inflation_nonlinear` that studies a nonlinear version of the model in this lecture. + +These outcomes set the stage for the analysis to be presented in this lecture {doc}`laffer_adaptive` that studies a nonlinear version of the present model; it assumes a version of "adaptive expectations" instead of rational expectations. + +That lecture will show that + +* replacing rational expectations with adaptive expectations leaves the two stationary inflation rates unchanged, but that $\ldots$ +* it reverse the pervese dynamics by making the **lower** stationary inflation rate the one to which the system typically converges +* a more plausible comparative dynamic outcome emerges in which now inflation can be **reduced** by running **lower** government deficits + +This outcome will be used to justify a selection of a stationary inflation rate that underlies the analysis of unpleasant monetarist arithmetic to be studies in this lecture {doc}`unpleasant`. + +We'll use theses tools from linear algebra: + + * matrix multiplication + * matrix inversion + * eigenvalues and eigenvectors of a matrix + + +## Demand for and Supply of Money + +We say demand**s** and supp**ies** (plurals) because there is one of each for each $t \geq 0$. + +Let + + * $m_{t+1}$ be the supply of currency at the end of time $t \geq 0$ + * $m_{t}$ be the supply of currency brought into time $t$ from time $t-1$ + * $g$ be the government deficit that is financed by printing currency at $t \geq 1$ + * $m_{t+1}^d$ be the demand at time $t$ for currency to bring into time $t+1$ + * $p_t$ be the price level at time $t$ + * $b_t = \frac{m_{t+1}}{p_t}$ is real balances at the end of time $t$ + * $R_t = \frac{p_t}{p_{t+1}} $ be the gross rate of return on currency held from time $t$ to time $t+1$ + +It is often helpful to state units in which quantities are measured: + + * $m_t$ and $m_t^d$ are measured in dollars + * $g$ is measured in time $t$ goods + * $p_t$ is measured in dollars per time $t$ goods + * $R_t$ is measured in time $t+1$ goods per unit of time $t$ goods + * $b_t$ is measured in time $t$ goods + + +Our job now is to specify demand and supply functions for money. + +We assume that the demand for currency satisfies the Cagan-like demand function + +$$ +m_{t+1}^d/p_t =\gamma_1 - \gamma_2 \frac{p_{t+1}}{p_t}, \quad t \geq 0 +$$ (eq:demandmoney) + + +Now we turn to the supply of money. + +We assume that $m_0 >0$ is an "initial condition" determined outside the model. + +We set $m_0$ at some arbitrary positive value, say \$100. + +For $ t \geq 1$, we assume that the supply of money is determined by the government's budget constraint + +$$ +m_{t+1} - m_{t} = p_t g , \quad t \geq 0 +$$ (eq:budgcontraint) + +According to this equation, each period, the government prints money to pay for quantity $g$ of goods. + +In an **equilibrium**, the demand for currency equals the supply: + +$$ +m_{t+1}^d = m_{t+1}, \quad t \geq 0 +$$ (eq:syeqdemand) + +Let's take a moment to think about what equation {eq}`eq:syeqdemand` tells us. + +The demand for money at any time $t$ depends on the price level at time $t$ and the price level at time $t+1$. + +The supply of money at time $t+1$ depends on the money supply at time $t$ and the price level at time $t$. + +So the infinite sequence of equations {eq}`eq:syeqdemand` for $ t \geq 0$ imply that the **sequences** $\{p_t\}_{t=0}^\infty$ and $\{m_t\}_{t=0}^\infty$ are tied together and ultimately simulataneously determined. + + +## Equilibrium price and money supply sequences + + +The preceding specifications imply that for $t \geq 1$, **real balances** evolve according to + + +$$ +\frac{m_{t+1}}{p_t} - \frac{m_{t}}{p_{t-1}} \frac{p_{t-1}}{p_t} = g +$$ + +or + +$$ +b_t - b_{t-1} R_{t-1} = g +$$ (eq:bmotion) + +where + + * $b_t = \frac{m_{t+1}}{p_t}$ is real balances at the end of period $t$ + * $R_{t-1} = \frac{p_{t-1}}{p_t}$ is the gross rate of return on real balances held from $t-1$ to $t$ + +The demand for real balances is + +$$ +b_t = \gamma_1 - \gamma_2 R_t^{-1} . +$$ (eq:bdemand) + +We'll restrict our attention to parameter values and associated gross real rates of return on real balances that assure that the demand for real balances is positive, which according to {eq}`eq:bdemand` means that + +$$ +b_t = \gamma_1 - \gamma_2 R_t^{-1} > 0 +$$ + +which implies that + +$$ +R_t \geq \left( \frac{\gamma_2}{\gamma_1} \right) \equiv \underline R +$$ (eq:Requation) + +Gross real rate of return $\underline R$ is the smallest rate of return on currency +that is consistent with a nonnegative demand for real balances. + + + +We shall describe two distinct but closely related ways of computing a pair $\{p_t, m_t\}_{t=0}^\infty$ of sequences for the price level and money supply. + +But first it is instructive to describe a special type of equilibrium known as a **steady state**. + +In a steady state equilibrium, a subset of key variables remain constant or **invariant** over time, while remaining variables can be expressed as functions of those constant variables. + +Finding such state variables is something of an art. + +In many models, a good source of candidates for such invariant variables is a set of **ratios**. + +This is true in the present model. + +### Steady States + +In a **steady state** equilibrium of the model we are studying, + +\begin{aligned} +R_t & = \bar R \cr +b_t & = \bar b +\end{aligned} + +for $t \geq 0$. + +Notice that both $R_t = \frac{p_t}{p_{t+1}}$ and $b_t = \frac{m_{t+1}}{p_t} $ are **ratios**. + +To compute a steady state, we seek gross rates of return on currency $\bar R, \bar b$ that satisfy steady-state versions of both the government budget constraint and the demand function for real balances: + +$$ +\begin{aligned} +g & = \bar b ( 1 - \bar R) \cr +\bar b & = \gamma_1- \gamma_2 \bar R^{-1} +\end{aligned} +$$ + +Together these equations imply + +$$ +(\gamma_1 + \gamma_2) - \frac{\gamma_2}{\bar R} - \gamma_1 \bar R = g +$$ (eq:seignsteady) + + +The left side is the steady-state amount of **seigniorage** or government revenues that the government gathers by paying a gross rate of return $\bar R < 1$ on currency. + +The right side is government expenditures. + +Define steady-state seigniorage as + +$$ +S(\bar R) = (\gamma_1 + \gamma_2) - \frac{\gamma_2}{\bar R} - \gamma_1 \bar R +$$ (eq:SSsigng) + +Notice that $S(\bar R) \geq 0$ only when $\bar R \in [\frac{\gamma2}{\gamma1}, 1] +\equiv [\underline R, \overline R]$ and that $S(\bar R) = 0$ if $\bar R = \underline R$ +or if $\bar R = \overline R$. + +We shall study equilibrium sequences that satisfy + +$$ +R_t \in \bar R = [\underline R, \overline R], \quad t \geq 0. +$$ + +Maximizing steady state seigniorage {eq}`eq:SSsigng` with respect to $\bar R$, we find that the maximizing rate of return on currency is + +$$ +\bar R_{\rm max} = \sqrt{\frac{\gamma_2}{\gamma_1}} +$$ + +and that the associated maximum seigniorage revenue that the government can gather from printing money is + +$$ +(\gamma_1 + \gamma_2) - \frac{\gamma_2}{\bar R_{\rm max}} - \gamma_1 \bar R_{\rm max} +$$ + +It is useful to rewrite equation {eq}`eq:seignsteady` as + +$$ +-\gamma_2 + (\gamma_1 + \gamma_2 - g) \bar R - \gamma_1 \bar R^2 = 0 +$$ (eq:steadyquadratic) + +A steady state gross rate of return $\bar R$ solves quadratic equation {eq}`eq:steadyquadratic`. + + +So two steady states typically exist. + + + +## Some Code + + +Let's start with some imports: + +```{code-cell} ipython3 +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.ticker import MaxNLocator +plt.rcParams['figure.dpi'] = 300 +from collections import namedtuple +``` + + +Let's set some parameter values and compute possible steady state rates of return on currency $\bar R$, the seigniorage maximizing rate of return on currency, and an object that we'll discuss later, namely, an initial price level $p_0$ associated with the maximum steady state rate of return on currency. + ++++ + +First, we create a `namedtuple` to store parameters so that we can reuse this `namedtuple` in our functions throughout this lecture + +```{code-cell} ipython3 +# Create a namedtuple that contains parameters +MoneySupplyModel = namedtuple("MoneySupplyModel", + ["γ1", "γ2", "g", + "M0", "R_u", "R_l"]) + +def create_model(γ1=100, γ2=50, g=3.0, M0=100): + + # Calculate the steady states for R + R_steady = np.roots((-γ1, γ1 + γ2 - g, -γ2)) + R_u, R_l = R_steady + print("[R_u, R_l] =", R_steady) + + return MoneySupplyModel(γ1=γ1, γ2=γ2, g=g, M0=M0, R_u=R_u, R_l=R_l) +``` + +Now we compute the $\bar R_{\rm max}$ and corresponding revenue + +```{code-cell} ipython3 +def seign(R, model): + γ1, γ2, g = model.γ1, model.γ2, model.g + return -γ2/R + (γ1 + γ2) - γ1 * R + +msm = create_model() + +# Calculate initial guess for p0 +p0_guess = msm.M0 / (msm.γ1 - msm.g - msm.γ2 / msm.R_u) +print(f'p0 guess = {p0_guess:.4f}') + +# Calculate seigniorage maximizing rate of return +R_max = np.sqrt(msm.γ2/msm.γ1) +g_max = seign(R_max, msm) +print(f'R_max, g_max = {R_max:.4f}, {g_max:.4f}') +``` + +Now let's plot seigniorage as a function of alternative potential steady-state values of $R$. + +We'll see that there are two values of $R$ that attain seigniorage levels equal to $g$, +one that we'll denote $R_l$, another that we'll denote $R_u$. + +They satisfy $R_l < R_u$ and are affiliated with a higher inflation tax rate $(1-R_l)$ and a lower +inflation tax rate $1 - R_u$. + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Steady state revenue from inflation tax as function of steady state gross return on currency (solid blue curve) and real government expenditures (dotted red line) plotted against steady-state rate of return currency + name: infl_tax + width: 500px +--- +# Generate values for R +R_values = np.linspace(msm.γ2/msm.γ1, 1, 250) + +# Calculate the function values +seign_values = seign(R_values, msm) + +# Visualize seign_values against R values +fig, ax = plt.subplots(figsize=(11, 5)) +plt.plot(R_values, seign_values, label='inflation tax revenue') +plt.axhline(y=msm.g, color='red', linestyle='--', label='government deficit') +plt.xlabel('$R$') +plt.ylabel('seigniorage') + +plt.legend() +plt.grid(True) +plt.show() +``` + +Let's print the two steady-state rates of return $\bar R$ and the associated seigniorage revenues that the government collects. + +(By construction, both steady state rates of return should raise the same amounts real revenue). + +We hope that the following code will confirm this. + +```{code-cell} ipython3 +g1 = seign(msm.R_u, msm) +print(f'R_u, g_u = {msm.R_u:.4f}, {g1:.4f}') + +g2 = seign(msm.R_l, msm) +print(f'R_l, g_l = {msm.R_l:.4f}, {g2:.4f}') +``` + +Now let's compute the maximum steady state amount of seigniorage that could be gathered by printing money and the state state rate of return on money that attains it. + ++++ + +## Two Computation Strategies + + +We now proceed to compute equilibria, not necessarily steady states. + +We shall deploy two distinct computation strategies. + +### Method 1 + + * set $R_0 \in [\frac{\gamma_2}{\gamma_1}, R_u]$ and compute $b_0 = \gamma_1 - \gamma_2/R_0$. + + * compute sequences $\{R_t, b_t\}_{t=1}^\infty$ of rates of return and real balances that are associated with an equilibrium by solving equation {eq}`eq:bmotion` and {eq}`eq:bdemand` sequentially for $t \geq 1$: + \begin{aligned} +b_t & = b_{t-1} R_{t-1} + g \cr +R_t^{-1} & = \frac{\gamma_1}{\gamma_2} - \gamma_2^{-1} b_t +\end{aligned} + + * Construct the associated equilibrium $p_0$ from + + $$ + p_0 = \frac{m_0}{\gamma_1 - g - \gamma_2/R_0} + $$ (eq:p0fromR0) + + * compute $\{p_t, m_t\}_{t=1}^\infty$ by solving the following equations sequentially + + $$ + \begin{aligned} + p_t & = R_t p_{t-1} \cr + m_t & = b_{t-1} p_t + \end{aligned} + $$ (eq:method1) + +**Remark 1:** method 1 uses an indirect approach to computing an equilibrium by first computing an equilibrium $\{R_t, b_t\}_{t=0}^\infty$ sequence and then using it to back out an equilibrium $\{p_t, m_t\}_{t=0}^\infty$ sequence. + + + **Remark 2:** notice that method 1 starts by picking an **initial condition** $R_0$ from a set $[\frac{\gamma_2}{\gamma_1}, R_u]$. An equilibrium $\{p_t, m_t\}_{t=0}^\infty$ sequences are not unique. There is actually a continuum of equilibria indexed by a choice of $R_0$ from the set $[\frac{\gamma_2}{\gamma_1}, R_u]$. + + **Remark 3:** associated with each selection of $R_0$ there is a unique $p_0$ described by + equation {eq}`eq:p0fromR0`. + +### Method 2 + + This method deploys a direct approach. + It defines a "state vector" + $y_t = \begin{bmatrix} m_t \cr p_t\end{bmatrix} $ + and formulates equilibrium conditions {eq}`eq:demandmoney`, {eq}`eq:budgcontraint`, and + {eq}`eq:syeqdemand` + in terms of a first-order vector difference equation + + $$ + y_{t+1} = M y_t, \quad t \geq 0 , + $$ + + where we temporarily take $y_0 = \begin{bmatrix} m_0 \cr p_0 \end{bmatrix}$ as an **initial condition**. + + The solution is + + $$ + y_t = M^t y_0 . + $$ + + Now let's think about the initial condition $y_0$. + + It is natural to take the initial stock of money $m_0 >0$ as an initial condition. + + But what about $p_0$? + + Isn't it something that we want to be **determined** by our model? + + Yes, but sometimes we want too much, because there is actually a continuum of initial $p_0$ levels that are compatible with the existence of an equilibrium. + + As we shall see soon, selecting an initial $p_0$ in method 2 is intimately tied to selecting an initial rate of return on currency $R_0$ in method 1. + +## Computation Method 1 + +%We start from an arbitrary $R_0$ and $b_t = \frac{m_{t+1}}{p_t}$, we have + +%$$ +%b_0 = \gamma_1 - \gamma_0 R_0^{-1} +%$$ + +Remember that there exist two steady state equilibrium values $ R_l < R_u$ of the rate of return on currency $R_t$. + +We proceed as follows. + +Start at $t=0$ + * select a $R_0 \in [\frac{\gamma_2}{\gamma_1}, R_u]$ + * compute $b_0 = \gamma_1 - \gamma_0 R_0^{-1} $ + +Then for $t \geq 1$ construct $(b_t, R_t)$ by +iterating on the system +\begin{aligned} +b_t & = b_{t-1} R_{t-1} + g \cr +R_t^{-1} & = \frac{\gamma_1}{\gamma_2} - \gamma_2^{-1} b_t +\end{aligned} + + +When we implement this part of method 1, we shall discover the following striking +outcome: + + * starting from an $R_0$ in $[\frac{\gamma_2}{\gamma_1}, R_u]$, we shall find that +$\{R_t\}$ always converges to a limiting "steady state" value $\bar R$ that depends on the initial +condition $R_0$. + + * there are only two possible limit points $\{ R_l, R_u\}$. + + * for almost every initial condition $R_0$, $\lim_{t \rightarrow +\infty} R_t = R_l$. + + * if and only if $R_0 = R_u$, $\lim_{t \rightarrow +\infty} R_t = R_u$. + +The quantity $1 - R_t$ can be interpreted as an **inflation tax rate** that the government imposes on holders of its currency. + + +We shall soon see that the existence of two steady state rates of return on currency +that serve to finance the government deficit of $g$ indicates the presence of a **Laffer curve** in the inflation tax rate. + +```{note} +Arthur Laffer's curve plots a hump shaped curve of revenue raised from a tax against the tax rate. +Its hump shape indicates that there are typically two tax rates that yield the same amount of revenue. This is due to two countervailing courses, one being that raising a tax rate typically decreases the **base** of the tax as people take decisions to reduce their exposure to the tax. +``` + +```{code-cell} ipython3 +def simulate_system(R0, model, num_steps): + γ1, γ2, g = model.γ1, model.γ2, model.g + + # Initialize arrays to store results + b_values = np.empty(num_steps) + R_values = np.empty(num_steps) + + # Initial values + b_values[0] = γ1 - γ2/R0 + R_values[0] = 1 / (γ1/γ2 - (1 / γ2) * b_values[0]) + + # Iterate over time steps + for t in range(1, num_steps): + b_t = b_values[t - 1] * R_values[t - 1] + g + R_values[t] = 1 / (γ1/γ2 - (1/γ2) * b_t) + b_values[t] = b_t + + return b_values, R_values +``` + +Let's write some code plot outcomes for several possible initial values $R_0$. + +```{code-cell} ipython3 +:tags: [hide-cell] + +line_params = {'lw': 1.5, + 'marker': 'o', + 'markersize': 3} + +def annotate_graph(ax, model, num_steps): + for y, label in [(model.R_u, '$R_u$'), (model.R_l, '$R_l$'), + (model.γ2 / model.γ1, r'$\frac{\gamma_2}{\gamma_1}$')]: + ax.axhline(y=y, color='grey', linestyle='--', lw=1.5, alpha=0.6) + ax.text(num_steps * 1.02, y, label, verticalalignment='center', + color='grey', size=12) + +def draw_paths(R0_values, model, line_params, num_steps): + + fig, axes = plt.subplots(2, 1, figsize=(8, 8), sharex=True) + + # Pre-compute time steps + time_steps = np.arange(num_steps) + + # Iterate over R_0s and simulate the system + for R0 in R0_values: + b_values, R_values = simulate_system(R0, model, num_steps) + + # Plot R_t against time + axes[0].plot(time_steps, R_values, **line_params) + + # Plot b_t against time + axes[1].plot(time_steps, b_values, **line_params) + + # Add line and text annotations to the subgraph + annotate_graph(axes[0], model, num_steps) + + # Add Labels + axes[0].set_ylabel('$R_t$') + axes[1].set_xlabel('timestep') + axes[1].set_ylabel('$b_t$') + axes[1].xaxis.set_major_locator(MaxNLocator(integer=True)) + + plt.tight_layout() + plt.show() +``` + +Let's plot distinct outcomes associated with several $R_0 \in [\frac{\gamma_2}{\gamma_1}, R_u]$. + +Each line below shows a path associated with a different $R_0$. + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Paths of $R_t$ (top panel) and $b_t$ (bottom panel) starting from different + initial condition $R_0$ + name: R0_path + width: 500px +--- +# Create a grid of R_0s +R0s = np.linspace(msm.γ2/msm.γ1, msm.R_u, 9) +R0s = np.append(msm.R_l, R0s) +draw_paths(R0s, msm, line_params, num_steps=20) +``` + +Notice how sequences that start from $R_0$ in the half-open interval $[R_l, R_u)$ converge to the steady state associated with to $ R_l$. + ++++ {"user_expressions": []} + +## Computation method 2 + +Set $m_t = m_t^d $ for all $t \geq -1$. + +Let + +$$ + y_t = \begin{bmatrix} m_{t} \cr p_{t} \end{bmatrix} . +$$ + +Represent equilibrium conditions {eq}`eq:demandmoney`, {eq}`eq:budgcontraint`, and {eq}`eq:syeqdemand` as + +$$ +\begin{bmatrix} 1 & \gamma_2 \cr + 1 & 0 \end{bmatrix} \begin{bmatrix} m_{t+1} \cr p_{t+1} \end{bmatrix} = + \begin{bmatrix} 0 & \gamma_1 \cr + 1 & g \end{bmatrix} \begin{bmatrix} m_{t} \cr p_{t} \end{bmatrix} +$$ (eq:sytem101) + +or + +$$ +H_1 y_t = H_2 y_{t-1} +$$ + +where + +\begin{aligned} H_1 & = \begin{bmatrix} 1 & \gamma_2 \cr + 1 & 0 \end{bmatrix} \cr + H_2 & = \begin{bmatrix} 0 & \gamma_1 \cr + 1 & g \end{bmatrix} +\end{aligned} + +```{code-cell} ipython3 +H1 = np.array([[1, msm.γ2], + [1, 0]]) +H2 = np.array([[0, msm.γ1], + [1, msm.g]]) +``` + +Define + +$$ +H = H_1^{-1} H_2 +$$ + +```{code-cell} ipython3 +H = np.linalg.inv(H1) @ H2 +print('H = \n', H) +``` + +and write the system {eq}`eq:sytem101` as + +$$ +y_{t+1} = H y_t, \quad t \geq 0 +$$ (eq:Vaughn) + +so that $\{y_t\}_{t=0}$ can be computed from + +$$ +y_t = H^t y_0, t \geq 0 +$$ (eq:ytiterate) + +where + +$$ +y_0 = \begin{bmatrix} m_{0} \cr p_0 \end{bmatrix} . +$$ + +It is natural to take $m_0$ as an initial condition determined outside the model. + +The mathematics seems to tell us that $p_0$ must also be determined outside the model, even though +it is something that we actually wanted to be determined by the model. + +(As usual, we should listen when mathematics talks to us.) + +For now, let's just proceed mechanically on faith. + +Compute the eigenvector decomposition + +$$ +H = Q \Lambda Q^{-1} +$$ + +where $\Lambda$ is a diagonal matrix of eigenvalues and the columns of $Q$ are eigenvectors corresponding to those eigenvalues. + +It turns out that + + +$$ +\begin{bmatrix} {R_l}^{-1} & 0 \cr + 0 & {R_u}^{-1} \end{bmatrix} +$$ + +where $R_l$ and $R_u$ are the lower and higher steady-state rates of return on currency that we computed above. + +```{code-cell} ipython3 +Λ, Q = np.linalg.eig(H) +print('Λ = \n', Λ) +print('Q = \n', Q) +``` + +```{code-cell} ipython3 +R_l = 1 / Λ[0] +R_u = 1 / Λ[1] + +print(f'R_l = {R_l:.4f}') +print(f'R_u = {R_u:.4f}') +``` + +Partition $Q$ as + +$$ +Q =\begin{bmatrix} Q_{11} & Q_{12} \cr + Q_{21} & Q_{22} \end{bmatrix} +$$ + +Below we shall verify the following claims: + + +**Claims:** If we set + +$$ +p_0 = \overline p_0 \equiv Q_{21} Q_{11}^{-1} m_{0} , +$$ (eq:magicp0) + +it turns out that + +$$ +\frac{p_{t+1}}{p_t} = {R_u}^{-1}, \quad t \geq 0 +$$ + + +However, if we set + +$$ +p_0 > \bar p_0 +$$ + +then + +$$ +\lim_{t\rightarrow + \infty} \frac{p_{t+1}}{p_t} = {R_l}^{-1}. +$$ + +Let's verify these claims step by step. + + + +Note that + +$$ +H^t = Q \Lambda^t Q^{-1} +$$ + +so that + +$$ +y_t = Q \Lambda^t Q^{-1} y_0 +$$ + +```{code-cell} ipython3 +def iterate_H(y_0, H, num_steps): + Λ, Q = np.linalg.eig(H) + Q_inv = np.linalg.inv(Q) + y = np.stack( + [Q @ np.diag(Λ**t) @ Q_inv @ y_0 for t in range(num_steps)], 1) + + return y +``` + +For almost all initial vectors $y_0$, the gross rate of inflation $\frac{p_{t+1}}{p_t}$ eventually converges to the larger eigenvalue ${R_l}^{-1}$. + +The only way to avoid this outcome is for $p_0$ to take the specific value described by {eq}`eq:magicp0`. + +To understand this situation, we use the following +transformation + +$$ +y^*_t = Q^{-1} y_t . +$$ + +Dynamics of $y^*_t$ are evidently governed by + +$$ +y^*_{t+1} = \Lambda^t y^*_t . +$$ (eq:stardynamics) + +This equation represents the dynamics of our system in a way that lets us isolate the +force that causes gross inflation to converge to the inverse of the lower steady state rate +of inflation $R_l$ that we discovered earlier. + +Staring at equation {eq}`eq:stardynamics` indicates that unless + +```{math} +:label: equation_11 + +y^*_0 = \begin{bmatrix} y^*_{1,0} \cr 0 \end{bmatrix} +``` + +the path of $y^*_t$, and therefore the paths of both $m_t$ and $p_t$ given by +$y_t = Q y^*_t$ will eventually grow at gross rates ${R_l}^{-1}$ as +$t \rightarrow +\infty$. + +Equation {eq}`equation_11` also leads us to conclude that there is a unique setting +for the initial vector $y_0$ for which both components forever grow at the lower rate ${R_u}^{-1}$. + + +For this to occur, the required setting of $y_0$ must evidently have the property +that + +$$ +Q y_0 = y^*_0 = \begin{bmatrix} y^*_{1,0} \cr 0 \end{bmatrix} . +$$ + +But note that since +$y_0 = \begin{bmatrix} m_0 \cr p_0 \end{bmatrix}$ and $m_0$ +is given to us an initial condition, $p_0$ has to do all the adjusting to satisfy this equation. + +Sometimes this situation is described informally by saying that while $m_0$ +is truly a **state** variable, $p_0$ is a **jump** variable that +must adjust at $t=0$ in order to satisfy the equation. + +Thus, in a nutshell the unique value of the vector $y_0$ for which +the paths of $y_t$ **don't** eventually grow at rate ${R_l}^{-1}$ requires setting the second component +of $y^*_0$ equal to zero. + +The component $p_0$ of the initial vector +$y_0 = \begin{bmatrix} m_0 \cr p_0 \end{bmatrix}$ must evidently +satisfy + +$$ +Q^{\{2\}} y_0 =0 +$$ + +where $Q^{\{2\}}$ denotes the second row of $Q^{-1}$, a +restriction that is equivalent to + +```{math} +:label: equation_12 + +Q^{21} m_0 + Q^{22} p_0 = 0 +``` + +where $Q^{ij}$ denotes the $(i,j)$ component of +$Q^{-1}$. + +Solving this equation for $p_0$, we find + +```{math} +:label: equation_13 + +p_0 = - (Q^{22})^{-1} Q^{21} m_0. +``` + + +### More convenient formula + +We can get the equivalent but perhaps more convenient formula {eq}`eq:magicp0` for $p_0$ that is cast +in terms of components of $Q$ instead of components of +$Q^{-1}$. + +To get this formula, first note that because $(Q^{21}\ Q^{22})$ is +the second row of the inverse of $Q$ and because +$Q^{-1} Q = I$, it follows that + +$$ +\begin{bmatrix} Q^{21} & Q^{22} \end{bmatrix} \begin{bmatrix} Q_{11}\cr Q_{21} \end{bmatrix} = 0 +$$ + +which implies that + +$$ +Q^{21} Q_{11} + Q^{22} Q_{21} = 0. +$$ + +Therefore, + +$$ +-(Q^{22})^{-1} Q^{21} = Q_{21} Q^{-1}_{11}. +$$ + +So we can write + +```{math} + +p_0 = Q_{21} Q_{11}^{-1} m_0 . +``` + +which is our formula {eq}`eq:magicp0`. + +```{code-cell} ipython3 +p0_bar = (Q[1, 0]/Q[0, 0]) * msm.M0 + +print(f'p0_bar = {p0_bar:.4f}') +``` + +It can be verified that this formula replicates itself over time in the sense that + +```{math} +:label: equation_15 + +p_t = Q_{21} Q^{-1}_{11} m_t. +``` + +Now let's visualize the dynamics of $m_t$, $p_t$, and $R_t$ starting from different $p_0$ values to verify our claims above. + +We create a function `draw_iterations` to generate the plot + +```{code-cell} ipython3 +:tags: [hide-cell] + +def draw_iterations(p0s, model, line_params, num_steps): + + fig, axes = plt.subplots(3, 1, figsize=(8, 10), sharex=True) + + # Pre-compute time steps + time_steps = np.arange(num_steps) + + # Plot the first two y-axes in log scale + for ax in axes[:2]: + ax.set_yscale('log') + + # Iterate over p_0s and calculate a series of y_t + for p0 in p0s: + y0 = np.array([msm.M0, p0]) + y_series = iterate_H(y0, H, num_steps) + M, P = y_series[0, :], y_series[1, :] + + # Plot R_t against time + axes[0].plot(time_steps, M, **line_params) + + # Plot b_t against time + axes[1].plot(time_steps, P, **line_params) + + # Calculate R_t + R = np.insert(P[:-1] / P[1:], 0, np.NAN) + axes[2].plot(time_steps, R, **line_params) + + # Add line and text annotations to the subgraph + annotate_graph(axes[2], model, num_steps) + + # Draw labels + axes[0].set_ylabel('$m_t$') + axes[1].set_ylabel('$p_t$') + axes[2].set_ylabel('$R_t$') + axes[2].set_xlabel('timestep') + + # Enforce integar axis label + axes[2].xaxis.set_major_locator(MaxNLocator(integer=True)) + + plt.tight_layout() + plt.show() +``` + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Starting from different initial values of $p_0$, paths of $m_t$ (top + panel, log scale for $m$), $p_t$ (middle panel, log scale for $m$), $R_t$ (bottom + panel) + name: p0_path + width: 500px +--- +p0s = [p0_bar, 2.34, 2.5, 3, 4, 7, 30, 100_000] + +draw_iterations(p0s, msm, line_params, num_steps=20) +``` + +Please notice that for $m_t$ and $p_t$, we have used log scales for the coordinate (i.e., vertical) axes. + +Using log scales allows us to spot distinct constant limiting gross rates of growth ${R_u}^{-1}$ and +${R_l}^{-1}$ by eye. + + +## Peculiar stationary outcomes + +As promised at the start of this lecture, we have encountered these concepts from macroeconomics: + +* an **inflation tax** that a government gathers by printing paper or electronic money +* a dynamic **Laffer curve** in the inflation tax rate that has two stationary equilibria + +Staring at the paths of rates of return on the price level in figure {numref}`R0_path` and price levels in {numref}`p0_path` show indicate that almost all paths converge to the **higher** inflation tax rate displayed in the stationary state Laffer curve displayed in figure {numref}`infl_tax`. + +Thus, we have indeed discovered what we earlier called "perverse" dynamics under rational expectations in which the system converges to the higher of two possible stationary inflation tax rates. + +Those dynamics are "perverse" not only in the sense that they imply that the monetary and fiscal authorities that have chosen to finance government expenditures eventually impose a higher inflation tax than required to finance government expenditures, but because of the following "counterintuitive" situation that we can deduce by staring at the stationary state Laffer curve displayed in figure {numref}`infl_tax`: + +* the figure indicates that inflation can be **reduced** by running **higher** government deficits, i.e., by raising more resources through printing money. + + +```{note} +The same qualitive outcomes prevail in this lecture {doc}`money_inflation_nonlinear` that studies a nonlinear version of the model in this lecture. +``` + + +## Equilibrium selection + +We have discovered that as a model of price level paths or model is **incomplete** because there is a continuum of "equilibrium" paths for $\{m_{t+1}, p_t\}_{t=0}^\infty$ that are consistent with the demand for real balances always equaling the supply. + + +Through application of our computational methods 1 and 2, we have learned that this continuum can be indexed by choice of one of two scalars: + +* for computational method 1, $R_0$ +* for computational method 2, $p_0$ + +To apply our model, we have somehow to **complete** it by **selecting** an equilibrium path from among the continuum of possible paths. + +We discovered that + + * all but one of the equilibrium paths converge to limits in which the higher of two possible stationary inflation tax prevails + * there is a unique equilibrium path associated with "plausible" statements about how reductions in government deficits affect a stationary inflation rate + +On grounds of plausibility, we recommend following many macroeconomists in selecting the unique equilibrium that converges to the lower stationary inflation tax rate. + +As we shall see, we shall accept this recommendation in lecture {doc}`unpleasant`. + +In lecture, {doc}`laffer_adaptive`, we shall explore how {cite}`bruno1990seigniorage` and others justified this in other ways. + + + + + + diff --git a/lectures/money_inflation_nonlinear.md b/lectures/money_inflation_nonlinear.md new file mode 100644 index 00000000..8f43e249 --- /dev/null +++ b/lectures/money_inflation_nonlinear.md @@ -0,0 +1,452 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.14.5 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +--- + ++++ {"user_expressions": []} + +# Inflation Rate Laffer Curves + +## Overview + +This lecture studies stationary and dynamic **Laffer curves** in the inflation tax rate in a non-linear version of the model studied in this lecture {doc}`money_inflation`. + +This lecture uses the log-linear version of the demand function for money that {cite}`Cagan` +used in his classic paper in place of the linear demand function used in this lecture {doc}`money_inflation`. + +That change requires that we modify parts of our analysis. + +In particular, our dynamic system is no longer linear in state variables. + +Nevertheless, the economic logic underlying an analysis based on what we called ''method 2'' remains unchanged. + + +in this lecture we shall discover qualitatively similar outcomnes to those that we studied in the lecture {doc}`money_inflation`. + +That lecture presented a linear version of the model in this lecture. + +As in that lecture, we discussed these topics: + +* an **inflation tax** that a government gathers by printing paper or electronic money +* a dynamic **Laffer curve** in the inflation tax rate that has two stationary equilibria +* perverse dynamics under rational expectations in which the system converges to the higher stationary inflation tax rate +* a peculiar comparative stationary-state analysis connected with that stationary inflation rate that assert that inflation can be **reduced** by running **higher** government deficits + + + +These outcomes will set the stage for the analysis of this lecture {doc}`laffer_adaptive` that studies a version of the present model that uses a version of "adaptive expectations" instead of rational expectations. + +That lecture will show that + +* replacing rational expectations with adaptive expectations leaves the two stationary inflation rates unchanged, but that $\ldots$ +* it reverse the pervese dynamics by making the **lower** stationary inflation rate the one to which the system typically converges +* a more plausible comparative dynamic outcome emerges in which now inflation can be **reduced** by running **lower** government deficits + + + + + + + +## The Model + +Let + + * $m_t$ be the log of the money supply at the beginning of time $t$ + * $p_t$ be the log of the price level at time $t$ + +The demand function for money is + +$$ +m_{t+1} - p_t = -\alpha (p_{t+1} - p_t) +$$ (eq:mdemand) + +where $\alpha \geq 0$. + +The law of motion of the money supply is + +$$ +\exp(m_{t+1}) - \exp(m_t) = g \exp(p_t) +$$ (eq:msupply) + +where $g$ is the part of government expenditures financed by printing money. + +**Remark:** Please notice that while equation {eq}`eq:mdemand` is linear in logs of the money supply and price level, equation {eq}`eq:msupply` is linear in levels. This will require adapting the equilibrium computation methods that we deployed in {doc}`money_inflation`. + +## Computing An Equilibrium Sequence + +We'll deploy a method similar to **Method 2** used in {doc}`money_inflation`. + +We'll take the time $t$ state vector to be $m_t, p_t$. + + * we'll treat $m_t$ as a ''natural state variable'' and $p_t$ as a ''jump'' variable. + +Let + +$$ +\lambda \equiv \frac{\alpha}{1+ \alpha} +$$ + +Let's rewrite equations {eq}`eq:msupply` and {eq}`eq:mdemand`, respectively, as + + +$$ +\exp(m_{t+1}) - \exp(m_t) = g \exp(p_t) +$$ (eq:msupply2) + +and + +$$ +p_t = (1-\lambda) m_{t+1} + \lambda p_{t+1} +$$ (eq:mdemand2) + +We'll summarize our algorithm with the following pseudo-code. + +**Pseudo-code** + + * start for $m_0, p_0$ at time $t =0$ + + * solve {eq}`eq:msupply2` for $m_{t+1}$ + + * solve {eq}`eq:mdemand2` for $p_{t+1} = \lambda^{-1} p_t + (1 - \lambda^{-1}) m_{t+1}$ + + * compute $\pi_t = p_{t+1} - p_t$ and $\mu_t = m_{t+1} - m_t $ + + * iterate on $t$ to convergence of $\pi_t \rightarrow \overline \pi$ and $\mu_t \rightarrow \overline \mu$ + + +It will turn out that + + * if they exist, limiting values $\overline \pi$ and $\overline \mu$ will be equal + + * if limiting values exists, there are two possible limiting values, one high, one low + + * for almost all initial log price levels $p_0$, the limiting $\overline \pi = \overline \mu$ is + the higher value + + * for each of the two possible limiting values $\bar \pi$ ,there is a unique initial log price level $p_0$ that implies that $\pi_t = \mu_t = \bar \mu$ for all $t \geq 0$ + + * this unique initial log price level solves $\log(\exp(m_0) + g \exp(p_0)) - p_0 = - \alpha \bar \pi $ + + * the preceding equation for $p_0$ comes from $m_1 - p_0 = - \alpha \bar \pi$ + ++++ {"user_expressions": []} + +## Limiting Values of Inflation Rate + +We can compute the two prospective limiting values for $\bar \pi$ by studying the steady-state Laffer curve. + +Thus, in a **steady state** + +$$ +m_{t+1} - m_t = p_{t+1} - p_t = x \quad \forall t , +$$ + +where $x > 0 $ is a common rate of growth of logarithms of the money supply and price level. + +A few lines of algebra yields the following equation that $x$ satisfies + +$$ +\exp(-\alpha x) - \exp(-(1 + \alpha) x) = g +$$ (eq:steadypi) + +where we require that + +$$ +g \leq \max_{x: x \geq 0} \exp(-\alpha x) - \exp(-(1 + \alpha) x) , +$$ (eq:revmax) + +so that it is feasible to finance $g$ by printing money. + +The left side of {eq}`eq:steadypi` is steady state revenue raised by printing money. + +The right side of {eq}`eq:steadypi` is the quantity of time $t$ goods that the government raises by printing money. + +Soon we'll plot the left and right sides of equation {eq}`eq:steadypi`. + +But first we'll write code that computes a steady-state +$\bar \pi$. + + + +Let's start by importing some libraries + +```{code-cell} ipython3 +from collections import namedtuple +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.ticker import MaxNLocator +from scipy.optimize import fsolve +``` + ++++ {"user_expressions": []} + +Let's create a `namedtuple` to store the parameters of the model + +```{code-cell} ipython3 +CaganLaffer = namedtuple('CaganLaffer', + ["m0", # log of the money supply at t=0 + "α", # sensitivity of money demand + "λ", + "g" ]) + +# Create a CaganLaffer model +def create_model(α=0.5, m0=np.log(100), g=0.35): + return CaganLaffer(α=α, m0=m0, λ=α/(1+α), g=g) + +model = create_model() +``` + ++++ {"user_expressions": []} + +Now we write code that computes steady-state $\bar \pi$s. + +```{code-cell} ipython3 +# Define formula for π_bar +def solve_π(x, α, g): + return np.exp(-α * x) - np.exp(-(1 + α) * x) - g + +def solve_π_bar(model, x0): + π_bar = fsolve(solve_π, x0=x0, xtol=1e-10, args=(model.α, model.g))[0] + return π_bar + +# Solve for the two steady state of π +π_l = solve_π_bar(model, x0=0.6) +π_u = solve_π_bar(model, x0=3.0) +print(f'The two steady state of π are: {π_l, π_u}') +``` + ++++ {"user_expressions": []} + +We find two steady state $\bar \pi$ values + ++++ {"user_expressions": []} + + + +## Steady State Laffer Curve + +The following figure plots the steady state Laffer curve together with the two stationary inflation rates. + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Seigniorage as function of steady state inflation. The dashed brown lines indicate $\pi_l$ and $\pi_u$. + name: laffer_curve_nonlinear + width: 500px +--- + +def compute_seign(x, α): + return np.exp(-α * x) - np.exp(-(1 + α) * x) + +def plot_laffer(model, πs): + α, g = model.α, model.g + + # Generate π values + x_values = np.linspace(0, 5, 1000) + + # Compute corresponding seigniorage values for the function + y_values = compute_seign(x_values, α) + + # Plot the function + plt.plot(x_values, y_values, + label=f'$exp((-{α})x) - exp(- (1- {α}) x)$') + for π, label in zip(πs, ['$\pi_l$', '$\pi_u$']): + plt.text(π, plt.gca().get_ylim()[0]*2, + label, horizontalalignment='center', + color='brown', size=10) + plt.axvline(π, color='brown', linestyle='--') + plt.axhline(g, color='red', linewidth=0.5, + linestyle='--', label='g') + plt.xlabel('$\pi$') + plt.ylabel('seigniorage') + plt.legend() + plt.grid(True) + plt.show() + +# Steady state Laffer curve +plot_laffer(model, (π_l, π_u)) +``` + +## Associated Initial Price Levels + + Now that we have our hands on the two possible steady states, we can compute two initial log price levels $p_0$, which as initial conditions, imply that $\pi_t = \bar \pi $ for all $t \geq 0$. + +```{code-cell} ipython3 +def solve_p0(p0, m0, α, g, π): + return np.log(np.exp(m0) + g * np.exp(p0)) + α * π - p0 + +def solve_p0_bar(model, x0, π_bar): + p0_bar = fsolve(solve_p0, x0=x0, xtol=1e-20, args=(model.m0, + model.α, + model.g, + π_bar))[0] + return p0_bar + +# Compute two initial price levels associated with π_l and π_u +p0_l = solve_p0_bar(model, + x0=np.log(220), + π_bar=π_l) +p0_u = solve_p0_bar(model, + x0=np.log(220), + π_bar=π_u) +print(f'Associated initial p_0s are: {p0_l, p0_u}') +``` + ++++ {"user_expressions": []} + +### Verification + +To start, let's write some code to verify that if the initial log price level $p_0$ takes one +of the two values we just calculated, the inflation rate $\pi_t$ will be constant for all $t \geq 0$. + +The following code verifies this. + +```{code-cell} ipython3 +# Implement pseudo-code above +def simulate_seq(p0, model, num_steps): + λ, g = model.λ, model.g + π_seq, μ_seq, m_seq, p_seq = [], [], [model.m0], [p0] + + for t in range(num_steps): + + m_seq.append(np.log(np.exp(m_seq[t]) + g * np.exp(p_seq[t]))) + p_seq.append(1/λ * p_seq[t] + (1 - 1/λ) * m_seq[t+1]) + + μ_seq.append(m_seq[t+1]-m_seq[t]) + π_seq.append(p_seq[t+1]-p_seq[t]) + + return π_seq, μ_seq, m_seq, p_seq +``` + +```{code-cell} ipython3 +π_seq, μ_seq, m_seq, p_seq = simulate_seq(p0_l, model, 150) + +# Check π and μ at steady state +print('π_bar == μ_bar:', π_seq[-1] == μ_seq[-1]) + +# Check steady state m_{t+1} - m_t and p_{t+1} - p_t +print('m_{t+1} - m_t:', m_seq[-1] - m_seq[-2]) +print('p_{t+1} - p_t:', p_seq[-1] - p_seq[-2]) + +# Check if exp(-αx) - exp(-(1 + α)x) = g +eq_g = lambda x: np.exp(-model.α * x) - np.exp(-(1 + model.α) * x) + +print('eq_g == g:', np.isclose(eq_g(m_seq[-1] - m_seq[-2]), model.g)) +``` + ++++ {"user_expressions": []} + +## Slippery Side of Laffer Curve Dynamics + +We are now equipped to compute time series starting from different $p_0$ settings, like those in this lecture {doc}`money_inflation`. + +```{code-cell} ipython3 +:tags: [hide-cell] + +def draw_iterations(p0s, model, line_params, p0_bars, num_steps): + + fig, axes = plt.subplots(4, 1, figsize=(8, 10), sharex=True) + + # Pre-compute time steps + time_steps = np.arange(num_steps) + + # Plot the first two y-axes in log scale + for ax in axes[:2]: + ax.set_yscale('log') + + # Iterate over p_0s and calculate a series of y_t + for p0 in p0s: + π_seq, μ_seq, m_seq, p_seq = simulate_seq(p0, model, num_steps) + + # Plot m_t + axes[0].plot(time_steps, m_seq[1:], **line_params) + + # Plot p_t + axes[1].plot(time_steps, p_seq[1:], **line_params) + + # Plot π_t + axes[2].plot(time_steps, π_seq, **line_params) + + # Plot μ_t + axes[3].plot(time_steps, μ_seq, **line_params) + + # Draw labels + axes[0].set_ylabel('$m_t$') + axes[1].set_ylabel('$p_t$') + axes[2].set_ylabel('$\pi_t$') + axes[3].set_ylabel('$\mu_t$') + axes[3].set_xlabel('timestep') + + for p_0, label in [(p0_bars[0], '$p_0=p_l$'), (p0_bars[1], '$p_0=p_u$')]: + y = simulate_seq(p_0, model, 1)[0] + for ax in axes[2:]: + ax.axhline(y=y[0], color='grey', linestyle='--', lw=1.5, alpha=0.6) + ax.text(num_steps * 1.02, y[0], label, verticalalignment='center', + color='grey', size=10) + + # Enforce integar axis label + axes[3].xaxis.set_major_locator(MaxNLocator(integer=True)) + + plt.tight_layout() + plt.show() +``` + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Starting from different initial values of $p_0$, paths of $m_t$ (top + panel, log scale for $m$), $p_t$ (second panel, log scale for $p$), $\pi_t$ (third panel), and $\mu_t$ (bottom + panel) + name: p0_path_nonlin + width: 500px +--- + +# Generate a sequence from p0_l to p0_u +p0s = np.arange(p0_l, p0_u, 0.1) + +line_params = {'lw': 1.5, + 'marker': 'o', + 'markersize': 3} + +p0_bars = (p0_l, p0_u) + +draw_iterations(p0s, model, line_params, p0_bars, num_steps=20) +``` + + +Staring at the paths of price levels in {numref}`p0_path_nonlin` reveals that almost all paths converge to the **higher** inflation tax rate displayed in the stationary state Laffer curve. displayed in figure {numref}`laffer_curve_nonlinear`. + +Thus, we have reconfirmed what we have called the "perverse" dynamics under rational expectations in which the system converges to the higher of two possible stationary inflation tax rates. + +Those dynamics are "perverse" not only in the sense that they imply that the monetary and fiscal authorities that have chosen to finance government expenditures eventually impose a higher inflation tax than required to finance government expenditures, but because of the following "counterintuitive" situation that we can deduce by staring at the stationary state Laffer curve displayed in figure {numref}`laffer_curve_nonlinear`: + +* the figure indicates that inflation can be **reduced** by running **higher** government deficits, i.e., by raising more resources through printing money. + + +```{note} +The same qualitive outcomes prevail in this lecture {doc}`money_inflation` that studies a linear version of the model in this lecture`. +``` + +We discovered that + + * all but one of the equilibrium paths converge to limits in which the higher of two possible stationary inflation tax prevails + * there is a unique equilibrium path associated with "plausible" statements about how reductions in government deficits affect a stationary inflation rate + +As in this lecture {doc}`money_inflation`, +on grounds of plausibility, we again recommend selecting the unique equilibrium that converges to the lower stationary inflation tax rate. + +As we shall see, we accepting this recommendation is a key ingredient of outcomes of the "unpleasant arithmetic" that we describe in lecture {doc}`unpleasant`. + +In lecture, {doc}`laffer_adaptive`, we shall explore how {cite}`bruno1990seigniorage` and others justified our equilibrium selection in other ways. + diff --git a/lectures/unpleasant.md b/lectures/unpleasant.md new file mode 100644 index 00000000..0d744bf1 --- /dev/null +++ b/lectures/unpleasant.md @@ -0,0 +1,524 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.14.1 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +--- + + +# Unpleasant Monetarist Arithmetic + +## Overview + + +This lecture builds on concepts and issues introduced in our lecture on **Money Supplies and Price Levels**. + +That lecture describes stationary equilibria that reveal a **Laffer curve** in the inflation tax rate and the associated stationary rate of return +on currency. + +In this lecture we study a situation in which a stationary equilibrium prevails after date $T > 0$, but not before then. + +For $t=0, \ldots, T-1$, the money supply, price level, and interest-bearing government debt vary along a transition path that ends at $t=T$. + +During this transition, the ratio of the real balances $\frac{m_{t+1}}{{p_t}}$ to indexed one-period government bonds $\tilde R B_{t-1}$ maturing at time $t$ decreases each period. + +This has consequences for the **gross-of-interest** government deficit that must be financed by printing money for times $t \geq T$. + +The critical **money-to-bonds** ratio stabilizes only at time $T$ and afterwards. + +And the larger is $T$, the higher is the gross-of-interest government deficit that must be financed +by printing money at times $t \geq T$. + +These outcomes are the essential finding of Sargent and Wallace's **unpleasant monetarist arithmetic** {cite}`sargent1981`. + +**Reader's Guide:** Please read our lecture on Money Supplies and Price levels before diving into this lecture. + +That lecture described supplies and demands for money that appear in lecture. + +It also characterized the steady state equilibrium from which we work backwards in this lecture. + +In addition to learning about ''unpleasant monetarist arithmetic", in this lecture we'll learn how to implement a **fixed point** algorithm for computing an initial price level. + + + + + + + +## Setup + +Let's start with quick reminders of the model's components set out in our lecture on **Money Supplies and Price Levels**. + +Please consult that lecture for more details and Python code that we'll also use in this lecture. + +For $t \geq 1$, **real balances** evolve according to + + +$$ +\frac{m_{t+1}}{p_t} - \frac{m_{t}}{p_{t-1}} \frac{p_{t-1}}{p_t} = g +$$ + +or + +$$ +b_t - b_{t-1} R_{t-1} = g +$$ (eq:up_bmotion) + +where + + * $b_t = \frac{m_{t+1}}{p_t}$ is real balances at the end of period $t$ + * $R_{t-1} = \frac{p_{t-1}}{p_t}$ is the gross rate of return on real balances held from $t-1$ to $t$ + +The demand for real balances is + +$$ +b_t = \gamma_1 - \gamma_2 R_t^{-1} . +$$ (eq:up_bdemand) + + + +## Monetary-Fiscal Policy + +To the basic model of our lecture on **Money Supplies and Price Levels**, we add inflation-indexed one-period government bonds as an additional way for the government to finance government expenditures. + +Let $\widetilde R > 1$ be a time-invariant gross real rate of return on government one-period inflation-indexed bonds. + + +With this additional source of funds, the government's budget constraint at time $t \geq 0$ is now + +$$ +B_t + \frac{m_{t+1}}{p_t} = \widetilde R B_{t-1} + \frac{m_t}{p_t} + g +$$ + + +Just before the beginning of time $0$, the public owns $\check m_0$ units of currency (measured in dollars) +and $\widetilde R \check B_{-1}$ units of one-period indexed bonds (measured in time $0$ goods); these two quantities are initial conditions set outside the model. + +Notice that $\check m_0$ is a **nominal** quantity, being measured in dollar, while +$\widetilde R \check B_{-1}$ is a **real** quantity, being measured in time $0$ goods. + + +### Open market operations + +At time $0$, government can rearrange its portolio of debts with subject to the following constraint (on open-market operations): + +$$ +\widetilde R B_{-1} + \frac{m_0}{p_0} = \widetilde R \check B_{-1} + \frac{\check m_0}{p_0} +$$ + +or + +$$ +B_{-1} - \check B_{-1} = \frac{1}{p_0 \widetilde R} \left( \check m_0 - m_0 \right) +$$ (eq:openmarketconstraint) + +This equation says that the government (e.g., the central bank) can **decrease** $m_0$ relative to +$\check m_0$ by **increasing** $B_{-1}$ relative to $\check B_{-1}$. + +This is a version of a standard constraint on a central bank's **open market operations** in which it expands the stock of money by buying government bonds from the public. + +## An open market operation at $t=0$ + +Following Sargent and Wallace (1981), we analyze consequences of a central bank policy that +uses an open market operation to lower the price level in the face of a peristent fiscal +deficit that takes the form of a positive $g$. + +Just before time $0$, the government chooses $(m_0, B_{-1})$ subject to constraint +{eq}`eq:openmarketconstraint`. + +For $t =0, 1, \ldots, T-1$, + +$$ +\begin{aligned} +B_t & = \widetilde R B_{t-1} + g \cr +m_{t+1} & = m_0 +\end{aligned} +$$ + +while for $t \geq T$, + +$$ +\begin{aligned} +B_t & = B_{T-1} \cr +m_{t+1} & = m_t + p_t \overline g +\end{aligned} +$$ + +where + +$$ +\overline g = \left[(\tilde R -1) B_{T-1} + g \right] +$$ (eq:overlineg) + +We want to compute an equilibrium $\{p_t,m_t,b_t, R_t\}_{t=0}$ sequence under this scheme for +running monetary-fiscal policy. + +**TOM: add definitions of monetary and fiscal policy and coordination here.** + +## Algorithm (basic idea) + + +We work backwards from $t=T$ and first compute $p_T, R_u$ associated with the low-inflation, low-inflation-tax-rate stationary equilibrium of our lecture on the dynamic Laffer curve for the inflation tax. + +To start our description of our algorithm, it is useful to recall that a stationary rate of return +on currency $\bar R$ solves the quadratic equation + +$$ +-\gamma_2 + (\gamma_1 + \gamma_2 - \overline g) \bar R - \gamma_1 \bar R^2 = 0 +$$ (eq:up_steadyquadratic) + +Quadratic equation {eq}`eq:up_steadyquadratic` has two roots, $R_l < R_u < 1$. + +For reasons described at the end of **this lecture**, we select the larger root $R_u$. + + +Next, we compute + +$$ +\begin{aligned} +R_T & = R_u \cr +b_T & = \gamma_1 - \gamma_2 R_u^{-1} \cr +p_T & = \frac{m_0}{\gamma_1 - \overline g - \gamma_2 R_u^{-1}} +\end{aligned} +$$ (eq:LafferTstationary) + + +We can compute continuation sequences $\{R_t, b_t\}_{t=T+1}^\infty$ of rates of return and real balances that are associated with an equilibrium by solving equation {eq}`eq:up_bmotion` and {eq}`eq:up_bdemand` sequentially for $t \geq 1$: + \begin{aligned} +b_t & = b_{t-1} R_{t-1} + \overline g \cr +R_t^{-1} & = \frac{\gamma_1}{\gamma_2} - \gamma_2^{-1} b_t \cr +p_t & = R_t p_{t-1} \cr + m_t & = b_{t-1} p_t +\end{aligned} + + + +## Before time $T$ + +Define + +$$ +\lambda \equiv \frac{\gamma_2}{\gamma_1}. +$$ + +Our restrictions that $\gamma_1 > \gamma_2 > 0$ imply that $\lambda \in [0,1)$. + +We want to compute + +$$ +\begin{aligned} +p_0 & = \gamma_1^{-1} \left[ \sum_{j=0}^\infty \lambda^j m_{1+j} \right] \cr +& = \gamma_1^{-1} \left[ \sum_{j=0}^{T-1} \lambda^j m_{0} + \sum_{j=T}^\infty \lambda^j m_{1+j} \right] +\end{aligned} +$$ + +Thus, + +$$ +\begin{aligned} +p_0 & = \gamma_1^{-1} m_0 \left\{ \frac{1 - \lambda^T}{1-\lambda} + \frac{\lambda^T}{R_u-\lambda} \right\} \cr +p_1 & = \gamma_1^{-1} m_0 \left\{ \frac{1 - \lambda^{T-1}}{1-\lambda} + \frac{\lambda^{T-1}}{R_u-\lambda} \right\} \cr +\quad \vdots & \quad \quad \vdots \cr +p_{T-1} & = \gamma_1^{-1} m_0 \left\{ \frac{1 - \lambda}{1-\lambda} + \frac{\lambda}{R_u-\lambda} \right\} \cr +p_T & = \gamma_1^{-1} m_0 \left\{\frac{1}{R_u-\lambda} \right\} +\end{aligned} +$$ (eq:allts) + +We can implement the preceding formulas by iterating on + +$$ +p_t = \gamma_1^{-1} m_0 + \lambda p_{t+1}, \quad t = T-1, T-2, \ldots, 0 +$$ + +starting from + +$$ +p_T = \frac{m_0}{\gamma_1 - \overline g - \gamma_2 R_u^{-1}} = \gamma_1^{-1} m_0 \left\{\frac{1}{R_u-\lambda} \right\} +$$ (eq:pTformula) + +**Remark:** +We can verify the equivalence of the two formulas on the right sides of {eq}`eq:pTformula` by recalling that +$R_u$ is a root of the quadratic equation {eq}`eq:up_steadyquadratic` that determines steady state rates of return on currency. + +## Algorithm (pseudo code) + +Now let's describe a computational algorithm in more detail in the form of a description +that constitutes ''pseudo code'' because it approaches a set of instructions we could provide to a +Python coder. + +To compute an equilibrium, we deploy the following algorithm. + +Given **parameters** include $g, \check m_0, \check B_{-1}, \widetilde R >1, T $ + +We define a mappying from $p_0$ to $p_0$ as follows. + +* Set $m_0$ and then compute $B_{-1}$ to satisfy the constraint on time $0$ **open market operations** + +$$ +B_{-1}- \check B_{-1} = \frac{\widetilde R}{p_0} \left( \check m_0 - m_0 \right) +$$ + +* Compute $B_{T-1}$ from + +$$ +B_{T-1} = \widetilde R^T B_{-1} + \left( \frac{1 - \widetilde R^T}{1-\widetilde R} \right) g +$$ + +* Compute + +$$ +\overline g = g + \left[ \tilde R - 1\right] B_{T-1} +$$ + + + +* Compute $R_u, p_T$ from formulas {eq}`eq:up_steadyquadratic` and {eq}`eq:LafferTstationary` above + +* Compute a new estimate of $p_0$, call it $\widehat p_0$, from equation {eq}`eq:allts` above + + +* Note that the preceding steps define a mapping + +$$ +\widehat p_0 = {\mathcal S}(p_0) +$$ + +* We seek a fixed point of ${\mathcal S}$, i.e., a solution of $p_0 = {\mathcal S}(p_0)$. + +* Compute a fixed point by iterating to convergence on the relaxation algorithm + +$$ +p_{0,j+1} = (1-\theta) {\mathcal S}(p_{0,j}) + \theta p_{0,j}, +$$ + +where $\theta \in [0,1)$ is a relaxation parameter. + + +## Example Calculations + +We'll set parameters of the model so that the steady state after time $T$ is initially the same +as in our lecture on "Money and Inflation". + +In particular, we set $\gamma_1=100, \gamma_2 =50, g=3.0$. We set $m_0 = 100$ in that lecture, +but now the counterpart will be $M_T$, which is endogenous. + +As for new parameters, we'll set $\tilde R = 1.01, \check B_{-1} = 0, \check m_0 = 105, T = 5$. + +We'll study a "small" open market operation by setting $m_0 = 100$. + +These parameter settings mean that just before time $0$, the "central bank" sells the public bonds in exchange for $\check m_0 - m_0 = 5$ units of currency. + +That leaves the public with less currency but more government interest-bearing bonds. + +Since the public has less currency (it's supply has diminished) it is plausible to anticipate that the price level at time $0$ will be driven downward. + +But that is not the end of the story, because this ''open market operation'' at time $0$ has consequences for future settings of $m_{t+1}$ and the gross-of-interest government deficit $\bar g_t$. + + +Let's start with some imports: + +```{code-cell} ipython3 +import numpy as np +import matplotlib.pyplot as plt +from collections import namedtuple +``` + +Now let's dive in and implement our ''pseudo code'' in Python. + +```{code-cell} ipython3 +# Create a namedtuple that contains parameters +MoneySupplyModel = namedtuple("MoneySupplyModel", + ["γ1", "γ2", "g", + "R_tilde", "m0_check", "Bm1_check", + "T"]) + +def create_model(γ1=100, γ2=50, g=3.0, + R_tilde=1.01, + Bm1_check=0, m0_check=105, + T=5): + + return MoneySupplyModel(γ1=γ1, γ2=γ2, g=g, + R_tilde=R_tilde, + m0_check=m0_check, Bm1_check=Bm1_check, + T=T) +``` + +```{code-cell} ipython3 +msm = create_model() +``` + +```{code-cell} ipython3 +def S(p0, m0, model): + + # unpack parameters + γ1, γ2, g = model.γ1, model.γ2, model.g + R_tilde = model.R_tilde + m0_check, Bm1_check = model.m0_check, model.Bm1_check + T = model.T + + # open market operation + Bm1 = 1 / (p0 * R_tilde) * (m0_check - m0) + Bm1_check + + # compute B_{T-1} + BTm1 = R_tilde ** T * Bm1 + ((1 - R_tilde ** T) / (1 - R_tilde)) * g + + # compute g bar + g_bar = g + (R_tilde - 1) * BTm1 + + # solve the quadratic equation + Ru = np.roots((-γ1, γ1 + γ2 - g_bar, -γ2)).max() + + # compute p0 + λ = γ2 / γ1 + p0_new = (1 / γ1) * m0 * ((1 - λ ** T) / (1 - λ) + λ ** T / (Ru - λ)) + + return p0_new +``` + +```{code-cell} ipython3 +def compute_fixed_point(m0, p0_guess, model, θ=0.5, tol=1e-6): + + p0 = p0_guess + error = tol + 1 + + while error > tol: + p0_next = (1 - θ) * S(p0, m0, model) + θ * p0 + + error = np.abs(p0_next - p0) + p0 = p0_next + + return p0 +``` +Let's look at how price level $p_0$ in the stationary $R_u$ equilibrium depends on the initial +money supply $m_0$. + +Notice that the slope of $p_0$ as a function of $m_0$ is constant. + +This outcome indicates that our model verifies a ''quantity theory of money'' outcome, +something that Sargent and Wallace {cite}`sargent1981` purposefully built into their model to justify +the adjective **monetarist** in their title. + + +```{code-cell} ipython3 +m0_arr = np.arange(10, 110, 10) +``` + +```{code-cell} ipython3 +plt.plot(m0_arr, [compute_fixed_point(m0, 1, msm) for m0 in m0_arr]) + +plt.ylabel('$p_0$') +plt.xlabel('$m_0$') + +plt.show() +``` + +Now let's write and implement code that let's us experiment with the time $0$ open market operation described earlier. + +```{code-cell} ipython3 +def simulate(m0, model, length=15, p0_guess=1): + + # unpack parameters + γ1, γ2, g = model.γ1, model.γ2, model.g + R_tilde = model.R_tilde + m0_check, Bm1_check = model.m0_check, model.Bm1_check + T = model.T + + # (pt, mt, bt, Rt) + paths = np.empty((4, length)) + + # open market operation + p0 = compute_fixed_point(m0, 1, model) + Bm1 = 1 / (p0 * R_tilde) * (m0_check - m0) + Bm1_check + BTm1 = R_tilde ** T * Bm1 + ((1 - R_tilde ** T) / (1 - R_tilde)) * g + g_bar = g + (R_tilde - 1) * BTm1 + Ru = np.roots((-γ1, γ1 + γ2 - g_bar, -γ2)).max() + + λ = γ2 / γ1 + + # t = 0 + paths[0, 0] = p0 + paths[1, 0] = m0 + + # 1 <= t <= T + for t in range(1, T+1, 1): + paths[0, t] = (1 / γ1) * m0 * \ + ((1 - λ ** (T - t)) / (1 - λ) + + (λ ** (T - t) / (Ru - λ))) + paths[1, t] = m0 + + # t > T + for t in range(T+1, length): + paths[0, t] = paths[0, t-1] / Ru + paths[1, t] = paths[1, t-1] + paths[0, t] * g_bar + + # Rt = pt / pt+1 + paths[3, :T] = paths[0, :T] / paths[0, 1:T+1] + paths[3, T:] = Ru + + # bt = γ1 - γ2 / Rt + paths[2, :] = γ1 - γ2 / paths[3, :] + + return paths +``` + +```{code-cell} ipython3 +def plot_path(m0_arr, model, length=15): + + fig, axs = plt.subplots(2, 2, figsize=(8, 5)) + + for m0 in m0_arr: + paths = simulate(m0, msm, length=length) + + axs[0, 0].plot(paths[0]) + axs[0, 0].set_title('$p_t$') + + axs[0, 1].plot(paths[1]) + axs[0, 1].set_title('$m_t$') + + axs[1, 0].plot(paths[2]) + axs[1, 0].set_title('$b_t$') + + axs[1, 1].plot(paths[3]) + axs[1, 1].set_title('$R_t$') + + axs[0, 1].hlines(model.m0_check, 0, length, + color='r', linestyle='--') + axs[0, 1].text(length*0.8, model.m0_check*0.9, '$\check{m}_0$') + plt.show() +``` + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: "Unpleasant Arithmetic" + name: fig:unpl1 +--- +plot_path([80, 100], msm) +``` + +Figure {numref}`fig:unpl1` summarizes outcomes of two experiments that convey messages of +Sargent and Wallace's **unpleasant monetarist arithmetic** {cite}`sargent1981`. + + * An open market operation that reduces the supply of money at time $t=0$ reduces the price level at time $t=0$ + +* The lower is the post-open-market-operation money supply at time $0$, lower is the price level at time $0$. + +* An open market operation that reduces the post-open-market-operation money supply at time $0$ also **lowers** the rate of return on money $R_u$ at times $t \geq T$ because it brings a higher gross-of-interest government deficit that must be financed by printing money (i.e., levying an inflation tax) at time $t \geq T$. + + + + + + + + + + +