{
"cells": [
{
"cell_type": "markdown",
"id": "37d08e1a",
"metadata": {},
"source": [
"\n",
""
]
},
{
"cell_type": "markdown",
"id": "61296b4b",
"metadata": {},
"source": [
"# Optimal Taxation in an LQ Economy\n",
"\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"id": "63f9db96",
"metadata": {},
"source": [
"## Contents\n",
"\n",
"- [Optimal Taxation in an LQ Economy](#Optimal-Taxation-in-an-LQ-Economy) \n",
" - [Overview](#Overview) \n",
" - [The Ramsey Problem](#The-Ramsey-Problem) \n",
" - [Implementation](#Implementation) \n",
" - [Examples](#Examples) \n",
" - [Exercises](#Exercises) "
]
},
{
"cell_type": "markdown",
"id": "512ade81",
"metadata": {},
"source": [
"In addition to what’s in Anaconda, this lecture will need the following libraries:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2e72f126",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"!pip install --upgrade quantecon"
]
},
{
"cell_type": "markdown",
"id": "24e3dfc2",
"metadata": {},
"source": [
"## Overview\n",
"\n",
"In this lecture, we study optimal fiscal policy in a linear quadratic setting.\n",
"\n",
"We modify a model of Robert Lucas and Nancy Stokey [[LS83](https://python-advanced.quantecon.org/zreferences.html#id176)] so that convenient formulas for\n",
"solving linear-quadratic models can be applied.\n",
"\n",
"The economy consists of a representative household and a benevolent government.\n",
"\n",
"The government finances an exogenous stream of government purchases with state-contingent loans and a linear tax on labor income.\n",
"\n",
"A linear tax is sometimes called a flat-rate tax.\n",
"\n",
"The household maximizes utility by choosing paths for consumption and labor, taking prices and the government’s tax rate and borrowing plans as given.\n",
"\n",
"Maximum attainable utility for the household depends on the government’s tax and borrowing plans.\n",
"\n",
"The *Ramsey problem* [[Ram27](https://python-advanced.quantecon.org/zreferences.html#id194)] is to choose tax and borrowing plans that maximize the household’s welfare, taking the household’s optimizing behavior as given.\n",
"\n",
"There is a large number of competitive equilibria indexed by different government fiscal policies.\n",
"\n",
"The Ramsey planner chooses the best competitive equilibrium.\n",
"\n",
"We want to study the dynamics of tax rates, tax revenues, government debt under a Ramsey plan.\n",
"\n",
"Because the Lucas and Stokey model features state-contingent government debt, the government debt dynamics differ substantially from those in a model of Robert Barro [[Bar79](https://python-advanced.quantecon.org/zreferences.html#id136)].\n",
"\n",
"We cover only the key features of the problem in this lecture, leaving you to refer to that source for additional results and intuition.\n",
"\n",
"We’ll need the following imports:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3531676e",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"import sys\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline\n",
"from numpy import sqrt, eye, zeros, cumsum\n",
"from numpy.random import randn\n",
"import scipy.linalg\n",
"from collections import namedtuple\n",
"from quantecon import nullspace, mc_sample_path, var_quadratic_sum"
]
},
{
"cell_type": "markdown",
"id": "c71d319b",
"metadata": {},
"source": [
"### Model Features\n",
"\n",
"- Linear quadratic (LQ) model \n",
"- Representative household \n",
"- Stochastic dynamic programming over an infinite horizon \n",
"- Distortionary taxation "
]
},
{
"cell_type": "markdown",
"id": "ca5c880a",
"metadata": {},
"source": [
"## The Ramsey Problem\n",
"\n",
"We begin by outlining the key assumptions regarding technology, households and the government sector."
]
},
{
"cell_type": "markdown",
"id": "9518b813",
"metadata": {},
"source": [
"### Technology\n",
"\n",
"Labor can be converted one-for-one into a single, non-storable consumption good.\n",
"\n",
"In the usual spirit of the LQ model, the amount of labor supplied in each period is unrestricted.\n",
"\n",
"This is unrealistic, but helpful when it comes to solving the model.\n",
"\n",
"Realistic labor supply can be induced by suitable parameter values."
]
},
{
"cell_type": "markdown",
"id": "e8ef01aa",
"metadata": {},
"source": [
"### Households\n",
"\n",
"Consider a representative household who chooses a path $ \\{\\ell_t, c_t\\} $\n",
"for labor and consumption to maximize\n",
"\n",
"\n",
"\n",
"$$\n",
"-\\mathbb E \\frac{1}{2} \\sum_{t=0}^{\\infty} \\beta^t\n",
"\\left[\n",
" (c_t - b_t)^2 + \\ell_t^2\n",
"\\right] \\tag{12.1}\n",
"$$\n",
"\n",
"subject to the budget constraint\n",
"\n",
"\n",
"\n",
"$$\n",
"\\mathbb E \\sum_{t=0}^{\\infty} \\beta^t p^0_t\n",
"\\left[\n",
" d_t + (1 - \\tau_t) \\ell_t + s_t - c_t\n",
"\\right] = 0 \\tag{12.2}\n",
"$$\n",
"\n",
"Here\n",
"\n",
"- $ \\beta $ is a discount factor in $ (0, 1) $. \n",
"- $ p_t^0 $ is a scaled Arrow-Debreu price at time $ 0 $ of history contingent goods at time $ t+j $. \n",
"- $ b_t $ is a stochastic preference parameter. \n",
"- $ d_t $ is an endowment process. \n",
"- $ \\tau_t $ is a flat tax rate on labor income. \n",
"- $ s_t $ is a promised time-$ t $ coupon payment on debt issued by the government. \n",
"\n",
"\n",
"The scaled Arrow-Debreu price $ p^0_t $ is related to the unscaled Arrow-Debreu price as follows.\n",
"\n",
"If we let $ \\pi^0_t(x^t) $\n",
"denote the probability (density) of a history $ x^t = [x_t, x_{t-1}, \\ldots, x_0] $ of the state $ x^t $, then\n",
"the Arrow-Debreu time $ 0 $ price of a claim on one unit of consumption at date $ t $, history $ x^t $ would be\n",
"\n",
"$$\n",
"\\frac{\\beta^t p^0_t} {\\pi_t^0(x^t)}\n",
"$$\n",
"\n",
"Thus, our scaled Arrow-Debreu price is the ordinary Arrow-Debreu price multiplied by the discount factor $ \\beta^t $ and divided\n",
"by an appropriate probability.\n",
"\n",
"The budget constraint [(12.2)](#equation-lq-hc) requires that the present value of consumption be restricted to equal the present value of endowments, labor income and coupon payments on bond holdings."
]
},