{
"cells": [
{
"cell_type": "markdown",
"id": "4a371a69",
"metadata": {},
"source": [
"# Money Financed Government Deficits and Price Levels"
]
},
{
"cell_type": "markdown",
"id": "1b156c23",
"metadata": {},
"source": [
"## Overview\n",
"\n",
"This lecture extends and modifies the model in this lecture [A Monetarist Theory of Price Levels](https://intro.quantecon.org/cagan_ree.html) by modifying the\n",
"law of motion that governed the supply of money.\n",
"\n",
"The model in this lecture consists of two components\n",
"\n",
"- a demand function for money \n",
"- a law of motion for the supply of money \n",
"\n",
"\n",
"The demand function describes the public’s demand for “real balances”, defined as the ratio of nominal money balances to the price level\n",
"\n",
"- 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 \n",
"- it assumes that the public’s forecast of that rate of inflation is perfect \n",
"\n",
"\n",
"The law of motion for the supply of money assumes that the government prints money to finance government expenditures\n",
"\n",
"Our model equates the demand for money to the supply at each time $ t \\geq 0 $.\n",
"\n",
"Equality between those demands and supply gives a *dynamic* model in which money supply\n",
"and price level *sequences* are simultaneously determined by a set of simultaneous linear equations.\n",
"\n",
"These equations take the form of what is often called vector linear **difference equations**.\n",
"\n",
"In this lecture, we’ll roll up our sleeves and solve those equations in two different ways.\n",
"\n",
"(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 [Eigenvalues and Eigenvectors](https://intro.quantecon.org/eigen_I.html).)\n",
"\n",
"In this lecture we will encounter these concepts from macroeconomics:\n",
"\n",
"- an **inflation tax** that a government gathers by printing paper or electronic money \n",
"- a dynamic **Laffer curve** in the inflation tax rate that has two stationary equilibria \n",
"- perverse dynamics under rational expectations in which the system converges to the higher stationary inflation tax rate \n",
"- 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. \n",
"\n",
"\n",
"The same qualitative outcomes prevail in this lecture [Inflation Rate Laffer Curves](https://intro.quantecon.org/money_inflation_nonlinear.html) that studies a nonlinear version of the model in this lecture.\n",
"\n",
"These outcomes set the stage for the analysis to be presented in this lecture [Laffer Curves with Adaptive Expectations](https://intro.quantecon.org/laffer_adaptive.html) that studies a nonlinear version of the present model; it assumes a version of “adaptive expectations” instead of rational expectations.\n",
"\n",
"That lecture will show that\n",
"\n",
"- replacing rational expectations with adaptive expectations leaves the two stationary inflation rates unchanged, but that $ \\ldots $ \n",
"- it reverses the perverse dynamics by making the *lower* stationary inflation rate the one to which the system typically converges \n",
"- a more plausible comparative dynamic outcome emerges in which now inflation can be *reduced* by running *lower* government deficits \n",
"\n",
"\n",
"This outcome will be used to justify a selection of a stationary inflation rate that underlies the analysis of unpleasant monetarist arithmetic to be studied in this lecture [Some Unpleasant Monetarist Arithmetic](https://intro.quantecon.org/unpleasant.html).\n",
"\n",
"We’ll use these tools from linear algebra:\n",
"\n",
"- matrix multiplication \n",
"- matrix inversion \n",
"- eigenvalues and eigenvectors of a matrix "
]
},
{
"cell_type": "markdown",
"id": "a9d5308b",
"metadata": {},
"source": [
"## Demand for and supply of money\n",
"\n",
"We say demand*s* and suppl*ies* (plurals) because there is one of each for each $ t \\geq 0 $.\n",
"\n",
"Let\n",
"\n",
"- $ m_{t+1} $ be the supply of currency at the end of time $ t \\geq 0 $ \n",
"- $ m_{t} $ be the supply of currency brought into time $ t $ from time $ t-1 $ \n",
"- $ g $ be the government deficit that is financed by printing currency at $ t \\geq 1 $ \n",
"- $ m_{t+1}^d $ be the demand at time $ t $ for currency to bring into time $ t+1 $ \n",
"- $ p_t $ be the price level at time $ t $ \n",
"- $ b_t = \\frac{m_{t+1}}{p_t} $ is real balances at the end of time $ t $ \n",
"- $ R_t = \\frac{p_t}{p_{t+1}} $ be the gross rate of return on currency held from time $ t $ to time $ t+1 $ \n",
"\n",
"\n",
"It is often helpful to state units in which quantities are measured:\n",
"\n",
"- $ m_t $ and $ m_t^d $ are measured in dollars \n",
"- $ g $ is measured in time $ t $ goods \n",
"- $ p_t $ is measured in dollars per time $ t $ goods \n",
"- $ R_t $ is measured in time $ t+1 $ goods per unit of time $ t $ goods \n",
"- $ b_t $ is measured in time $ t $ goods \n",
"\n",
"\n",
"Our job now is to specify demand and supply functions for money.\n",
"\n",
"We assume that the demand for currency satisfies the Cagan-like demand function\n",
"\n",
"\n",
"\n",
"$$\n",
"\\frac{m_{t+1}^d}{p_t}=\\gamma_1 - \\gamma_2 \\frac{p_{t+1}}{p_t}, \\quad t \\geq 0 \\tag{28.1}\n",
"$$\n",
"\n",
"where $ \\gamma_1, \\gamma_2 $ are positive parameters.\n",
"\n",
"Now we turn to the supply of money.\n",
"\n",
"We assume that $ m_0 >0 $ is an “initial condition” determined outside the model.\n",
"\n",
"We set $ m_0 $ at some arbitrary positive value, say \\$100.\n",
"\n",
"For $ t \\geq 1 $, we assume that the supply of money is determined by the government’s budget constraint\n",
"\n",
"\n",
"\n",
"$$\n",
"m_{t+1} - m_{t} = p_t g , \\quad t \\geq 0 \\tag{28.2}\n",
"$$\n",
"\n",
"According to this equation, each period, the government prints money to pay for quantity $ g $ of goods.\n",
"\n",
"In an **equilibrium**, the demand for currency equals the supply:\n",
"\n",
"\n",
"\n",
"$$\n",
"m_{t+1}^d = m_{t+1}, \\quad t \\geq 0 \\tag{28.3}\n",
"$$\n",
"\n",
"Let’s take a moment to think about what equation [(28.3)](#equation-eq-syeqdemand) tells us.\n",
"\n",
"The demand for money at any time $ t $ depends on the price level at time $ t $ and the price level at time $ t+1 $.\n",
"\n",
"The supply of money at time $ t+1 $ depends on the money supply at time $ t $ and the price level at time $ t $.\n",
"\n",
"So the infinite sequence of equations [(28.3)](#equation-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."
]
},
{
"cell_type": "markdown",
"id": "46e30b24",
"metadata": {},
"source": [
"## Equilibrium price and money supply sequences\n",
"\n",
"The preceding specifications imply that for $ t \\geq 1 $, **real balances** evolve according to\n",
"\n",
"$$\n",
"\\frac{m_{t+1}}{p_t} - \\frac{m_{t}}{p_{t-1}} \\frac{p_{t-1}}{p_t} = g\n",
"$$\n",
"\n",
"or\n",
"\n",
"\n",
"\n",
"$$\n",
"b_t - b_{t-1} R_{t-1} = g \\tag{28.4}\n",
"$$\n",
"\n",
"The demand for real balances is\n",
"\n",
"\n",
"\n",
"$$\n",
"b_t = \\gamma_1 - \\gamma_2 R_t^{-1} . \\tag{28.5}\n",
"$$\n",
"\n",
"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 [(28.5)](#equation-eq-bdemand) means that\n",
"\n",
"$$\n",
"b_t = \\gamma_1 - \\gamma_2 R_t^{-1} > 0\n",
"$$\n",
"\n",
"which implies that\n",
"\n",
"\n",
"\n",
"$$\n",
"R_t \\geq \\left( \\frac{\\gamma_2}{\\gamma_1} \\right) \\equiv \\underline R \\tag{28.6}\n",
"$$\n",
"\n",
"Gross real rate of return $ \\underline R $ is the smallest rate of return on currency\n",
"that is consistent with a nonnegative demand for real balances.\n",
"\n",
"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.\n",
"\n",
"But first it is instructive to describe a special type of equilibrium known as a **steady state**.\n",
"\n",
"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.\n",
"\n",
"Finding such state variables is something of an art.\n",
"\n",
"In many models, a good source of candidates for such invariant variables is a set of *ratios*.\n",
"\n",
"This is true in the present model."
]
},
{
"cell_type": "markdown",
"id": "f7d5a9f4",
"metadata": {},
"source": [
"### Steady states\n",
"\n",
"In a steady-state equilibrium of the model we are studying,\n",
"\n",
"$$\n",
"\\begin{aligned}\n",
"R_t & = \\bar R \\cr\n",
"b_t & = \\bar b\n",
"\\end{aligned}\n",
"$$\n",
"\n",
"for $ t \\geq 0 $.\n",
"\n",
"Notice that both $ R_t = \\frac{p_t}{p_{t+1}} $ and $ b_t = \\frac{m_{t+1}}{p_t} $ are *ratios*.\n",
"\n",
"To compute a steady state, we seek gross rates of return on currency and real balances $ \\bar R, \\bar b $ that satisfy steady-state versions of both the government budget constraint and the demand function for real balances:\n",
"\n",
"$$\n",
"\\begin{aligned}\n",
"g & = \\bar b ( 1 - \\bar R) \\cr\n",
"\\bar b & = \\gamma_1- \\gamma_2 \\bar R^{-1}\n",
"\\end{aligned}\n",
"$$\n",
"\n",
"Together these equations imply\n",
"\n",
"\n",
"\n",
"$$\n",
"(\\gamma_1 + \\gamma_2) - \\frac{\\gamma_2}{\\bar R} - \\gamma_1 \\bar R = g \\tag{28.7}\n",
"$$\n",
"\n",
"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 \\le 1 $ on currency.\n",
"\n",
"The right side is government expenditures.\n",
"\n",
"Define steady-state seigniorage as\n",
"\n",
"\n",
"\n",
"$$\n",
"S(\\bar R) = (\\gamma_1 + \\gamma_2) - \\frac{\\gamma_2}{\\bar R} - \\gamma_1 \\bar R \\tag{28.8}\n",
"$$\n",
"\n",
"Notice that $ S(\\bar R) \\geq 0 $ only when $ \\bar R \\in [\\frac{\\gamma_2}{\\gamma_1}, 1] \n",
"\\equiv [\\underline R, \\overline R] $ and that $ S(\\bar R) = 0 $ if $ \\bar R = \\underline R $\n",
"or if $ \\bar R = \\overline R $.\n",
"\n",
"We shall study equilibrium sequences that satisfy\n",
"\n",
"$$\n",
"R_t \\in [\\underline R, \\overline R], \\quad t \\geq 0.\n",
"$$\n",
"\n",
"Maximizing steady-state seigniorage [(28.8)](#equation-eq-sssigng) with respect to $ \\bar R $, we find that the maximizing rate of return on currency is\n",
"\n",
"$$\n",
"\\bar R_{\\rm max} = \\sqrt{\\frac{\\gamma_2}{\\gamma_1}}\n",
"$$\n",
"\n",
"and that the associated maximum seigniorage revenue that the government can gather from printing money is\n",
"\n",
"$$\n",
"(\\gamma_1 + \\gamma_2) - \\frac{\\gamma_2}{\\bar R_{\\rm max}} - \\gamma_1 \\bar R_{\\rm max}\n",
"$$\n",
"\n",
"It is useful to rewrite equation [(28.7)](#equation-eq-seignsteady) as\n",
"\n",
"\n",
"\n",
"$$\n",
"-\\gamma_2 + (\\gamma_1 + \\gamma_2 - g) \\bar R - \\gamma_1 \\bar R^2 = 0 \\tag{28.9}\n",
"$$\n",
"\n",
"A steady state gross rate of return $ \\bar R $ solves quadratic equation [(28.9)](#equation-eq-steadyquadratic).\n",
"\n",
"So two steady states typically exist."
]
},