
{
"cell_type": "markdown",
"id": "d57d60ff",
"metadata": {},
"source": [
"### Government\n",
"\n",
"The government imposes a linear tax on labor income, fully committing to a stochastic path of tax rates at time zero.\n",
"\n",
"The government also issues state-contingent debt.\n",
"\n",
"Given government tax and borrowing plans, we can construct a competitive equilibrium with distorting government taxes.\n",
"\n",
"Among all such competitive equilibria, the Ramsey plan is the one that maximizes the welfare of the representative consumer."
]
},
{
"cell_type": "markdown",
"id": "4d728aec",
"metadata": {},
"source": [
"### Exogenous Variables\n",
"\n",
"Endowments, government expenditure, the preference shock process $ b_t $, and\n",
"promised coupon payments on initial government debt $ s_t $ are all exogenous, and given by\n",
"\n",
"- $ d_t = S_d x_t $ \n",
"- $ g_t = S_g x_t $ \n",
"- $ b_t = S_b x_t $ \n",
"- $ s_t = S_s x_t $ \n",
"\n",
"\n",
"The matrices $ S_d, S_g, S_b, S_s $ are primitives and $ \\{x_t\\} $ is\n",
"an exogenous stochastic process taking values in $ \\mathbb R^k $.\n",
"\n",
"We consider two specifications for $ \\{x_t\\} $.\n",
"\n",
"\n",
"\n",
"1. Discrete case: $ \\{x_t\\} $ is a discrete state Markov chain with transition matrix $ P $. \n",
"1. VAR case: $ \\{x_t\\} $ obeys $ x_{t+1} = A x_t + C w_{t+1} $ where $ \\{w_t\\} $ is independent zero-mean Gaussian with identify covariance matrix. "
]
},
{
"cell_type": "markdown",
"id": "83d0c15b",
"metadata": {},
"source": [
"### Feasibility\n",
"\n",
"The period-by-period feasibility restriction for this economy is\n",
"\n",
"\n",
"\n",
"$$\n",
"c_t + g_t = d_t + \\ell_t \\tag{12.3}\n",
"$$\n",
"\n",
"A labor-consumption process $ \\{\\ell_t, c_t\\} $ is called *feasible* if [(12.3)](#equation-lq-feasible) holds for all $ t $."
]
},
{
"cell_type": "markdown",
"id": "ebd12e6b",
"metadata": {},
"source": [
"### Government Budget Constraint\n",
"\n",
"Where $ p_t^0 $ is again a scaled Arrow-Debreu price, the time zero government budget constraint is\n",
"\n",
"\n",
"\n",
"$$\n",
"\\mathbb E \\sum_{t=0}^{\\infty} \\beta^t p^0_t\n",
"(s_t + g_t - \\tau_t \\ell_t ) = 0 \\tag{12.4}\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "f0a343be",
"metadata": {},
"source": [
"### Equilibrium\n",
"\n",
"An *equilibrium* is a feasible allocation $ \\{\\ell_t, c_t\\} $, a sequence\n",
"of prices $ \\{p_t^0\\} $, and a tax system $ \\{\\tau_t\\} $ such that\n",
"\n",
"1. The allocation $ \\{\\ell_t, c_t\\} $ is optimal for the household given $ \\{p_t^0\\} $ and $ \\{\\tau_t\\} $. \n",
"1. The government’s budget constraint [(12.4)](#equation-lq-gc) is satisfied. \n",
"\n",
"\n",
"The *Ramsey problem* is to choose the equilibrium $ \\{\\ell_t, c_t, \\tau_t, p_t^0\\} $ that maximizes the\n",
"household’s welfare.\n",
"\n",
"If $ \\{\\ell_t, c_t, \\tau_t, p_t^0\\} $ solves the Ramsey problem,\n",
"then $ \\{\\tau_t\\} $ is called the *Ramsey plan*.\n",
"\n",
"The solution procedure we adopt is\n",
"\n",
"1. Use the first-order conditions from the household problem to pin down\n",
" prices and allocations given $ \\{\\tau_t\\} $. \n",
"1. Use these expressions to rewrite the government budget constraint\n",
" [(12.4)](#equation-lq-gc) in terms of exogenous variables and allocations. \n",
"1. Maximize the household’s objective function [(12.1)](#equation-lq-hu) subject to the\n",
" constraint constructed in step 2 and the feasibility constraint\n",
" [(12.3)](#equation-lq-feasible). \n",
"\n",
"\n",
"The solution to this maximization problem pins down all quantities of interest."
]
},