
{
"cell_type": "markdown",
"id": "2c0a2eb1",
"metadata": {},
"source": [
"## Some code\n",
"\n",
"Let’s start with some imports:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a43c8758",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from matplotlib.ticker import MaxNLocator\n",
"plt.rcParams['figure.dpi'] = 300\n",
"from collections import namedtuple"
]
},
{
"cell_type": "markdown",
"id": "971bbb5b",
"metadata": {},
"source": [
"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.\n",
"\n",
"First, we create a `namedtuple` to store parameters so that we can reuse this `namedtuple` in our functions throughout this lecture"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "122b592e",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"# Create a namedtuple that contains parameters\n",
"MoneySupplyModel = namedtuple(\"MoneySupplyModel\", \n",
" [\"γ1\", \"γ2\", \"g\", \n",
" \"M0\", \"R_u\", \"R_l\"])\n",
"\n",
"def create_model(γ1=100, γ2=50, g=3.0, M0=100):\n",
" \n",
" # Calculate the steady states for R\n",
" R_steady = np.roots((-γ1, γ1 + γ2 - g, -γ2))\n",
" R_u, R_l = R_steady\n",
" print(\"[R_u, R_l] =\", R_steady)\n",
" \n",
" return MoneySupplyModel(γ1=γ1, γ2=γ2, g=g, M0=M0, R_u=R_u, R_l=R_l)"
]
},
{
"cell_type": "markdown",
"id": "e7dae2ae",
"metadata": {},
"source": [
"Now we compute the $ \\bar R_{\\rm max} $ and corresponding revenue"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "94b7cb82",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"def seign(R, model):\n",
" γ1, γ2, g = model.γ1, model.γ2, model.g\n",
" return -γ2/R + (γ1 + γ2) - γ1 * R\n",
"\n",
"msm = create_model()\n",
"\n",
"# Calculate initial guess for p0\n",
"p0_guess = msm.M0 / (msm.γ1 - msm.g - msm.γ2 / msm.R_u)\n",
"print(f'p0 guess = {p0_guess:.4f}')\n",
"\n",
"# Calculate seigniorage maximizing rate of return\n",
"R_max = np.sqrt(msm.γ2/msm.γ1)\n",
"g_max = seign(R_max, msm)\n",
"print(f'R_max, g_max = {R_max:.4f}, {g_max:.4f}')"
]
},
{
"cell_type": "markdown",
"id": "4b38b8f1",
"metadata": {},
"source": [
"Now let’s plot seigniorage as a function of alternative potential steady-state values of $ R $.\n",
"\n",
"We’ll see that there are two steady-state values of $ R $ that attain seigniorage levels equal to $ g $,\n",
"one that we’ll denote $ R_\\ell $, another that we’ll denote $ R_u $.\n",
"\n",
"They satisfy $ R_\\ell < R_u $ and are affiliated with a higher inflation tax rate $ (1-R_\\ell) $ and a lower\n",
"inflation tax rate $ 1 - R_u $."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7c2e3e3c",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"# Generate values for R\n",
"R_values = np.linspace(msm.γ2/msm.γ1, 1, 250)\n",
"\n",
"# Calculate the function values\n",
"seign_values = seign(R_values, msm)\n",
"\n",
"# Visualize seign_values against R values\n",
"fig, ax = plt.subplots(figsize=(11, 5))\n",
"plt.plot(R_values, seign_values, label='inflation tax revenue')\n",
"plt.axhline(y=msm.g, color='red', linestyle='--', label='government deficit')\n",
"plt.xlabel('$R$')\n",
"plt.ylabel('seigniorage')\n",
"\n",
"plt.legend()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "fce3ee3a",
"metadata": {},
"source": [
"Let’s print the two steady-state rates of return $ \\bar R $ and the associated seigniorage revenues that the government collects.\n",
"\n",
"(By construction, both steady-state rates of return should raise the same amounts real revenue.)\n",
"\n",
"We hope that the following code will confirm this."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fbca4c08",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"g1 = seign(msm.R_u, msm)\n",
"print(f'R_u, g_u = {msm.R_u:.4f}, {g1:.4f}')\n",
"\n",
"g2 = seign(msm.R_l, msm)\n",
"print(f'R_l, g_l = {msm.R_l:.4f}, {g2:.4f}')"
]
},