
{
"cell_type": "markdown",
"id": "435aef4c",
"metadata": {},
"source": [
"### Solution\n",
"\n",
"Step one is to obtain the first-conditions for the household’s problem,\n",
"taking taxes and prices as given.\n",
"\n",
"Letting $ \\mu $ be the Lagrange multiplier on [(12.2)](#equation-lq-hc), the first-order\n",
"conditions are $ p_t^0 = (c_t - b_t) / \\mu $ and $ \\ell_t = (c_t - b_t)\n",
"(1 - \\tau_t) $.\n",
"\n",
"Rearranging and normalizing at $ \\mu = b_0 - c_0 $, we can write these\n",
"conditions as\n",
"\n",
"\n",
"\n",
"$$\n",
"p_t^0 = \\frac{b_t - c_t}{b_0 - c_0}\n",
"\\quad \\text{and} \\quad\n",
"\\tau_t = 1 - \\frac{\\ell_t}{b_t - c_t} \\tag{12.5}\n",
"$$\n",
"\n",
"Substituting [(12.5)](#equation-lq-hfoc) into the government’s budget constraint [(12.4)](#equation-lq-gc)\n",
"yields\n",
"\n",
"\n",
"\n",
"$$\n",
"\\mathbb E \\sum_{t=0}^{\\infty} \\beta^t\n",
"\\left[ (b_t - c_t)(s_t + g_t - \\ell_t) + \\ell_t^2 \\right] = 0 \\tag{12.6}\n",
"$$\n",
"\n",
"The Ramsey problem now amounts to maximizing [(12.1)](#equation-lq-hu) subject to\n",
"[(12.6)](#equation-lq-gc2) and [(12.3)](#equation-lq-feasible).\n",
"\n",
"The associated Lagrangian is\n",
"\n",
"\n",
"\n",
"$$\n",
"\\mathscr L =\n",
"\\mathbb E \\sum_{t=0}^{\\infty} \\beta^t\n",
"\\left\\{\n",
"-\\frac{1}{2} \\left[ (c_t - b_t)^2 + \\ell_t^2 \\right] +\n",
"\\lambda \\left[ (b_t - c_t)(\\ell_t - s_t - g_t) - \\ell_t^2 \\right] +\n",
"\\mu_t [d_t + \\ell_t - c_t - g_t]\n",
"\\right\\} \\tag{12.7}\n",
"$$\n",
"\n",
"The first-order conditions associated with $ c_t $ and $ \\ell_t $ are\n",
"\n",
"$$\n",
"-(c_t - b_t ) + \\lambda [- \\ell_t + (g_t + s_t )] = \\mu_t\n",
"$$\n",
"\n",
"and\n",
"\n",
"$$\n",
"\\ell_t - \\lambda [(b_t - c_t) - 2 \\ell_t ] = \\mu_t\n",
"$$\n",
"\n",
"Combining these last two equalities with [(12.3)](#equation-lq-feasible) and working\n",
"through the algebra, one can show that\n",
"\n",
"\n",
"\n",
"$$\n",
"\\ell_t = \\bar \\ell_t - \\nu m_t\n",
"\\quad \\text{and} \\quad\n",
"c_t = \\bar c_t - \\nu m_t \\tag{12.8}\n",
"$$\n",
"\n",
"where\n",
"\n",
"- $ \\nu := \\lambda / (1 + 2 \\lambda) $ \n",
"- $ \\bar \\ell_t := (b_t - d_t + g_t) / 2 $ \n",
"- $ \\bar c_t := (b_t + d_t - g_t) / 2 $ \n",
"- $ m_t := (b_t - d_t - s_t ) / 2 $ \n",
"\n",
"\n",
"Apart from $ \\nu $, all of these quantities are expressed in terms of exogenous variables.\n",
"\n",
"To solve for $ \\nu $, we can use the government’s budget constraint again.\n",
"\n",
"The term inside the brackets in [(12.6)](#equation-lq-gc2) is $ (b_t - c_t)(s_t + g_t) - (b_t - c_t) \\ell_t + \\ell_t^2 $.\n",
"\n",
"Using [(12.8)](#equation-lq-lcex), the definitions above and the fact that $ \\bar \\ell\n",
"= b - \\bar c $, this term can be rewritten as\n",
"\n",
"$$\n",
"(b_t - \\bar c_t) (g_t + s_t ) + 2 m_t^2 ( \\nu^2 - \\nu)\n",
"$$\n",
"\n",
"Reinserting into [(12.6)](#equation-lq-gc2), we get\n",
"\n",
"\n",
"\n",
"$$\n",
"\\mathbb E\n",
"\\left\\{\n",
"\\sum_{t=0}^{\\infty} \\beta^t\n",
"(b_t - \\bar c_t) (g_t + s_t )\n",
"\\right\\} +\n",
"( \\nu^2 - \\nu) \\mathbb E\n",
"\\left\\{\n",
"\\sum_{t=0}^{\\infty} \\beta^t 2 m_t^2\n",
"\\right\\} = 0 \\tag{12.9}\n",
"$$\n",
"\n",
"Although it might not be clear yet, we are nearly there because:\n",
"\n",
"- The two expectations terms in [(12.9)](#equation-lq-gc22) can be solved for in terms of model primitives. \n",
"- This in turn allows us to solve for the Lagrange multiplier $ \\nu $. \n",
"- With $ \\nu $ in hand, we can go back and solve for the allocations via [(12.8)](#equation-lq-lcex). \n",
"- Once we have the allocations, prices and the tax system can be derived from\n",
" [(12.5)](#equation-lq-hfoc). "
]
},