
{
"cell_type": "markdown",
"id": "fd3a1073",
"metadata": {},
"source": [
"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."
]
},
{
"cell_type": "markdown",
"id": "f8997cc7",
"metadata": {},
"source": [
"## Two computation strategies\n",
"\n",
"We now proceed to compute equilibria, not necessarily steady states.\n",
"\n",
"We shall deploy two distinct computation strategies."
]
},
{
"cell_type": "markdown",
"id": "8e7422cd",
"metadata": {},
"source": [
"### Method 1\n",
"\n",
"- set $ R_0 \\in [\\frac{\\gamma_2}{\\gamma_1}, R_u] $ and compute $ b_0 = \\gamma_1 - \\gamma_2/R_0 $. \n",
"- 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 [(28.4)](#equation-eq-bmotion) and [(28.5)](#equation-eq-bdemand) sequentially for $ t \\geq 1 $: \n",
"\n",
"\n",
"\n",
"\n",
"$$\n",
"\\begin{aligned}\n",
"b_t & = b_{t-1} R_{t-1} + g \\cr\n",
"R_t^{-1} & = \\frac{\\gamma_1}{\\gamma_2} - \\gamma_2^{-1} b_t \n",
"\\end{aligned} \\tag{28.10}\n",
"$$\n",
"\n",
"- Construct the associated equilibrium $ p_0 $ from \n",
"\n",
"\n",
"\n",
"\n",
"$$\n",
"p_0 = \\frac{m_0}{\\gamma_1 - g - \\gamma_2/R_0} \\tag{28.11}\n",
"$$\n",
"\n",
"- compute $ \\{p_t, m_t\\}_{t=1}^\\infty $ by solving the following equations sequentially \n",
"\n",
"\n",
"\n",
"\n",
"$$\n",
"\\begin{aligned}\n",
"p_t & = R_t p_{t-1} \\cr\n",
"m_t & = b_{t-1} p_t \n",
"\\end{aligned} \\tag{28.12}\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "8d39d213",
"metadata": {},
"source": [
"### \n",
"\n",
"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."
]
},
{
"cell_type": "markdown",
"id": "5ca91261",
"metadata": {},
"source": [
"### \n",
"\n",
"Notice that method 1 starts by picking an **initial condition** $ R_0 $ from a set $ [\\frac{\\gamma_2}{\\gamma_1}, R_u] $. 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] $."
]
},
{
"cell_type": "markdown",
"id": "38913524",
"metadata": {},
"source": [
"### \n",
"\n",
"Associated with each selection of $ R_0 $ there is a unique $ p_0 $ described by\n",
"equation [(28.11)](#equation-eq-p0fromr0)."
]
},
{
"cell_type": "markdown",
"id": "424260a0",
"metadata": {},
"source": [
"### Method 2\n",
"\n",
"This method deploys a direct approach.\n",
"It defines a “state vector”\n",
"$ y_t = \\begin{bmatrix} m_t \\cr p_t\\end{bmatrix} $\n",
"and formulates equilibrium conditions [(28.1)](#equation-eq-demandmoney), [(28.2)](#equation-eq-budgcontraint), and\n",
"[(28.3)](#equation-eq-syeqdemand)\n",
"in terms of a first-order vector difference equation\n",
"\n",
"$$\n",
"y_{t+1} = M y_t, \\quad t \\geq 0 ,\n",
"$$\n",
"\n",
"where we temporarily take $ y_0 = \\begin{bmatrix} m_0 \\cr p_0 \\end{bmatrix} $ as an **initial condition**.\n",
"\n",
"The solution is\n",
"\n",
"$$\n",
"y_t = M^t y_0 .\n",
"$$\n",
"\n",
"Now let’s think about the initial condition $ y_0 $.\n",
"\n",
"It is natural to take the initial stock of money $ m_0 >0 $ as an initial condition.\n",
"\n",
"But what about $ p_0 $?\n",
"\n",
"Isn’t it something that we want to be *determined* by our model?\n",
"\n",
"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.\n",
"\n",
"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."
]
},