
{
"cell_type": "markdown",
"id": "26a18f89",
"metadata": {},
"source": [
"### Computing the Quadratic Term\n",
"\n",
"Let’s consider how to obtain the term $ \\nu $ in [(12.9)](#equation-lq-gc22).\n",
"\n",
"If we can compute the two expected geometric sums\n",
"\n",
"\n",
"\n",
"$$\n",
"b_0 := \\mathbb E\n",
"\\left\\{\n",
"\\sum_{t=0}^{\\infty} \\beta^t\n",
"(b_t - \\bar c_t) (g_t + s_t )\n",
"\\right\\}\n",
"\\quad \\text{and} \\quad\n",
"a_0 := \\mathbb E\n",
"\\left\\{\n",
"\\sum_{t=0}^{\\infty} \\beta^t 2 m_t^2\n",
"\\right\\} \\tag{12.10}\n",
"$$\n",
"\n",
"then the problem reduces to solving\n",
"\n",
"$$\n",
"b_0 + a_0 (\\nu^2 - \\nu) = 0\n",
"$$\n",
"\n",
"for $ \\nu $.\n",
"\n",
"Provided that $ 4 b_0 < a_0 $, there is a unique solution $ \\nu \\in\n",
"(0, 1/2) $, and a unique corresponding $ \\lambda > 0 $.\n",
"\n",
"Let’s work out how to compute mathematical expectations in [(12.10)](#equation-lq-gc3).\n",
"\n",
"For the first one, the random variable $ (b_t - \\bar c_t) (g_t + s_t ) $ inside the summation can be expressed as\n",
"\n",
"$$\n",
"\\frac{1}{2} x_t' (S_b - S_d + S_g)' (S_g + S_s) x_t\n",
"$$\n",
"\n",
"For the second expectation in [(12.10)](#equation-lq-gc3), the random variable $ 2 m_t^2 $ can be written as\n",
"\n",
"$$\n",
"\\frac{1}{2} x_t' (S_b - S_d - S_s)' (S_b - S_d - S_s) x_t\n",
"$$\n",
"\n",
"It follows that both objects of interest are special cases of the expression\n",
"\n",
"\n",
"\n",
"$$\n",
"q(x_0) = \\mathbb E \\sum_{t=0}^{\\infty} \\beta^t x_t' H x_t \\tag{12.11}\n",
"$$\n",
"\n",
"where $ H $ is a matrix conformable to $ x_t $ and $ x_t' $ is the transpose of column vector $ x_t $.\n",
"\n",
"Suppose first that $ \\{x_t\\} $ is the Gaussian VAR described [above](#lq-twospec).\n",
"\n",
"In this case, the formula for computing $ q(x_0) $ is known to be $ q(x_0) = x_0' Q x_0 + v $, where\n",
"\n",
"- $ Q $ is the solution to $ Q = H + \\beta A' Q A $, and \n",
"- $ v = \\text{trace} \\, (C' Q C) \\beta / (1 - \\beta) $ \n",
"\n",
"\n",
"The first equation is known as a discrete Lyapunov equation and can be solved\n",
"using [this function](https://github.com/QuantEcon/QuantEcon.py/blob/master/quantecon/matrix_eqn.py#L25)."
]
},
{
"cell_type": "markdown",
"id": "73afcd63",
"metadata": {},
"source": [
"### Finite State Markov Case\n",
"\n",
"Next, suppose that $ \\{x_t\\} $ is the discrete Markov process described [above](#lq-twospec).\n",
"\n",
"Suppose further that each $ x_t $ takes values in the state space $ \\{x^1, \\ldots, x^N\\} \\subset \\mathbb R^k $.\n",
"\n",
"Let $ h \\colon \\mathbb R^k \\to \\mathbb R $ be a given function, and suppose that we\n",
"wish to evaluate\n",
"\n",
"$$\n",
"q(x_0) = \\mathbb E \\sum_{t=0}^{\\infty} \\beta^t h(x_t)\n",
"\\quad \\text{given} \\quad x_0 = x^j\n",
"$$\n",
"\n",
"For example, in the discussion above, $ h(x_t) = x_t' H x_t $.\n",
"\n",
"It is legitimate to pass the expectation through the sum, leading to\n",
"\n",
"\n",
"\n",
"$$\n",
"q(x_0) = \\sum_{t=0}^{\\infty} \\beta^t (P^t h)[j] \\tag{12.12}\n",
"$$\n",
"\n",
"Here\n",
"\n",
"- $ P^t $ is the $ t $-th power of the transition matrix $ P $. \n",
"- $ h $ is, with some abuse of notation, the vector $ (h(x^1), \\ldots, h(x^N)) $. \n",
"- $ (P^t h)[j] $ indicates the $ j $-th element of $ P^t h $. \n",
"\n",
"\n",
"It can be shown that [(12.12)](#equation-lq-ise) is in fact equal to the $ j $-th element of\n",
"the vector $ (I - \\beta P)^{-1} h $.\n",
"\n",
"This last fact is applied in the calculations below."
]
},
{
"cell_type": "markdown",
"id": "404ee79f",
"metadata": {},
"source": [
"### Other Variables\n",
"\n",
"We are interested in tracking several other variables besides the ones\n",
"described above.\n",
"\n",
"To prepare the way for this, we define\n",
"\n",
"$$\n",
"p^t_{t+j} = \\frac{b_{t+j}- c_{t+j}}{b_t - c_t}\n",
"$$\n",
"\n",
"as the scaled Arrow-Debreu time $ t $ price of a history contingent claim on one unit of consumption at time $ t+j $.\n",
"\n",
"These are prices that would prevail at time $ t $ if markets were reopened at time $ t $.\n",
"\n",
"These prices are constituents of the present value of government obligations outstanding at time $ t $, which can be expressed as\n",
"\n",
"\n",
"\n",
"$$\n",
"B_t :=\n",
"\\mathbb E_t \\sum_{j=0}^{\\infty} \\beta^j p^t_{t+j}\n",
"(\\tau_{t+j} \\ell_{t+j} - g_{t+j}) \\tag{12.13}\n",
"$$\n",
"\n",
"Using our expression for prices and the Ramsey plan, we can also write\n",
"$ B_t $ as\n",
"\n",
"$$\n",
"B_t =\n",
"\\mathbb E_t \\sum_{j=0}^{\\infty} \\beta^j\n",
"\\frac{ (b_{t+j} - c_{t+j})(\\ell_{t+j} - g_{t+j}) - \\ell^2_{t+j} }\n",
"{ b_t - c_t }\n",
"$$\n",
"\n",
"This version is more convenient for computation.\n",
"\n",
"Using the equation\n",
"\n",
"$$\n",
"p^t_{t+j} = p^t_{t+1} p^{t+1}_{t+j}\n",
"$$\n",
"\n",
"it is possible to verify that [(12.13)](#equation-lq-cb) implies that\n",
"\n",
"$$\n",
"B_t = (\\tau_t \\ell_t - g_t) + E_t \\sum_{j=1}^\\infty p^t_{t+j} (\\tau_{t+j} \\ell_{t+j} - g_{t+j})\n",
"$$\n",
"\n",
"and\n",
"\n",
"\n",
"\n",
"$$\n",
"B_t = (\\tau_t \\ell_t - g_t) + \\beta E_t p^t_{t+1} B_{t+1} \\tag{12.14}\n",
"$$\n",
"\n",
"Define\n",
"\n",
"\n",
"\n",
"$$\n",
"R^{-1}_{t} := \\mathbb E_t \\beta^j p^t_{t+1} \\tag{12.15}\n",
"$$\n",
"\n",
"$ R_{t} $ is the gross $ 1 $-period risk-free rate for loans\n",
"between $ t $ and $ t+1 $."
]
},
{
"cell_type": "markdown",
"id": "c1e349a1",
"metadata": {},
"source": [
"### A Martingale\n",
"\n",
"We now want to study the following two objects, namely,\n",
"\n",
"$$\n",
"\\pi_{t+1} := B_{t+1} - R_t [B_t - (\\tau_t \\ell_t - g_t)]\n",
"$$\n",
"\n",
"and the cumulation of $ \\pi_t $\n",
"\n",
"$$\n",
"\\Pi_t := \\sum_{s=0}^t \\pi_t\n",
"$$\n",
"\n",
"The term $ \\pi_{t+1} $ is the difference between two quantities:\n",
"\n",
"- $ B_{t+1} $, the value of government debt at the start of period $ t+1 $. \n",
"- $ R_t [B_t + g_t - \\tau_t ] $, which is what the government would have owed at the beginning of\n",
" period $ t+1 $ if it had simply borrowed at the one-period risk-free rate rather than selling state-contingent securities. \n",
"\n",
"\n",
"Thus, $ \\pi_{t+1} $ is the excess payout on the actual portfolio of state-contingent government debt relative to an alternative\n",
"portfolio sufficient to finance $ B_t + g_t - \\tau_t \\ell_t $ and consisting entirely of risk-free one-period bonds.\n",
"\n",
"Use expressions [(12.14)](#equation-lq-cb22) and [(12.15)](#equation-lq-rfr) to obtain\n",
"\n",
"$$\n",
"\\pi_{t+1} = B_{t+1} - \\frac{1}{\\beta E_t p^t_{t+1}} \\left[\\beta E_t p^t_{t+1} B_{t+1} \\right]\n",
"$$\n",
"\n",
"or\n",
"\n",
"\n",
"\n",
"$$\n",
"\\pi_{t+1} = B_{t+1} - \\tilde E_t B_{t+1} \\tag{12.16}\n",
"$$\n",
"\n",
"where $ \\tilde E_t $ is the conditional mathematical expectation taken with respect to a one-step transition density\n",
"that has been formed by multiplying the original transition density with the likelihood ratio\n",
"\n",
"$$\n",
"m^t_{t+1} = \\frac{p^t_{t+1}}{E_t p^t_{t+1}}\n",
"$$\n",
"\n",
"It follows from equation [(12.16)](#equation-lq-pidist) that\n",
"\n",
"$$\n",
"\\tilde E_t \\pi_{t+1} = \\tilde E_t B_{t+1} - \\tilde E_t B_{t+1} = 0\n",
"$$\n",
"\n",
"which asserts that $ \\{\\pi_{t+1}\\} $ is a martingale difference sequence under the distorted probability measure, and\n",
"that $ \\{\\Pi_t\\} $ is a martingale under the distorted probability measure.\n",
"\n",
"In the tax-smoothing model of Robert Barro [[Bar79](https://python-advanced.quantecon.org/zreferences.html#id136)], government debt is a random walk.\n",
"\n",
"In the current model, government debt $ \\{B_t\\} $ is not a random walk, but the `excess payoff` $ \\{\\Pi_t\\} $ on it is."
]
},