
{
"cell_type": "markdown",
"id": "4994a958",
"metadata": {},
"source": [
"## Computation method 1\n",
"\n",
"Remember that there exist two steady-state equilibrium values $ R_\\ell < R_u $ of the rate of return on currency $ R_t $.\n",
"\n",
"We proceed as follows.\n",
"\n",
"Start at $ t=0 $\n",
"\n",
"- select a $ R_0 \\in [\\frac{\\gamma_2}{\\gamma_1}, R_u] $ \n",
"- compute $ b_0 = \\gamma_1 - \\gamma_0 R_0^{-1} $ \n",
"\n",
"\n",
"Then for $ t \\geq 1 $ construct $ b_t, R_t $ by\n",
"iterating on equation [(28.10)](#equation-eq-rtbt).\n",
"\n",
"When we implement this part of method 1, we shall discover the following striking\n",
"outcome:\n",
"\n",
"- starting from an $ R_0 $ in $ [\\frac{\\gamma_2}{\\gamma_1}, R_u] $, we shall find that\n",
" $ \\{R_t\\} $ always converges to a limiting “steady state” value $ \\bar R $ that depends on the initial\n",
" condition $ R_0 $. \n",
"- there are only two possible limit points $ \\{ R_\\ell, R_u\\} $. \n",
"- for almost every initial condition $ R_0 $, $ \\lim_{t \\rightarrow +\\infty} R_t = R_\\ell $. \n",
"- if and only if $ R_0 = R_u $, $ \\lim_{t \\rightarrow +\\infty} R_t = R_u $. \n",
"\n",
"\n",
"The quantity $ 1 - R_t $ can be interpreted as an **inflation tax rate** that the government imposes on holders of its currency.\n",
"\n",
"We shall soon see that the existence of two steady-state rates of return on currency\n",
"that serve to finance the government deficit of $ g $ indicates the presence of a **Laffer curve** in the inflation tax rate.\n",
"\n",
">**Note**\n",
">\n",
">Arthur Laffer’s curve plots a hump shaped curve of revenue raised from a tax against the tax rate.\\\\\n",
"\n",
"\n",
"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."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b02baf91",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"def simulate_system(R0, model, num_steps):\n",
" γ1, γ2, g = model.γ1, model.γ2, model.g\n",
"\n",
" # Initialize arrays to store results\n",
" b_values = np.empty(num_steps)\n",
" R_values = np.empty(num_steps)\n",
"\n",
" # Initial values\n",
" b_values[0] = γ1 - γ2/R0\n",
" R_values[0] = 1 / (γ1/γ2 - (1 / γ2) * b_values[0])\n",
"\n",
" # Iterate over time steps\n",
" for t in range(1, num_steps):\n",
" b_t = b_values[t - 1] * R_values[t - 1] + g\n",
" R_values[t] = 1 / (γ1/γ2 - (1/γ2) * b_t)\n",
" b_values[t] = b_t\n",
"\n",
" return b_values, R_values"
]
},
{
"cell_type": "markdown",
"id": "635c7fd2",
"metadata": {},
"source": [
"Let’s write some code to plot outcomes for several possible initial values $ R_0 $."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2a8eac14",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"line_params = {'lw': 1.5, \n",
" 'marker': 'o',\n",
" 'markersize': 3}\n",
"\n",
"def annotate_graph(ax, model, num_steps):\n",
" for y, label in [(model.R_u, '$R_u$'), (model.R_l, '$R_l$'), \n",
" (model.γ2 / model.γ1, r'$\\frac{\\gamma_2}{\\gamma_1}$')]:\n",
" ax.axhline(y=y, color='grey', linestyle='--', lw=1.5, alpha=0.6)\n",
" ax.text(num_steps * 1.02, y, label, verticalalignment='center', \n",
" color='grey', size=12)\n",
"\n",
"def draw_paths(R0_values, model, line_params, num_steps):\n",
"\n",
" fig, axes = plt.subplots(2, 1, figsize=(8, 8), sharex=True)\n",
" \n",
" # Pre-compute time steps\n",
" time_steps = np.arange(num_steps) \n",
" \n",
" # Iterate over R_0s and simulate the system \n",
" for R0 in R0_values:\n",
" b_values, R_values = simulate_system(R0, model, num_steps)\n",
" \n",
" # Plot R_t against time\n",
" axes[0].plot(time_steps, R_values, **line_params)\n",
" \n",
" # Plot b_t against time\n",
" axes[1].plot(time_steps, b_values, **line_params)\n",
" \n",
" # Add line and text annotations to the subgraph \n",
" annotate_graph(axes[0], model, num_steps)\n",
" \n",
" # Add Labels\n",
" axes[0].set_ylabel('$R_t$')\n",
" axes[1].set_xlabel('timestep')\n",
" axes[1].set_ylabel('$b_t$')\n",
" axes[1].xaxis.set_major_locator(MaxNLocator(integer=True))\n",
" \n",
" plt.tight_layout()\n",
" plt.show()"
]
},
{
"cell_type": "markdown",
"id": "ded94129",
"metadata": {},
"source": [
"Let’s plot distinct outcomes associated with several $ R_0 \\in [\\frac{\\gamma_2}{\\gamma_1}, R_u] $.\n",
"\n",
"Each line below shows a path associated with a different $ R_0 $."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fcae23b3",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"# Create a grid of R_0s\n",
"R0s = np.linspace(msm.γ2/msm.γ1, msm.R_u, 9)\n",
"R0s = np.append(msm.R_l, R0s)\n",
"draw_paths(R0s, msm, line_params, num_steps=20)"
]
},
{
"cell_type": "markdown",
"id": "56ebdb33",
"metadata": {},
"source": [
"Notice how sequences that start from $ R_0 $ in the half-open interval $ [R_\\ell, R_u) $ converge to the steady state associated with to $ R_\\ell $."
]
},
{
"cell_type": "markdown",
"id": "3ee66e3b",
"metadata": {},
"source": [
"## Computation method 2\n",
"\n",
"Set $ m_t = m_t^d $ for all $ t \\geq -1 $.\n",
"\n",
"Let\n",
"\n",
"$$\n",
"y_t = \\begin{bmatrix} m_{t} \\cr p_{t} \\end{bmatrix} .\n",
"$$\n",
"\n",
"Represent equilibrium conditions [(28.1)](#equation-eq-demandmoney), [(28.2)](#equation-eq-budgcontraint), and [(28.3)](#equation-eq-syeqdemand) as\n",
"\n",
"\n",
"\n",
"$$\n",
"\\begin{bmatrix} 1 & \\gamma_2 \\cr\n",
" 1 & 0 \\end{bmatrix} \\begin{bmatrix} m_{t+1} \\cr p_{t+1} \\end{bmatrix} =\n",
" \\begin{bmatrix} 0 & \\gamma_1 \\cr\n",
" 1 & g \\end{bmatrix} \\begin{bmatrix} m_{t} \\cr p_{t} \\end{bmatrix} \\tag{28.13}\n",
"$$\n",
"\n",
"or\n",
"\n",
"$$\n",
"H_1 y_t = H_2 y_{t-1}\n",
"$$\n",
"\n",
"where\n",
"\n",
"$$\n",
"\\begin{aligned} H_1 & = \\begin{bmatrix} 1 & \\gamma_2 \\cr\n",
" 1 & 0 \\end{bmatrix} \\cr\n",
" H_2 & = \\begin{bmatrix} 0 & \\gamma_1 \\cr\n",
" 1 & g \\end{bmatrix} \n",
"\\end{aligned}\n",
"$$"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a70fde43",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"H1 = np.array([[1, msm.γ2], \n",
" [1, 0]])\n",
"H2 = np.array([[0, msm.γ1], \n",
" [1, msm.g]]) "
]
},
{
"cell_type": "markdown",
"id": "7653ece6",
"metadata": {},
"source": [
"Define\n",
"\n",
"$$\n",
"H = H_1^{-1} H_2\n",
"$$"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0af67ca4",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"H = np.linalg.solve(H1, H2)\n",
"print('H = \\n', H)"
]
},
{
"cell_type": "markdown",
"id": "eadab536",
"metadata": {},
"source": [
"and write the system [(28.13)](#equation-eq-sytem101) as\n",
"\n",
"\n",
"\n",
"$$\n",
"y_{t+1} = H y_t, \\quad t \\geq 0 \\tag{28.14}\n",
"$$\n",
"\n",
"so that $ \\{y_t\\}_{t=0} $ can be computed from\n",
"\n",
"\n",
"\n",
"$$\n",
"y_t = H^t y_0, t \\geq 0 \\tag{28.15}\n",
"$$\n",
"\n",
"where\n",
"\n",
"$$\n",
"y_0 = \\begin{bmatrix} m_{0} \\cr p_0 \\end{bmatrix} .\n",
"$$\n",
"\n",
"It is natural to take $ m_0 $ as an initial condition determined outside the model.\n",
"\n",
"The mathematics seems to tell us that $ p_0 $ must also be determined outside the model, even though\n",
"it is something that we actually wanted to be determined by the model.\n",
"\n",
"(As usual, we should listen when mathematics talks to us.)\n",
"\n",
"For now, let’s just proceed mechanically on faith.\n",
"\n",
"Compute the eigenvector decomposition\n",
"\n",
"$$\n",
"H = Q \\Lambda Q^{-1}\n",
"$$\n",
"\n",
"where $ \\Lambda $ is a diagonal matrix of eigenvalues and the columns of $ Q $ are eigenvectors corresponding to those eigenvalues.\n",
"\n",
"It turns out that\n",
"\n",
"$$\n",
"\\Lambda = \\begin{bmatrix} {R_\\ell}^{-1} & 0 \\cr \n",
" 0 & {R_u}^{-1} \\end{bmatrix}\n",
"$$\n",
"\n",
"where $ R_\\ell $ and $ R_u $ are the lower and higher steady-state rates of return on currency that we computed above."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d4fcdf80",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"Λ, Q = np.linalg.eig(H)\n",
"print('Λ = \\n', Λ)\n",
"print('Q = \\n', Q)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ea3b0208",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"R_l = 1 / Λ[0]\n",
"R_u = 1 / Λ[1]\n",
"\n",
"print(f'R_l = {R_l:.4f}')\n",
"print(f'R_u = {R_u:.4f}')"
]
},
{
"cell_type": "markdown",
"id": "abaaaef1",
"metadata": {},
"source": [
"Partition $ Q $ as\n",
"\n",
"$$\n",
"Q =\\begin{bmatrix} Q_{11} & Q_{12} \\cr\n",
" Q_{21} & Q_{22} \\end{bmatrix}\n",
"$$\n",
"\n",
"Below we shall verify the following claims:\n",
"\n",
"**Claims:** If we set\n",
"\n",
"\n",
"\n",
"$$\n",
"p_0 = \\overline p_0 \\equiv Q_{21} Q_{11}^{-1} m_{0} , \\tag{28.16}\n",
"$$\n",
"\n",
"it turns out that\n",
"\n",
"$$\n",
"\\frac{p_{t+1}}{p_t} = {R_u}^{-1}, \\quad t \\geq 0\n",
"$$\n",
"\n",
"However, if we set\n",
"\n",
"$$\n",
"p_0 > \\bar p_0\n",
"$$\n",
"\n",
"then\n",
"\n",
"$$\n",
"\\lim_{t\\rightarrow + \\infty} \\frac{p_{t+1}}{p_t} = {R_\\ell}^{-1}.\n",
"$$\n",
"\n",
"Let’s verify these claims step by step.\n",
"\n",
"Note that\n",
"\n",
"$$\n",
"H^t = Q \\Lambda^t Q^{-1}\n",
"$$\n",
"\n",
"so that\n",
"\n",
"$$\n",
"y_t = Q \\Lambda^t Q^{-1} y_0\n",
"$$"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1bfbd18b",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"def iterate_H(y_0, H, num_steps):\n",
" Λ, Q = np.linalg.eig(H)\n",
" Q_inv = np.linalg.inv(Q)\n",
" y = np.stack(\n",
" [Q @ np.diag(Λ**t) @ Q_inv @ y_0 for t in range(num_steps)], 1)\n",
" \n",
" return y"
]
},