
{
"cell_type": "markdown",
"id": "fe0557b5",
"metadata": {},
"source": [
"## Implementation\n",
"\n",
"The following code provides functions for\n",
"\n",
"1. Solving for the Ramsey plan given a specification of the economy. \n",
"1. Simulating the dynamics of the major variables. \n",
"\n",
"\n",
"Description and clarifications are given below"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a58844f1",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"# Set up a namedtuple to store data on the model economy\n",
"Economy = namedtuple('economy',\n",
" ('β', # Discount factor\n",
" 'Sg', # Govt spending selector matrix\n",
" 'Sd', # Exogenous endowment selector matrix\n",
" 'Sb', # Utility parameter selector matrix\n",
" 'Ss', # Coupon payments selector matrix\n",
" 'discrete', # Discrete or continuous -- boolean\n",
" 'proc')) # Stochastic process parameters\n",
"\n",
"# Set up a namedtuple to store return values for compute_paths()\n",
"Path = namedtuple('path',\n",
" ('g', # Govt spending\n",
" 'd', # Endowment\n",
" 'b', # Utility shift parameter\n",
" 's', # Coupon payment on existing debt\n",
" 'c', # Consumption\n",
" 'l', # Labor\n",
" 'p', # Price\n",
" 'τ', # Tax rate\n",
" 'rvn', # Revenue\n",
" 'B', # Govt debt\n",
" 'R', # Risk-free gross return\n",
" 'π', # One-period risk-free interest rate\n",
" 'Π', # Cumulative rate of return, adjusted\n",
" 'ξ')) # Adjustment factor for Π\n",
"\n",
"\n",
"def compute_paths(T, econ):\n",
" \"\"\"\n",
" Compute simulated time paths for exogenous and endogenous variables.\n",
"\n",
" Parameters\n",
" ===========\n",
" T: int\n",
" Length of the simulation\n",
"\n",
" econ: a namedtuple of type 'Economy', containing\n",
" β - Discount factor\n",
" Sg - Govt spending selector matrix\n",
" Sd - Exogenous endowment selector matrix\n",
" Sb - Utility parameter selector matrix\n",
" Ss - Coupon payments selector matrix\n",
" discrete - Discrete exogenous process (True or False)\n",
" proc - Stochastic process parameters\n",
"\n",
" Returns\n",
" ========\n",
" path: a namedtuple of type 'Path', containing\n",
" g - Govt spending\n",
" d - Endowment\n",
" b - Utility shift parameter\n",
" s - Coupon payment on existing debt\n",
" c - Consumption\n",
" l - Labor\n",
" p - Price\n",
" τ - Tax rate\n",
" rvn - Revenue\n",
" B - Govt debt\n",
" R - Risk-free gross return\n",
" π - One-period risk-free interest rate\n",
" Π - Cumulative rate of return, adjusted\n",
" ξ - Adjustment factor for Π\n",
"\n",
" The corresponding values are flat numpy ndarrays.\n",
"\n",
" \"\"\"\n",
"\n",
" # Simplify names\n",
" β, Sg, Sd, Sb, Ss = econ.β, econ.Sg, econ.Sd, econ.Sb, econ.Ss\n",
"\n",
" if econ.discrete:\n",
" P, x_vals = econ.proc\n",
" else:\n",
" A, C = econ.proc\n",
"\n",
" # Simulate the exogenous process x\n",
" if econ.discrete:\n",
" state = mc_sample_path(P, init=0, sample_size=T)\n",
" x = x_vals[:, state]\n",
" else:\n",
" # Generate an initial condition x0 satisfying x0 = A x0\n",
" nx, nx = A.shape\n",
" x0 = nullspace((eye(nx) - A))\n",
" x0 = -x0 if (x0[nx-1] < 0) else x0\n",
" x0 = x0 / x0[nx-1]\n",
"\n",
" # Generate a time series x of length T starting from x0\n",
" nx, nw = C.shape\n",
" x = zeros((nx, T))\n",
" w = randn(nw, T)\n",
" x[:, 0] = x0.T\n",
" for t in range(1, T):\n",
" x[:, t] = A @ x[:, t-1] + C @ w[:, t]\n",
"\n",
" # Compute exogenous variable sequences\n",
" g, d, b, s = ((S @ x).flatten() for S in (Sg, Sd, Sb, Ss))\n",
"\n",
" # Solve for Lagrange multiplier in the govt budget constraint\n",
" # In fact we solve for ν = lambda / (1 + 2*lambda). Here ν is the\n",
" # solution to a quadratic equation a(ν**2 - ν) + b = 0 where\n",
" # a and b are expected discounted sums of quadratic forms of the state.\n",
" Sm = Sb - Sd - Ss\n",
" # Compute a and b\n",
" if econ.discrete:\n",
" ns = P.shape[0]\n",
" F = scipy.linalg.inv(eye(ns) - β * P)\n",
" a0 = 0.5 * (F @ (x_vals.T @ Sm.T)**2)[0]\n",
" H = ((Sb - Sd + Sg) @ x_vals) * ((Sg - Ss) @ x_vals)\n",
" b0 = 0.5 * (F @ H.T)[0]\n",
" a0, b0 = float(a0), float(b0)\n",
" else:\n",
" H = Sm.T @ Sm\n",
" a0 = 0.5 * var_quadratic_sum(A, C, H, β, x0)\n",
" H = (Sb - Sd + Sg).T @ (Sg + Ss)\n",
" b0 = 0.5 * var_quadratic_sum(A, C, H, β, x0)\n",
"\n",
" # Test that ν has a real solution before assigning\n",
" warning_msg = \"\"\"\n",
" Hint: you probably set government spending too {}. Elect a {}\n",
" Congress and start over.\n",
" \"\"\"\n",
" disc = a0**2 - 4 * a0 * b0\n",
" if disc >= 0:\n",
" ν = 0.5 * (a0 - sqrt(disc)) / a0\n",
" else:\n",
" print(\"There is no Ramsey equilibrium for these parameters.\")\n",
" print(warning_msg.format('high', 'Republican'))\n",
" sys.exit(0)\n",
"\n",
" # Test that the Lagrange multiplier has the right sign\n",
" if ν * (0.5 - ν) < 0:\n",
" print(\"Negative multiplier on the government budget constraint.\")\n",
" print(warning_msg.format('low', 'Democratic'))\n",
" sys.exit(0)\n",
"\n",
" # Solve for the allocation given ν and x\n",
" Sc = 0.5 * (Sb + Sd - Sg - ν * Sm)\n",
" Sl = 0.5 * (Sb - Sd + Sg - ν * Sm)\n",
" c = (Sc @ x).flatten()\n",
" l = (Sl @ x).flatten()\n",
" p = ((Sb - Sc) @ x).flatten() # Price without normalization\n",
" τ = 1 - l / (b - c)\n",
" rvn = l * τ\n",
"\n",
" # Compute remaining variables\n",
" if econ.discrete:\n",
" H = ((Sb - Sc) @ x_vals) * ((Sl - Sg) @ x_vals) - (Sl @ x_vals)**2\n",
" temp = (F @ H.T).flatten()\n",
" B = temp[state] / p\n",
" H = (P[state, :] @ x_vals.T @ (Sb - Sc).T).flatten()\n",
" R = p / (β * H)\n",
" temp = ((P[state, :] @ x_vals.T @ (Sb - Sc).T)).flatten()\n",
" ξ = p[1:] / temp[:T-1]\n",
" else:\n",
" H = Sl.T @ Sl - (Sb - Sc).T @ (Sl - Sg)\n",
" L = np.empty(T)\n",
" for t in range(T):\n",
" L[t] = var_quadratic_sum(A, C, H, β, x[:, t])\n",
" B = L / p\n",
" Rinv = (β * ((Sb - Sc) @ A @ x)).flatten() / p\n",
" R = 1 / Rinv\n",
" AF1 = (Sb - Sc) @ x[:, 1:]\n",
" AF2 = (Sb - Sc) @ A @ x[:, :T-1]\n",
" ξ = AF1 / AF2\n",
" ξ = ξ.flatten()\n",
"\n",
" π = B[1:] - R[:T-1] * B[:T-1] - rvn[:T-1] + g[:T-1]\n",
" Π = cumsum(π * ξ)\n",
"\n",
" # Prepare return values\n",
" path = Path(g=g, d=d, b=b, s=s, c=c, l=l, p=p,\n",
" τ=τ, rvn=rvn, B=B, R=R, π=π, Π=Π, ξ=ξ)\n",
"\n",
" return path\n",
"\n",
"\n",
"def gen_fig_1(path):\n",
" \"\"\"\n",
" The parameter is the path namedtuple returned by compute_paths(). See\n",
" the docstring of that function for details.\n",
" \"\"\"\n",
"\n",
" T = len(path.c)\n",
"\n",
" # Prepare axes\n",
" num_rows, num_cols = 2, 2\n",
" fig, axes = plt.subplots(num_rows, num_cols, figsize=(14, 10))\n",
" plt.subplots_adjust(hspace=0.4)\n",
" for i in range(num_rows):\n",
" for j in range(num_cols):\n",
" axes[i, j].grid()\n",
" axes[i, j].set_xlabel('Time')\n",
" bbox = (0., 1.02, 1., .102)\n",
" legend_args = {'bbox_to_anchor': bbox, 'loc': 3, 'mode': 'expand'}\n",
" p_args = {'lw': 2, 'alpha': 0.7}\n",
"\n",
" # Plot consumption, govt expenditure and revenue\n",
" ax = axes[0, 0]\n",
" ax.plot(path.rvn, label=r'$\\tau_t \\ell_t$', **p_args)\n",
" ax.plot(path.g, label='$g_t$', **p_args)\n",
" ax.plot(path.c, label='$c_t$', **p_args)\n",
" ax.legend(ncol=3, **legend_args)\n",
"\n",
" # Plot govt expenditure and debt\n",
" ax = axes[0, 1]\n",
" ax.plot(list(range(1, T+1)), path.rvn, label=r'$\\tau_t \\ell_t$', **p_args)\n",
" ax.plot(list(range(1, T+1)), path.g, label='$g_t$', **p_args)\n",
" ax.plot(list(range(1, T)), path.B[1:T], label='$B_{t+1}$', **p_args)\n",
" ax.legend(ncol=3, **legend_args)\n",
"\n",
" # Plot risk-free return\n",
" ax = axes[1, 0]\n",
" ax.plot(list(range(1, T+1)), path.R - 1, label='$R_t - 1$', **p_args)\n",
" ax.legend(ncol=1, **legend_args)\n",
"\n",
" # Plot revenue, expenditure and risk free rate\n",
" ax = axes[1, 1]\n",
" ax.plot(list(range(1, T+1)), path.rvn, label=r'$\\tau_t \\ell_t$', **p_args)\n",
" ax.plot(list(range(1, T+1)), path.g, label='$g_t$', **p_args)\n",
" axes[1, 1].plot(list(range(1, T)), path.π, label=r'$\\pi_{t+1}$', **p_args)\n",
" ax.legend(ncol=3, **legend_args)\n",
"\n",
" plt.show()\n",
"\n",
"\n",
"def gen_fig_2(path):\n",
" \"\"\"\n",
" The parameter is the path namedtuple returned by compute_paths(). See\n",
" the docstring of that function for details.\n",
" \"\"\"\n",
"\n",
" T = len(path.c)\n",
"\n",
" # Prepare axes\n",
" num_rows, num_cols = 2, 1\n",
" fig, axes = plt.subplots(num_rows, num_cols, figsize=(10, 10))\n",
" plt.subplots_adjust(hspace=0.5)\n",
" bbox = (0., 1.02, 1., .102)\n",
" bbox = (0., 1.02, 1., .102)\n",
" legend_args = {'bbox_to_anchor': bbox, 'loc': 3, 'mode': 'expand'}\n",
" p_args = {'lw': 2, 'alpha': 0.7}\n",
"\n",
" # Plot adjustment factor\n",
" ax = axes[0]\n",
" ax.plot(list(range(2, T+1)), path.ξ, label=r'$\\xi_t$', **p_args)\n",
" ax.grid()\n",
" ax.set_xlabel('Time')\n",
" ax.legend(ncol=1, **legend_args)\n",
"\n",
" # Plot adjusted cumulative return\n",
" ax = axes[1]\n",
" ax.plot(list(range(2, T+1)), path.Π, label=r'$\\Pi_t$', **p_args)\n",
" ax.grid()\n",
" ax.set_xlabel('Time')\n",
" ax.legend(ncol=1, **legend_args)\n",
"\n",
" plt.show()"
]
},
{
"cell_type": "markdown",
"id": "6204f549",
"metadata": {},
"source": [
"### Comments on the Code\n",
"\n",
"The function `var_quadratic_sum` imported from `quadsums` is for computing the value of [(12.11)](#equation-lq-eqs)\n",
"when the exogenous process $ \\{ x_t \\} $ is of the VAR type described [above](#lq-twospec).\n",
"\n",
"Below the definition of the function, you will see definitions of two `namedtuple` objects, `Economy` and `Path`.\n",
"\n",
"The first is used to collect all the parameters and primitives of a given LQ\n",
"economy, while the second collects output of the computations.\n",
"\n",
"In Python, a `namedtuple` is a popular data type from the `collections` module of the standard library that replicates the functionality of a tuple, but also allows you to assign a name to each tuple element.\n",
"\n",
"These elements can then be references via dotted attribute notation — see for example the use of `path` in the functions `gen_fig_1()` and `gen_fig_2()`.\n",
"\n",
"The benefits of using `namedtuples`:\n",
"\n",
"- Keeps content organized by meaning. \n",
"- Helps reduce the number of global variables. \n",
"\n",
"\n",
"Other than that, our code is long but relatively straightforward."
]
},
{
"cell_type": "markdown",
"id": "922270db",
"metadata": {},
"source": [
"## Examples\n",
"\n",
"Let’s look at two examples of usage.\n",
"\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"id": "35c8c764",
"metadata": {},
"source": [
"### The Continuous Case\n",
"\n",
"Our first example adopts the VAR specification described [above](#lq-twospec).\n",
"\n",
"Regarding the primitives, we set\n",
"\n",
"- $ \\beta = 1 / 1.05 $ \n",
"- $ b_t = 2.135 $ and $ s_t = d_t = 0 $ for all $ t $ \n",
"\n",
"\n",
"Government spending evolves according to\n",
"\n",
"$$\n",
"g_{t+1} - \\mu_g = \\rho (g_t - \\mu_g) + C_g w_{g, t+1}\n",
"$$\n",
"\n",
"with $ \\rho = 0.7 $, $ \\mu_g = 0.35 $ and $ C_g = \\mu_g \\sqrt{1 - \\rho^2} / 10 $.\n",
"\n",
"Here’s the code"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1c244169",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"# == Parameters == #\n",
"β = 1 / 1.05\n",
"ρ, mg = .7, .35\n",
"A = eye(2)\n",
"A[0, :] = ρ, mg * (1-ρ)\n",
"C = np.zeros((2, 1))\n",
"C[0, 0] = np.sqrt(1 - ρ**2) * mg / 10\n",
"Sg = np.array((1, 0)).reshape(1, 2)\n",
"Sd = np.array((0, 0)).reshape(1, 2)\n",
"Sb = np.array((0, 2.135)).reshape(1, 2)\n",
"Ss = np.array((0, 0)).reshape(1, 2)\n",
"\n",
"economy = Economy(β=β, Sg=Sg, Sd=Sd, Sb=Sb, Ss=Ss,\n",
" discrete=False, proc=(A, C))\n",
"\n",
"T = 50\n",
"path = compute_paths(T, economy)\n",
"gen_fig_1(path)"
]
},