
{
"cell_type": "markdown",
"id": "94d61445",
"metadata": {},
"source": [
"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_\\ell}^{-1} $.\n",
"\n",
"The only way to avoid this outcome is for $ p_0 $ to take the specific value described by [(28.16)](#equation-eq-magicp0).\n",
"\n",
"To understand this situation, we use the following\n",
"transformation\n",
"\n",
"$$\n",
"y^*_t = Q^{-1} y_t .\n",
"$$\n",
"\n",
"Dynamics of $ y^*_t $ are evidently governed by\n",
"\n",
"\n",
"\n",
"$$\n",
"y^*_{t+1} = \\Lambda^t y^*_t . \\tag{28.17}\n",
"$$\n",
"\n",
"This equation represents the dynamics of our system in a way that lets us isolate the\n",
"force that causes gross inflation to converge to the inverse of the lower steady-state rate\n",
"of inflation $ R_\\ell $ that we discovered earlier.\n",
"\n",
"Staring at equation [(28.17)](#equation-eq-stardynamics) indicates that unless\n",
"\n",
"\n",
"\n",
"$$\n",
"y^*_0 = \\begin{bmatrix} y^*_{1,0} \\cr 0 \\end{bmatrix} \\tag{28.18}\n",
"$$\n",
"\n",
"the path of $ y^*_t $, and therefore the paths of both $ m_t $ and $ p_t $ given by\n",
"$ y_t = Q y^*_t $ will eventually grow at gross rates $ {R_\\ell}^{-1} $ as\n",
"$ t \\rightarrow +\\infty $.\n",
"\n",
"Equation [(28.18)](#equation-equation-11) also leads us to conclude that there is a unique setting\n",
"for the initial vector $ y_0 $ for which both components forever grow at the lower rate $ {R_u}^{-1} $.\n",
"\n",
"For this to occur, the required setting of $ y_0 $ must evidently have the property\n",
"that\n",
"\n",
"$$\n",
"Q^{-1} y_0 = y^*_0 = \\begin{bmatrix} y^*_{1,0} \\cr 0 \\end{bmatrix} .\n",
"$$\n",
"\n",
"But note that since\n",
"$ y_0 = \\begin{bmatrix} m_0 \\cr p_0 \\end{bmatrix} $ and $ m_0 $\n",
"is given to us an initial condition, $ p_0 $ has to do all the adjusting to satisfy this equation.\n",
"\n",
"Sometimes this situation is described informally by saying that while $ m_0 $\n",
"is truly a **state** variable, $ p_0 $ is a **jump** variable that\n",
"must adjust at $ t=0 $ in order to satisfy the equation.\n",
"\n",
"Thus, in a nutshell the unique value of the vector $ y_0 $ for which\n",
"the paths of $ y_t $ *don’t* eventually grow at rate $ {R_\\ell}^{-1} $ requires setting the second component\n",
"of $ y^*_0 $ equal to zero.\n",
"\n",
"The component $ p_0 $ of the initial vector\n",
"$ y_0 = \\begin{bmatrix} m_0 \\cr p_0 \\end{bmatrix} $ must evidently\n",
"satisfy\n",
"\n",
"$$\n",
"Q^{\\{2\\}} y_0 =0\n",
"$$\n",
"\n",
"where $ Q^{\\{2\\}} $ denotes the second row of $ Q^{-1} $, a\n",
"restriction that is equivalent to\n",
"\n",
"\n",
"\n",
"$$\n",
"Q^{21} m_0 + Q^{22} p_0 = 0 \\tag{28.19}\n",
"$$\n",
"\n",
"where $ Q^{ij} $ denotes the $ (i,j) $ component of\n",
"$ Q^{-1} $.\n",
"\n",
"Solving this equation for $ p_0 $, we find\n",
"\n",
"\n",
"\n",
"$$\n",
"p_0 = - (Q^{22})^{-1} Q^{21} m_0. \\tag{28.20}\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "50d9de8e",
"metadata": {},
"source": [
"### More convenient formula\n",
"\n",
"We can get the equivalent but perhaps more convenient formula [(28.16)](#equation-eq-magicp0) for $ p_0 $ that is cast\n",
"in terms of components of $ Q $ instead of components of\n",
"$ Q^{-1} $.\n",
"\n",
"To get this formula, first note that because $ (Q^{21}\\ Q^{22}) $ is\n",
"the second row of the inverse of $ Q $ and because\n",
"$ Q^{-1} Q = I $, it follows that\n",
"\n",
"$$\n",
"\\begin{bmatrix} Q^{21} & Q^{22} \\end{bmatrix} \\begin{bmatrix} Q_{11}\\cr Q_{21} \\end{bmatrix} = 0\n",
"$$\n",
"\n",
"which implies that\n",
"\n",
"$$\n",
"Q^{21} Q_{11} + Q^{22} Q_{21} = 0.\n",
"$$\n",
"\n",
"Therefore,\n",
"\n",
"$$\n",
"-(Q^{22})^{-1} Q^{21} = Q_{21} Q^{-1}_{11}.\n",
"$$\n",
"\n",
"So we can write\n",
"\n",
"$$\n",
"p_0 = Q_{21} Q_{11}^{-1} m_0 .\n",
"$$\n",
"\n",
"which is our formula [(28.16)](#equation-eq-magicp0)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e6daf090",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"p0_bar = (Q[1, 0]/Q[0, 0]) * msm.M0\n",
"\n",
"print(f'p0_bar = {p0_bar:.4f}')"
]
},