
{
"cell_type": "markdown",
"id": "37e1c279",
"metadata": {},
"source": [
"The legends on the figures indicate the variables being tracked.\n",
"\n",
"Most obvious from the figure is tax smoothing in the sense that tax revenue is\n",
"much less variable than government expenditure."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bc56c7ca",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"gen_fig_2(path)"
]
},
{
"cell_type": "markdown",
"id": "2faa85d9",
"metadata": {},
"source": [
"### The Discrete Case\n",
"\n",
"Our second example adopts a discrete Markov specification for the exogenous process"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b9fb416a",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"# == Parameters == #\n",
"β = 1 / 1.05\n",
"P = np.array([[0.8, 0.2, 0.0],\n",
" [0.0, 0.5, 0.5],\n",
" [0.0, 0.0, 1.0]])\n",
"\n",
"# Possible states of the world\n",
"# Each column is a state of the world. The rows are [g d b s 1]\n",
"x_vals = np.array([[0.5, 0.5, 0.25],\n",
" [0.0, 0.0, 0.0],\n",
" [2.2, 2.2, 2.2],\n",
" [0.0, 0.0, 0.0],\n",
" [1.0, 1.0, 1.0]])\n",
"\n",
"Sg = np.array((1, 0, 0, 0, 0)).reshape(1, 5)\n",
"Sd = np.array((0, 1, 0, 0, 0)).reshape(1, 5)\n",
"Sb = np.array((0, 0, 1, 0, 0)).reshape(1, 5)\n",
"Ss = np.array((0, 0, 0, 1, 0)).reshape(1, 5)\n",
"\n",
"economy = Economy(β=β, Sg=Sg, Sd=Sd, Sb=Sb, Ss=Ss,\n",
" discrete=True, proc=(P, x_vals))\n",
"\n",
"T = 15\n",
"path = compute_paths(T, economy)\n",
"gen_fig_1(path)"
]
},
{
"cell_type": "markdown",
"id": "87474220",
"metadata": {},
"source": [
"The call `gen_fig_2(path)` generates"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bafa2fa2",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"gen_fig_2(path)"
]
},
{
"cell_type": "markdown",
"id": "4c6c6c57",
"metadata": {},
"source": [
"## Exercises\n",
"\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"id": "211be7d3",
"metadata": {},
"source": [
"## Exercise 12.1\n",
"\n",
"Modify the VAR example [given above](#lq-cc), setting\n",
"\n",
"$$\n",
"g_{t+1} - \\mu_g = \\rho (g_{t-3} - \\mu_g) + C_g w_{g, t+1}\n",
"$$\n",
"\n",
"with $ \\rho = 0.95 $ and $ C_g = 0.7 \\sqrt{1 - \\rho^2} $.\n",
"\n",
"Produce the corresponding figures."
]
},
{
"cell_type": "markdown",
"id": "9f22a4a2",
"metadata": {},
"source": [
"## Solution to[ Exercise 12.1](https://python-advanced.quantecon.org/#lq_ex1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "857ec82f",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"# == Parameters == #\n",
"β = 1 / 1.05\n",
"ρ, mg = .95, .35\n",
"A = np.array([[0, 0, 0, ρ, mg*(1-ρ)],\n",
" [1, 0, 0, 0, 0],\n",
" [0, 1, 0, 0, 0],\n",
" [0, 0, 1, 0, 0],\n",
" [0, 0, 0, 0, 1]])\n",
"C = np.zeros((5, 1))\n",
"C[0, 0] = np.sqrt(1 - ρ**2) * mg / 8\n",
"Sg = np.array((1, 0, 0, 0, 0)).reshape(1, 5)\n",
"Sd = np.array((0, 0, 0, 0, 0)).reshape(1, 5)\n",
"# Chosen st. (Sc + Sg) * x0 = 1\n",
"Sb = np.array((0, 0, 0, 0, 2.135)).reshape(1, 5)\n",
"Ss = np.array((0, 0, 0, 0, 0)).reshape(1, 5)\n",
"\n",
"economy = Economy(β=β, Sg=Sg, Sd=Sd, Sb=Sb,\n",
" Ss=Ss, discrete=False, proc=(A, C))\n",
"\n",
"T = 50\n",
"path = compute_paths(T, economy)\n",
"\n",
"gen_fig_1(path)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "78f9257b",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"gen_fig_2(path)"
]
}
],
"metadata": {
"date": 1672634194.6264424,
"filename": "lqramsey.md",
"kernelspec": {
"display_name": "Python",
"language": "python3",
"name": "python3"
},
"title": "Optimal Taxation in an LQ Economy"
},
"nbformat": 4,
"nbformat_minor": 5
}