
{
"cell_type": "markdown",
"id": "f8d45eae",
"metadata": {},
"source": [
"It can be verified that this formula replicates itself over time in the sense that\n",
"\n",
"\n",
"\n",
"$$\n",
"p_t = Q_{21} Q^{-1}_{11} m_t. \\tag{28.21}\n",
"$$\n",
"\n",
"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.\n",
"\n",
"We create a function `draw_iterations` to generate the plot"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "799ba9dc",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"def draw_iterations(p0s, model, line_params, num_steps):\n",
"\n",
" fig, axes = plt.subplots(3, 1, figsize=(8, 10), sharex=True)\n",
" \n",
" # Pre-compute time steps\n",
" time_steps = np.arange(num_steps) \n",
" \n",
" # Plot the first two y-axes in log scale\n",
" for ax in axes[:2]:\n",
" ax.set_yscale('log')\n",
"\n",
" # Iterate over p_0s and calculate a series of y_t\n",
" for p0 in p0s:\n",
" y0 = np.array([msm.M0, p0])\n",
" y_series = iterate_H(y0, H, num_steps)\n",
" M, P = y_series[0, :], y_series[1, :]\n",
"\n",
" # Plot R_t against time\n",
" axes[0].plot(time_steps, M, **line_params)\n",
"\n",
" # Plot b_t against time\n",
" axes[1].plot(time_steps, P, **line_params)\n",
" \n",
" # Calculate R_t\n",
" R = np.insert(P[:-1] / P[1:], 0, np.NAN)\n",
" axes[2].plot(time_steps, R, **line_params)\n",
" \n",
" # Add line and text annotations to the subgraph \n",
" annotate_graph(axes[2], model, num_steps)\n",
" \n",
" # Draw labels\n",
" axes[0].set_ylabel('$m_t$')\n",
" axes[1].set_ylabel('$p_t$')\n",
" axes[2].set_ylabel('$R_t$')\n",
" axes[2].set_xlabel('timestep')\n",
" \n",
" # Enforce integar axis label\n",
" axes[2].xaxis.set_major_locator(MaxNLocator(integer=True))\n",
"\n",
" plt.tight_layout()\n",
" plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "92aac729",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"p0s = [p0_bar, 2.34, 2.5, 3, 4, 7, 30, 100_000]\n",
"\n",
"draw_iterations(p0s, msm, line_params, num_steps=20)"
]
},
{
"cell_type": "markdown",
"id": "88dea924",
"metadata": {},
"source": [
"Please notice that for $ m_t $ and $ p_t $, we have used log scales for the coordinate (i.e., vertical) axes.\n",
"\n",
"Using log scales allows us to spot distinct constant limiting gross rates of growth $ {R_u}^{-1} $ and\n",
"$ {R_\\ell}^{-1} $ by eye."
]
},
{
"cell_type": "markdown",
"id": "5fa7a397",
"metadata": {},
"source": [
"## Peculiar stationary outcomes\n",
"\n",
"As promised at the start of this lecture, we have encountered these concepts from macroeconomics:\n",
"\n",
"- an **inflation tax** that a government gathers by printing paper or electronic money \n",
"- a dynamic **Laffer curve** in the inflation tax rate that has two stationary equilibria \n",
"\n",
"\n",
"Staring at the paths of rates of return on the price level in figure Fig. 28.2 and price levels in Fig. 28.3 show indicate that almost all paths converge to the *higher* inflation tax rate displayed in the stationary state Laffer curve displayed in figure Fig. 28.1.\n",
"\n",
"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.\n",
"\n",
"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 Fig. 28.1:\n",
"\n",
"- the figure indicates that inflation can be *reduced* by running *higher* government deficits, i.e., by raising more resources through printing money. \n",
"\n",
"\n",
">**Note**\n",
">\n",
">The same qualitative outcomes prevail in this lecture [Inflation Rate Laffer Curves](https://intro.quantecon.org/money_inflation_nonlinear.html) that studies a nonlinear version of the model in this lecture."
]
},
{
"cell_type": "markdown",
"id": "e435b476",
"metadata": {},
"source": [
"## Equilibrium selection\n",
"\n",
"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.\n",
"\n",
"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:\n",
"\n",
"- for computational method 1, $ R_0 $ \n",
"- for computational method 2, $ p_0 $ \n",
"\n",
"\n",
"To apply our model, we have somehow to *complete* it by *selecting* an equilibrium path from among the continuum of possible paths.\n",
"\n",
"We discovered that\n",
"\n",
"- all but one of the equilibrium paths converge to limits in which the higher of two possible stationary inflation tax prevails \n",
"- there is a unique equilibrium path associated with “plausible” statements about how reductions in government deficits affect a stationary inflation rate \n",
"\n",
"\n",
"On grounds of plausibility, we recommend following many macroeconomists in selecting the unique equilibrium that converges to the lower stationary inflation tax rate.\n",
"\n",
"As we shall see, we shall accept this recommendation in lecture [Some Unpleasant Monetarist Arithmetic](https://intro.quantecon.org/unpleasant.html).\n",
"\n",
"In lecture, [Laffer Curves with Adaptive Expectations](https://intro.quantecon.org/laffer_adaptive.html), we shall explore how [[Bruno and Fischer, 1990](https://intro.quantecon.org/zreferences.html#id296)] and others justified this in other ways."
]
}
],
"metadata": {
"date": 1727242854.934664,
"filename": "money_inflation.md",
"kernelspec": {
"display_name": "Python",
"language": "python3",
"name": "python3"
},
"title": "Money Financed Government Deficits and Price Levels"
},
"nbformat": 4,
"nbformat_minor": 5
}