├── README.md ├── about_lectures.ipynb ├── about_py.ipynb ├── additive_functionals.ipynb ├── aiyagari.ipynb ├── amss.ipynb ├── amss2.ipynb ├── amss3.ipynb ├── ar1_processes.ipynb ├── arellano.ipynb ├── arma.ipynb ├── black_litterman.ipynb ├── calvo.ipynb ├── career.ipynb ├── cass_koopmans.ipynb ├── cattle_cycles.ipynb ├── chang_credible.ipynb ├── chang_ramsey.ipynb ├── classical_filtering.ipynb ├── coase.ipynb ├── coleman_policy_iter.ipynb ├── complex_and_trig.ipynb ├── cons_news.ipynb ├── debugging.ipynb ├── discrete_dp.ipynb ├── dyn_stack.ipynb ├── egm_policy_iter.ipynb ├── estspec.ipynb ├── exchangeable.ipynb ├── finite_markov.ipynb ├── functions.ipynb ├── geom_series.ipynb ├── getting_started.ipynb ├── growth_in_dles.ipynb ├── harrison_kreps.ipynb ├── heavy_tails.ipynb ├── hs_invertibility_example.ipynb ├── hs_recursive_models.ipynb ├── ifp.ipynb ├── inventory_dynamics.ipynb ├── irfs_in_hall_model.ipynb ├── jv.ipynb ├── kalman.ipynb ├── kesten_processes.ipynb ├── lake_model.ipynb ├── likelihood_ratio_process.ipynb ├── linear_algebra.ipynb ├── linear_models.ipynb ├── lln_clt.ipynb ├── lq_inventories.ipynb ├── lqcontrol.ipynb ├── lqramsey.ipynb ├── lu_tricks.ipynb ├── lucas_asset_pricing_dles.ipynb ├── lucas_model.ipynb ├── markov_asset.ipynb ├── markov_jump_lq.ipynb ├── markov_perf.ipynb ├── matplotlib.ipynb ├── matsuyama.ipynb ├── mccall_correlated.ipynb ├── mccall_fitted_vfi.ipynb ├── mccall_model.ipynb ├── mccall_model_with_separation.ipynb ├── mle.ipynb ├── multiplicative_functionals.ipynb ├── muth_kalman.ipynb ├── need_for_speed.ipynb ├── numba.ipynb ├── numpy.ipynb ├── odu.ipynb ├── ols.ipynb ├── oop_intro.ipynb ├── opt_tax_recur.ipynb ├── optgrowth.ipynb ├── optgrowth_fast.ipynb ├── orth_proj.ipynb ├── pandas.ipynb ├── pandas_panel.ipynb ├── parallelization.ipynb ├── perm_income.ipynb ├── perm_income_cons.ipynb ├── permanent_income_dles.ipynb ├── python_advanced_features.ipynb ├── python_by_example.ipynb ├── python_essentials.ipynb ├── python_oop.ipynb ├── rational_expectations.ipynb ├── re_with_feedback.ipynb ├── rob_markov_perf.ipynb ├── robustness.ipynb ├── rosen_schooling_model.ipynb ├── samuelson.ipynb ├── scalar_dynam.ipynb ├── schelling.ipynb ├── sci_libs.ipynb ├── scipy.ipynb ├── short_path.ipynb ├── smoothing.ipynb ├── smoothing_tax.ipynb ├── stationary_densities.ipynb ├── tax_smoothing_1.ipynb ├── tax_smoothing_2.ipynb ├── tax_smoothing_3.ipynb ├── troubleshooting.ipynb ├── uncertainty_traps.ipynb ├── von_neumann_model.ipynb ├── wald_friedman.ipynb ├── wealth_dynamics.ipynb ├── writing_good_code.ipynb └── zreferences.ipynb /README.md: -------------------------------------------------------------------------------- 1 | # lecture-py-notebooks 2 | 3 | A Repository of Notebooks for the QuantEcon Python Lecture Site 4 | 5 | These files are generated and sources are at https://github.com/QuantEcon/lecture-source-py 6 | -------------------------------------------------------------------------------- /about_lectures.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "
\n", 10 | " \n", 11 | " \"QuantEcon\"\n", 12 | " \n", 13 | "
" 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "metadata": {}, 19 | "source": [ 20 | "# About these Lectures" 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "## Contents\n", 28 | "\n", 29 | "- [About these Lectures](#About-these-Lectures) \n", 30 | " - [Overview](#Overview) \n", 31 | " - [Python](#Python) \n", 32 | " - [Open Source](#Open-Source) \n", 33 | " - [How about Other Languages?](#How-about-Other-Languages?) \n", 34 | " - [Credits](#Credits) " 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": {}, 47 | "source": [ 48 | "## Overview\n", 49 | "\n", 50 | "Programming, mathematics and statistics are powerful tools for analyzing the functioning of economies.\n", 51 | "\n", 52 | "This lecture series provides a hands-on instruction manual.\n", 53 | "\n", 54 | "Topics include\n", 55 | "\n", 56 | "- algorithms and numerical methods for studying economic problems, \n", 57 | "- related mathematical and statistical concepts, and \n", 58 | "- basics of coding skills and software engineering. \n", 59 | "\n", 60 | "\n", 61 | "The intended audience is undergraduate students, graduate students and\n", 62 | "researchers in economics, finance and related fields." 63 | ] 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "metadata": {}, 68 | "source": [ 69 | "## Python\n", 70 | "\n", 71 | "The coding language for this lecture series is Python.\n", 72 | "\n", 73 | "Note that there’s also a related set of Julia lectures .\n", 74 | "\n", 75 | "In terms of the differences,\n", 76 | "\n", 77 | "- Python is a general-purpose language featuring a massive user community in the sciences and an outstanding scientific ecosystem. \n", 78 | "- Julia is a more recent language with many exciting features. \n", 79 | "\n", 80 | "\n", 81 | "Both are modern, open-source, high productivity languages with all the key features needed for\n", 82 | "high-performance computing.\n", 83 | "\n", 84 | "Julia has the advantage that third party libraries are often written entirely in Julia itself.\n", 85 | "\n", 86 | "Python has the advantage of being supported by a vast collection of scientific libraries (and being a highly marketable skill)." 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "## Open Source\n", 94 | "\n", 95 | "All the computing environments we work with are free and open-source.\n", 96 | "\n", 97 | "This means that you, your coauthors and your students can install them and their libraries on all of your computers without cost or concern about licenses.\n", 98 | "\n", 99 | "Another advantage of open source libraries is that you can read them and learn\n", 100 | "how they work.\n", 101 | "\n", 102 | "For example, let’s say you want to know exactly how [statsmodels](https://github.com/statsmodels/statsmodels) computes Newey-West covariance matrices.\n", 103 | "\n", 104 | "No problem: You can go ahead and [read the code](https://github.com/statsmodels/statsmodels/blob/master/statsmodels/stats/sandwich_covariance.py).\n", 105 | "\n", 106 | "While dipping into external code libraries takes a bit of coding maturity, it’s very useful for\n", 107 | "\n", 108 | "1. helping you understand the details of a particular implementation, and \n", 109 | "1. building your programming skills by showing you code written by first-rate programmers. \n", 110 | "\n", 111 | "\n", 112 | "Also, you can modify the library to suit your needs: if the functionality provided is not exactly what you want, you are free to change it.\n", 113 | "\n", 114 | "Another, a more philosophical advantage of open-source software is that it conforms to the [scientific ideal of reproducibility](https://en.wikipedia.org/wiki/Scientific_method)." 115 | ] 116 | }, 117 | { 118 | "cell_type": "markdown", 119 | "metadata": {}, 120 | "source": [ 121 | "## How about Other Languages?\n", 122 | "\n", 123 | "But why don’t you use language XYZ?" 124 | ] 125 | }, 126 | { 127 | "cell_type": "markdown", 128 | "metadata": {}, 129 | "source": [ 130 | "### MATLAB\n", 131 | "\n", 132 | "While MATLAB has many nice features, it’s starting to show its age.\n", 133 | "\n", 134 | "It can no longer match Python or Julia in terms of performance and design.\n", 135 | "\n", 136 | "MATLAB is also proprietary, which comes with its own set of disadvantages.\n", 137 | "\n", 138 | "Given what’s available now, it’s hard to find any good reason to invest in MATLAB.\n", 139 | "\n", 140 | "Incidentally, if you decide to jump from MATLAB to Python, [this cheat-sheet](http://cheatsheets.quantecon.org/) will be useful." 141 | ] 142 | }, 143 | { 144 | "cell_type": "markdown", 145 | "metadata": {}, 146 | "source": [ 147 | "### R\n", 148 | "\n", 149 | "[R](https://cran.r-project.org/) is a very useful open source statistical environment and programming language\n", 150 | "\n", 151 | "Its primary strength is its [vast collection](https://cran.r-project.org/web/packages) of extension packages\n", 152 | "\n", 153 | "Python is more general-purpose than R and hence a better fit for this course\n", 154 | "\n", 155 | "Moreover, if there are R libraries you find you want to use, you can now call them from within Python or Julia" 156 | ] 157 | }, 158 | { 159 | "cell_type": "markdown", 160 | "metadata": {}, 161 | "source": [ 162 | "### C / C++ / Fortran?\n", 163 | "\n", 164 | "Isn’t Fortran / C / C++ faster than Python? In which case it must be better, right?\n", 165 | "\n", 166 | "This is an outdated view.\n", 167 | "\n", 168 | "First, you can achieve speeds equal to or faster than those of compiled languages in Python through features like a just-in-time compilation — we’ll talk about how later on.\n", 169 | "\n", 170 | "Second, remember that the correct objective function to minimize is" 171 | ] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "metadata": { 176 | "hide-output": false 177 | }, 178 | "source": [ 179 | "```python\n", 180 | "total time = development time + execution time\n", 181 | "```\n" 182 | ] 183 | }, 184 | { 185 | "cell_type": "markdown", 186 | "metadata": {}, 187 | "source": [ 188 | "In assessing this trade off, it’s necessary to bear in mind that\n", 189 | "\n", 190 | "- Your time is a far more valuable resource than the computer’s time. \n", 191 | "- Languages like Python are much faster to write and debug in. \n", 192 | "- In any one program, the vast majority of CPU time will be spent iterating over just a few lines of your code. " 193 | ] 194 | }, 195 | { 196 | "cell_type": "markdown", 197 | "metadata": {}, 198 | "source": [ 199 | "#### Last Word\n", 200 | "\n", 201 | "Writing your entire program in Fortran / C / C++ is best thought of as “premature optimization”\n", 202 | "\n", 203 | "On this topic we quote the godfather:\n", 204 | "\n", 205 | "> We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. – [Donald Knuth](https://en.wikipedia.org/wiki/Donald_Knuth)" 206 | ] 207 | }, 208 | { 209 | "cell_type": "markdown", 210 | "metadata": {}, 211 | "source": [ 212 | "## Credits\n", 213 | "\n", 214 | "These lectures have benefited greatly from comments and suggestions from our\n", 215 | "colleagues, students and friends. Special thanks are due to our sponsoring\n", 216 | "organization the Alfred P. Sloan Foundation and our research assistants Chase\n", 217 | "Coleman, Spencer Lyon and Matthew McKay for innumerable contributions to the\n", 218 | "code library and functioning of the website.\n", 219 | "\n", 220 | "We also thank [Andrij Stachurski](http://drdrij.com/) for his great web\n", 221 | "skills, and the many others who have contributed suggestions, bug fixes or\n", 222 | "improvements. They include but are not limited to Anmol Bhandari, Long Bui,\n", 223 | "Jeong-Hun Choi, David Evans, Shunsuke Hori, Chenghan Hou, Doc-Jin Jang,\n", 224 | "Qingyin Ma, Akira Matsushita, Tomohito Okabe, Daisuke Oyama, David Pugh, Alex\n", 225 | "Olssen, Nathan Palmer, Bill Tubbs, Natasha Watkins, Pablo Winant and Yixiao\n", 226 | "Zhou." 227 | ] 228 | } 229 | ], 230 | "metadata": { 231 | "date": 1584334732.3616617, 232 | "filename": "about_lectures.rst", 233 | "kernelspec": { 234 | "display_name": "Python", 235 | "language": "python3", 236 | "name": "python3" 237 | }, 238 | "title": "About these Lectures" 239 | }, 240 | "nbformat": 4, 241 | "nbformat_minor": 2 242 | } -------------------------------------------------------------------------------- /cattle_cycles.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "
\n", 10 | " \n", 11 | " \"QuantEcon\"\n", 12 | " \n", 13 | "
\n", 14 | "\n", 15 | "\n", 16 | "" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# Cattle Cycles" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "## Contents\n", 31 | "\n", 32 | "- [Cattle Cycles](#Cattle-Cycles) \n", 33 | " - [The Model](#The-Model) \n", 34 | " - [Mapping into HS2013 Framework](#Mapping-into-HS2013-Framework) " 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "This is another member of a suite of lectures that use the quantecon DLE class to instantiate models within the\n", 42 | "[[HS13b]](https://python.quantecon.org/zreferences.html#hs2013) class of models described in detail in [Recursive Models of Dynamic Linear Economies](https://python.quantecon.org/hs_recursive_models.html).\n", 43 | "\n", 44 | "In addition to what’s in Anaconda, this lecture uses the quantecon library." 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": null, 50 | "metadata": { 51 | "hide-output": true 52 | }, 53 | "outputs": [], 54 | "source": [ 55 | "!pip install --upgrade quantecon" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "This lecture uses the DLE class to construct instances of the “Cattle Cycles” model\n", 63 | "of Rosen, Murphy and Scheinkman (1994) [[RMS94]](https://python.quantecon.org/zreferences.html#rosen1994cattle).\n", 64 | "\n", 65 | "That paper constructs a rational expectations equilibrium model to\n", 66 | "understand sources of recurrent cycles in US cattle stocks and prices.\n", 67 | "\n", 68 | "We make the following imports:" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": null, 74 | "metadata": { 75 | "hide-output": false 76 | }, 77 | "outputs": [], 78 | "source": [ 79 | "import numpy as np\n", 80 | "import matplotlib.pyplot as plt\n", 81 | "from quantecon import LQ\n", 82 | "from collections import namedtuple\n", 83 | "from quantecon import DLE\n", 84 | "from math import sqrt\n", 85 | "%matplotlib inline" 86 | ] 87 | }, 88 | { 89 | "cell_type": "markdown", 90 | "metadata": {}, 91 | "source": [ 92 | "## The Model\n", 93 | "\n", 94 | "The model features a static linear demand curve and a “time-to-grow”\n", 95 | "structure for cattle.\n", 96 | "\n", 97 | "Let $ p_t $ be the price of slaughtered beef, $ m_t $ the cost\n", 98 | "of preparing an animal for slaughter, $ h_t $ the holding cost for a\n", 99 | "mature animal, $ \\gamma_1 h_t $ the holding cost for a yearling, and\n", 100 | "$ \\gamma_0 h_t $ the holding cost for a calf.\n", 101 | "\n", 102 | "The cost processes $ \\{h_t, m_t \\}_{t=0}^\\infty $ are exogenous,\n", 103 | "while the price process $ \\{p_t \\}_{t=0}^\\infty $ is determined\n", 104 | "within a rational expectations equilibrium.\n", 105 | "\n", 106 | "Let $ x_t $ be the breeding stock, and $ y_t $ be the total\n", 107 | "stock of cattle.\n", 108 | "\n", 109 | "The law of motion for the breeding stock is\n", 110 | "\n", 111 | "$$\n", 112 | "x_t = (1-\\delta)x_{t-1} + gx_{t-3} - c_t\n", 113 | "$$\n", 114 | "\n", 115 | "where $ g < 1 $ is the number of calves that each member of the\n", 116 | "breeding stock has each year, and $ c_t $ is the number of cattle\n", 117 | "slaughtered.\n", 118 | "\n", 119 | "The total headcount of cattle is\n", 120 | "\n", 121 | "$$\n", 122 | "y_t = x_t + gx_{t-1} + gx_{t-2}\n", 123 | "$$\n", 124 | "\n", 125 | "This equation states that the total number of cattle equals the sum of\n", 126 | "adults, calves and yearlings, respectively.\n", 127 | "\n", 128 | "A representative farmer chooses $ \\{c_t, x_t\\} $ to maximize:\n", 129 | "\n", 130 | "$$\n", 131 | "\\mathbb{E}_0 \\sum_{t=0}^\\infty \\beta^t \\{p_tc_t - h_tx_t - \\gamma_0 h_t(gx_{t-1}) - \\gamma_1 h_t(gx_{t-2}) - m_tc_t - \\frac{\\psi_1}{2}x_t^2 - \\frac{\\psi_2}{2}x_{t-1}^2 - \\frac{\\psi_3}{2}x_{t-3}^2 - \\frac{\\psi_4}{2}c_t^2 \\}\n", 132 | "$$\n", 133 | "\n", 134 | "subject to the law of motion for $ x_t $, taking as given the\n", 135 | "stochastic laws of motion for the exogenous processes, the equilibrium\n", 136 | "price process, and the initial state [$ x_{-1},x_{-2},x_{-3} $].\n", 137 | "\n", 138 | "**Remark** The $ \\psi_j $ parameters are very small quadratic costs\n", 139 | "that are included for technical reasons to make well posed and well\n", 140 | "behaved the linear quadratic dynamic programming problem solved by the\n", 141 | "fictitious planner who in effect chooses equilibrium quantities and shadow\n", 142 | "prices.\n", 143 | "\n", 144 | "Demand for beef is government by $ c_t = a_0 - a_1p_t + \\tilde d_t $\n", 145 | "where $ \\tilde d_t $ is a stochastic process with mean zero,\n", 146 | "representing a demand shifter." 147 | ] 148 | }, 149 | { 150 | "cell_type": "markdown", 151 | "metadata": {}, 152 | "source": [ 153 | "## Mapping into HS2013 Framework" 154 | ] 155 | }, 156 | { 157 | "cell_type": "markdown", 158 | "metadata": {}, 159 | "source": [ 160 | "### Preferences\n", 161 | "\n", 162 | "We set\n", 163 | "$ \\Lambda = 0, \\Delta_h = 0, \\Theta_h = 0, \\Pi = \\alpha_1^{-\\frac{1}{2}} $\n", 164 | "and $ b_t = \\Pi \\tilde d_t + \\Pi \\alpha_0 $.\n", 165 | "\n", 166 | "With these settings, the FOC for the household’s problem becomes the\n", 167 | "demand curve of the “Cattle Cycles” model." 168 | ] 169 | }, 170 | { 171 | "cell_type": "markdown", 172 | "metadata": {}, 173 | "source": [ 174 | "### Technology\n", 175 | "\n", 176 | "To capture the law of motion for cattle, we set\n", 177 | "\n", 178 | "$$\n", 179 | "\\Delta_k =\n", 180 | "\\left[ {\\begin{array}{ccc}\n", 181 | " (1-\\delta) & 0 & g \\\\ 1 & 0 & 0 \\\\ 0 & 1 & 0\n", 182 | " \\end{array} }\n", 183 | " \\right] , \\\n", 184 | " \\Theta_k =\n", 185 | "\\left[ {\\begin{array}{c}\n", 186 | " 1 \\\\ 0 \\\\ 0\n", 187 | " \\end{array} }\n", 188 | " \\right]\n", 189 | "$$\n", 190 | "\n", 191 | "(where $ i_t = - c_t $).\n", 192 | "\n", 193 | "To capture the production of cattle, we set\n", 194 | "\n", 195 | "$$\n", 196 | "\\Phi_c =\n", 197 | "\\left[ {\\begin{array}{c}\n", 198 | " 1 \\\\ f_1 \\\\ 0 \\\\ 0 \\\\ -f_7\n", 199 | " \\end{array} }\n", 200 | " \\right] , \\\n", 201 | " \\Phi_g =\n", 202 | "\\left[ {\\begin{array}{cccc}\n", 203 | " 0 & 0 & 0 & 0 \\\\ 1 & 0 & 0 & 0 \\\\ 0 & 1 & 0 & 0 \\\\ 0 & 0 & 1 & 0 \\\\ 0 & 0 & 0 & 1\n", 204 | " \\end{array} }\n", 205 | " \\right] , \\\n", 206 | " \\Phi_i =\n", 207 | "\\left[ {\\begin{array}{c}\n", 208 | " 1 \\\\ 0 \\\\ 0 \\\\ 0 \\\\ 0\n", 209 | " \\end{array} }\n", 210 | " \\right] , \\\n", 211 | " \\Gamma =\n", 212 | "\\left[ {\\begin{array}{ccc}\n", 213 | " 0 & 0 & 0 \\\\ f_1(1-\\delta) & 0 & g f_1 \\\\ f_3 & 0 & 0 \\\\ 0 & f_5 & 0 \\\\ 0 & 0 & 0\n", 214 | " \\end{array} }\n", 215 | " \\right]\n", 216 | "$$" 217 | ] 218 | }, 219 | { 220 | "cell_type": "markdown", 221 | "metadata": {}, 222 | "source": [ 223 | "### Information\n", 224 | "\n", 225 | "We set\n", 226 | "\n", 227 | "$$\n", 228 | "A_{22} =\n", 229 | "\\left[ {\\begin{array}{cccc}\n", 230 | " 1 & 0 & 0 & 0\\\\ 0 & \\rho_1 & 0 & 0 \\\\ 0 & 0 & \\rho_2 & 0 \\\\ 0 & 0 & 0 & \\rho_3\n", 231 | " \\end{array} }\n", 232 | " \\right] \\\n", 233 | ", C_2 =\n", 234 | "\\left[ {\\begin{array}{ccc}\n", 235 | " 0 & 0 & 0\\\\ 1 & 0 & 0 \\\\ 0 & 1 & 0 \\\\ 0 & 0 & 15\n", 236 | " \\end{array} }\n", 237 | " \\right] \\\n", 238 | ", U_b =\n", 239 | "\\left[ {\\begin{array}{cccc}\n", 240 | " \\Pi \\alpha_0 & 0 & 0 & \\Pi\n", 241 | " \\end{array} }\n", 242 | " \\right] \\\n", 243 | ", U_d =\n", 244 | "\\left[ {\\begin{array}{c}\n", 245 | " 0 \\\\ f_2 U_h \\\\ f_4 U_h \\\\ f_6 U_h \\\\ f_8 U_h\n", 246 | " \\end{array} }\n", 247 | " \\right]\n", 248 | "$$\n", 249 | "\n", 250 | "To map this into our class, we set $ f_1^2 = \\frac{\\Psi_1}{2} $,\n", 251 | "$ f_2^2 = \\frac{\\Psi_2}{2} $, $ f_3^2 = \\frac{\\Psi_3}{2} $,\n", 252 | "$ 2f_1f_2 = 1 $, $ 2f_3f_4 = \\gamma_0g $,\n", 253 | "$ 2f_5f_6 = \\gamma_1g $." 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": null, 259 | "metadata": { 260 | "hide-output": false 261 | }, 262 | "outputs": [], 263 | "source": [ 264 | "# We define namedtuples in this way as it allows us to check, for example,\n", 265 | "# what matrices are associated with a particular technology.\n", 266 | "\n", 267 | "Information = namedtuple('Information', ['a22', 'c2', 'ub', 'ud'])\n", 268 | "Technology = namedtuple('Technology', ['ϕ_c', 'ϕ_g', 'ϕ_i', 'γ', 'δ_k', 'θ_k'])\n", 269 | "Preferences = namedtuple('Preferences', ['β', 'l_λ', 'π_h', 'δ_h', 'θ_h'])" 270 | ] 271 | }, 272 | { 273 | "cell_type": "markdown", 274 | "metadata": {}, 275 | "source": [ 276 | "We set parameters to those used by [[RMS94]](https://python.quantecon.org/zreferences.html#rosen1994cattle)" 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": null, 282 | "metadata": { 283 | "hide-output": false 284 | }, 285 | "outputs": [], 286 | "source": [ 287 | "β = np.array([[0.909]])\n", 288 | "lλ = np.array([[0]])\n", 289 | "\n", 290 | "a1 = 0.5\n", 291 | "πh = np.array([[1 / (sqrt(a1))]])\n", 292 | "δh = np.array([[0]])\n", 293 | "θh = np.array([[0]])\n", 294 | "\n", 295 | "δ = 0.1\n", 296 | "g = 0.85\n", 297 | "f1 = 0.001\n", 298 | "f3 = 0.001\n", 299 | "f5 = 0.001\n", 300 | "f7 = 0.001\n", 301 | "\n", 302 | "ϕc = np.array([[1], [f1], [0], [0], [-f7]])\n", 303 | "\n", 304 | "ϕg = np.array([[0, 0, 0, 0],\n", 305 | " [1, 0, 0, 0],\n", 306 | " [0, 1, 0, 0],\n", 307 | " [0, 0, 1,0],\n", 308 | " [0, 0, 0, 1]])\n", 309 | "\n", 310 | "ϕi = np.array([[1], [0], [0], [0], [0]])\n", 311 | "\n", 312 | "γ = np.array([[ 0, 0, 0],\n", 313 | " [f1 * (1 - δ), 0, g * f1],\n", 314 | " [ f3, 0, 0],\n", 315 | " [ 0, f5, 0],\n", 316 | " [ 0, 0, 0]])\n", 317 | "\n", 318 | "δk = np.array([[1 - δ, 0, g],\n", 319 | " [ 1, 0, 0],\n", 320 | " [ 0, 1, 0]])\n", 321 | "\n", 322 | "θk = np.array([[1], [0], [0]])\n", 323 | "\n", 324 | "ρ1 = 0\n", 325 | "ρ2 = 0\n", 326 | "ρ3 = 0.6\n", 327 | "a0 = 500\n", 328 | "γ0 = 0.4\n", 329 | "γ1 = 0.7\n", 330 | "f2 = 1 / (2 * f1)\n", 331 | "f4 = γ0 * g / (2 * f3)\n", 332 | "f6 = γ1 * g / (2 * f5)\n", 333 | "f8 = 1 / (2 * f7)\n", 334 | "\n", 335 | "a22 = np.array([[1, 0, 0, 0],\n", 336 | " [0, ρ1, 0, 0],\n", 337 | " [0, 0, ρ2, 0],\n", 338 | " [0, 0, 0, ρ3]])\n", 339 | "\n", 340 | "c2 = np.array([[0, 0, 0],\n", 341 | " [1, 0, 0],\n", 342 | " [0, 1, 0],\n", 343 | " [0, 0, 15]])\n", 344 | "\n", 345 | "ub = np.array([[πh * a0, 0, 0, πh]])\n", 346 | "uh = np.array([[50, 1, 0, 0]])\n", 347 | "um = np.array([[100, 0, 1, 0]])\n", 348 | "ud = np.vstack(([0, 0, 0, 0],\n", 349 | " f2 * uh, f4 * uh, f6 * uh, f8 * um))" 350 | ] 351 | }, 352 | { 353 | "cell_type": "markdown", 354 | "metadata": {}, 355 | "source": [ 356 | "Notice that we have set $ \\rho_1 = \\rho_2 = 0 $, so $ h_t $ and\n", 357 | "$ m_t $ consist of a constant and a white noise component.\n", 358 | "\n", 359 | "We set up the economy using tuples for information, technology and\n", 360 | "preference matrices below.\n", 361 | "\n", 362 | "We also construct two extra information matrices, corresponding to cases\n", 363 | "when $ \\rho_3 = 1 $ and $ \\rho_3 = 0 $ (as opposed to the\n", 364 | "baseline case of $ \\rho_3 = 0.6 $)." 365 | ] 366 | }, 367 | { 368 | "cell_type": "code", 369 | "execution_count": null, 370 | "metadata": { 371 | "hide-output": false 372 | }, 373 | "outputs": [], 374 | "source": [ 375 | "info1 = Information(a22, c2, ub, ud)\n", 376 | "tech1 = Technology(ϕc, ϕg, ϕi, γ, δk, θk)\n", 377 | "pref1 = Preferences(β, lλ, πh, δh, θh)\n", 378 | "\n", 379 | "ρ3_2 = 1\n", 380 | "a22_2 = np.array([[1, 0, 0, 0],\n", 381 | " [0, ρ1, 0, 0],\n", 382 | " [0, 0, ρ2, 0],\n", 383 | " [0, 0, 0, ρ3_2]])\n", 384 | "\n", 385 | "info2 = Information(a22_2, c2, ub, ud)\n", 386 | "\n", 387 | "ρ3_3 = 0\n", 388 | "a22_3 = np.array([[1, 0, 0, 0],\n", 389 | " [0, ρ1, 0, 0],\n", 390 | " [0, 0, ρ2, 0],\n", 391 | " [0, 0, 0, ρ3_3]])\n", 392 | "\n", 393 | "info3 = Information(a22_3, c2, ub, ud)\n", 394 | "\n", 395 | "# Example of how we can look at the matrices associated with a given namedtuple\n", 396 | "info1.a22" 397 | ] 398 | }, 399 | { 400 | "cell_type": "code", 401 | "execution_count": null, 402 | "metadata": { 403 | "hide-output": false 404 | }, 405 | "outputs": [], 406 | "source": [ 407 | "# Use tuples to define DLE class\n", 408 | "econ1 = DLE(info1, tech1, pref1)\n", 409 | "econ2 = DLE(info2, tech1, pref1)\n", 410 | "econ3 = DLE(info3, tech1, pref1)\n", 411 | "\n", 412 | "# Calculate steady-state in baseline case and use to set the initial condition\n", 413 | "econ1.compute_steadystate(nnc=4)\n", 414 | "x0 = econ1.zz" 415 | ] 416 | }, 417 | { 418 | "cell_type": "code", 419 | "execution_count": null, 420 | "metadata": { 421 | "hide-output": false 422 | }, 423 | "outputs": [], 424 | "source": [ 425 | "econ1.compute_sequence(x0, ts_length=100)" 426 | ] 427 | }, 428 | { 429 | "cell_type": "markdown", 430 | "metadata": {}, 431 | "source": [ 432 | "[[RMS94]](https://python.quantecon.org/zreferences.html#rosen1994cattle) use the model to understand the\n", 433 | "sources of recurrent cycles in total cattle stocks.\n", 434 | "\n", 435 | "Plotting $ y_t $ for a simulation of their model shows its ability\n", 436 | "to generate cycles in quantities" 437 | ] 438 | }, 439 | { 440 | "cell_type": "code", 441 | "execution_count": null, 442 | "metadata": { 443 | "hide-output": false 444 | }, 445 | "outputs": [], 446 | "source": [ 447 | "# Calculation of y_t\n", 448 | "totalstock = econ1.k[0] + g * econ1.k[1] + g * econ1.k[2]\n", 449 | "fig, ax = plt.subplots()\n", 450 | "ax.plot(totalstock)\n", 451 | "ax.set_xlim((-1, 100))\n", 452 | "ax.set_title('Total number of cattle')\n", 453 | "plt.show()" 454 | ] 455 | }, 456 | { 457 | "cell_type": "markdown", 458 | "metadata": {}, 459 | "source": [ 460 | "In their Figure 3, [[RMS94]](https://python.quantecon.org/zreferences.html#rosen1994cattle) plot the impulse response functions\n", 461 | "of consumption and the breeding stock of cattle to the demand shock,\n", 462 | "$ \\tilde d_t $, under the three different values of $ \\rho_3 $.\n", 463 | "\n", 464 | "We replicate their Figure 3 below" 465 | ] 466 | }, 467 | { 468 | "cell_type": "code", 469 | "execution_count": null, 470 | "metadata": { 471 | "hide-output": false 472 | }, 473 | "outputs": [], 474 | "source": [ 475 | "shock_demand = np.array([[0], [0], [1]])\n", 476 | "\n", 477 | "econ1.irf(ts_length=25, shock=shock_demand)\n", 478 | "econ2.irf(ts_length=25, shock=shock_demand)\n", 479 | "econ3.irf(ts_length=25, shock=shock_demand)\n", 480 | "\n", 481 | "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))\n", 482 | "ax1.plot(econ1.c_irf, label='$\\\\rho=0.6$')\n", 483 | "ax1.plot(econ2.c_irf, label='$\\\\rho=1$')\n", 484 | "ax1.plot(econ3.c_irf, label='$\\\\rho=0$')\n", 485 | "ax1.set_title('Consumption response to demand shock')\n", 486 | "ax1.legend()\n", 487 | "\n", 488 | "ax2.plot(econ1.k_irf[:, 0], label='$\\\\rho=0.6$')\n", 489 | "ax2.plot(econ2.k_irf[:, 0], label='$\\\\rho=1$')\n", 490 | "ax2.plot(econ3.k_irf[:, 0], label='$\\\\rho=0$')\n", 491 | "ax2.set_title('Breeding stock response to demand shock')\n", 492 | "ax2.legend()\n", 493 | "plt.show()" 494 | ] 495 | }, 496 | { 497 | "cell_type": "markdown", 498 | "metadata": {}, 499 | "source": [ 500 | "The above figures show how consumption patterns differ markedly,\n", 501 | "depending on the persistence of the demand shock:\n", 502 | "\n", 503 | "- If it is purely transitory ($ \\rho_3 = 0 $) then consumption\n", 504 | " rises immediately but is later reduced to build stocks up again. \n", 505 | "- If it is permanent ($ \\rho_3 = 1 $), then consumption falls\n", 506 | " immediately, in order to build up stocks to satisfy the permanent\n", 507 | " rise in future demand. \n", 508 | "\n", 509 | "\n", 510 | "In Figure 4 of their paper, [[RMS94]](https://python.quantecon.org/zreferences.html#rosen1994cattle) plot the response to a demand shock\n", 511 | "of the breeding stock *and* the total stock, for $ \\rho_3 = 0 $ and\n", 512 | "$ \\rho_3 = 0.6 $.\n", 513 | "\n", 514 | "We replicate their Figure 4 below" 515 | ] 516 | }, 517 | { 518 | "cell_type": "code", 519 | "execution_count": null, 520 | "metadata": { 521 | "hide-output": false 522 | }, 523 | "outputs": [], 524 | "source": [ 525 | "total1_irf = econ1.k_irf[:, 0] + g * econ1.k_irf[:, 1] + g * econ1.k_irf[:, 2]\n", 526 | "total3_irf = econ3.k_irf[:, 0] + g * econ3.k_irf[:, 1] + g * econ3.k_irf[:, 2]\n", 527 | "\n", 528 | "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))\n", 529 | "ax1.plot(econ1.k_irf[:, 0], label='Breeding Stock')\n", 530 | "ax1.plot(total1_irf, label='Total Stock')\n", 531 | "ax1.set_title('$\\\\rho=0.6$')\n", 532 | "\n", 533 | "ax2.plot(econ3.k_irf[:, 0], label='Breeding Stock')\n", 534 | "ax2.plot(total3_irf, label='Total Stock')\n", 535 | "ax2.set_title('$\\\\rho=0$')\n", 536 | "plt.show()" 537 | ] 538 | }, 539 | { 540 | "cell_type": "markdown", 541 | "metadata": {}, 542 | "source": [ 543 | "The fact that $ y_t $ is a weighted moving average of $ x_t $\n", 544 | "creates a humped shape response of the total stock in response to demand\n", 545 | "shocks, contributing to the cyclicality seen in the first graph of this\n", 546 | "lecture." 547 | ] 548 | } 549 | ], 550 | "metadata": { 551 | "date": 1584334734.8176475, 552 | "filename": "cattle_cycles.rst", 553 | "kernelspec": { 554 | "display_name": "Python", 555 | "language": "python3", 556 | "name": "python3" 557 | }, 558 | "title": "Cattle Cycles" 559 | }, 560 | "nbformat": 4, 561 | "nbformat_minor": 2 562 | } -------------------------------------------------------------------------------- /debugging.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "
\n", 10 | " \n", 11 | " \"QuantEcon\"\n", 12 | " \n", 13 | "
" 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "metadata": {}, 19 | "source": [ 20 | "# Debugging\n", 21 | "\n", 22 | "\n", 23 | "" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "## Contents\n", 31 | "\n", 32 | "- [Debugging](#Debugging) \n", 33 | " - [Overview](#Overview) \n", 34 | " - [Debugging](#Debugging) \n", 35 | " - [Other Useful Magics](#Other-Useful-Magics) " 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "> “Debugging is twice as hard as writing the code in the first place.\n", 43 | "> Therefore, if you write the code as cleverly as possible, you are, by definition,\n", 44 | "> not smart enough to debug it.” – Brian Kernighan" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "## Overview\n", 52 | "\n", 53 | "Are you one of those programmers who fills their code with `print` statements when trying to debug their programs?\n", 54 | "\n", 55 | "Hey, we all used to do that.\n", 56 | "\n", 57 | "(OK, sometimes we still do that…)\n", 58 | "\n", 59 | "But once you start writing larger programs you’ll need a better system.\n", 60 | "\n", 61 | "Debugging tools for Python vary across platforms, IDEs and editors.\n", 62 | "\n", 63 | "Here we’ll focus on Jupyter and leave you to explore other settings.\n", 64 | "\n", 65 | "We’ll need the following imports" 66 | ] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": null, 71 | "metadata": { 72 | "hide-output": false 73 | }, 74 | "outputs": [], 75 | "source": [ 76 | "import numpy as np\n", 77 | "import matplotlib.pyplot as plt\n", 78 | "%matplotlib inline" 79 | ] 80 | }, 81 | { 82 | "cell_type": "markdown", 83 | "metadata": {}, 84 | "source": [ 85 | "## Debugging\n", 86 | "\n", 87 | "\n", 88 | "" 89 | ] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "metadata": {}, 94 | "source": [ 95 | "### The `debug` Magic\n", 96 | "\n", 97 | "Let’s consider a simple (and rather contrived) example" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": null, 103 | "metadata": { 104 | "hide-output": false 105 | }, 106 | "outputs": [], 107 | "source": [ 108 | "def plot_log():\n", 109 | " fig, ax = plt.subplots(2, 1)\n", 110 | " x = np.linspace(1, 2, 10)\n", 111 | " ax.plot(x, np.log(x))\n", 112 | " plt.show()\n", 113 | "\n", 114 | "plot_log() # Call the function, generate plot" 115 | ] 116 | }, 117 | { 118 | "cell_type": "markdown", 119 | "metadata": {}, 120 | "source": [ 121 | "This code is intended to plot the `log` function over the interval $ [1, 2] $.\n", 122 | "\n", 123 | "But there’s an error here: `plt.subplots(2, 1)` should be just `plt.subplots()`.\n", 124 | "\n", 125 | "(The call `plt.subplots(2, 1)` returns a NumPy array containing two axes objects, suitable for having two subplots on the same figure)\n", 126 | "\n", 127 | "The traceback shows that the error occurs at the method call `ax.plot(x, np.log(x))`.\n", 128 | "\n", 129 | "The error occurs because we have mistakenly made `ax` a NumPy array, and a NumPy array has no `plot` method.\n", 130 | "\n", 131 | "But let’s pretend that we don’t understand this for the moment.\n", 132 | "\n", 133 | "We might suspect there’s something wrong with `ax` but when we try to investigate this object, we get the following exception:" 134 | ] 135 | }, 136 | { 137 | "cell_type": "code", 138 | "execution_count": null, 139 | "metadata": { 140 | "hide-output": false 141 | }, 142 | "outputs": [], 143 | "source": [ 144 | "ax" 145 | ] 146 | }, 147 | { 148 | "cell_type": "markdown", 149 | "metadata": {}, 150 | "source": [ 151 | "The problem is that `ax` was defined inside `plot_log()`, and the name is\n", 152 | "lost once that function terminates.\n", 153 | "\n", 154 | "Let’s try doing it a different way.\n", 155 | "\n", 156 | "We run the first cell block again, generating the same error" 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": null, 162 | "metadata": { 163 | "hide-output": false 164 | }, 165 | "outputs": [], 166 | "source": [ 167 | "def plot_log():\n", 168 | " fig, ax = plt.subplots(2, 1)\n", 169 | " x = np.linspace(1, 2, 10)\n", 170 | " ax.plot(x, np.log(x))\n", 171 | " plt.show()\n", 172 | "\n", 173 | "plot_log() # Call the function, generate plot" 174 | ] 175 | }, 176 | { 177 | "cell_type": "markdown", 178 | "metadata": {}, 179 | "source": [ 180 | "But this time we type in the following cell block" 181 | ] 182 | }, 183 | { 184 | "cell_type": "markdown", 185 | "metadata": { 186 | "hide-output": false 187 | }, 188 | "source": [ 189 | "```ipython\n", 190 | "%debug\n", 191 | "```\n" 192 | ] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "metadata": {}, 197 | "source": [ 198 | "You should be dropped into a new prompt that looks something like this" 199 | ] 200 | }, 201 | { 202 | "cell_type": "markdown", 203 | "metadata": { 204 | "hide-output": false 205 | }, 206 | "source": [ 207 | "```ipython\n", 208 | "ipdb>\n", 209 | "```\n" 210 | ] 211 | }, 212 | { 213 | "cell_type": "markdown", 214 | "metadata": {}, 215 | "source": [ 216 | "(You might see pdb> instead)\n", 217 | "\n", 218 | "Now we can investigate the value of our variables at this point in the program, step forward through the code, etc.\n", 219 | "\n", 220 | "For example, here we simply type the name `ax` to see what’s happening with\n", 221 | "this object:" 222 | ] 223 | }, 224 | { 225 | "cell_type": "markdown", 226 | "metadata": { 227 | "hide-output": false 228 | }, 229 | "source": [ 230 | "```ipython\n", 231 | "ipdb> ax\n", 232 | "array([,\n", 233 | " ], dtype=object)\n", 234 | "```\n" 235 | ] 236 | }, 237 | { 238 | "cell_type": "markdown", 239 | "metadata": {}, 240 | "source": [ 241 | "It’s now very clear that `ax` is an array, which clarifies the source of the\n", 242 | "problem.\n", 243 | "\n", 244 | "To find out what else you can do from inside `ipdb` (or `pdb`), use the\n", 245 | "online help" 246 | ] 247 | }, 248 | { 249 | "cell_type": "markdown", 250 | "metadata": { 251 | "hide-output": false 252 | }, 253 | "source": [ 254 | "```ipython\n", 255 | "ipdb> h\n", 256 | "\n", 257 | "Documented commands (type help ):\n", 258 | "========================================\n", 259 | "EOF bt cont enable jump pdef r tbreak w\n", 260 | "a c continue exit l pdoc restart u whatis\n", 261 | "alias cl d h list pinfo return unalias where\n", 262 | "args clear debug help n pp run unt\n", 263 | "b commands disable ignore next q s until\n", 264 | "break condition down j p quit step up\n", 265 | "\n", 266 | "Miscellaneous help topics:\n", 267 | "==========================\n", 268 | "exec pdb\n", 269 | "\n", 270 | "Undocumented commands:\n", 271 | "======================\n", 272 | "retval rv\n", 273 | "\n", 274 | "ipdb> h c\n", 275 | "c(ont(inue))\n", 276 | "Continue execution, only stop when a breakpoint is encountered.\n", 277 | "```\n" 278 | ] 279 | }, 280 | { 281 | "cell_type": "markdown", 282 | "metadata": {}, 283 | "source": [ 284 | "### Setting a Break Point\n", 285 | "\n", 286 | "The preceding approach is handy but sometimes insufficient.\n", 287 | "\n", 288 | "Consider the following modified version of our function above" 289 | ] 290 | }, 291 | { 292 | "cell_type": "code", 293 | "execution_count": null, 294 | "metadata": { 295 | "hide-output": false 296 | }, 297 | "outputs": [], 298 | "source": [ 299 | "def plot_log():\n", 300 | " fig, ax = plt.subplots()\n", 301 | " x = np.logspace(1, 2, 10)\n", 302 | " ax.plot(x, np.log(x))\n", 303 | " plt.show()\n", 304 | "\n", 305 | "plot_log()" 306 | ] 307 | }, 308 | { 309 | "cell_type": "markdown", 310 | "metadata": {}, 311 | "source": [ 312 | "Here the original problem is fixed, but we’ve accidentally written\n", 313 | "`np.logspace(1, 2, 10)` instead of `np.linspace(1, 2, 10)`.\n", 314 | "\n", 315 | "Now there won’t be any exception, but the plot won’t look right.\n", 316 | "\n", 317 | "To investigate, it would be helpful if we could inspect variables like `x` during execution of the function.\n", 318 | "\n", 319 | "To this end, we add a “break point” by inserting `breakpoint()` inside the function code block" 320 | ] 321 | }, 322 | { 323 | "cell_type": "markdown", 324 | "metadata": { 325 | "hide-output": false 326 | }, 327 | "source": [ 328 | "```python3\n", 329 | "def plot_log():\n", 330 | " breakpoint()\n", 331 | " fig, ax = plt.subplots()\n", 332 | " x = np.logspace(1, 2, 10)\n", 333 | " ax.plot(x, np.log(x))\n", 334 | " plt.show()\n", 335 | "\n", 336 | "plot_log()\n", 337 | "```\n" 338 | ] 339 | }, 340 | { 341 | "cell_type": "markdown", 342 | "metadata": {}, 343 | "source": [ 344 | "Now let’s run the script, and investigate via the debugger" 345 | ] 346 | }, 347 | { 348 | "cell_type": "markdown", 349 | "metadata": { 350 | "hide-output": false 351 | }, 352 | "source": [ 353 | "```ipython\n", 354 | "> (6)plot_log()\n", 355 | "-> fig, ax = plt.subplots()\n", 356 | "(Pdb) n\n", 357 | "> (7)plot_log()\n", 358 | "-> x = np.logspace(1, 2, 10)\n", 359 | "(Pdb) n\n", 360 | "> (8)plot_log()\n", 361 | "-> ax.plot(x, np.log(x))\n", 362 | "(Pdb) x\n", 363 | "array([ 10. , 12.91549665, 16.68100537, 21.5443469 ,\n", 364 | " 27.82559402, 35.93813664, 46.41588834, 59.94842503,\n", 365 | " 77.42636827, 100. ])\n", 366 | "```\n" 367 | ] 368 | }, 369 | { 370 | "cell_type": "markdown", 371 | "metadata": {}, 372 | "source": [ 373 | "We used `n` twice to step forward through the code (one line at a time).\n", 374 | "\n", 375 | "Then we printed the value of `x` to see what was happening with that variable.\n", 376 | "\n", 377 | "To exit from the debugger, use `q`." 378 | ] 379 | }, 380 | { 381 | "cell_type": "markdown", 382 | "metadata": {}, 383 | "source": [ 384 | "## Other Useful Magics\n", 385 | "\n", 386 | "In this lecture, we used the `%debug` IPython magic.\n", 387 | "\n", 388 | "There are many other useful magics:\n", 389 | "\n", 390 | "- `%precision 4` sets printed precision for floats to 4 decimal places \n", 391 | "- `%whos` gives a list of variables and their values \n", 392 | "- `%quickref` gives a list of magics \n", 393 | "\n", 394 | "\n", 395 | "The full list of magics is [here](http://ipython.readthedocs.org/en/stable/interactive/magics.html)." 396 | ] 397 | } 398 | ], 399 | "metadata": { 400 | "date": 1584334736.3417926, 401 | "filename": "debugging.rst", 402 | "kernelspec": { 403 | "display_name": "Python", 404 | "language": "python3", 405 | "name": "python3" 406 | }, 407 | "title": "Debugging" 408 | }, 409 | "nbformat": 4, 410 | "nbformat_minor": 2 411 | } -------------------------------------------------------------------------------- /hs_invertibility_example.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "
\n", 10 | " \n", 11 | " \"QuantEcon\"\n", 12 | " \n", 13 | "
\n", 14 | "\n", 15 | "\n", 16 | "" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# Shock Non Invertibility" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "## Contents\n", 31 | "\n", 32 | "- [Shock Non Invertibility](#Shock-Non-Invertibility) \n", 33 | " - [Overview](#Overview) \n", 34 | " - [Model](#Model) \n", 35 | " - [Code](#Code) " 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "## Overview\n", 43 | "\n", 44 | "This is another member of a suite of lectures that use the quantecon DLE class to instantiate models within the\n", 45 | "[[HS13b]](https://python.quantecon.org/zreferences.html#hs2013) class of models described in detail in [Recursive Models of Dynamic Linear Economies](https://python.quantecon.org/hs_recursive_models.html).\n", 46 | "\n", 47 | "In addition to what’s in Anaconda, this lecture uses the quantecon library." 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": { 54 | "hide-output": true 55 | }, 56 | "outputs": [], 57 | "source": [ 58 | "!pip install --upgrade quantecon" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "metadata": {}, 64 | "source": [ 65 | "We’ll make these imports:" 66 | ] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": null, 71 | "metadata": { 72 | "hide-output": false 73 | }, 74 | "outputs": [], 75 | "source": [ 76 | "import numpy as np\n", 77 | "import quantecon as qe\n", 78 | "import matplotlib.pyplot as plt\n", 79 | "from quantecon import LQ\n", 80 | "from quantecon import DLE\n", 81 | "from math import sqrt\n", 82 | "%matplotlib inline" 83 | ] 84 | }, 85 | { 86 | "cell_type": "markdown", 87 | "metadata": {}, 88 | "source": [ 89 | "This lecture can be viewed as introducing an early contribution to what is now often called\n", 90 | "a **news and noise** issue.\n", 91 | "\n", 92 | "In particular, it analyzes a **shock-invertibility** issue that is\n", 93 | "endemic within a class of permanent income models.\n", 94 | "\n", 95 | "Technically, the invertibility problem indicates a situation in which\n", 96 | "histories of the shocks in an econometrician’s autoregressive or Wold\n", 97 | "moving average representation span a smaller information space than do\n", 98 | "the shocks that are seen by the agents inside the econometrician’s model.\n", 99 | "\n", 100 | "This situation sets the stage for an econometrician who is unaware of the\n", 101 | "problem and consequently misinterprets shocks and likely responses to them.\n", 102 | "\n", 103 | "A shock-invertibility that is technically close to the one studied here is discussed by\n", 104 | "Eric Leeper, Todd Walker, and Susan Yang [[LWY13]](https://python.quantecon.org/zreferences.html#leeper-walker-yang) in their analysis of **fiscal foresight**.\n", 105 | "\n", 106 | "A distinct shock-invertibility issue is present in the special LQ consumption smoothing model\n", 107 | "in [quantecon lecture](https://python.quantecon.org/cons_news.html)." 108 | ] 109 | }, 110 | { 111 | "cell_type": "markdown", 112 | "metadata": {}, 113 | "source": [ 114 | "## Model\n", 115 | "\n", 116 | "We consider the following modification of Robert Hall’s (1978) model [[Hal78]](https://python.quantecon.org/zreferences.html#hall1978) in which the endowment process is the sum of two orthogonal autoregressive processes:\n", 117 | "\n", 118 | "**Preferences**\n", 119 | "\n", 120 | "$$\n", 121 | "-\\frac{1}{2}\\mathbb{E}\\sum_{t=0}^\\infty \\beta^t[(c_t - b_t)^2 + l_t^2]|J_0\n", 122 | "$$\n", 123 | "\n", 124 | "$$\n", 125 | "s_t = c_t\n", 126 | "$$\n", 127 | "\n", 128 | "$$\n", 129 | "b_t = U_bz_t\n", 130 | "$$\n", 131 | "\n", 132 | "**Technology**\n", 133 | "\n", 134 | "$$\n", 135 | "c_t + i_t = \\gamma k_{t-1} + d_t\n", 136 | "$$\n", 137 | "\n", 138 | "$$\n", 139 | "k_t = \\delta_k k_{t-1} + i_t\n", 140 | "$$\n", 141 | "\n", 142 | "$$\n", 143 | "g_t = \\phi_1 i_t \\, , \\phi_1 > 0\n", 144 | "$$\n", 145 | "\n", 146 | "$$\n", 147 | "g_t \\cdot g_t = l_t^2\n", 148 | "$$\n", 149 | "\n", 150 | "**Information**\n", 151 | "\n", 152 | "$$\n", 153 | "z_{t+1} =\n", 154 | "\\left[ {\\begin{array}{cccccc}\n", 155 | " 1 & 0 & 0 & 0 & 0 & 0 \\\\ 0 & 0.9 & 0 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & 0 & 0 & 0 \\\\ 0 & 0 & 1 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & 1 & 0 & 0 \\\\ 0 & 0 & 0 & 0 & 1 & 0\n", 156 | " \\end{array} }\n", 157 | " \\right]\n", 158 | " z_t +\n", 159 | " \\left[ {\\begin{array}{cc}\n", 160 | " 0 & 0 \\\\ 1 & 0 \\\\ 0 & 4 \\\\ 0 & 0 \\\\ 0 & 0 \\\\ 0 & 0\n", 161 | " \\end{array} }\n", 162 | " \\right]\n", 163 | " w_{t+1}\n", 164 | "$$\n", 165 | "\n", 166 | "$$\n", 167 | "U_b =\n", 168 | " \\left[ {\\begin{array}{cccccc}\n", 169 | " 30 & 0 & 0 & 0 & 0 & 0\n", 170 | " \\end{array} }\n", 171 | " \\right]\n", 172 | "$$\n", 173 | "\n", 174 | "$$\n", 175 | "U_d =\n", 176 | " \\left[ {\\begin{array}{cccccc}\n", 177 | " 5 & 1 & 1 & 0.8 & 0.6 & 0.4 \\\\ 0 & 0 & 0 & 0 & 0 & 0\n", 178 | " \\end{array} }\n", 179 | " \\right]\n", 180 | "$$\n", 181 | "\n", 182 | "The preference shock is constant at 30, while the endowment process is\n", 183 | "the sum of a constant and two orthogonal processes.\n", 184 | "\n", 185 | "Specifically:\n", 186 | "\n", 187 | "$$\n", 188 | "d_t = 5 + d_{1t} + d_{2t}\n", 189 | "$$\n", 190 | "\n", 191 | "$$\n", 192 | "d_{1t} = 0.9d_{1t-1} + w_{1t}\n", 193 | "$$\n", 194 | "\n", 195 | "$$\n", 196 | "d_{2t} = 4w_{2t} + 0.8(4w_{2t-1})+ 0.6(4w_{2t-2})+ 0.4(4w_{2t-3})\n", 197 | "$$\n", 198 | "\n", 199 | "$ d_{1t} $ is a first-order AR process, while $ d_{2t} $ is a\n", 200 | "third-order pure moving average process." 201 | ] 202 | }, 203 | { 204 | "cell_type": "code", 205 | "execution_count": null, 206 | "metadata": { 207 | "hide-output": false 208 | }, 209 | "outputs": [], 210 | "source": [ 211 | "γ_1 = 0.05\n", 212 | "γ = np.array([[γ_1], [0]])\n", 213 | "ϕ_c = np.array([[1], [0]])\n", 214 | "ϕ_g = np.array([[0], [1]])\n", 215 | "ϕ_1 = 0.00001\n", 216 | "ϕ_i = np.array([[1], [-ϕ_1]])\n", 217 | "δ_k = np.array([[1]])\n", 218 | "θ_k = np.array([[1]])\n", 219 | "β = np.array([[1 / 1.05]])\n", 220 | "l_λ = np.array([[0]])\n", 221 | "π_h = np.array([[1]])\n", 222 | "δ_h = np.array([[.9]])\n", 223 | "θ_h = np.array([[1]]) - δ_h\n", 224 | "ud = np.array([[5, 1, 1, 0.8, 0.6, 0.4],\n", 225 | " [0, 0, 0, 0, 0, 0]])\n", 226 | "a22 = np.zeros((6, 6))\n", 227 | "# Chase's great trick\n", 228 | "a22[[0, 1, 3, 4, 5], [0, 1, 2, 3, 4]] = np.array([1.0, 0.9, 1.0, 1.0, 1.0])\n", 229 | "c2 = np.zeros((6, 2))\n", 230 | "c2[[1, 2], [0, 1]] = np.array([1.0, 4.0])\n", 231 | "ub = np.array([[30, 0, 0, 0, 0, 0]])\n", 232 | "x0 = np.array([[5], [150], [1], [0], [0], [0], [0], [0]])\n", 233 | "\n", 234 | "info1 = (a22, c2, ub, ud)\n", 235 | "tech1 = (ϕ_c, ϕ_g, ϕ_i, γ, δ_k, θ_k)\n", 236 | "pref1 = (β, l_λ, π_h, δ_h, θ_h)\n", 237 | "\n", 238 | "econ1 = DLE(info1, tech1, pref1)" 239 | ] 240 | }, 241 | { 242 | "cell_type": "markdown", 243 | "metadata": {}, 244 | "source": [ 245 | "We define the household’s net of interest deficit as $ c_t - d_t $.\n", 246 | "\n", 247 | "Hall’s model imposes “expected present-value budget balance” in the\n", 248 | "sense that\n", 249 | "\n", 250 | "$$\n", 251 | "\\mathbb{E}\\sum_{j=0}^\\infty \\beta^j (c_{t+j} - d_{t+j})|J_t = \\beta^{-1}k_{t-1} \\, \\forall t\n", 252 | "$$\n", 253 | "\n", 254 | "If we define the moving average representation of\n", 255 | "$ (c_t, c_t - d_t) $ in terms of the $ w_t $s to be:\n", 256 | "\n", 257 | "$$\n", 258 | "\\left[ {\\begin{array}{c}\n", 259 | " c_t \\\\ c_t - d_t\n", 260 | " \\end{array} }\n", 261 | " \\right] = \\left[ {\\begin{array}{c}\n", 262 | " \\sigma_1(L) \\\\ \\sigma_2(L)\n", 263 | " \\end{array} }\n", 264 | " \\right] w_t\n", 265 | "$$\n", 266 | "\n", 267 | "then Hall’s model imposes the restriction\n", 268 | "$ \\sigma_2(\\beta) = [0\\,\\,\\,0] $.\n", 269 | "\n", 270 | "The agent inside this model sees histories of both components of the\n", 271 | "endowment process $ d_{1t} $ and $ d_{2t} $.\n", 272 | "\n", 273 | "The econometrician has data on the history of the pair\n", 274 | "$ [c_t,d_t] $, but not directly on the history of $ w_t $.\n", 275 | "\n", 276 | "The econometrician obtains a Wold representation for the process\n", 277 | "$ [c_t,c_t-d_t] $:\n", 278 | "\n", 279 | "$$\n", 280 | "\\left[ {\\begin{array}{c}\n", 281 | " c_t \\\\ c_t - d_t\n", 282 | " \\end{array} }\n", 283 | " \\right] = \\left[ {\\begin{array}{c}\n", 284 | " \\sigma_1^*(L) \\\\ \\sigma_2^*(L)\n", 285 | " \\end{array} }\n", 286 | " \\right] u_t\n", 287 | "$$\n", 288 | "\n", 289 | "The Appendix of chapter 8 of [[HS13b]](https://python.quantecon.org/zreferences.html#hs2013) explains why the impulse\n", 290 | "response functions in the Wold representation estimated by the\n", 291 | "econometrician do not resemble the impulse response functions that\n", 292 | "depict the response of consumption and the deficit to innovations to\n", 293 | "agents’ information.\n", 294 | "\n", 295 | "Technically, $ \\sigma_2(\\beta) = [0\\,\\,\\,0] $ implies that the\n", 296 | "history of $ u_t $s spans a *smaller* linear space than does the\n", 297 | "history of $ w_t $s.\n", 298 | "\n", 299 | "This means that $ u_t $ will typically be a distributed lag of\n", 300 | "$ w_t $ that is not concentrated at zero lag:\n", 301 | "\n", 302 | "$$\n", 303 | "u_t = \\sum_{j=0}^\\infty \\alpha_j w_{t-j}\n", 304 | "$$\n", 305 | "\n", 306 | "Thus, the econometrician’s news $ u_t $ potentially responds\n", 307 | "belatedly to agents’ news $ w_t $." 308 | ] 309 | }, 310 | { 311 | "cell_type": "markdown", 312 | "metadata": {}, 313 | "source": [ 314 | "## Code\n", 315 | "\n", 316 | "We will construct Figures from Chapter 8 Appendix E of [[HS13b]](https://python.quantecon.org/zreferences.html#hs2013) to\n", 317 | "illustrate these ideas:" 318 | ] 319 | }, 320 | { 321 | "cell_type": "code", 322 | "execution_count": null, 323 | "metadata": { 324 | "hide-output": false 325 | }, 326 | "outputs": [], 327 | "source": [ 328 | "# This is Fig 8.E.1 from p.188 of HS2013\n", 329 | "\n", 330 | "econ1.irf(ts_length=40, shock=None)\n", 331 | "\n", 332 | "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))\n", 333 | "ax1.plot(econ1.c_irf, label='Consumption')\n", 334 | "ax1.plot(econ1.c_irf - econ1.d_irf[:,0].reshape(40,1), label='Deficit')\n", 335 | "ax1.legend()\n", 336 | "ax1.set_title('Response to $w_{1t}$')\n", 337 | "\n", 338 | "shock2 = np.array([[0], [1]])\n", 339 | "econ1.irf(ts_length=40, shock=shock2)\n", 340 | "\n", 341 | "ax2.plot(econ1.c_irf, label='Consumption')\n", 342 | "ax2.plot(econ1.c_irf - econ1.d_irf[:,0].reshape(40, 1), label='Deficit')\n", 343 | "ax2.legend()\n", 344 | "ax2.set_title('Response to $w_{2t}$')\n", 345 | "plt.show()" 346 | ] 347 | }, 348 | { 349 | "cell_type": "markdown", 350 | "metadata": {}, 351 | "source": [ 352 | "The above figure displays the impulse response of consumption and the\n", 353 | "deficit to the endowment innovations.\n", 354 | "\n", 355 | "Consumption displays the characteristic “random walk” response with\n", 356 | "respect to each innovation.\n", 357 | "\n", 358 | "Each endowment innovation leads to a\n", 359 | "temporary surplus followed by a permanent net-of-interest deficit.\n", 360 | "\n", 361 | "The temporary surplus just offsets the permanent deficit in terms of\n", 362 | "expected present value." 363 | ] 364 | }, 365 | { 366 | "cell_type": "code", 367 | "execution_count": null, 368 | "metadata": { 369 | "hide-output": false 370 | }, 371 | "outputs": [], 372 | "source": [ 373 | "G_HS = np.vstack([econ1.Sc, econ1.Sc-econ1.Sd[0, :].reshape(1, 8)])\n", 374 | "H_HS = 1e-8 * np.eye(2) # Set very small so there is no measurement error\n", 375 | "lss_hs = qe.LinearStateSpace(econ1.A0, econ1.C, G_HS, H_HS)\n", 376 | "\n", 377 | "hs_kal = qe.Kalman(lss_hs)\n", 378 | "w_lss = hs_kal.whitener_lss()\n", 379 | "ma_coefs = hs_kal.stationary_coefficients(50, 'ma')\n", 380 | "\n", 381 | "# This is Fig 8.E.2 from p.189 of HS2013\n", 382 | "\n", 383 | "ma_coefs = ma_coefs\n", 384 | "jj = 50\n", 385 | "y1_w1 = np.empty(jj)\n", 386 | "y2_w1 = np.empty(jj)\n", 387 | "y1_w2 = np.empty(jj)\n", 388 | "y2_w2 = np.empty(jj)\n", 389 | "\n", 390 | "for t in range(jj):\n", 391 | " y1_w1[t] = ma_coefs[t][0, 0]\n", 392 | " y1_w2[t] = ma_coefs[t][0, 1]\n", 393 | " y2_w1[t] = ma_coefs[t][1, 0]\n", 394 | " y2_w2[t] = ma_coefs[t][1, 1]\n", 395 | "\n", 396 | "# This scales the impulse responses to match those in the book\n", 397 | "y1_w1 = sqrt(hs_kal.stationary_innovation_covar()[0, 0]) * y1_w1\n", 398 | "y2_w1 = sqrt(hs_kal.stationary_innovation_covar()[0, 0]) * y2_w1\n", 399 | "y1_w2 = sqrt(hs_kal.stationary_innovation_covar()[1, 1]) * y1_w2\n", 400 | "y2_w2 = sqrt(hs_kal.stationary_innovation_covar()[1, 1]) * y2_w2\n", 401 | "\n", 402 | "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))\n", 403 | "ax1.plot(y1_w1, label='Consumption')\n", 404 | "ax1.plot(y2_w1, label='Deficit')\n", 405 | "ax1.legend()\n", 406 | "ax1.set_title('Response to $u_{1t}$')\n", 407 | "\n", 408 | "ax2.plot(y1_w2, label='Consumption')\n", 409 | "ax2.plot(y2_w2, label='Deficit')\n", 410 | "ax2.legend()\n", 411 | "ax2.set_title('Response to $u_{2t}$')\n", 412 | "plt.show()" 413 | ] 414 | }, 415 | { 416 | "cell_type": "markdown", 417 | "metadata": {}, 418 | "source": [ 419 | "The above figure displays the impulse response of consumption and the\n", 420 | "deficit to the innovations in the econometrician’s Wold representation\n", 421 | "\n", 422 | "- this is the object that would be recovered from a high order vector\n", 423 | " autoregression on the econometrician’s observations. \n", 424 | "\n", 425 | "\n", 426 | "Consumption responds only to the first innovation\n", 427 | "\n", 428 | "- this is indicative of the Granger causality imposed on the\n", 429 | " $ [c_t, c_t - d_t] $ process by Hall’s model: consumption Granger\n", 430 | " causes $ c_t - d_t $, with no reverse causality. " 431 | ] 432 | }, 433 | { 434 | "cell_type": "code", 435 | "execution_count": null, 436 | "metadata": { 437 | "hide-output": false 438 | }, 439 | "outputs": [], 440 | "source": [ 441 | "# This is Fig 8.E.3 from p.189 of HS2013\n", 442 | "\n", 443 | "jj = 20\n", 444 | "irf_wlss = w_lss.impulse_response(jj)\n", 445 | "ycoefs = irf_wlss[1]\n", 446 | "# Pull out the shocks\n", 447 | "a1_w1 = np.empty(jj)\n", 448 | "a1_w2 = np.empty(jj)\n", 449 | "a2_w1 = np.empty(jj)\n", 450 | "a2_w2 = np.empty(jj)\n", 451 | "\n", 452 | "for t in range(jj):\n", 453 | " a1_w1[t] = ycoefs[t][0, 0]\n", 454 | " a1_w2[t] = ycoefs[t][0, 1]\n", 455 | " a2_w1[t] = ycoefs[t][1, 0]\n", 456 | " a2_w2[t] = ycoefs[t][1, 1]\n", 457 | "\n", 458 | "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))\n", 459 | "ax1.plot(a1_w1, label='Consumption innov.')\n", 460 | "ax1.plot(a2_w1, label='Deficit innov.')\n", 461 | "ax1.set_title('Response to $w_{1t}$')\n", 462 | "ax1.legend()\n", 463 | "ax2.plot(a1_w2, label='Consumption innov.')\n", 464 | "ax2.plot(a2_w2, label='Deficit innov.')\n", 465 | "ax2.legend()\n", 466 | "ax2.set_title('Response to $w_{2t}$')\n", 467 | "plt.show()" 468 | ] 469 | }, 470 | { 471 | "cell_type": "markdown", 472 | "metadata": {}, 473 | "source": [ 474 | "The above figure displays the impulse responses of $ u_t $ to\n", 475 | "$ w_t $, as depicted in:\n", 476 | "\n", 477 | "$$\n", 478 | "u_t = \\sum_{j=0}^\\infty \\alpha_j w_{t-j}\n", 479 | "$$\n", 480 | "\n", 481 | "While the responses of the innovations to consumption are concentrated\n", 482 | "at lag zero for both components of $ w_t $, the responses of the\n", 483 | "innovations to $ (c_t - d_t) $ are spread over time (especially in\n", 484 | "response to $ w_{1t} $).\n", 485 | "\n", 486 | "Thus, the innovations to $ (c_t - d_t) $ as revealed by the vector\n", 487 | "autoregression depend on what the economic agent views as “old news”." 488 | ] 489 | } 490 | ], 491 | "metadata": { 492 | "date": 1584334739.209215, 493 | "filename": "hs_invertibility_example.rst", 494 | "kernelspec": { 495 | "display_name": "Python", 496 | "language": "python3", 497 | "name": "python3" 498 | }, 499 | "title": "Shock Non Invertibility" 500 | }, 501 | "nbformat": 4, 502 | "nbformat_minor": 2 503 | } -------------------------------------------------------------------------------- /irfs_in_hall_model.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "
\n", 10 | " \n", 11 | " \"QuantEcon\"\n", 12 | " \n", 13 | "
\n", 14 | "\n", 15 | "\n", 16 | "" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# IRFs in Hall Models" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "## Contents\n", 31 | "\n", 32 | "- [IRFs in Hall Models](#IRFs-in-Hall-Models) \n", 33 | " - [Example 1: Hall (1978)](#Example-1:-Hall-%281978%29) \n", 34 | " - [Example 2: Higher Adjustment Costs](#Example-2:-Higher-Adjustment-Costs) \n", 35 | " - [Example 3: Durable Consumption Goods](#Example-3:-Durable-Consumption-Goods) " 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "This is another member of a suite of lectures that use the quantecon DLE class to instantiate models within the\n", 43 | "[[HS13b]](https://python.quantecon.org/zreferences.html#hs2013) class of models described in detail in [Recursive Models of Dynamic Linear Economies](https://python.quantecon.org/hs_recursive_models.html).\n", 44 | "\n", 45 | "In addition to what’s in Anaconda, this lecture uses the quantecon library." 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": null, 51 | "metadata": { 52 | "hide-output": true 53 | }, 54 | "outputs": [], 55 | "source": [ 56 | "!pip install --upgrade quantecon" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "We’ll make these imports:" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": null, 69 | "metadata": { 70 | "hide-output": false 71 | }, 72 | "outputs": [], 73 | "source": [ 74 | "import numpy as np\n", 75 | "import matplotlib.pyplot as plt\n", 76 | "%matplotlib inline\n", 77 | "from quantecon import LQ\n", 78 | "from quantecon import DLE" 79 | ] 80 | }, 81 | { 82 | "cell_type": "markdown", 83 | "metadata": {}, 84 | "source": [ 85 | "This lecture shows how the DLE class can be used to create impulse\n", 86 | "response functions for three related economies, starting from\n", 87 | "Hall (1978) [[Hal78]](https://python.quantecon.org/zreferences.html#hall1978).\n", 88 | "\n", 89 | "Knowledge of the basic economic environment is assumed.\n", 90 | "\n", 91 | "See the lecture “Growth in Dynamic Linear Economies” for more details." 92 | ] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "metadata": {}, 97 | "source": [ 98 | "## Example 1: Hall (1978)\n", 99 | "\n", 100 | "First, we set parameters to make consumption (almost) follow a random\n", 101 | "walk.\n", 102 | "\n", 103 | "We set\n", 104 | "\n", 105 | "$$\n", 106 | "\\lambda = 0, \\pi = 1, \\gamma_1 = 0.1, \\phi_1 = 0.00001, \\delta_k = 0.95, \\beta = \\frac{1}{1.05}\n", 107 | "$$\n", 108 | "\n", 109 | "(In this example $ \\delta_h $ and $ \\theta_h $ are arbitrary as\n", 110 | "household capital does not enter the equation for consumption services.\n", 111 | "\n", 112 | "We set them to values that will become useful in Example 3)\n", 113 | "\n", 114 | "It is worth noting that this choice of parameter values ensures that\n", 115 | "$ \\beta(\\gamma_1 + \\delta_k) = 1 $.\n", 116 | "\n", 117 | "For simulations of this economy, we choose an initial condition of:\n", 118 | "\n", 119 | "$$\n", 120 | "x_0 =\n", 121 | " \\left[ {\\begin{array}{ccccc}\n", 122 | " 5 & 150 & 1 & 0 & 0\n", 123 | " \\end{array} }\n", 124 | " \\right]'\n", 125 | "$$" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": null, 131 | "metadata": { 132 | "hide-output": false 133 | }, 134 | "outputs": [], 135 | "source": [ 136 | "γ_1 = 0.1\n", 137 | "γ = np.array([[γ_1], [0]])\n", 138 | "ϕ_c = np.array([[1], [0]])\n", 139 | "ϕ_g = np.array([[0], [1]])\n", 140 | "ϕ_1 = 1e-5\n", 141 | "ϕ_i = np.array([[1], [-ϕ_1]])\n", 142 | "δ_k = np.array([[.95]])\n", 143 | "θ_k = np.array([[1]])\n", 144 | "β = np.array([[1 / 1.05]])\n", 145 | "l_λ = np.array([[0]])\n", 146 | "π_h = np.array([[1]])\n", 147 | "δ_h = np.array([[.9]])\n", 148 | "θ_h = np.array([[1]])\n", 149 | "a22 = np.array([[1, 0, 0],\n", 150 | " [0, 0.8, 0],\n", 151 | " [0, 0, 0.5]])\n", 152 | "c2 = np.array([[0, 0],\n", 153 | " [1, 0],\n", 154 | " [0, 1]])\n", 155 | "ud = np.array([[5, 1, 0],\n", 156 | " [0, 0, 0]])\n", 157 | "ub = np.array([[30, 0, 0]])\n", 158 | "x0 = np.array([[5], [150], [1], [0], [0]])\n", 159 | "\n", 160 | "info1 = (a22, c2, ub, ud)\n", 161 | "tech1 = (ϕ_c, ϕ_g, ϕ_i, γ, δ_k, θ_k)\n", 162 | "pref1 = (β, l_λ, π_h, δ_h, θ_h)" 163 | ] 164 | }, 165 | { 166 | "cell_type": "markdown", 167 | "metadata": {}, 168 | "source": [ 169 | "These parameter values are used to define an economy of the DLE class.\n", 170 | "\n", 171 | "We can then simulate the economy for a chosen length of time, from our\n", 172 | "initial state vector $ x_0 $.\n", 173 | "\n", 174 | "The economy stores the simulated values for each variable. Below we plot\n", 175 | "consumption and investment:" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": null, 181 | "metadata": { 182 | "hide-output": false 183 | }, 184 | "outputs": [], 185 | "source": [ 186 | "econ1 = DLE(info1, tech1, pref1)\n", 187 | "econ1.compute_sequence(x0, ts_length=300)\n", 188 | "\n", 189 | "# This is the right panel of Fig 5.7.1 from p.105 of HS2013\n", 190 | "plt.plot(econ1.c[0], label='Cons.')\n", 191 | "plt.plot(econ1.i[0], label='Inv.')\n", 192 | "plt.legend()\n", 193 | "plt.show()" 194 | ] 195 | }, 196 | { 197 | "cell_type": "markdown", 198 | "metadata": {}, 199 | "source": [ 200 | "The DLE class can be used to create impulse response functions for each\n", 201 | "of the endogenous variables: $ \\{c_t,s_t,h_t,i_t,k_t,g_t\\} $.\n", 202 | "\n", 203 | "If no selector vector for the shock is specified, the default choice is\n", 204 | "to give IRFs to the first shock in $ w_{t+1} $.\n", 205 | "\n", 206 | "Below we plot the impulse response functions of investment and\n", 207 | "consumption to an endowment innovation (the first shock) in the Hall\n", 208 | "model:" 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": null, 214 | "metadata": { 215 | "hide-output": false 216 | }, 217 | "outputs": [], 218 | "source": [ 219 | "econ1.irf(ts_length=40, shock=None)\n", 220 | "# This is the left panel of Fig 5.7.1 from p.105 of HS2013\n", 221 | "plt.plot(econ1.c_irf, label='Cons.')\n", 222 | "plt.plot(econ1.i_irf, label='Inv.')\n", 223 | "plt.legend()\n", 224 | "plt.show()" 225 | ] 226 | }, 227 | { 228 | "cell_type": "markdown", 229 | "metadata": {}, 230 | "source": [ 231 | "It can be seen that the endowment shock has permanent effects on the\n", 232 | "level of both consumption and investment, consistent with the endogenous\n", 233 | "unit eigenvalue in this economy.\n", 234 | "\n", 235 | "Investment is much more responsive to the endowment shock at shorter time\n", 236 | "horizons." 237 | ] 238 | }, 239 | { 240 | "cell_type": "markdown", 241 | "metadata": {}, 242 | "source": [ 243 | "## Example 2: Higher Adjustment Costs\n", 244 | "\n", 245 | "We generate our next economy by making only one change to the parameters\n", 246 | "of Example 1: we raise the parameter associated with the cost of\n", 247 | "adjusting capital,$ \\phi_1 $, from 0.00001 to 0.2.\n", 248 | "\n", 249 | "This will lower the endogenous eigenvalue that is unity in Example 1 to\n", 250 | "a value slightly below 1." 251 | ] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "execution_count": null, 256 | "metadata": { 257 | "hide-output": false 258 | }, 259 | "outputs": [], 260 | "source": [ 261 | "ϕ_12 = 0.2\n", 262 | "ϕ_i2 = np.array([[1], [-ϕ_12]])\n", 263 | "tech2 = (ϕ_c, ϕ_g, ϕ_i2, γ, δ_k, θ_k)\n", 264 | "\n", 265 | "econ2 = DLE(info1, tech2, pref1)\n", 266 | "econ2.compute_sequence(x0, ts_length = 300)\n", 267 | "\n", 268 | "# This is the right panel of Fig 5.8.1 from p.106 of HS2013\n", 269 | "plt.plot(econ2.c[0], label='Cons.')\n", 270 | "plt.plot(econ2.i[0], label='Inv.')\n", 271 | "plt.legend()\n", 272 | "plt.show()" 273 | ] 274 | }, 275 | { 276 | "cell_type": "code", 277 | "execution_count": null, 278 | "metadata": { 279 | "hide-output": false 280 | }, 281 | "outputs": [], 282 | "source": [ 283 | "econ2.irf(ts_length=40,shock=None)\n", 284 | "# This is the left panel of Fig 5.8.1 from p.106 of HS2013\n", 285 | "plt.plot(econ2.c_irf,label='Cons.')\n", 286 | "plt.plot(econ2.i_irf,label='Inv.')\n", 287 | "plt.legend()\n", 288 | "plt.show()" 289 | ] 290 | }, 291 | { 292 | "cell_type": "code", 293 | "execution_count": null, 294 | "metadata": { 295 | "hide-output": false 296 | }, 297 | "outputs": [], 298 | "source": [ 299 | "econ2.endo" 300 | ] 301 | }, 302 | { 303 | "cell_type": "code", 304 | "execution_count": null, 305 | "metadata": { 306 | "hide-output": false 307 | }, 308 | "outputs": [], 309 | "source": [ 310 | "econ2.compute_steadystate()\n", 311 | "print(econ2.css, econ2.iss, econ2.kss)" 312 | ] 313 | }, 314 | { 315 | "cell_type": "markdown", 316 | "metadata": {}, 317 | "source": [ 318 | "The first graph shows that there seems to be a downward trend in both\n", 319 | "consumption and investment.\n", 320 | "\n", 321 | "his is a consequence of the decrease in the largest endogenous\n", 322 | "eigenvalue from unity in the earlier economy, caused by the higher\n", 323 | "adjustment cost.\n", 324 | "\n", 325 | "The present economy has a nonstochastic steady state value of 5 for\n", 326 | "consumption and 0 for both capital and investment.\n", 327 | "\n", 328 | "Because the largest endogenous eigenvalue is still close to 1, the\n", 329 | "economy heads only slowly towards these mean values.\n", 330 | "\n", 331 | "The impulse response functions now show that an endowment shock does not\n", 332 | "have a permanent effect on the levels of either consumption or\n", 333 | "investment." 334 | ] 335 | }, 336 | { 337 | "cell_type": "markdown", 338 | "metadata": {}, 339 | "source": [ 340 | "## Example 3: Durable Consumption Goods\n", 341 | "\n", 342 | "We generate our third economy by raising $ \\phi_1 $ further, to 1.0.\n", 343 | "We also raise the production function parameter from 0.1 to 0.15 (which\n", 344 | "raises the non-stochastic steady state value of capital above zero).\n", 345 | "\n", 346 | "We also change the specification of preferences to make the consumption\n", 347 | "good *durable*.\n", 348 | "\n", 349 | "Specifically, we allow for a single durable household good obeying:\n", 350 | "\n", 351 | "$$\n", 352 | "h_t = \\delta_h h_{t-1} + c_t \\, , 0<\\delta_h<1\n", 353 | "$$\n", 354 | "\n", 355 | "Services are related to the stock of durables at the beginning of the\n", 356 | "period:\n", 357 | "\n", 358 | "$$\n", 359 | "s_t = \\lambda h_{t-1} \\, , \\lambda > 0\n", 360 | "$$\n", 361 | "\n", 362 | "And preferences are ordered by:\n", 363 | "\n", 364 | "$$\n", 365 | "- \\frac{1}{2} \\mathbb{E} \\sum_{t=0}^\\infty \\beta^t [(\\lambda h_{t-1} - b_t)^2 + l_t^2]|J_0\n", 366 | "$$\n", 367 | "\n", 368 | "To implement this, we set $ \\lambda=0.1 $ and $ \\pi = 0 $ (we\n", 369 | "have already set $ \\theta_h = 1 $ and $ \\delta_h = 0.9 $).\n", 370 | "\n", 371 | "We start from an initial condition that makes consumption begin near\n", 372 | "around its non-stochastic steady state." 373 | ] 374 | }, 375 | { 376 | "cell_type": "code", 377 | "execution_count": null, 378 | "metadata": { 379 | "hide-output": false 380 | }, 381 | "outputs": [], 382 | "source": [ 383 | "ϕ_13 = 1\n", 384 | "ϕ_i3 = np.array([[1], [-ϕ_13]])\n", 385 | "\n", 386 | "γ_12 = 0.15\n", 387 | "γ_2 = np.array([[γ_12], [0]])\n", 388 | "\n", 389 | "l_λ2 = np.array([[0.1]])\n", 390 | "π_h2 = np.array([[0]])\n", 391 | "\n", 392 | "x01 = np.array([[150], [100], [1], [0], [0]])\n", 393 | "\n", 394 | "tech3 = (ϕ_c, ϕ_g, ϕ_i3, γ_2, δ_k, θ_k)\n", 395 | "pref2 = (β, l_λ2, π_h2, δ_h, θ_h)\n", 396 | "\n", 397 | "econ3 = DLE(info1, tech3, pref2)\n", 398 | "econ3.compute_sequence(x01, ts_length=300)\n", 399 | "\n", 400 | "# This is the right panel of Fig 5.11.1 from p.111 of HS2013\n", 401 | "plt.plot(econ3.c[0], label='Cons.')\n", 402 | "plt.plot(econ3.i[0], label='Inv.')\n", 403 | "plt.legend()\n", 404 | "plt.show()" 405 | ] 406 | }, 407 | { 408 | "cell_type": "markdown", 409 | "metadata": {}, 410 | "source": [ 411 | "In contrast to Hall’s original model of Example 1, it is now investment\n", 412 | "that is much smoother than consumption.\n", 413 | "\n", 414 | "This illustrates how making consumption goods durable tends to undo the\n", 415 | "strong consumption smoothing result that Hall obtained." 416 | ] 417 | }, 418 | { 419 | "cell_type": "code", 420 | "execution_count": null, 421 | "metadata": { 422 | "hide-output": false 423 | }, 424 | "outputs": [], 425 | "source": [ 426 | "econ3.irf(ts_length=40, shock=None)\n", 427 | "# This is the left panel of Fig 5.11.1 from p.111 of HS2013\n", 428 | "plt.plot(econ3.c_irf, label='Cons.')\n", 429 | "plt.plot(econ3.i_irf, label='Inv.')\n", 430 | "plt.legend()\n", 431 | "plt.show()" 432 | ] 433 | }, 434 | { 435 | "cell_type": "markdown", 436 | "metadata": {}, 437 | "source": [ 438 | "The impulse response functions confirm that consumption is now much more\n", 439 | "responsive to an endowment shock (and investment less so) than in\n", 440 | "Example 1.\n", 441 | "\n", 442 | "As in Example 2, the endowment shock has permanent effects on\n", 443 | "neither variable." 444 | ] 445 | } 446 | ], 447 | "metadata": { 448 | "date": 1584334741.572115, 449 | "filename": "irfs_in_hall_model.rst", 450 | "kernelspec": { 451 | "display_name": "Python", 452 | "language": "python3", 453 | "name": "python3" 454 | }, 455 | "title": "IRFs in Hall Models" 456 | }, 457 | "nbformat": 4, 458 | "nbformat_minor": 2 459 | } -------------------------------------------------------------------------------- /lucas_asset_pricing_dles.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "
\n", 10 | " \n", 11 | " \"QuantEcon\"\n", 12 | " \n", 13 | "
\n", 14 | "\n", 15 | "\n", 16 | "" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# Lucas Asset Pricing Using DLE" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "## Contents\n", 31 | "\n", 32 | "- [Lucas Asset Pricing Using DLE](#Lucas-Asset-Pricing-Using-DLE) \n", 33 | " - [Asset Pricing Equations](#Asset-Pricing-Equations) \n", 34 | " - [Asset Pricing Simulations](#Asset-Pricing-Simulations) " 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "This is one of a suite of lectures that use the quantecon DLE class to instantiate models within the\n", 42 | "[[HS13b]](https://python.quantecon.org/zreferences.html#hs2013) class of models described in detail in [Recursive Models of Dynamic Linear Economies](https://python.quantecon.org/hs_recursive_models.html).\n", 43 | "\n", 44 | "In addition to what’s in Anaconda, this lecture uses the quantecon library" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": null, 50 | "metadata": { 51 | "hide-output": true 52 | }, 53 | "outputs": [], 54 | "source": [ 55 | "!pip install --upgrade quantecon" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "This lecture uses the DLE class to price payout\n", 63 | "streams that are linear functions of the economy’s state vector, as well\n", 64 | "as risk-free assets that pay out one unit of the first consumption good\n", 65 | "with certainty.\n", 66 | "\n", 67 | "We assume basic knowledge of the class of economic environments that fall within the domain of the\n", 68 | "DLE class.\n", 69 | "\n", 70 | "Many details about the basic environment are contained in the lecture\n", 71 | "[Growth in Dynamic Linear Economies](https://python.quantecon.org/growth_in_dles.html).\n", 72 | "\n", 73 | "We’ll also need the following imports" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": null, 79 | "metadata": { 80 | "hide-output": false 81 | }, 82 | "outputs": [], 83 | "source": [ 84 | "import numpy as np\n", 85 | "import matplotlib.pyplot as plt\n", 86 | "from quantecon import LQ\n", 87 | "from quantecon import DLE\n", 88 | "%matplotlib inline" 89 | ] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "metadata": {}, 94 | "source": [ 95 | "We use a linear-quadratic version of an economy that Lucas (1978) [[Luc78]](https://python.quantecon.org/zreferences.html#lucas1978) used\n", 96 | "to develop an equilibrium theory of asset prices:\n", 97 | "\n", 98 | "**Preferences**\n", 99 | "\n", 100 | "$$\n", 101 | "-\\frac{1}{2}\\mathbb{E}\\sum_{t=0}^\\infty \\beta^t[(c_t - b_t)^2 + l_t^2]|J_0\n", 102 | "$$\n", 103 | "\n", 104 | "$$\n", 105 | "s_t = c_t\n", 106 | "$$\n", 107 | "\n", 108 | "$$\n", 109 | "b_t = U_bz_t\n", 110 | "$$\n", 111 | "\n", 112 | "**Technology**\n", 113 | "\n", 114 | "$$\n", 115 | "c_t = d_{1t}\n", 116 | "$$\n", 117 | "\n", 118 | "$$\n", 119 | "k_t = \\delta_k k_{t-1} + i_t\n", 120 | "$$\n", 121 | "\n", 122 | "$$\n", 123 | "g_t = \\phi_1 i_t \\, , \\phi_1 > 0\n", 124 | "$$\n", 125 | "\n", 126 | "$$\n", 127 | "\\left[ {\\begin{array}{c}\n", 128 | " d_{1t} \\\\ 0\n", 129 | " \\end{array} }\n", 130 | " \\right] = U_dz_t\n", 131 | "$$\n", 132 | "\n", 133 | "**Information**\n", 134 | "\n", 135 | "$$\n", 136 | "z_{t+1} =\n", 137 | "\\left[ {\\begin{array}{ccc}\n", 138 | " 1 & 0 & 0 \\\\ 0 & 0.8 & 0 \\\\ 0 & 0 & 0.5\n", 139 | " \\end{array} }\n", 140 | " \\right]\n", 141 | " z_t +\n", 142 | " \\left[ {\\begin{array}{cc}\n", 143 | " 0 & 0 \\\\ 1 & 0 \\\\ 0 & 1\n", 144 | " \\end{array} }\n", 145 | " \\right]\n", 146 | " w_{t+1}\n", 147 | "$$\n", 148 | "\n", 149 | "$$\n", 150 | "U_b =\n", 151 | " \\left[ {\\begin{array}{ccc}\n", 152 | " 30 & 0 & 0\n", 153 | " \\end{array} }\n", 154 | " \\right]\n", 155 | "$$\n", 156 | "\n", 157 | "$$\n", 158 | "U_d =\n", 159 | " \\left[ {\\begin{array}{ccc}\n", 160 | " 5 & 1 & 0 \\\\ 0 & 0 & 0\n", 161 | " \\end{array} }\n", 162 | " \\right]\n", 163 | "$$\n", 164 | "\n", 165 | "$$\n", 166 | "x_0 =\n", 167 | " \\left[ {\\begin{array}{ccccc}\n", 168 | " 5 & 150 & 1 & 0 & 0\n", 169 | " \\end{array} }\n", 170 | " \\right]'\n", 171 | "$$" 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "## Asset Pricing Equations\n", 179 | "\n", 180 | "[[HS13b]](https://python.quantecon.org/zreferences.html#hs2013) show that the time t value of a permanent claim to a stream\n", 181 | "$ y_s = U_ax_s \\, , s \\geq t $ is:\n", 182 | "\n", 183 | "$$\n", 184 | "a_t = (x_t'\\mu_ax_t + \\sigma_a)/(\\bar e _1M_cx_t)\n", 185 | "$$\n", 186 | "\n", 187 | "with\n", 188 | "\n", 189 | "$$\n", 190 | "\\mu_a = \\sum_{\\tau = 0}^\\infty \\beta^\\tau(A^{o'})^\\tau Z_a A^{o\\tau}\n", 191 | "$$\n", 192 | "\n", 193 | "$$\n", 194 | "\\sigma_a = \\frac{\\beta}{1-\\beta} \\text{trace} (Z_a \\sum_{\\tau = 0}^\\infty \\beta^\\tau (A^{o})^\\tau C C^{'} (A^{o'})^\\tau)\n", 195 | "$$\n", 196 | "\n", 197 | "where\n", 198 | "\n", 199 | "$$\n", 200 | "Z_a = U_a^{'}M_c\n", 201 | "$$\n", 202 | "\n", 203 | "The use of $ \\bar e _1 $ indicates that the first consumption good\n", 204 | "is the numeraire." 205 | ] 206 | }, 207 | { 208 | "cell_type": "markdown", 209 | "metadata": {}, 210 | "source": [ 211 | "## Asset Pricing Simulations" 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": null, 217 | "metadata": { 218 | "hide-output": false 219 | }, 220 | "outputs": [], 221 | "source": [ 222 | "gam = 0\n", 223 | "γ = np.array([[gam], [0]])\n", 224 | "ϕ_c = np.array([[1], [0]])\n", 225 | "ϕ_g = np.array([[0], [1]])\n", 226 | "ϕ_1 = 1e-4\n", 227 | "ϕ_i = np.array([[0], [-ϕ_1]])\n", 228 | "δ_k = np.array([[.95]])\n", 229 | "θ_k = np.array([[1]])\n", 230 | "β = np.array([[1 / 1.05]])\n", 231 | "ud = np.array([[5, 1, 0],\n", 232 | " [0, 0, 0]])\n", 233 | "a22 = np.array([[1, 0, 0],\n", 234 | " [0, 0.8, 0],\n", 235 | " [0, 0, 0.5]])\n", 236 | "c2 = np.array([[0, 1, 0],\n", 237 | " [0, 0, 1]]).T\n", 238 | "l_λ = np.array([[0]])\n", 239 | "π_h = np.array([[1]])\n", 240 | "δ_h = np.array([[.9]])\n", 241 | "θ_h = np.array([[1]]) - δ_h\n", 242 | "ub = np.array([[30, 0, 0]])\n", 243 | "x0 = np.array([[5, 150, 1, 0, 0]]).T\n", 244 | "\n", 245 | "info1 = (a22, c2, ub, ud)\n", 246 | "tech1 = (ϕ_c, ϕ_g, ϕ_i, γ, δ_k, θ_k)\n", 247 | "pref1 = (β, l_λ, π_h, δ_h, θ_h)" 248 | ] 249 | }, 250 | { 251 | "cell_type": "code", 252 | "execution_count": null, 253 | "metadata": { 254 | "hide-output": false 255 | }, 256 | "outputs": [], 257 | "source": [ 258 | "econ1 = DLE(info1, tech1, pref1)" 259 | ] 260 | }, 261 | { 262 | "cell_type": "markdown", 263 | "metadata": {}, 264 | "source": [ 265 | "After specifying a “Pay” matrix, we simulate the economy.\n", 266 | "\n", 267 | "The particular choice of “Pay” used below means that we are pricing a\n", 268 | "perpetual claim on the endowment process $ d_{1t} $" 269 | ] 270 | }, 271 | { 272 | "cell_type": "code", 273 | "execution_count": null, 274 | "metadata": { 275 | "hide-output": false 276 | }, 277 | "outputs": [], 278 | "source": [ 279 | "econ1.compute_sequence(x0, ts_length=100, Pay=np.array([econ1.Sd[0, :]]))" 280 | ] 281 | }, 282 | { 283 | "cell_type": "markdown", 284 | "metadata": {}, 285 | "source": [ 286 | "The graph below plots the price of this claim over time:" 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "execution_count": null, 292 | "metadata": { 293 | "hide-output": false 294 | }, 295 | "outputs": [], 296 | "source": [ 297 | "### Fig 7.12.1 from p.147 of HS2013\n", 298 | "plt.plot(econ1.Pay_Price, label='Price of Tree')\n", 299 | "plt.legend()\n", 300 | "plt.show()" 301 | ] 302 | }, 303 | { 304 | "cell_type": "markdown", 305 | "metadata": {}, 306 | "source": [ 307 | "The next plot displays the realized gross rate of return on this “Lucas\n", 308 | "tree” as well as on a risk-free one-period bond:" 309 | ] 310 | }, 311 | { 312 | "cell_type": "code", 313 | "execution_count": null, 314 | "metadata": { 315 | "hide-output": false 316 | }, 317 | "outputs": [], 318 | "source": [ 319 | "### Left panel of Fig 7.12.2 from p.148 of HS2013\n", 320 | "plt.plot(econ1.Pay_Gross, label='Tree')\n", 321 | "plt.plot(econ1.R1_Gross, label='Risk-Free')\n", 322 | "plt.legend()\n", 323 | "plt.show()" 324 | ] 325 | }, 326 | { 327 | "cell_type": "code", 328 | "execution_count": null, 329 | "metadata": { 330 | "hide-output": false 331 | }, 332 | "outputs": [], 333 | "source": [ 334 | "np.corrcoef(econ1.Pay_Gross[1:, 0], econ1.R1_Gross[1:, 0])" 335 | ] 336 | }, 337 | { 338 | "cell_type": "markdown", 339 | "metadata": {}, 340 | "source": [ 341 | "Above we have also calculated the correlation coefficient between these\n", 342 | "two returns.\n", 343 | "\n", 344 | "To give an idea of how the term structure of interest rates moves in\n", 345 | "this economy, the next plot displays the *net* rates of return on\n", 346 | "one-period and five-period risk-free bonds:" 347 | ] 348 | }, 349 | { 350 | "cell_type": "code", 351 | "execution_count": null, 352 | "metadata": { 353 | "hide-output": false 354 | }, 355 | "outputs": [], 356 | "source": [ 357 | "### Right panel of Fig 7.12.2 from p.148 of HS2013\n", 358 | "plt.plot(econ1.R1_Net, label='One-Period')\n", 359 | "plt.plot(econ1.R5_Net, label='Five-Period')\n", 360 | "plt.legend()\n", 361 | "plt.show()" 362 | ] 363 | }, 364 | { 365 | "cell_type": "markdown", 366 | "metadata": {}, 367 | "source": [ 368 | "From the above plot, we can see the tendency of the term structure to\n", 369 | "slope up when rates are low and to slope down when rates are high.\n", 370 | "\n", 371 | "Comparing it to the previous plot of the price of the “Lucas tree”, we\n", 372 | "can also see that net rates of return are low when the price of the tree\n", 373 | "is high, and vice versa.\n", 374 | "\n", 375 | "We now plot the realized gross rate of return on a “Lucas tree” as well\n", 376 | "as on a risk-free one-period bond when the autoregressive parameter for\n", 377 | "the endowment process is reduced to 0.4:" 378 | ] 379 | }, 380 | { 381 | "cell_type": "code", 382 | "execution_count": null, 383 | "metadata": { 384 | "hide-output": false 385 | }, 386 | "outputs": [], 387 | "source": [ 388 | "a22_2 = np.array([[1, 0, 0],\n", 389 | " [0, 0.4, 0],\n", 390 | " [0, 0, 0.5]])\n", 391 | "info2 = (a22_2, c2, ub, ud)\n", 392 | "\n", 393 | "econ2 = DLE(info2, tech1, pref1)\n", 394 | "econ2.compute_sequence(x0, ts_length=100, Pay=np.array([econ2.Sd[0, :]]))" 395 | ] 396 | }, 397 | { 398 | "cell_type": "code", 399 | "execution_count": null, 400 | "metadata": { 401 | "hide-output": false 402 | }, 403 | "outputs": [], 404 | "source": [ 405 | "### Left panel of Fig 7.12.3 from p.148 of HS2013\n", 406 | "plt.plot(econ2.Pay_Gross, label='Tree')\n", 407 | "plt.plot(econ2.R1_Gross, label='Risk-Free')\n", 408 | "plt.legend()\n", 409 | "plt.show()" 410 | ] 411 | }, 412 | { 413 | "cell_type": "code", 414 | "execution_count": null, 415 | "metadata": { 416 | "hide-output": false 417 | }, 418 | "outputs": [], 419 | "source": [ 420 | "np.corrcoef(econ2.Pay_Gross[1:, 0], econ2.R1_Gross[1:, 0])" 421 | ] 422 | }, 423 | { 424 | "cell_type": "markdown", 425 | "metadata": {}, 426 | "source": [ 427 | "The correlation between these two gross rates is now more negative.\n", 428 | "\n", 429 | "Next, we again plot the *net* rates of return on one-period and\n", 430 | "five-period risk-free bonds:" 431 | ] 432 | }, 433 | { 434 | "cell_type": "code", 435 | "execution_count": null, 436 | "metadata": { 437 | "hide-output": false 438 | }, 439 | "outputs": [], 440 | "source": [ 441 | "### Right panel of Fig 7.12.3 from p.148 of HS2013\n", 442 | "plt.plot(econ2.R1_Net, label='One-Period')\n", 443 | "plt.plot(econ2.R5_Net, label='Five-Period')\n", 444 | "plt.legend()\n", 445 | "plt.show()" 446 | ] 447 | }, 448 | { 449 | "cell_type": "markdown", 450 | "metadata": {}, 451 | "source": [ 452 | "We can see the tendency of the term structure to slope up when rates are\n", 453 | "low (and down when rates are high) has been accentuated relative to the\n", 454 | "first instance of our economy." 455 | ] 456 | } 457 | ], 458 | "metadata": { 459 | "date": 1584334744.7887528, 460 | "filename": "lucas_asset_pricing_dles.rst", 461 | "kernelspec": { 462 | "display_name": "Python", 463 | "language": "python3", 464 | "name": "python3" 465 | }, 466 | "title": "Lucas Asset Pricing Using DLE" 467 | }, 468 | "nbformat": 4, 469 | "nbformat_minor": 2 470 | } -------------------------------------------------------------------------------- /matplotlib.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "
\n", 10 | " \n", 11 | " \"QuantEcon\"\n", 12 | " \n", 13 | "
" 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "metadata": {}, 19 | "source": [ 20 | "# Matplotlib\n", 21 | "\n", 22 | "\n", 23 | "" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "## Contents\n", 31 | "\n", 32 | "- [Matplotlib](#Matplotlib) \n", 33 | " - [Overview](#Overview) \n", 34 | " - [The APIs](#The-APIs) \n", 35 | " - [More Features](#More-Features) \n", 36 | " - [Further Reading](#Further-Reading) \n", 37 | " - [Exercises](#Exercises) \n", 38 | " - [Solutions](#Solutions) " 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": {}, 44 | "source": [ 45 | "## Overview\n", 46 | "\n", 47 | "We’ve already generated quite a few figures in these lectures using [Matplotlib](http://matplotlib.org/).\n", 48 | "\n", 49 | "Matplotlib is an outstanding graphics library, designed for scientific computing, with\n", 50 | "\n", 51 | "- high-quality 2D and 3D plots \n", 52 | "- output in all the usual formats (PDF, PNG, etc.) \n", 53 | "- LaTeX integration \n", 54 | "- fine-grained control over all aspects of presentation \n", 55 | "- animation, etc. " 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "### Matplotlib’s Split Personality\n", 63 | "\n", 64 | "Matplotlib is unusual in that it offers two different interfaces to plotting.\n", 65 | "\n", 66 | "One is a simple MATLAB-style API (Application Programming Interface) that was written to help MATLAB refugees find a ready home.\n", 67 | "\n", 68 | "The other is a more “Pythonic” object-oriented API.\n", 69 | "\n", 70 | "For reasons described below, we recommend that you use the second API.\n", 71 | "\n", 72 | "But first, let’s discuss the difference." 73 | ] 74 | }, 75 | { 76 | "cell_type": "markdown", 77 | "metadata": {}, 78 | "source": [ 79 | "## The APIs\n", 80 | "\n", 81 | "\n", 82 | "" 83 | ] 84 | }, 85 | { 86 | "cell_type": "markdown", 87 | "metadata": {}, 88 | "source": [ 89 | "### The MATLAB-style API\n", 90 | "\n", 91 | "Here’s the kind of easy example you might find in introductory treatments" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": null, 97 | "metadata": { 98 | "hide-output": false 99 | }, 100 | "outputs": [], 101 | "source": [ 102 | "import matplotlib.pyplot as plt\n", 103 | "%matplotlib inline\n", 104 | "import numpy as np\n", 105 | "\n", 106 | "x = np.linspace(0, 10, 200)\n", 107 | "y = np.sin(x)\n", 108 | "\n", 109 | "plt.plot(x, y, 'b-', linewidth=2)\n", 110 | "plt.show()" 111 | ] 112 | }, 113 | { 114 | "cell_type": "markdown", 115 | "metadata": {}, 116 | "source": [ 117 | "This is simple and convenient, but also somewhat limited and un-Pythonic.\n", 118 | "\n", 119 | "For example, in the function calls, a lot of objects get created and passed around without making themselves known to the programmer.\n", 120 | "\n", 121 | "Python programmers tend to prefer a more explicit style of programming (run `import this` in a code block and look at the second line).\n", 122 | "\n", 123 | "This leads us to the alternative, object-oriented Matplotlib API." 124 | ] 125 | }, 126 | { 127 | "cell_type": "markdown", 128 | "metadata": {}, 129 | "source": [ 130 | "### The Object-Oriented API\n", 131 | "\n", 132 | "Here’s the code corresponding to the preceding figure using the object-oriented API" 133 | ] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "execution_count": null, 138 | "metadata": { 139 | "hide-output": false 140 | }, 141 | "outputs": [], 142 | "source": [ 143 | "fig, ax = plt.subplots()\n", 144 | "ax.plot(x, y, 'b-', linewidth=2)\n", 145 | "plt.show()" 146 | ] 147 | }, 148 | { 149 | "cell_type": "markdown", 150 | "metadata": {}, 151 | "source": [ 152 | "Here the call `fig, ax = plt.subplots()` returns a pair, where\n", 153 | "\n", 154 | "- `fig` is a `Figure` instance—like a blank canvas. \n", 155 | "- `ax` is an `AxesSubplot` instance—think of a frame for plotting in. \n", 156 | "\n", 157 | "\n", 158 | "The `plot()` function is actually a method of `ax`.\n", 159 | "\n", 160 | "While there’s a bit more typing, the more explicit use of objects gives us better control.\n", 161 | "\n", 162 | "This will become more clear as we go along." 163 | ] 164 | }, 165 | { 166 | "cell_type": "markdown", 167 | "metadata": {}, 168 | "source": [ 169 | "### Tweaks\n", 170 | "\n", 171 | "Here we’ve changed the line to red and added a legend" 172 | ] 173 | }, 174 | { 175 | "cell_type": "code", 176 | "execution_count": null, 177 | "metadata": { 178 | "hide-output": false 179 | }, 180 | "outputs": [], 181 | "source": [ 182 | "fig, ax = plt.subplots()\n", 183 | "ax.plot(x, y, 'r-', linewidth=2, label='sine function', alpha=0.6)\n", 184 | "ax.legend()\n", 185 | "plt.show()" 186 | ] 187 | }, 188 | { 189 | "cell_type": "markdown", 190 | "metadata": {}, 191 | "source": [ 192 | "We’ve also used `alpha` to make the line slightly transparent—which makes it look smoother.\n", 193 | "\n", 194 | "The location of the legend can be changed by replacing `ax.legend()` with `ax.legend(loc='upper center')`." 195 | ] 196 | }, 197 | { 198 | "cell_type": "code", 199 | "execution_count": null, 200 | "metadata": { 201 | "hide-output": false 202 | }, 203 | "outputs": [], 204 | "source": [ 205 | "fig, ax = plt.subplots()\n", 206 | "ax.plot(x, y, 'r-', linewidth=2, label='sine function', alpha=0.6)\n", 207 | "ax.legend(loc='upper center')\n", 208 | "plt.show()" 209 | ] 210 | }, 211 | { 212 | "cell_type": "markdown", 213 | "metadata": {}, 214 | "source": [ 215 | "If everything is properly configured, then adding LaTeX is trivial" 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": null, 221 | "metadata": { 222 | "hide-output": false 223 | }, 224 | "outputs": [], 225 | "source": [ 226 | "fig, ax = plt.subplots()\n", 227 | "ax.plot(x, y, 'r-', linewidth=2, label='$y=\\sin(x)$', alpha=0.6)\n", 228 | "ax.legend(loc='upper center')\n", 229 | "plt.show()" 230 | ] 231 | }, 232 | { 233 | "cell_type": "markdown", 234 | "metadata": {}, 235 | "source": [ 236 | "Controlling the ticks, adding titles and so on is also straightforward" 237 | ] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": null, 242 | "metadata": { 243 | "hide-output": false 244 | }, 245 | "outputs": [], 246 | "source": [ 247 | "fig, ax = plt.subplots()\n", 248 | "ax.plot(x, y, 'r-', linewidth=2, label='$y=\\sin(x)$', alpha=0.6)\n", 249 | "ax.legend(loc='upper center')\n", 250 | "ax.set_yticks([-1, 0, 1])\n", 251 | "ax.set_title('Test plot')\n", 252 | "plt.show()" 253 | ] 254 | }, 255 | { 256 | "cell_type": "markdown", 257 | "metadata": {}, 258 | "source": [ 259 | "## More Features\n", 260 | "\n", 261 | "Matplotlib has a huge array of functions and features, which you can discover\n", 262 | "over time as you have need for them.\n", 263 | "\n", 264 | "We mention just a few." 265 | ] 266 | }, 267 | { 268 | "cell_type": "markdown", 269 | "metadata": {}, 270 | "source": [ 271 | "### Multiple Plots on One Axis\n", 272 | "\n", 273 | "\n", 274 | "\n", 275 | "It’s straightforward to generate multiple plots on the same axes.\n", 276 | "\n", 277 | "Here’s an example that randomly generates three normal densities and adds a label with their mean" 278 | ] 279 | }, 280 | { 281 | "cell_type": "code", 282 | "execution_count": null, 283 | "metadata": { 284 | "hide-output": false 285 | }, 286 | "outputs": [], 287 | "source": [ 288 | "from scipy.stats import norm\n", 289 | "from random import uniform\n", 290 | "\n", 291 | "fig, ax = plt.subplots()\n", 292 | "x = np.linspace(-4, 4, 150)\n", 293 | "for i in range(3):\n", 294 | " m, s = uniform(-1, 1), uniform(1, 2)\n", 295 | " y = norm.pdf(x, loc=m, scale=s)\n", 296 | " current_label = f'$\\mu = {m:.2}$'\n", 297 | " ax.plot(x, y, linewidth=2, alpha=0.6, label=current_label)\n", 298 | "ax.legend()\n", 299 | "plt.show()" 300 | ] 301 | }, 302 | { 303 | "cell_type": "markdown", 304 | "metadata": {}, 305 | "source": [ 306 | "### Multiple Subplots\n", 307 | "\n", 308 | "\n", 309 | "\n", 310 | "Sometimes we want multiple subplots in one figure.\n", 311 | "\n", 312 | "Here’s an example that generates 6 histograms" 313 | ] 314 | }, 315 | { 316 | "cell_type": "code", 317 | "execution_count": null, 318 | "metadata": { 319 | "hide-output": false 320 | }, 321 | "outputs": [], 322 | "source": [ 323 | "num_rows, num_cols = 3, 2\n", 324 | "fig, axes = plt.subplots(num_rows, num_cols, figsize=(10, 12))\n", 325 | "for i in range(num_rows):\n", 326 | " for j in range(num_cols):\n", 327 | " m, s = uniform(-1, 1), uniform(1, 2)\n", 328 | " x = norm.rvs(loc=m, scale=s, size=100)\n", 329 | " axes[i, j].hist(x, alpha=0.6, bins=20)\n", 330 | " t = f'$\\mu = {m:.2}, \\quad \\sigma = {s:.2}$'\n", 331 | " axes[i, j].set(title=t, xticks=[-4, 0, 4], yticks=[])\n", 332 | "plt.show()" 333 | ] 334 | }, 335 | { 336 | "cell_type": "markdown", 337 | "metadata": {}, 338 | "source": [ 339 | "### 3D Plots\n", 340 | "\n", 341 | "\n", 342 | "\n", 343 | "Matplotlib does a nice job of 3D plots — here is one example" 344 | ] 345 | }, 346 | { 347 | "cell_type": "code", 348 | "execution_count": null, 349 | "metadata": { 350 | "hide-output": false 351 | }, 352 | "outputs": [], 353 | "source": [ 354 | "from mpl_toolkits.mplot3d.axes3d import Axes3D\n", 355 | "from matplotlib import cm\n", 356 | "\n", 357 | "\n", 358 | "def f(x, y):\n", 359 | " return np.cos(x**2 + y**2) / (1 + x**2 + y**2)\n", 360 | "\n", 361 | "xgrid = np.linspace(-3, 3, 50)\n", 362 | "ygrid = xgrid\n", 363 | "x, y = np.meshgrid(xgrid, ygrid)\n", 364 | "\n", 365 | "fig = plt.figure(figsize=(8, 6))\n", 366 | "ax = fig.add_subplot(111, projection='3d')\n", 367 | "ax.plot_surface(x,\n", 368 | " y,\n", 369 | " f(x, y),\n", 370 | " rstride=2, cstride=2,\n", 371 | " cmap=cm.jet,\n", 372 | " alpha=0.7,\n", 373 | " linewidth=0.25)\n", 374 | "ax.set_zlim(-0.5, 1.0)\n", 375 | "plt.show()" 376 | ] 377 | }, 378 | { 379 | "cell_type": "markdown", 380 | "metadata": {}, 381 | "source": [ 382 | "### A Customizing Function\n", 383 | "\n", 384 | "Perhaps you will find a set of customizations that you regularly use.\n", 385 | "\n", 386 | "Suppose we usually prefer our axes to go through the origin, and to have a grid.\n", 387 | "\n", 388 | "Here’s a nice example from [Matthew Doty](https://github.com/xcthulhu) of how the object-oriented API can be used to build a custom `subplots` function that implements these changes.\n", 389 | "\n", 390 | "Read carefully through the code and see if you can follow what’s going on" 391 | ] 392 | }, 393 | { 394 | "cell_type": "code", 395 | "execution_count": null, 396 | "metadata": { 397 | "hide-output": false 398 | }, 399 | "outputs": [], 400 | "source": [ 401 | "def subplots():\n", 402 | " \"Custom subplots with axes through the origin\"\n", 403 | " fig, ax = plt.subplots()\n", 404 | "\n", 405 | " # Set the axes through the origin\n", 406 | " for spine in ['left', 'bottom']:\n", 407 | " ax.spines[spine].set_position('zero')\n", 408 | " for spine in ['right', 'top']:\n", 409 | " ax.spines[spine].set_color('none')\n", 410 | "\n", 411 | " ax.grid()\n", 412 | " return fig, ax\n", 413 | "\n", 414 | "\n", 415 | "fig, ax = subplots() # Call the local version, not plt.subplots()\n", 416 | "x = np.linspace(-2, 10, 200)\n", 417 | "y = np.sin(x)\n", 418 | "ax.plot(x, y, 'r-', linewidth=2, label='sine function', alpha=0.6)\n", 419 | "ax.legend(loc='lower right')\n", 420 | "plt.show()" 421 | ] 422 | }, 423 | { 424 | "cell_type": "markdown", 425 | "metadata": {}, 426 | "source": [ 427 | "The custom `subplots` function\n", 428 | "\n", 429 | "1. calls the standard `plt.subplots` function internally to generate the `fig, ax` pair, \n", 430 | "1. makes the desired customizations to `ax`, and \n", 431 | "1. passes the `fig, ax` pair back to the calling code. " 432 | ] 433 | }, 434 | { 435 | "cell_type": "markdown", 436 | "metadata": {}, 437 | "source": [ 438 | "## Further Reading\n", 439 | "\n", 440 | "- The [Matplotlib gallery](http://matplotlib.org/gallery.html) provides many examples. \n", 441 | "- A nice [Matplotlib tutorial](http://scipy-lectures.org/intro/matplotlib/index.html) by Nicolas Rougier, Mike Muller and Gael Varoquaux. \n", 442 | "- [mpltools](http://tonysyu.github.io/mpltools/index.html) allows easy\n", 443 | " switching between plot styles. \n", 444 | "- [Seaborn](https://github.com/mwaskom/seaborn) facilitates common statistics plots in Matplotlib. " 445 | ] 446 | }, 447 | { 448 | "cell_type": "markdown", 449 | "metadata": {}, 450 | "source": [ 451 | "## Exercises" 452 | ] 453 | }, 454 | { 455 | "cell_type": "markdown", 456 | "metadata": {}, 457 | "source": [ 458 | "### Exercise 1\n", 459 | "\n", 460 | "Plot the function\n", 461 | "\n", 462 | "$$\n", 463 | "f(x) = \\cos(\\pi \\theta x) \\exp(-x)\n", 464 | "$$\n", 465 | "\n", 466 | "over the interval $ [0, 5] $ for each $ \\theta $ in `np.linspace(0, 2, 10)`.\n", 467 | "\n", 468 | "Place all the curves in the same figure.\n", 469 | "\n", 470 | "The output should look like this\n", 471 | "\n", 472 | "" 473 | ] 474 | }, 475 | { 476 | "cell_type": "markdown", 477 | "metadata": {}, 478 | "source": [ 479 | "## Solutions" 480 | ] 481 | }, 482 | { 483 | "cell_type": "markdown", 484 | "metadata": {}, 485 | "source": [ 486 | "### Exercise 1\n", 487 | "\n", 488 | "Here’s one solution" 489 | ] 490 | }, 491 | { 492 | "cell_type": "code", 493 | "execution_count": null, 494 | "metadata": { 495 | "hide-output": false 496 | }, 497 | "outputs": [], 498 | "source": [ 499 | "def f(x, θ):\n", 500 | " return np.cos(np.pi * θ * x ) * np.exp(- x)\n", 501 | "\n", 502 | "θ_vals = np.linspace(0, 2, 10)\n", 503 | "x = np.linspace(0, 5, 200)\n", 504 | "fig, ax = plt.subplots()\n", 505 | "\n", 506 | "for θ in θ_vals:\n", 507 | " ax.plot(x, f(x, θ))\n", 508 | "\n", 509 | "plt.show()" 510 | ] 511 | } 512 | ], 513 | "metadata": { 514 | "date": 1584334745.8795545, 515 | "filename": "matplotlib.rst", 516 | "kernelspec": { 517 | "display_name": "Python", 518 | "language": "python3", 519 | "name": "python3" 520 | }, 521 | "title": "Matplotlib" 522 | }, 523 | "nbformat": 4, 524 | "nbformat_minor": 2 525 | } -------------------------------------------------------------------------------- /muth_kalman.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "
\n", 10 | " \n", 11 | " \"QuantEcon\"\n", 12 | " \n", 13 | "
\n", 14 | "\n", 15 | "\n", 16 | "" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# Reverse Engineering a la Muth" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "## Contents\n", 31 | "\n", 32 | "- [Reverse Engineering a la Muth](#Reverse-Engineering-a-la-Muth) \n", 33 | " - [Friedman (1956) and Muth (1960)](#Friedman-%281956%29-and-Muth-%281960%29) " 34 | ] 35 | }, 36 | { 37 | "cell_type": "markdown", 38 | "metadata": {}, 39 | "source": [ 40 | "In addition to what’s in Anaconda, this lecture uses the quantecon library." 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": null, 46 | "metadata": { 47 | "hide-output": true 48 | }, 49 | "outputs": [], 50 | "source": [ 51 | "!pip install --upgrade quantecon" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "We’ll also need the following imports:" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": null, 64 | "metadata": { 65 | "hide-output": false 66 | }, 67 | "outputs": [], 68 | "source": [ 69 | "import matplotlib.pyplot as plt\n", 70 | "%matplotlib inline\n", 71 | "import numpy as np\n", 72 | "import scipy.linalg as la\n", 73 | "\n", 74 | "from quantecon import Kalman\n", 75 | "from quantecon import LinearStateSpace\n", 76 | "from scipy.stats import norm\n", 77 | "np.set_printoptions(linewidth=120, precision=4, suppress=True)" 78 | ] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "metadata": {}, 83 | "source": [ 84 | "This lecture uses the Kalman filter to reformulate John F. Muth’s first\n", 85 | "paper [[Mut60]](https://python.quantecon.org/zreferences.html#muth1960) about rational expectations.\n", 86 | "\n", 87 | "Muth used *classical* prediction methods to reverse engineer a\n", 88 | "stochastic process that renders optimal Milton Friedman’s [[Fri56]](https://python.quantecon.org/zreferences.html#friedman1956) “adaptive\n", 89 | "expectations” scheme." 90 | ] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "metadata": {}, 95 | "source": [ 96 | "## Friedman (1956) and Muth (1960)\n", 97 | "\n", 98 | "Milton Friedman [[Fri56]](https://python.quantecon.org/zreferences.html#friedman1956) (1956) posited that\n", 99 | "consumer’s forecast their future disposable income with the adaptive\n", 100 | "expectations scheme\n", 101 | "\n", 102 | "\n", 103 | "\n", 104 | "$$\n", 105 | "y_{t+i,t}^* = K \\sum_{j=0}^\\infty (1 - K)^j y_{t-j} \\tag{1}\n", 106 | "$$\n", 107 | "\n", 108 | "where $ K \\in (0,1) $ and $ y_{t+i,t}^* $ is a forecast of\n", 109 | "future $ y $ over horizon $ i $.\n", 110 | "\n", 111 | "Milton Friedman justified the **exponential smoothing** forecasting\n", 112 | "scheme [(1)](#equation-expectations) informally, noting that it seemed a plausible way to use\n", 113 | "past income to forecast future income.\n", 114 | "\n", 115 | "In his first paper about rational expectations, John F. Muth [[Mut60]](https://python.quantecon.org/zreferences.html#muth1960)\n", 116 | "reverse-engineered a univariate stochastic process\n", 117 | "$ \\{y_t\\}_{t=- \\infty}^\\infty $ for which Milton Friedman’s adaptive\n", 118 | "expectations scheme gives linear least forecasts of $ y_{t+j} $ for\n", 119 | "any horizon $ i $.\n", 120 | "\n", 121 | "Muth sought a setting and a sense in which Friedman’s forecasting scheme\n", 122 | "is optimal.\n", 123 | "\n", 124 | "That is, Muth asked for what optimal forecasting **question** is Milton\n", 125 | "Friedman’s adaptive expectation scheme the **answer**.\n", 126 | "\n", 127 | "Muth (1960) used classical prediction methods based on lag-operators and\n", 128 | "$ z $-transforms to find the answer to his question.\n", 129 | "\n", 130 | "Please see lectures [Classical Control with Linear Algebra](https://python.quantecon.org/lu_tricks.html) and\n", 131 | "[Classical Filtering and Prediction with Linear Algebra](https://python.quantecon.org/classical_filtering.html) for an introduction to the classical\n", 132 | "tools that Muth used.\n", 133 | "\n", 134 | "Rather than using those classical tools, in this lecture we apply the\n", 135 | "Kalman filter to express the heart of Muth’s analysis concisely.\n", 136 | "\n", 137 | "The lecture [First Look at Kalman Filter](https://python.quantecon.org/kalman.html) describes the Kalman filter.\n", 138 | "\n", 139 | "We’ll use limiting versions of the Kalman filter corresponding to what are called **stationary values** in that lecture." 140 | ] 141 | }, 142 | { 143 | "cell_type": "markdown", 144 | "metadata": {}, 145 | "source": [ 146 | "### A Process for Which Adaptive Expectations are Optimal\n", 147 | "\n", 148 | "Suppose that an observable $ y_t $ is the sum of an unobserved\n", 149 | "random walk $ x_t $ and an IID shock $ \\epsilon_{2,t} $:\n", 150 | "\n", 151 | "\n", 152 | "\n", 153 | "$$\n", 154 | "\\begin{aligned} x_{t+1} & = x_t + \\sigma_x \\epsilon_{1,t+1} \\cr\n", 155 | " y_t & = x_t + \\sigma_y \\epsilon_{2,t} \\end{aligned} \\tag{2}\n", 156 | "$$\n", 157 | "\n", 158 | "where\n", 159 | "\n", 160 | "$$\n", 161 | "\\begin{bmatrix} \\epsilon_{1,t+1} \\cr \\epsilon_{2,t} \\end{bmatrix} \\sim {\\mathcal N} (0, I)\n", 162 | "$$\n", 163 | "\n", 164 | "is an IID process.\n", 165 | "\n", 166 | "**Note:** A property of the state-space representation [(2)](#equation-state-space) is that in\n", 167 | "general neither $ \\epsilon_{1,t} $ nor $ \\epsilon_{2,t} $ is in\n", 168 | "the space spanned by square-summable linear combinations of\n", 169 | "$ y_t, y_{t-1}, \\ldots $.\n", 170 | "\n", 171 | "In general\n", 172 | "$ \\begin{bmatrix} \\epsilon_{1,t} \\cr \\epsilon_{2t} \\end{bmatrix} $\n", 173 | "has more information about future $ y_{t+j} $’s than is contained\n", 174 | "in $ y_t, y_{t-1}, \\ldots $.\n", 175 | "\n", 176 | "We can use the asymptotic or stationary values of the Kalman gain and\n", 177 | "the one-step-ahead conditional state covariance matrix to compute a\n", 178 | "time-invariant *innovations representation*\n", 179 | "\n", 180 | "\n", 181 | "\n", 182 | "$$\n", 183 | "\\begin{aligned} \\hat x_{t+1} & = \\hat x_t + K a_t \\cr\n", 184 | " y_t & = \\hat x_t + a_t \\end{aligned} \\tag{3}\n", 185 | "$$\n", 186 | "\n", 187 | "where $ \\hat x_t = E [x_t | y_{t-1}, y_{t-2}, \\ldots ] $ and\n", 188 | "$ a_t = y_t - E[y_t |y_{t-1}, y_{t-2}, \\ldots ] $.\n", 189 | "\n", 190 | "**Note:** A key property about an *innovations representation* is that\n", 191 | "$ a_t $ is in the space spanned by square summable linear\n", 192 | "combinations of $ y_t, y_{t-1}, \\ldots $.\n", 193 | "\n", 194 | "For more ramifications of this property, see the lectures [Shock Non-Invertibility](https://python.quantecon.org/hs_invertibility_example.html) and\n", 195 | "[Recursive Models of Dynamic Linear Economies](https://python.quantecon.org/hs_recursive_models.html).\n", 196 | "\n", 197 | "Later we’ll stack these state-space systems [(2)](#equation-state-space) and [(3)](#equation-innovations) to display some\n", 198 | "classic findings of Muth.\n", 199 | "\n", 200 | "But first, let’s create an instance of the state-space system [(2)](#equation-state-space) then\n", 201 | "apply the quantecon `Kalman` class, then uses it to construct the associated “innovations representation”" 202 | ] 203 | }, 204 | { 205 | "cell_type": "code", 206 | "execution_count": null, 207 | "metadata": { 208 | "hide-output": false 209 | }, 210 | "outputs": [], 211 | "source": [ 212 | "# Make some parameter choices\n", 213 | "# sigx/sigy are state noise std err and measurement noise std err\n", 214 | "μ_0, σ_x, σ_y = 10, 1, 5\n", 215 | "\n", 216 | "# Create a LinearStateSpace object\n", 217 | "A, C, G, H = 1, σ_x, 1, σ_y\n", 218 | "ss = LinearStateSpace(A, C, G, H, mu_0=μ_0)\n", 219 | "\n", 220 | "# Set prior and initialize the Kalman type\n", 221 | "x_hat_0, Σ_0 = 10, 1\n", 222 | "kmuth = Kalman(ss, x_hat_0, Σ_0)\n", 223 | "\n", 224 | "# Computes stationary values which we need for the innovation\n", 225 | "# representation\n", 226 | "S1, K1 = kmuth.stationary_values()\n", 227 | "\n", 228 | "# Form innovation representation state-space\n", 229 | "Ak, Ck, Gk, Hk = A, K1, G, 1\n", 230 | "\n", 231 | "ssk = LinearStateSpace(Ak, Ck, Gk, Hk, mu_0=x_hat_0)" 232 | ] 233 | }, 234 | { 235 | "cell_type": "markdown", 236 | "metadata": {}, 237 | "source": [ 238 | "### Some Useful State-Space Math\n", 239 | "\n", 240 | "Now we want to map the time-invariant innovations representation [(3)](#equation-innovations) and\n", 241 | "the original state-space system [(2)](#equation-state-space) into a convenient form for deducing\n", 242 | "the impulse responses from the original shocks to the $ x_t $ and\n", 243 | "$ \\hat x_t $.\n", 244 | "\n", 245 | "Putting both of these representations into a single state-space system\n", 246 | "is yet another application of the insight that “finding the state is an\n", 247 | "art”.\n", 248 | "\n", 249 | "We’ll define a state vector and appropriate state-space matrices that\n", 250 | "allow us to represent both systems in one fell swoop.\n", 251 | "\n", 252 | "Note that\n", 253 | "\n", 254 | "$$\n", 255 | "a_t = x_t + \\sigma_y \\epsilon_{2,t} - \\hat x_t\n", 256 | "$$\n", 257 | "\n", 258 | "so that\n", 259 | "\n", 260 | "$$\n", 261 | "\\begin{aligned} \\hat x_{t+1} & = \\hat x_t + K (x_t + \\sigma_y \\epsilon_{2,t} - \\hat x_t) \\cr\n", 262 | " & = (1-K) \\hat x_t + K x_t + K \\sigma_y \\epsilon_{2,t} \\end{aligned}\n", 263 | "$$\n", 264 | "\n", 265 | "The stacked system\n", 266 | "\n", 267 | "$$\n", 268 | "\\begin{bmatrix} x_{t+1} \\cr \\hat x_{t+1} \\cr \\epsilon_{2,t+1} \\end{bmatrix} =\n", 269 | "\\begin{bmatrix} 1 & 0 & 0 \\cr K & (1-K) & K \\sigma_y \\cr 0 & 0 & 0 \\end{bmatrix}\n", 270 | "\\begin{bmatrix} x_{t} \\cr \\hat x_t \\cr \\epsilon_{2,t} \\end{bmatrix}+\n", 271 | "\\begin{bmatrix} \\sigma_x & 0 \\cr 0 & 0 \\cr 0 & 1 \\end{bmatrix}\n", 272 | "\\begin{bmatrix} \\epsilon_{1,t+1} \\cr \\epsilon_{2,t+1} \\end{bmatrix}\n", 273 | "$$\n", 274 | "\n", 275 | "$$\n", 276 | "\\begin{bmatrix} y_t \\cr a_t \\end{bmatrix} = \\begin{bmatrix} 1 & 0 & \\sigma_y \\cr\n", 277 | " 1 & -1 & \\sigma_y \\end{bmatrix} \\begin{bmatrix} x_{t} \\cr \\hat x_t \\cr \\epsilon_{2,t} \\end{bmatrix}\n", 278 | "$$\n", 279 | "\n", 280 | "is a state-space system that tells us how the shocks\n", 281 | "$ \\begin{bmatrix} \\epsilon_{1,t+1} \\cr \\epsilon_{2,t+1} \\end{bmatrix} $\n", 282 | "affect states $ \\hat x_{t+1}, x_t $, the observable $ y_t $, and\n", 283 | "the innovation $ a_t $.\n", 284 | "\n", 285 | "With this tool at our disposal, let’s form the composite system and\n", 286 | "simulate it" 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "execution_count": null, 292 | "metadata": { 293 | "hide-output": false 294 | }, 295 | "outputs": [], 296 | "source": [ 297 | "# Create grand state-space for y_t, a_t as observed vars -- Use\n", 298 | "# stacking trick above\n", 299 | "Af = np.array([[ 1, 0, 0],\n", 300 | " [K1, 1 - K1, K1 * σ_y],\n", 301 | " [ 0, 0, 0]])\n", 302 | "Cf = np.array([[σ_x, 0],\n", 303 | " [ 0, K1 * σ_y],\n", 304 | " [ 0, 1]])\n", 305 | "Gf = np.array([[1, 0, σ_y],\n", 306 | " [1, -1, σ_y]])\n", 307 | "\n", 308 | "μ_true, μ_prior = 10, 10\n", 309 | "μ_f = np.array([μ_true, μ_prior, 0]).reshape(3, 1)\n", 310 | "\n", 311 | "# Create the state-space\n", 312 | "ssf = LinearStateSpace(Af, Cf, Gf, mu_0=μ_f)\n", 313 | "\n", 314 | "# Draw observations of y from the state-space model\n", 315 | "N = 50\n", 316 | "xf, yf = ssf.simulate(N)\n", 317 | "\n", 318 | "print(f\"Kalman gain = {K1}\")\n", 319 | "print(f\"Conditional variance = {S1}\")" 320 | ] 321 | }, 322 | { 323 | "cell_type": "markdown", 324 | "metadata": {}, 325 | "source": [ 326 | "Now that we have simulated our joint system, we have $ x_t $,\n", 327 | "$ \\hat{x_t} $, and $ y_t $.\n", 328 | "\n", 329 | "We can now investigate how these\n", 330 | "variables are related by plotting some key objects." 331 | ] 332 | }, 333 | { 334 | "cell_type": "markdown", 335 | "metadata": {}, 336 | "source": [ 337 | "### Estimates of Unobservables\n", 338 | "\n", 339 | "First, let’s plot the hidden state $ x_t $ and the filtered version\n", 340 | "$ \\hat x_t $ that is linear-least squares projection of $ x_t $\n", 341 | "on the history $ y_{t-1}, y_{t-2}, \\ldots $" 342 | ] 343 | }, 344 | { 345 | "cell_type": "code", 346 | "execution_count": null, 347 | "metadata": { 348 | "hide-output": false 349 | }, 350 | "outputs": [], 351 | "source": [ 352 | "fig, ax = plt.subplots()\n", 353 | "ax.plot(xf[0, :], label=\"$x_t$\")\n", 354 | "ax.plot(xf[1, :], label=\"Filtered $x_t$\")\n", 355 | "ax.legend()\n", 356 | "ax.set_xlabel(\"Time\")\n", 357 | "ax.set_title(r\"$x$ vs $\\hat{x}$\")\n", 358 | "plt.show()" 359 | ] 360 | }, 361 | { 362 | "cell_type": "markdown", 363 | "metadata": {}, 364 | "source": [ 365 | "Note how $ x_t $ and $ \\hat{x_t} $ differ.\n", 366 | "\n", 367 | "For Friedman, $ \\hat x_t $ and not $ x_t $ is the consumer’s\n", 368 | "idea about her/his *permanent income*." 369 | ] 370 | }, 371 | { 372 | "cell_type": "markdown", 373 | "metadata": {}, 374 | "source": [ 375 | "### Relation between Unobservable and Observable\n", 376 | "\n", 377 | "Now let’s plot $ x_t $ and $ y_t $.\n", 378 | "\n", 379 | "Recall that $ y_t $ is just $ x_t $ plus white noise" 380 | ] 381 | }, 382 | { 383 | "cell_type": "code", 384 | "execution_count": null, 385 | "metadata": { 386 | "hide-output": false 387 | }, 388 | "outputs": [], 389 | "source": [ 390 | "fig, ax = plt.subplots()\n", 391 | "ax.plot(yf[0, :], label=\"y\")\n", 392 | "ax.plot(xf[0, :], label=\"x\")\n", 393 | "ax.legend()\n", 394 | "ax.set_title(r\"$x$ and $y$\")\n", 395 | "ax.set_xlabel(\"Time\")\n", 396 | "plt.show()" 397 | ] 398 | }, 399 | { 400 | "cell_type": "markdown", 401 | "metadata": {}, 402 | "source": [ 403 | "We see above that $ y $ seems to look like white noise around the\n", 404 | "values of $ x $." 405 | ] 406 | }, 407 | { 408 | "cell_type": "markdown", 409 | "metadata": {}, 410 | "source": [ 411 | "### Innovations\n", 412 | "\n", 413 | "Recall that we wrote down the innovation representation that depended on\n", 414 | "$ a_t $. We now plot the innovations $ \\{a_t\\} $:" 415 | ] 416 | }, 417 | { 418 | "cell_type": "code", 419 | "execution_count": null, 420 | "metadata": { 421 | "hide-output": false 422 | }, 423 | "outputs": [], 424 | "source": [ 425 | "fig, ax = plt.subplots()\n", 426 | "ax.plot(yf[1, :], label=\"a\")\n", 427 | "ax.legend()\n", 428 | "ax.set_title(r\"Innovation $a_t$\")\n", 429 | "ax.set_xlabel(\"Time\")\n", 430 | "plt.show()" 431 | ] 432 | }, 433 | { 434 | "cell_type": "markdown", 435 | "metadata": {}, 436 | "source": [ 437 | "### MA and AR Representations\n", 438 | "\n", 439 | "Now we shall extract from the `Kalman` instance `kmuth` coefficients of\n", 440 | "\n", 441 | "- a fundamental moving average representation that represents\n", 442 | " $ y_t $ as a one-sided moving sum of current and past\n", 443 | " $ a_t $s that are square summable linear combinations of $ y_t, y_{t-1}, \\ldots $. \n", 444 | "- a univariate autoregression representation that depicts the\n", 445 | " coefficients in a linear least square projection of $ y_t $ on\n", 446 | " the semi-infinite history $ y_{t-1}, y_{t-2}, \\ldots $. \n", 447 | "\n", 448 | "\n", 449 | "Then we’ll plot each of them" 450 | ] 451 | }, 452 | { 453 | "cell_type": "code", 454 | "execution_count": null, 455 | "metadata": { 456 | "hide-output": false 457 | }, 458 | "outputs": [], 459 | "source": [ 460 | "# Kalman Methods for MA and VAR\n", 461 | "coefs_ma = kmuth.stationary_coefficients(5, \"ma\")\n", 462 | "coefs_var = kmuth.stationary_coefficients(5, \"var\")\n", 463 | "\n", 464 | "# Coefficients come in a list of arrays, but we\n", 465 | "# want to plot them and so need to stack into an array\n", 466 | "coefs_ma_array = np.vstack(coefs_ma)\n", 467 | "coefs_var_array = np.vstack(coefs_var)\n", 468 | "\n", 469 | "fig, ax = plt.subplots(2)\n", 470 | "ax[0].plot(coefs_ma_array, label=\"MA\")\n", 471 | "ax[0].legend()\n", 472 | "ax[1].plot(coefs_var_array, label=\"VAR\")\n", 473 | "ax[1].legend()\n", 474 | "\n", 475 | "plt.show()" 476 | ] 477 | }, 478 | { 479 | "cell_type": "markdown", 480 | "metadata": {}, 481 | "source": [ 482 | "The **moving average** coefficients in the top panel show tell-tale\n", 483 | "signs of $ y_t $ being a process whose first difference is a first-order\n", 484 | "autoregression.\n", 485 | "\n", 486 | "The **autoregressive coefficients** decline geometrically with decay\n", 487 | "rate $ (1-K) $.\n", 488 | "\n", 489 | "These are exactly the target outcomes that Muth (1960) aimed to reverse\n", 490 | "engineer" 491 | ] 492 | }, 493 | { 494 | "cell_type": "code", 495 | "execution_count": null, 496 | "metadata": { 497 | "hide-output": false 498 | }, 499 | "outputs": [], 500 | "source": [ 501 | "print(f'decay parameter 1 - K1 = {1 - K1}')" 502 | ] 503 | } 504 | ], 505 | "metadata": { 506 | "date": 1584334747.4248579, 507 | "filename": "muth_kalman.rst", 508 | "kernelspec": { 509 | "display_name": "Python", 510 | "language": "python3", 511 | "name": "python3" 512 | }, 513 | "title": "Reverse Engineering a la Muth" 514 | }, 515 | "nbformat": 4, 516 | "nbformat_minor": 2 517 | } -------------------------------------------------------------------------------- /oop_intro.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "
\n", 10 | " \n", 11 | " \"QuantEcon\"\n", 12 | " \n", 13 | "
" 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "metadata": {}, 19 | "source": [ 20 | "# OOP I: Introduction to Object Oriented Programming" 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "## Contents\n", 28 | "\n", 29 | "- [OOP I: Introduction to Object Oriented Programming](#OOP-I:-Introduction-to-Object-Oriented-Programming) \n", 30 | " - [Overview](#Overview) \n", 31 | " - [Objects](#Objects) \n", 32 | " - [Summary](#Summary) " 33 | ] 34 | }, 35 | { 36 | "cell_type": "markdown", 37 | "metadata": {}, 38 | "source": [ 39 | "## Overview\n", 40 | "\n", 41 | "[OOP](https://en.wikipedia.org/wiki/Object-oriented_programming) is one of the major paradigms in programming.\n", 42 | "\n", 43 | "The traditional programming paradigm (think Fortran, C, MATLAB, etc.) is called *procedural*.\n", 44 | "\n", 45 | "It works as follows\n", 46 | "\n", 47 | "- The program has a state corresponding to the values of its variables. \n", 48 | "- Functions are called to act on these data. \n", 49 | "- Data are passed back and forth via function calls. \n", 50 | "\n", 51 | "\n", 52 | "In contrast, in the OOP paradigm\n", 53 | "\n", 54 | "- data and functions are “bundled together” into “objects” \n", 55 | "\n", 56 | "\n", 57 | "(Functions in this context are referred to as **methods**)" 58 | ] 59 | }, 60 | { 61 | "cell_type": "markdown", 62 | "metadata": {}, 63 | "source": [ 64 | "### Python and OOP\n", 65 | "\n", 66 | "Python is a pragmatic language that blends object-oriented and procedural styles, rather than taking a purist approach.\n", 67 | "\n", 68 | "However, at a foundational level, Python *is* object-oriented.\n", 69 | "\n", 70 | "In particular, in Python, *everything is an object*.\n", 71 | "\n", 72 | "In this lecture, we explain what that statement means and why it matters." 73 | ] 74 | }, 75 | { 76 | "cell_type": "markdown", 77 | "metadata": {}, 78 | "source": [ 79 | "## Objects\n", 80 | "\n", 81 | "\n", 82 | "\n", 83 | "In Python, an *object* is a collection of data and instructions held in computer memory that consists of\n", 84 | "\n", 85 | "1. a type \n", 86 | "1. a unique identity \n", 87 | "1. data (i.e., content) \n", 88 | "1. methods \n", 89 | "\n", 90 | "\n", 91 | "These concepts are defined and discussed sequentially below.\n", 92 | "\n", 93 | "\n", 94 | "" 95 | ] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "metadata": {}, 100 | "source": [ 101 | "### Type\n", 102 | "\n", 103 | "\n", 104 | "\n", 105 | "Python provides for different types of objects, to accommodate different categories of data.\n", 106 | "\n", 107 | "For example" 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": null, 113 | "metadata": { 114 | "hide-output": false 115 | }, 116 | "outputs": [], 117 | "source": [ 118 | "s = 'This is a string'\n", 119 | "type(s)" 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": null, 125 | "metadata": { 126 | "hide-output": false 127 | }, 128 | "outputs": [], 129 | "source": [ 130 | "x = 42 # Now let's create an integer\n", 131 | "type(x)" 132 | ] 133 | }, 134 | { 135 | "cell_type": "markdown", 136 | "metadata": {}, 137 | "source": [ 138 | "The type of an object matters for many expressions.\n", 139 | "\n", 140 | "For example, the addition operator between two strings means concatenation" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": null, 146 | "metadata": { 147 | "hide-output": false 148 | }, 149 | "outputs": [], 150 | "source": [ 151 | "'300' + 'cc'" 152 | ] 153 | }, 154 | { 155 | "cell_type": "markdown", 156 | "metadata": {}, 157 | "source": [ 158 | "On the other hand, between two numbers it means ordinary addition" 159 | ] 160 | }, 161 | { 162 | "cell_type": "code", 163 | "execution_count": null, 164 | "metadata": { 165 | "hide-output": false 166 | }, 167 | "outputs": [], 168 | "source": [ 169 | "300 + 400" 170 | ] 171 | }, 172 | { 173 | "cell_type": "markdown", 174 | "metadata": {}, 175 | "source": [ 176 | "Consider the following expression" 177 | ] 178 | }, 179 | { 180 | "cell_type": "code", 181 | "execution_count": null, 182 | "metadata": { 183 | "hide-output": false 184 | }, 185 | "outputs": [], 186 | "source": [ 187 | "'300' + 400" 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "metadata": {}, 193 | "source": [ 194 | "Here we are mixing types, and it’s unclear to Python whether the user wants to\n", 195 | "\n", 196 | "- convert `'300'` to an integer and then add it to `400`, or \n", 197 | "- convert `400` to string and then concatenate it with `'300'` \n", 198 | "\n", 199 | "\n", 200 | "Some languages might try to guess but Python is *strongly typed*\n", 201 | "\n", 202 | "- Type is important, and implicit type conversion is rare. \n", 203 | "- Python will respond instead by raising a `TypeError`. \n", 204 | "\n", 205 | "\n", 206 | "To avoid the error, you need to clarify by changing the relevant type.\n", 207 | "\n", 208 | "For example," 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": null, 214 | "metadata": { 215 | "hide-output": false 216 | }, 217 | "outputs": [], 218 | "source": [ 219 | "int('300') + 400 # To add as numbers, change the string to an integer" 220 | ] 221 | }, 222 | { 223 | "cell_type": "markdown", 224 | "metadata": {}, 225 | "source": [ 226 | "\n", 227 | "" 228 | ] 229 | }, 230 | { 231 | "cell_type": "markdown", 232 | "metadata": {}, 233 | "source": [ 234 | "### Identity\n", 235 | "\n", 236 | "\n", 237 | "\n", 238 | "In Python, each object has a unique identifier, which helps Python (and us) keep track of the object.\n", 239 | "\n", 240 | "The identity of an object can be obtained via the `id()` function" 241 | ] 242 | }, 243 | { 244 | "cell_type": "code", 245 | "execution_count": null, 246 | "metadata": { 247 | "hide-output": false 248 | }, 249 | "outputs": [], 250 | "source": [ 251 | "y = 2.5\n", 252 | "z = 2.5\n", 253 | "id(y)" 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": null, 259 | "metadata": { 260 | "hide-output": false 261 | }, 262 | "outputs": [], 263 | "source": [ 264 | "id(z)" 265 | ] 266 | }, 267 | { 268 | "cell_type": "markdown", 269 | "metadata": {}, 270 | "source": [ 271 | "In this example, `y` and `z` happen to have the same value (i.e., `2.5`), but they are not the same object.\n", 272 | "\n", 273 | "The identity of an object is in fact just the address of the object in memory." 274 | ] 275 | }, 276 | { 277 | "cell_type": "markdown", 278 | "metadata": {}, 279 | "source": [ 280 | "### Object Content: Data and Attributes\n", 281 | "\n", 282 | "\n", 283 | "\n", 284 | "If we set `x = 42` then we create an object of type `int` that contains\n", 285 | "the data `42`.\n", 286 | "\n", 287 | "In fact, it contains more, as the following example shows" 288 | ] 289 | }, 290 | { 291 | "cell_type": "code", 292 | "execution_count": null, 293 | "metadata": { 294 | "hide-output": false 295 | }, 296 | "outputs": [], 297 | "source": [ 298 | "x = 42\n", 299 | "x" 300 | ] 301 | }, 302 | { 303 | "cell_type": "code", 304 | "execution_count": null, 305 | "metadata": { 306 | "hide-output": false 307 | }, 308 | "outputs": [], 309 | "source": [ 310 | "x.imag" 311 | ] 312 | }, 313 | { 314 | "cell_type": "code", 315 | "execution_count": null, 316 | "metadata": { 317 | "hide-output": false 318 | }, 319 | "outputs": [], 320 | "source": [ 321 | "x.__class__" 322 | ] 323 | }, 324 | { 325 | "cell_type": "markdown", 326 | "metadata": {}, 327 | "source": [ 328 | "When Python creates this integer object, it stores with it various auxiliary information, such as the imaginary part, and the type.\n", 329 | "\n", 330 | "Any name following a dot is called an *attribute* of the object to the left of the dot.\n", 331 | "\n", 332 | "- e.g.,``imag`` and `__class__` are attributes of `x`. \n", 333 | "\n", 334 | "\n", 335 | "We see from this example that objects have attributes that contain auxiliary information.\n", 336 | "\n", 337 | "They also have attributes that act like functions, called *methods*.\n", 338 | "\n", 339 | "These attributes are important, so let’s discuss them in-depth.\n", 340 | "\n", 341 | "\n", 342 | "" 343 | ] 344 | }, 345 | { 346 | "cell_type": "markdown", 347 | "metadata": {}, 348 | "source": [ 349 | "### Methods\n", 350 | "\n", 351 | "\n", 352 | "\n", 353 | "Methods are *functions that are bundled with objects*.\n", 354 | "\n", 355 | "Formally, methods are attributes of objects that are callable (i.e., can be called as functions)" 356 | ] 357 | }, 358 | { 359 | "cell_type": "code", 360 | "execution_count": null, 361 | "metadata": { 362 | "hide-output": false 363 | }, 364 | "outputs": [], 365 | "source": [ 366 | "x = ['foo', 'bar']\n", 367 | "callable(x.append)" 368 | ] 369 | }, 370 | { 371 | "cell_type": "code", 372 | "execution_count": null, 373 | "metadata": { 374 | "hide-output": false 375 | }, 376 | "outputs": [], 377 | "source": [ 378 | "callable(x.__doc__)" 379 | ] 380 | }, 381 | { 382 | "cell_type": "markdown", 383 | "metadata": {}, 384 | "source": [ 385 | "Methods typically act on the data contained in the object they belong to, or combine that data with other data" 386 | ] 387 | }, 388 | { 389 | "cell_type": "code", 390 | "execution_count": null, 391 | "metadata": { 392 | "hide-output": false 393 | }, 394 | "outputs": [], 395 | "source": [ 396 | "x = ['a', 'b']\n", 397 | "x.append('c')\n", 398 | "s = 'This is a string'\n", 399 | "s.upper()" 400 | ] 401 | }, 402 | { 403 | "cell_type": "code", 404 | "execution_count": null, 405 | "metadata": { 406 | "hide-output": false 407 | }, 408 | "outputs": [], 409 | "source": [ 410 | "s.lower()" 411 | ] 412 | }, 413 | { 414 | "cell_type": "code", 415 | "execution_count": null, 416 | "metadata": { 417 | "hide-output": false 418 | }, 419 | "outputs": [], 420 | "source": [ 421 | "s.replace('This', 'That')" 422 | ] 423 | }, 424 | { 425 | "cell_type": "markdown", 426 | "metadata": {}, 427 | "source": [ 428 | "A great deal of Python functionality is organized around method calls.\n", 429 | "\n", 430 | "For example, consider the following piece of code" 431 | ] 432 | }, 433 | { 434 | "cell_type": "code", 435 | "execution_count": null, 436 | "metadata": { 437 | "hide-output": false 438 | }, 439 | "outputs": [], 440 | "source": [ 441 | "x = ['a', 'b']\n", 442 | "x[0] = 'aa' # Item assignment using square bracket notation\n", 443 | "x" 444 | ] 445 | }, 446 | { 447 | "cell_type": "markdown", 448 | "metadata": {}, 449 | "source": [ 450 | "It doesn’t look like there are any methods used here, but in fact the square bracket assignment notation is just a convenient interface to a method call.\n", 451 | "\n", 452 | "What actually happens is that Python calls the `__setitem__` method, as follows" 453 | ] 454 | }, 455 | { 456 | "cell_type": "code", 457 | "execution_count": null, 458 | "metadata": { 459 | "hide-output": false 460 | }, 461 | "outputs": [], 462 | "source": [ 463 | "x = ['a', 'b']\n", 464 | "x.__setitem__(0, 'aa') # Equivalent to x[0] = 'aa'\n", 465 | "x" 466 | ] 467 | }, 468 | { 469 | "cell_type": "markdown", 470 | "metadata": {}, 471 | "source": [ 472 | "(If you wanted to you could modify the `__setitem__` method, so that square bracket assignment does something totally different)" 473 | ] 474 | }, 475 | { 476 | "cell_type": "markdown", 477 | "metadata": {}, 478 | "source": [ 479 | "## Summary\n", 480 | "\n", 481 | "In Python, *everything in memory is treated as an object*.\n", 482 | "\n", 483 | "This includes not just lists, strings, etc., but also less obvious things, such as\n", 484 | "\n", 485 | "- functions (once they have been read into memory) \n", 486 | "- modules (ditto) \n", 487 | "- files opened for reading or writing \n", 488 | "- integers, etc. \n", 489 | "\n", 490 | "\n", 491 | "Consider, for example, functions.\n", 492 | "\n", 493 | "When Python reads a function definition, it creates a **function object** and stores it in memory.\n", 494 | "\n", 495 | "The following code illustrates" 496 | ] 497 | }, 498 | { 499 | "cell_type": "code", 500 | "execution_count": null, 501 | "metadata": { 502 | "hide-output": false 503 | }, 504 | "outputs": [], 505 | "source": [ 506 | "def f(x): return x**2\n", 507 | "f" 508 | ] 509 | }, 510 | { 511 | "cell_type": "code", 512 | "execution_count": null, 513 | "metadata": { 514 | "hide-output": false 515 | }, 516 | "outputs": [], 517 | "source": [ 518 | "type(f)" 519 | ] 520 | }, 521 | { 522 | "cell_type": "code", 523 | "execution_count": null, 524 | "metadata": { 525 | "hide-output": false 526 | }, 527 | "outputs": [], 528 | "source": [ 529 | "id(f)" 530 | ] 531 | }, 532 | { 533 | "cell_type": "code", 534 | "execution_count": null, 535 | "metadata": { 536 | "hide-output": false 537 | }, 538 | "outputs": [], 539 | "source": [ 540 | "f.__name__" 541 | ] 542 | }, 543 | { 544 | "cell_type": "markdown", 545 | "metadata": {}, 546 | "source": [ 547 | "We can see that `f` has type, identity, attributes and so on—just like any other object.\n", 548 | "\n", 549 | "It also has methods.\n", 550 | "\n", 551 | "One example is the `__call__` method, which just evaluates the function" 552 | ] 553 | }, 554 | { 555 | "cell_type": "code", 556 | "execution_count": null, 557 | "metadata": { 558 | "hide-output": false 559 | }, 560 | "outputs": [], 561 | "source": [ 562 | "f.__call__(3)" 563 | ] 564 | }, 565 | { 566 | "cell_type": "markdown", 567 | "metadata": {}, 568 | "source": [ 569 | "Another is the `__dir__` method, which returns a list of attributes.\n", 570 | "\n", 571 | "Modules loaded into memory are also treated as objects" 572 | ] 573 | }, 574 | { 575 | "cell_type": "code", 576 | "execution_count": null, 577 | "metadata": { 578 | "hide-output": false 579 | }, 580 | "outputs": [], 581 | "source": [ 582 | "import math\n", 583 | "\n", 584 | "id(math)" 585 | ] 586 | }, 587 | { 588 | "cell_type": "markdown", 589 | "metadata": {}, 590 | "source": [ 591 | "This uniform treatment of data in Python (everything is an object) helps keep the language simple and consistent." 592 | ] 593 | } 594 | ], 595 | "metadata": { 596 | "date": 1584334749.33412, 597 | "filename": "oop_intro.rst", 598 | "kernelspec": { 599 | "display_name": "Python", 600 | "language": "python3", 601 | "name": "python3" 602 | }, 603 | "title": "OOP I: Introduction to Object Oriented Programming" 604 | }, 605 | "nbformat": 4, 606 | "nbformat_minor": 2 607 | } -------------------------------------------------------------------------------- /optgrowth_fast.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "
\n", 10 | " \n", 11 | " \"QuantEcon\"\n", 12 | " \n", 13 | "
" 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "metadata": {}, 19 | "source": [ 20 | "# Optimal Growth II: Accelerating the Code with Numba" 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "## Contents\n", 28 | "\n", 29 | "- [Optimal Growth II: Accelerating the Code with Numba](#Optimal-Growth-II:-Accelerating-the-Code-with-Numba) \n", 30 | " - [Overview](#Overview) \n", 31 | " - [The Model](#The-Model) \n", 32 | " - [Computation](#Computation) \n", 33 | " - [Exercises](#Exercises) \n", 34 | " - [Solutions](#Solutions) " 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "In addition to what’s in Anaconda, this lecture will need the following libraries:" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": null, 47 | "metadata": { 48 | "hide-output": true 49 | }, 50 | "outputs": [], 51 | "source": [ 52 | "!pip install --upgrade quantecon\n", 53 | "!pip install --upgrade interpolation" 54 | ] 55 | }, 56 | { 57 | "cell_type": "markdown", 58 | "metadata": {}, 59 | "source": [ 60 | "## Overview\n", 61 | "\n", 62 | "In a [previous lecture](https://python.quantecon.org/optgrowth.html), we studied a stochastic optimal\n", 63 | "growth model with one representative agent.\n", 64 | "\n", 65 | "We solved the model using dynamic programming.\n", 66 | "\n", 67 | "In writing our code, we focused on clarity and flexibility.\n", 68 | "\n", 69 | "These are important, but there’s often a trade-off between flexibility and\n", 70 | "speed.\n", 71 | "\n", 72 | "The reason is that, when code is less flexible, we can exploit structure more\n", 73 | "easily.\n", 74 | "\n", 75 | "(This is true about algorithms and mathematical problems more generally:\n", 76 | "more specific problems have more structure, which, with some thought, can be\n", 77 | "exploited for better results.)\n", 78 | "\n", 79 | "So, in this lecture, we are going to accept less flexibility while gaining\n", 80 | "speed, using just-in-time (JIT) compilation to\n", 81 | "accelerate our code.\n", 82 | "\n", 83 | "Let’s start with some imports:" 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": null, 89 | "metadata": { 90 | "hide-output": false 91 | }, 92 | "outputs": [], 93 | "source": [ 94 | "import numpy as np\n", 95 | "import matplotlib.pyplot as plt\n", 96 | "from interpolation import interp\n", 97 | "from numba import jit, njit, jitclass, prange, float64, int32\n", 98 | "from quantecon.optimize.scalar_maximization import brent_max\n", 99 | "\n", 100 | "%matplotlib inline" 101 | ] 102 | }, 103 | { 104 | "cell_type": "markdown", 105 | "metadata": {}, 106 | "source": [ 107 | "We are using an interpolation function from\n", 108 | "[interpolation.py](https://github.com/EconForge/interpolation.py) because it\n", 109 | "helps us JIT-compile our code.\n", 110 | "\n", 111 | "The function brent_max is also designed for embedding in JIT-compiled code.\n", 112 | "\n", 113 | "These are alternatives to similar functions in SciPy (which, unfortunately, are not JIT-aware)." 114 | ] 115 | }, 116 | { 117 | "cell_type": "markdown", 118 | "metadata": {}, 119 | "source": [ 120 | "## The Model\n", 121 | "\n", 122 | "\n", 123 | "\n", 124 | "The model is the same as discussed in [this lecture](https://python.quantecon.org/optgrowth.html).\n", 125 | "\n", 126 | "We will use the same algorithm to solve it—the only difference is in the\n", 127 | "implementation itself.\n", 128 | "\n", 129 | "We will use the CRRA utility specification\n", 130 | "\n", 131 | "$$\n", 132 | "u(c) = \\frac{c^{1 - γ} - 1} {1 - γ}\n", 133 | "$$\n", 134 | "\n", 135 | "We continue to assume that\n", 136 | "\n", 137 | "- $ f(k) = k^{\\alpha} $ \n", 138 | "- $ \\phi $ is the distribution of $ \\exp(\\mu + s \\zeta) $ when $ \\zeta $ is standard normal " 139 | ] 140 | }, 141 | { 142 | "cell_type": "markdown", 143 | "metadata": {}, 144 | "source": [ 145 | "## Computation\n", 146 | "\n", 147 | "\n", 148 | "\n", 149 | "As before, we will store the primitives of the optimal growth model in a class.\n", 150 | "\n", 151 | "But now we are going to use [Numba’s](https://python.quantecon.org/numba.html) `@jitclass` decorator to\n", 152 | "target our class for JIT compilation.\n", 153 | "\n", 154 | "Because we are going to use Numba to compile our class, we need to specify the\n", 155 | "types of the data:" 156 | ] 157 | }, 158 | { 159 | "cell_type": "code", 160 | "execution_count": null, 161 | "metadata": { 162 | "hide-output": false 163 | }, 164 | "outputs": [], 165 | "source": [ 166 | "opt_growth_data = [\n", 167 | " ('α', float64), # Production parameter\n", 168 | " ('β', float64), # Discount factor\n", 169 | " ('μ', float64), # Shock location parameter\n", 170 | " ('γ', float64), # Preference parameter\n", 171 | " ('s', float64), # Shock scale parameter\n", 172 | " ('grid', float64[:]), # Grid (array)\n", 173 | " ('shocks', float64[:]) # Shock draws (array)\n", 174 | "]" 175 | ] 176 | }, 177 | { 178 | "cell_type": "markdown", 179 | "metadata": {}, 180 | "source": [ 181 | "Note the convention for specifying the types of each argument.\n", 182 | "\n", 183 | "Now we’re ready to create our class, which will combine parameters and a\n", 184 | "method that realizes the right hand side of the Bellman equation [(9)](https://python.quantecon.org/optgrowth.html#equation-fpb30).\n", 185 | "\n", 186 | "You will notice that, unlike in the [previous lecture](https://python.quantecon.org/optgrowth.html), we\n", 187 | "hardwire the Cobb-Douglas production and CRRA utility specifications into the\n", 188 | "class.\n", 189 | "\n", 190 | "Thus, we are losing flexibility, but we will gain substantial speed." 191 | ] 192 | }, 193 | { 194 | "cell_type": "code", 195 | "execution_count": null, 196 | "metadata": { 197 | "hide-output": false 198 | }, 199 | "outputs": [], 200 | "source": [ 201 | "@jitclass(opt_growth_data)\n", 202 | "class OptimalGrowthModel:\n", 203 | "\n", 204 | " def __init__(self,\n", 205 | " α=0.4,\n", 206 | " β=0.96,\n", 207 | " μ=0,\n", 208 | " s=0.1,\n", 209 | " γ=1.5,\n", 210 | " grid_max=4,\n", 211 | " grid_size=120,\n", 212 | " shock_size=250,\n", 213 | " seed=1234):\n", 214 | "\n", 215 | " self.α, self.β, self.γ, self.μ, self.s = α, β, γ, μ, s\n", 216 | "\n", 217 | " # Set up grid\n", 218 | " self.grid = np.linspace(1e-5, grid_max, grid_size)\n", 219 | "\n", 220 | " # Store shocks (with a seed, so results are reproducible)\n", 221 | " np.random.seed(seed)\n", 222 | " self.shocks = np.exp(μ + s * np.random.randn(shock_size))\n", 223 | "\n", 224 | " def f(self, k):\n", 225 | " return k**self.α\n", 226 | "\n", 227 | " def u(self, c):\n", 228 | " return (c**(1 - self.γ) - 1) / (1 - self.γ)\n", 229 | "\n", 230 | " def objective(self, c, y, v_array):\n", 231 | " \"\"\"\n", 232 | " Right hand side of the Bellman equation.\n", 233 | " \"\"\"\n", 234 | "\n", 235 | " u, f, β, shocks = self.u, self.f, self.β, self.shocks\n", 236 | "\n", 237 | " v = lambda x: interp(self.grid, v_array, x)\n", 238 | "\n", 239 | " return u(c) + β * np.mean(v(f(y - c) * shocks))" 240 | ] 241 | }, 242 | { 243 | "cell_type": "markdown", 244 | "metadata": {}, 245 | "source": [ 246 | "### The Bellman Operator\n", 247 | "\n", 248 | "Here’s a function that uses JIT compilation to accelerate the Bellman operator" 249 | ] 250 | }, 251 | { 252 | "cell_type": "code", 253 | "execution_count": null, 254 | "metadata": { 255 | "hide-output": false 256 | }, 257 | "outputs": [], 258 | "source": [ 259 | "@jit(nopython=True)\n", 260 | "def T(og, v):\n", 261 | " \"\"\"\n", 262 | " The Bellman operator.\n", 263 | "\n", 264 | " * og is an instance of OptimalGrowthModel\n", 265 | " * v is an array representing a guess of the value function\n", 266 | " \"\"\"\n", 267 | " v_new = np.empty_like(v)\n", 268 | "\n", 269 | " for i in range(len(og.grid)):\n", 270 | " y = og.grid[i]\n", 271 | "\n", 272 | " # Maximize RHS of Bellman equation at state y\n", 273 | " v_max = brent_max(og.objective, 1e-10, y, args=(y, v))[1]\n", 274 | " v_new[i] = v_max\n", 275 | "\n", 276 | " return v_new" 277 | ] 278 | }, 279 | { 280 | "cell_type": "markdown", 281 | "metadata": {}, 282 | "source": [ 283 | "Here’s another function, very similar to the last, that computes a $ v $-greedy\n", 284 | "policy:" 285 | ] 286 | }, 287 | { 288 | "cell_type": "code", 289 | "execution_count": null, 290 | "metadata": { 291 | "hide-output": false 292 | }, 293 | "outputs": [], 294 | "source": [ 295 | "@jit(nopython=True)\n", 296 | "def get_greedy(og, v):\n", 297 | " \"\"\"\n", 298 | " Compute a v-greedy policy.\n", 299 | "\n", 300 | " * og is an instance of OptimalGrowthModel\n", 301 | " * v is an array representing a guess of the value function\n", 302 | " \"\"\"\n", 303 | " v_greedy = np.empty_like(v)\n", 304 | "\n", 305 | " for i in range(len(og.grid)):\n", 306 | " y = og.grid[i]\n", 307 | "\n", 308 | " # Find maximizer of RHS of Bellman equation at state y\n", 309 | " c_star = brent_max(og.objective, 1e-10, y, args=(y, v))[0]\n", 310 | " v_greedy[i] = c_star\n", 311 | "\n", 312 | " return v_greedy" 313 | ] 314 | }, 315 | { 316 | "cell_type": "markdown", 317 | "metadata": {}, 318 | "source": [ 319 | "The last two functions could be merged, as they were in our [previous implementation](https://python.quantecon.org/optgrowth.html), but we resisted doing so to increase efficiency.\n", 320 | "\n", 321 | "Here’s a function that iterates from a starting guess of the value function until the difference between successive iterates is below a particular tolerance level." 322 | ] 323 | }, 324 | { 325 | "cell_type": "code", 326 | "execution_count": null, 327 | "metadata": { 328 | "hide-output": false 329 | }, 330 | "outputs": [], 331 | "source": [ 332 | "def solve_model(og,\n", 333 | " tol=1e-4,\n", 334 | " max_iter=1000,\n", 335 | " verbose=True,\n", 336 | " print_skip=25):\n", 337 | "\n", 338 | " # Set up loop\n", 339 | " v = np.log(og.grid) # Initial condition\n", 340 | " i = 0\n", 341 | " error = tol + 1\n", 342 | "\n", 343 | " while i < max_iter and error > tol:\n", 344 | " v_new = T(og, v)\n", 345 | " error = np.max(np.abs(v - v_new))\n", 346 | " i += 1\n", 347 | " if verbose and i % print_skip == 0:\n", 348 | " print(f\"Error at iteration {i} is {error}.\")\n", 349 | " v = v_new\n", 350 | "\n", 351 | " if i == max_iter:\n", 352 | " print(\"Failed to converge!\")\n", 353 | "\n", 354 | " if verbose and i < max_iter:\n", 355 | " print(f\"\\nConverged in {i} iterations.\")\n", 356 | "\n", 357 | " return v_new" 358 | ] 359 | }, 360 | { 361 | "cell_type": "markdown", 362 | "metadata": {}, 363 | "source": [ 364 | "Let’s compute the approximate solution at the default parameters.\n", 365 | "\n", 366 | "First we create an instance:" 367 | ] 368 | }, 369 | { 370 | "cell_type": "code", 371 | "execution_count": null, 372 | "metadata": { 373 | "hide-output": false 374 | }, 375 | "outputs": [], 376 | "source": [ 377 | "og = OptimalGrowthModel()" 378 | ] 379 | }, 380 | { 381 | "cell_type": "markdown", 382 | "metadata": {}, 383 | "source": [ 384 | "Now we call `solve_model`, using the `%%time` magic to check how long it\n", 385 | "takes." 386 | ] 387 | }, 388 | { 389 | "cell_type": "code", 390 | "execution_count": null, 391 | "metadata": { 392 | "hide-output": false 393 | }, 394 | "outputs": [], 395 | "source": [ 396 | "%%time\n", 397 | "v_solution = solve_model(og)" 398 | ] 399 | }, 400 | { 401 | "cell_type": "markdown", 402 | "metadata": {}, 403 | "source": [ 404 | "You will notice that this is *much* faster than our [original implementation](https://python.quantecon.org/optgrowth.html#ogex1).\n", 405 | "\n", 406 | "Let’s plot the resulting policy:" 407 | ] 408 | }, 409 | { 410 | "cell_type": "code", 411 | "execution_count": null, 412 | "metadata": { 413 | "hide-output": false 414 | }, 415 | "outputs": [], 416 | "source": [ 417 | "v_greedy = get_greedy(og, v_solution)\n", 418 | "\n", 419 | "fig, ax = plt.subplots()\n", 420 | "\n", 421 | "ax.plot(og.grid, v_greedy, lw=2,\n", 422 | " alpha=0.6, label='Approximate value function')\n", 423 | "\n", 424 | "ax.legend(loc='lower right')\n", 425 | "plt.show()" 426 | ] 427 | }, 428 | { 429 | "cell_type": "markdown", 430 | "metadata": {}, 431 | "source": [ 432 | "Everything seems in order, so our code acceleration has been successful!" 433 | ] 434 | }, 435 | { 436 | "cell_type": "markdown", 437 | "metadata": {}, 438 | "source": [ 439 | "## Exercises" 440 | ] 441 | }, 442 | { 443 | "cell_type": "markdown", 444 | "metadata": {}, 445 | "source": [ 446 | "### Exercise 1\n", 447 | "\n", 448 | "Once an optimal consumption policy $ \\sigma $ is given, income follows\n", 449 | "\n", 450 | "$$\n", 451 | "y_{t+1} = f(y_t - \\sigma(y_t)) \\xi_{t+1}\n", 452 | "$$\n", 453 | "\n", 454 | "The next figure shows a simulation of 100 elements of this sequence for three\n", 455 | "different discount factors (and hence three different policies).\n", 456 | "\n", 457 | "\n", 458 | "\n", 459 | " \n", 460 | "In each sequence, the initial condition is $ y_0 = 0.1 $.\n", 461 | "\n", 462 | "The discount factors are `discount_factors = (0.8, 0.9, 0.98)`.\n", 463 | "\n", 464 | "We have also dialed down the shocks a bit with `s = 0.05`.\n", 465 | "\n", 466 | "Otherwise, the parameters and primitives are the same as the log-linear model discussed earlier in the lecture.\n", 467 | "\n", 468 | "Notice that more patient agents typically have higher wealth.\n", 469 | "\n", 470 | "Replicate the figure modulo randomness." 471 | ] 472 | }, 473 | { 474 | "cell_type": "markdown", 475 | "metadata": {}, 476 | "source": [ 477 | "## Solutions" 478 | ] 479 | }, 480 | { 481 | "cell_type": "markdown", 482 | "metadata": {}, 483 | "source": [ 484 | "### Exercise 1\n", 485 | "\n", 486 | "Here’s one solution" 487 | ] 488 | }, 489 | { 490 | "cell_type": "code", 491 | "execution_count": null, 492 | "metadata": { 493 | "hide-output": false 494 | }, 495 | "outputs": [], 496 | "source": [ 497 | "def simulate_og(σ_func, og, y0=0.1, ts_length=100):\n", 498 | " '''\n", 499 | " Compute a time series given consumption policy σ.\n", 500 | " '''\n", 501 | " y = np.empty(ts_length)\n", 502 | " ξ = np.random.randn(ts_length-1)\n", 503 | " y[0] = y0\n", 504 | " for t in range(ts_length-1):\n", 505 | " y[t+1] = (y[t] - σ_func(y[t]))**og.α * np.exp(og.μ + og.s * ξ[t])\n", 506 | " return y" 507 | ] 508 | }, 509 | { 510 | "cell_type": "code", 511 | "execution_count": null, 512 | "metadata": { 513 | "hide-output": false 514 | }, 515 | "outputs": [], 516 | "source": [ 517 | "fig, ax = plt.subplots()\n", 518 | "\n", 519 | "for β in (0.8, 0.9, 0.98):\n", 520 | "\n", 521 | " og = OptimalGrowthModel(β=β, s=0.05)\n", 522 | "\n", 523 | " v_solution = solve_model(og)\n", 524 | " v_greedy = get_greedy(og, v_solution)\n", 525 | "\n", 526 | " # Define an optimal policy function\n", 527 | " σ_func = lambda x: interp(og.grid, v_greedy, x)\n", 528 | " y = simulate_og(σ_func, og)\n", 529 | " ax.plot(y, lw=2, alpha=0.6, label=rf'$\\beta = {β}$')\n", 530 | "\n", 531 | "ax.legend(loc='lower right')\n", 532 | "plt.show()" 533 | ] 534 | } 535 | ], 536 | "metadata": { 537 | "date": 1584334750.4842002, 538 | "filename": "optgrowth_fast.rst", 539 | "kernelspec": { 540 | "display_name": "Python", 541 | "language": "python3", 542 | "name": "python3" 543 | }, 544 | "title": "Optimal Growth II: Accelerating the Code with Numba" 545 | }, 546 | "nbformat": 4, 547 | "nbformat_minor": 2 548 | } -------------------------------------------------------------------------------- /permanent_income_dles.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "
\n", 10 | " \n", 11 | " \"QuantEcon\"\n", 12 | " \n", 13 | "
\n", 14 | "\n", 15 | "\n", 16 | "" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# Permanent Income Model using the DLE Class" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "## Contents\n", 31 | "\n", 32 | "- [Permanent Income Model using the DLE Class](#Permanent-Income-Model-using-the-DLE-Class) \n", 33 | " - [The Permanent Income Model](#The-Permanent-Income-Model) " 34 | ] 35 | }, 36 | { 37 | "cell_type": "markdown", 38 | "metadata": {}, 39 | "source": [ 40 | "This lecture is part of a suite of lectures that use the quantecon DLE class to instantiate models within the\n", 41 | "[[HS13b]](https://python.quantecon.org/zreferences.html#hs2013) class of models described in detail in [Recursive Models of Dynamic Linear Economies](https://python.quantecon.org/hs_recursive_models.html).\n", 42 | "\n", 43 | "In addition to what’s included in Anaconda, this lecture uses the quantecon library." 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": null, 49 | "metadata": { 50 | "hide-output": true 51 | }, 52 | "outputs": [], 53 | "source": [ 54 | "!pip install --upgrade quantecon" 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "metadata": {}, 60 | "source": [ 61 | "This lecture adds a third solution method for the\n", 62 | "linear-quadratic-Gaussian permanent income model with\n", 63 | "$ \\beta R = 1 $, complementing the other two solution methods described in\n", 64 | "[Optimal Savings I: The Permanent Income Model](https://python.quantecon.org/perm_income.html) and\n", 65 | "[Optimal Savings II: LQ Techniques](https://python.quantecon.org/perm_income_cons.html) and this Jupyter\n", 66 | "notebook [http://nbviewer.jupyter.org/github/QuantEcon/QuantEcon.notebooks/blob/master/permanent_income.ipynb](http://nbviewer.jupyter.org/github/QuantEcon/QuantEcon.notebooks/blob/master/permanent_income.ipynb).\n", 67 | "\n", 68 | "The additional solution method uses the **DLE** class.\n", 69 | "\n", 70 | "In this way, we map the permanent\n", 71 | "income model into the framework of Hansen & Sargent (2013) “Recursive\n", 72 | "Models of Dynamic Linear Economies” [[HS13b]](https://python.quantecon.org/zreferences.html#hs2013).\n", 73 | "\n", 74 | "We’ll also require the following imports" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": null, 80 | "metadata": { 81 | "hide-output": false 82 | }, 83 | "outputs": [], 84 | "source": [ 85 | "import quantecon as qe\n", 86 | "import numpy as np\n", 87 | "import scipy.linalg as la\n", 88 | "import matplotlib.pyplot as plt\n", 89 | "%matplotlib inline\n", 90 | "from quantecon import DLE\n", 91 | "\n", 92 | "np.set_printoptions(suppress=True, precision=4)" 93 | ] 94 | }, 95 | { 96 | "cell_type": "markdown", 97 | "metadata": {}, 98 | "source": [ 99 | "## The Permanent Income Model\n", 100 | "\n", 101 | "The LQ permanent income model is an example of a **savings problem**.\n", 102 | "\n", 103 | "A consumer has preferences over consumption streams that are ordered by\n", 104 | "the utility functional\n", 105 | "\n", 106 | "\n", 107 | "\n", 108 | "$$\n", 109 | "E_0 \\sum_{t=0}^\\infty \\beta^t u(c_t) \\tag{1}\n", 110 | "$$\n", 111 | "\n", 112 | "where $ E_t $ is the mathematical expectation conditioned on the\n", 113 | "consumer’s time $ t $ information, $ c_t $ is time $ t $\n", 114 | "consumption, $ u(c) $ is a strictly concave one-period utility\n", 115 | "function, and $ \\beta \\in (0,1) $ is a discount factor.\n", 116 | "\n", 117 | "The LQ model gets its name partly from assuming that the utility\n", 118 | "function $ u $ is quadratic:\n", 119 | "\n", 120 | "$$\n", 121 | "u(c) = -.5(c - \\gamma)^2\n", 122 | "$$\n", 123 | "\n", 124 | "where $ \\gamma>0 $ is a bliss level of consumption.\n", 125 | "\n", 126 | "The consumer maximizes the utility functional [(1)](#equation-perm-utility) by choosing a\n", 127 | "consumption, borrowing plan $ \\{c_t, b_{t+1}\\}_{t=0}^\\infty $\n", 128 | "subject to the sequence of budget constraints\n", 129 | "\n", 130 | "\n", 131 | "\n", 132 | "$$\n", 133 | "c_t + b_t = R^{-1} b_{t+1} + y_t, t \\geq 0 \\tag{2}\n", 134 | "$$\n", 135 | "\n", 136 | "where $ y_t $ is an exogenous stationary endowment process,\n", 137 | "$ R $ is a constant gross risk-free interest rate, $ b_t $ is\n", 138 | "one-period risk-free debt maturing at $ t $, and $ b_0 $ is a\n", 139 | "given initial condition.\n", 140 | "\n", 141 | "We shall assume that $ R^{-1} = \\beta $.\n", 142 | "\n", 143 | "Equation [(2)](#equation-max-utility) is linear.\n", 144 | "\n", 145 | "We use another set of linear equations to model the endowment process.\n", 146 | "\n", 147 | "In particular, we assume that the endowment process has the state-space\n", 148 | "representation\n", 149 | "\n", 150 | "\n", 151 | "\n", 152 | "$$\n", 153 | "\\begin{aligned} z_{t+1} & = A_{22} z_t + C_2 w_{t+1} \\cr\n", 154 | " y_t & = U_y z_t \\cr \\end{aligned} \\tag{3}\n", 155 | "$$\n", 156 | "\n", 157 | "where $ w_{t+1} $ is an IID process with mean zero and identity\n", 158 | "contemporaneous covariance matrix, $ A_{22} $ is a stable matrix,\n", 159 | "its eigenvalues being strictly below unity in modulus, and $ U_y $\n", 160 | "is a selection vector that identifies $ y $ with a particular linear\n", 161 | "combination of the $ z_t $.\n", 162 | "\n", 163 | "We impose the following condition on the consumption, borrowing plan:\n", 164 | "\n", 165 | "\n", 166 | "\n", 167 | "$$\n", 168 | "E_0 \\sum_{t=0}^\\infty \\beta^t b_t^2 < +\\infty \\tag{4}\n", 169 | "$$\n", 170 | "\n", 171 | "This condition suffices to rule out Ponzi schemes.\n", 172 | "\n", 173 | "(We impose this condition to rule out a borrow-more-and-more plan that\n", 174 | "would allow the household to enjoy bliss consumption forever)\n", 175 | "\n", 176 | "The state vector confronting the household at $ t $ is\n", 177 | "\n", 178 | "$$\n", 179 | "x_t = \\begin{bmatrix} z_t \\\\ b_t \\end{bmatrix}\n", 180 | "$$\n", 181 | "\n", 182 | "where $ b_t $ is its one-period debt falling due at the beginning of\n", 183 | "period $ t $ and $ z_t $ contains all variables useful for\n", 184 | "forecasting its future endowment.\n", 185 | "\n", 186 | "We assume that $ \\{y_t\\} $ follows a second order univariate\n", 187 | "autoregressive process:\n", 188 | "\n", 189 | "$$\n", 190 | "y_{t+1} = \\alpha + \\rho_1 y_t + \\rho_2 y_{t-1} + \\sigma w_{t+1}\n", 191 | "$$" 192 | ] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "metadata": {}, 197 | "source": [ 198 | "### Solution with the DLE Class\n", 199 | "\n", 200 | "One way of solving this model is to map the problem into the framework\n", 201 | "outlined in Section 4.8 of [[HS13b]](https://python.quantecon.org/zreferences.html#hs2013) by setting up our technology,\n", 202 | "information and preference matrices as follows:\n", 203 | "\n", 204 | "**Technology:**\n", 205 | "$ \\phi_c= \\left[ {\\begin{array}{c} 1 \\\\ 0 \\end{array} } \\right] $\n", 206 | ",\n", 207 | "$ \\phi_g= \\left[ {\\begin{array}{c} 0 \\\\ 1 \\end{array} } \\right] $\n", 208 | ",\n", 209 | "$ \\phi_i= \\left[ {\\begin{array}{c} -1 \\\\ -0.00001 \\end{array} } \\right] $,\n", 210 | "$ \\Gamma= \\left[ {\\begin{array}{c} -1 \\\\ 0 \\end{array} } \\right] $,\n", 211 | "$ \\Delta_k = 0 $,  $ \\Theta_k = R $.\n", 212 | "\n", 213 | "**Information:**\n", 214 | "$ A_{22} = \\left[ {\\begin{array}{ccc} 1 & 0 & 0 \\\\ \\alpha & \\rho_1 & \\rho_2 \\\\ 0 & 1 & 0 \\end{array} } \\right] $,\n", 215 | "$ C_{2} = \\left[ {\\begin{array}{c} 0 \\\\ \\sigma \\\\ 0 \\end{array} } \\right] $,\n", 216 | "$ U_b = \\left[ {\\begin{array}{ccc} \\gamma & 0 & 0 \\end{array} } \\right] $,\n", 217 | "$ U_d = \\left[ {\\begin{array}{ccc} 0 & 1 & 0 \\\\ 0 & 0 & 0 \\end{array} } \\right] $.\n", 218 | "\n", 219 | "**Preferences:** $ \\Lambda = 0 $, $ \\Pi = 1 $,\n", 220 | "$ \\Delta_h = 0 $, $ \\Theta_h = 0 $.\n", 221 | "\n", 222 | "We set parameters\n", 223 | "\n", 224 | "$ \\alpha = 10, \\beta = 0.95, \\rho_1 = 0.9, \\rho_2 = 0, \\sigma = 1 $\n", 225 | "\n", 226 | "(The value of $ \\gamma $ does not affect the optimal decision rule)\n", 227 | "\n", 228 | "The chosen matrices mean that the household’s technology is:\n", 229 | "\n", 230 | "$$\n", 231 | "c_t + k_{t-1} = i_t + y_t\n", 232 | "$$\n", 233 | "\n", 234 | "$$\n", 235 | "\\frac{k_t}{R} = i_t\n", 236 | "$$\n", 237 | "\n", 238 | "$$\n", 239 | "l_t^2 = (0.00001)^2i_t\n", 240 | "$$\n", 241 | "\n", 242 | "Combining the first two of these gives the budget constraint of the\n", 243 | "permanent income model, where $ k_t = b_{t+1} $.\n", 244 | "\n", 245 | "The third equation is a very small penalty on debt-accumulation to rule\n", 246 | "out Ponzi schemes.\n", 247 | "\n", 248 | "We set up this instance of the DLE class below:" 249 | ] 250 | }, 251 | { 252 | "cell_type": "code", 253 | "execution_count": null, 254 | "metadata": { 255 | "hide-output": false 256 | }, 257 | "outputs": [], 258 | "source": [ 259 | "α, β, ρ_1, ρ_2, σ = 10, 0.95, 0.9, 0, 1\n", 260 | "\n", 261 | "γ = np.array([[-1], [0]])\n", 262 | "ϕ_c = np.array([[1], [0]])\n", 263 | "ϕ_g = np.array([[0], [1]])\n", 264 | "ϕ_1 = 1e-5\n", 265 | "ϕ_i = np.array([[-1], [-ϕ_1]])\n", 266 | "δ_k = np.array([[0]])\n", 267 | "θ_k = np.array([[1 / β]])\n", 268 | "β = np.array([[β]])\n", 269 | "l_λ = np.array([[0]])\n", 270 | "π_h = np.array([[1]])\n", 271 | "δ_h = np.array([[0]])\n", 272 | "θ_h = np.array([[0]])\n", 273 | "\n", 274 | "a22 = np.array([[1, 0, 0],\n", 275 | " [α, ρ_1, ρ_2],\n", 276 | " [0, 1, 0]])\n", 277 | "\n", 278 | "c2 = np.array([[0], [σ], [0]])\n", 279 | "ud = np.array([[0, 1, 0],\n", 280 | " [0, 0, 0]])\n", 281 | "ub = np.array([[100, 0, 0]])\n", 282 | "\n", 283 | "x0 = np.array([[0], [0], [1], [0], [0]])\n", 284 | "\n", 285 | "info1 = (a22, c2, ub, ud)\n", 286 | "tech1 = (ϕ_c, ϕ_g, ϕ_i, γ, δ_k, θ_k)\n", 287 | "pref1 = (β, l_λ, π_h, δ_h, θ_h)\n", 288 | "econ1 = DLE(info1, tech1, pref1)" 289 | ] 290 | }, 291 | { 292 | "cell_type": "markdown", 293 | "metadata": {}, 294 | "source": [ 295 | "To check the solution of this model with that from the **LQ** problem,\n", 296 | "we select the $ S_c $ matrix from the DLE class.\n", 297 | "\n", 298 | "The solution to the\n", 299 | "DLE economy has:\n", 300 | "\n", 301 | "$$\n", 302 | "c_t = S_c x_t\n", 303 | "$$" 304 | ] 305 | }, 306 | { 307 | "cell_type": "code", 308 | "execution_count": null, 309 | "metadata": { 310 | "hide-output": false 311 | }, 312 | "outputs": [], 313 | "source": [ 314 | "econ1.Sc" 315 | ] 316 | }, 317 | { 318 | "cell_type": "markdown", 319 | "metadata": {}, 320 | "source": [ 321 | "The state vector in the DLE class is:\n", 322 | "\n", 323 | "$$\n", 324 | "x_t = \\left[ {\\begin{array}{c}\n", 325 | " h_{t-1} \\\\ k_{t-1} \\\\ z_t\n", 326 | " \\end{array} }\n", 327 | " \\right]\n", 328 | "$$\n", 329 | "\n", 330 | "where $ k_{t-1} $ = $ b_{t} $ is set up to be $ b_t $ in the\n", 331 | "permanent income model.\n", 332 | "\n", 333 | "The state vector in the LQ problem is\n", 334 | "$ \\begin{bmatrix} z_t \\\\ b_t \\end{bmatrix} $.\n", 335 | "\n", 336 | "Consequently, the relevant elements of econ1.Sc are the same as in\n", 337 | "$ -F $ occur when we apply other approaches to the same model in the lecture\n", 338 | "[Optimal Savings II: LQ Techniques](https://python.quantecon.org/perm_income_cons.html) and this Jupyter\n", 339 | "notebook [http://nbviewer.jupyter.org/github/QuantEcon/QuantEcon.notebooks/blob/master/permanent_income.ipynb](http://nbviewer.jupyter.org/github/QuantEcon/QuantEcon.notebooks/blob/master/permanent_income.ipynb).\n", 340 | "\n", 341 | "The plot below quickly replicates the first two figures of\n", 342 | "that lecture and that notebook to confirm that the solutions are the same" 343 | ] 344 | }, 345 | { 346 | "cell_type": "code", 347 | "execution_count": null, 348 | "metadata": { 349 | "hide-output": false 350 | }, 351 | "outputs": [], 352 | "source": [ 353 | "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 5))\n", 354 | "\n", 355 | "for i in range(25):\n", 356 | " econ1.compute_sequence(x0, ts_length=150)\n", 357 | " ax1.plot(econ1.c[0], c='g')\n", 358 | " ax1.plot(econ1.d[0], c='b')\n", 359 | "ax1.plot(econ1.c[0], label='Consumption', c='g')\n", 360 | "ax1.plot(econ1.d[0], label='Income', c='b')\n", 361 | "ax1.legend()\n", 362 | "\n", 363 | "for i in range(25):\n", 364 | " econ1.compute_sequence(x0, ts_length=150)\n", 365 | " ax2.plot(econ1.k[0], color='r')\n", 366 | "ax2.plot(econ1.k[0], label='Debt', c='r')\n", 367 | "ax2.legend()\n", 368 | "plt.show()" 369 | ] 370 | } 371 | ], 372 | "metadata": { 373 | "date": 1584334752.5977762, 374 | "filename": "permanent_income_dles.rst", 375 | "kernelspec": { 376 | "display_name": "Python", 377 | "language": "python3", 378 | "name": "python3" 379 | }, 380 | "title": "Permanent Income Model using the DLE Class" 381 | }, 382 | "nbformat": 4, 383 | "nbformat_minor": 2 384 | } -------------------------------------------------------------------------------- /rosen_schooling_model.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "
\n", 10 | " \n", 11 | " \"QuantEcon\"\n", 12 | " \n", 13 | "
\n", 14 | "\n", 15 | "\n", 16 | "" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# Rosen Schooling Model" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "## Contents\n", 31 | "\n", 32 | "- [Rosen Schooling Model](#Rosen-Schooling-Model) \n", 33 | " - [A One-Occupation Model](#A-One-Occupation-Model) \n", 34 | " - [Mapping into HS2013 Framework](#Mapping-into-HS2013-Framework) " 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "This lecture is yet another part of a suite of lectures that use the quantecon DLE class to instantiate models within the\n", 42 | "[[HS13b]](https://python.quantecon.org/zreferences.html#hs2013) class of models described in detail in [Recursive Models of Dynamic Linear Economies](https://python.quantecon.org/hs_recursive_models.html).\n", 43 | "\n", 44 | "In addition to what’s included in Anaconda, this lecture uses the quantecon library" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": null, 50 | "metadata": { 51 | "hide-output": true 52 | }, 53 | "outputs": [], 54 | "source": [ 55 | "!pip install --upgrade quantecon" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "We’ll also need the following imports:" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": null, 68 | "metadata": { 69 | "hide-output": false 70 | }, 71 | "outputs": [], 72 | "source": [ 73 | "import numpy as np\n", 74 | "import matplotlib.pyplot as plt\n", 75 | "from quantecon import LQ\n", 76 | "from collections import namedtuple\n", 77 | "from quantecon import DLE\n", 78 | "from math import sqrt\n", 79 | "%matplotlib inline" 80 | ] 81 | }, 82 | { 83 | "cell_type": "markdown", 84 | "metadata": {}, 85 | "source": [ 86 | "## A One-Occupation Model\n", 87 | "\n", 88 | "Ryoo and Rosen’s (2004) [[RR04]](https://python.quantecon.org/zreferences.html#ryoo2004engineering) partial equilibrium model determines\n", 89 | "\n", 90 | "- a stock of “Engineers” $ N_t $ \n", 91 | "- a number of new entrants in engineering school, $ n_t $ \n", 92 | "- the wage rate of engineers, $ w_t $ \n", 93 | "\n", 94 | "\n", 95 | "It takes k periods of schooling to become an engineer.\n", 96 | "\n", 97 | "The model consists of the following equations:\n", 98 | "\n", 99 | "- a demand curve for engineers: \n", 100 | "\n", 101 | "\n", 102 | "$$\n", 103 | "w_t = - \\alpha_d N_t + \\epsilon_{dt}\n", 104 | "$$\n", 105 | "\n", 106 | "- a time-to-build structure of the education process: \n", 107 | "\n", 108 | "\n", 109 | "$$\n", 110 | "N_{t+k} = \\delta_N N_{t+k-1} + n_t\n", 111 | "$$\n", 112 | "\n", 113 | "- a definition of the discounted present value of each new engineering\n", 114 | " student: \n", 115 | "\n", 116 | "\n", 117 | "$$\n", 118 | "v_t = \\beta_k \\mathbb{E} \\sum_{j=0}^\\infty (\\beta \\delta_N)^j w_{t+k+j}\n", 119 | "$$\n", 120 | "\n", 121 | "- a supply curve of new students driven by present value $ v_t $: \n", 122 | "\n", 123 | "\n", 124 | "$$\n", 125 | "n_t = \\alpha_s v_t + \\epsilon_{st}\n", 126 | "$$" 127 | ] 128 | }, 129 | { 130 | "cell_type": "markdown", 131 | "metadata": {}, 132 | "source": [ 133 | "## Mapping into HS2013 Framework\n", 134 | "\n", 135 | "We represent this model in the [[HS13b]](https://python.quantecon.org/zreferences.html#hs2013) framework by\n", 136 | "\n", 137 | "- sweeping the time-to-build structure and the demand for engineers\n", 138 | " into the household technology, and \n", 139 | "- putting the supply of engineers into the technology for producing\n", 140 | " goods " 141 | ] 142 | }, 143 | { 144 | "cell_type": "markdown", 145 | "metadata": {}, 146 | "source": [ 147 | "### Preferences\n", 148 | "\n", 149 | "$$\n", 150 | "\\Pi = 0, \\Lambda=\n", 151 | "\\begin{bmatrix}\n", 152 | " \\alpha_d & 0 & \\cdots & 0\n", 153 | " \\end{bmatrix}\n", 154 | ", \\Delta_h =\n", 155 | "\\begin{bmatrix}\n", 156 | " \\delta_N & 1 & 0 & \\cdots & 0 \\\\ 0 & 0 & 1 & \\cdots & 0 \\\\ \\vdots & \\vdots & \\vdots & \\ddots & \\vdots \\\\ 0 & \\cdots& \\cdots & 0 & 1 \\\\ 0 & 0 & 0 & \\cdots & 0\n", 157 | " \\end{bmatrix}\n", 158 | " , \\Theta_h =\n", 159 | "\\begin{bmatrix}\n", 160 | " 0 \\\\ 0 \\\\ \\vdots \\\\ 0 \\\\ 1\n", 161 | " \\end{bmatrix}\n", 162 | "$$\n", 163 | "\n", 164 | "where $ \\Lambda $ is a k+1 x 1 matrix, $ \\Delta_h $ is a k_1 x\n", 165 | "k+1 matrix, and $ \\Theta_h $ is a k+1 x 1 matrix.\n", 166 | "\n", 167 | "This specification sets $ N_t = h_{1t-1} $, $ n_t = c_t $,\n", 168 | "$ h_{\\tau+1,t-1} = n_{t-(k-\\tau)} $ for $ \\tau = 1,...,k $.\n", 169 | "\n", 170 | "Below we set things up so that the number of years of education, k, can\n", 171 | "be varied." 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "### Technology\n", 179 | "\n", 180 | "To capture Ryoo and Rosen’s [[RR04]](https://python.quantecon.org/zreferences.html#ryoo2004engineering) supply curve, we use the physical\n", 181 | "technology:\n", 182 | "\n", 183 | "$$\n", 184 | "c_t = i_t + d_{1t}\n", 185 | "$$\n", 186 | "\n", 187 | "$$\n", 188 | "\\psi_1i_t = g_t\n", 189 | "$$\n", 190 | "\n", 191 | "where $ \\psi_1 $ is inversely proportional to $ \\alpha_s $." 192 | ] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "metadata": {}, 197 | "source": [ 198 | "### Information\n", 199 | "\n", 200 | "Because we want $ b_t = \\epsilon_{dt} $ and $ d_{1t} =\\epsilon_{st} $, we set\n", 201 | "\n", 202 | "$$\n", 203 | "A_{22}=\n", 204 | "\\begin{bmatrix}\n", 205 | " 1 & 0 & 0 \\\\ 0 & \\rho_s & 0 \\\\ 0 & 0 & \\rho_d\n", 206 | " \\end{bmatrix}\n", 207 | ", C_2 =\n", 208 | "\\begin{bmatrix}\n", 209 | " 0 & 0 \\\\ 1 & 0 \\\\ 0 & 1\n", 210 | " \\end{bmatrix}\n", 211 | ", U_b =\n", 212 | "\\begin{bmatrix}\n", 213 | " 30 & 0 & 1\n", 214 | " \\end{bmatrix}\n", 215 | ", U_d =\n", 216 | "\\begin{bmatrix}\n", 217 | " 10 & 1 & 0 \\\\ 0 & 0 & 0\n", 218 | " \\end{bmatrix}\n", 219 | "$$\n", 220 | "\n", 221 | "where $ \\rho_s $ and $ \\rho_d $ describe the persistence of the\n", 222 | "supply and demand shocks" 223 | ] 224 | }, 225 | { 226 | "cell_type": "code", 227 | "execution_count": null, 228 | "metadata": { 229 | "hide-output": false 230 | }, 231 | "outputs": [], 232 | "source": [ 233 | "Information = namedtuple('Information', ['a22', 'c2','ub','ud'])\n", 234 | "Technology = namedtuple('Technology', ['ϕ_c', 'ϕ_g', 'ϕ_i', 'γ', 'δ_k', 'θ_k'])\n", 235 | "Preferences = namedtuple('Preferences', ['β', 'l_λ', 'π_h', 'δ_h', 'θ_h'])" 236 | ] 237 | }, 238 | { 239 | "cell_type": "markdown", 240 | "metadata": {}, 241 | "source": [ 242 | "### Effects of Changes in Education Technology and Demand\n", 243 | "\n", 244 | "We now study how changing\n", 245 | "\n", 246 | "- the number of years of education required to become an engineer and \n", 247 | "- the slope of the demand curve \n", 248 | "\n", 249 | "\n", 250 | "affects responses to demand shocks.\n", 251 | "\n", 252 | "To begin, we set $ k = 4 $ and $ \\alpha_d = 0.1 $" 253 | ] 254 | }, 255 | { 256 | "cell_type": "code", 257 | "execution_count": null, 258 | "metadata": { 259 | "hide-output": false 260 | }, 261 | "outputs": [], 262 | "source": [ 263 | "k = 4 # Number of periods of schooling required to become an engineer\n", 264 | "\n", 265 | "β = np.array([[1 / 1.05]])\n", 266 | "α_d = np.array([[0.1]])\n", 267 | "α_s = 1\n", 268 | "ε_1 = 1e-7\n", 269 | "λ_1 = np.ones((1, k)) * ε_1\n", 270 | "# Use of ε_1 is trick to aquire detectability, see HS2013 p. 228 footnote 4\n", 271 | "l_λ = np.hstack((α_d, λ_1))\n", 272 | "π_h = np.array([[0]])\n", 273 | "\n", 274 | "δ_n = np.array([[0.95]])\n", 275 | "d1 = np.vstack((δ_n, np.zeros((k - 1, 1))))\n", 276 | "d2 = np.hstack((d1, np.eye(k)))\n", 277 | "δ_h = np.vstack((d2, np.zeros((1, k + 1))))\n", 278 | "\n", 279 | "θ_h = np.vstack((np.zeros((k, 1)),\n", 280 | " np.ones((1, 1))))\n", 281 | "\n", 282 | "ψ_1 = 1 / α_s\n", 283 | "\n", 284 | "ϕ_c = np.array([[1], [0]])\n", 285 | "ϕ_g = np.array([[0], [-1]])\n", 286 | "ϕ_i = np.array([[-1], [ψ_1]])\n", 287 | "γ = np.array([[0], [0]])\n", 288 | "\n", 289 | "δ_k = np.array([[0]])\n", 290 | "θ_k = np.array([[0]])\n", 291 | "\n", 292 | "ρ_s = 0.8\n", 293 | "ρ_d = 0.8\n", 294 | "\n", 295 | "a22 = np.array([[1, 0, 0],\n", 296 | " [0, ρ_s, 0],\n", 297 | " [0, 0, ρ_d]])\n", 298 | "\n", 299 | "c2 = np.array([[0, 0], [10, 0], [0, 10]])\n", 300 | "ub = np.array([[30, 0, 1]])\n", 301 | "ud = np.array([[10, 1, 0], [0, 0, 0]])\n", 302 | "\n", 303 | "info1 = Information(a22, c2, ub, ud)\n", 304 | "tech1 = Technology(ϕ_c, ϕ_g, ϕ_i, γ, δ_k, θ_k)\n", 305 | "pref1 = Preferences(β, l_λ, π_h, δ_h, θ_h)\n", 306 | "\n", 307 | "econ1 = DLE(info1, tech1, pref1)" 308 | ] 309 | }, 310 | { 311 | "cell_type": "markdown", 312 | "metadata": {}, 313 | "source": [ 314 | "We create three other instances by:\n", 315 | "\n", 316 | "1. Raising $ \\alpha_d $ to 2 \n", 317 | "1. Raising k to 7 \n", 318 | "1. Raising k to 10 " 319 | ] 320 | }, 321 | { 322 | "cell_type": "code", 323 | "execution_count": null, 324 | "metadata": { 325 | "hide-output": false 326 | }, 327 | "outputs": [], 328 | "source": [ 329 | "α_d = np.array([[2]])\n", 330 | "l_λ = np.hstack((α_d, λ_1))\n", 331 | "pref2 = Preferences(β, l_λ, π_h, δ_h, θ_h)\n", 332 | "econ2 = DLE(info1, tech1, pref2)\n", 333 | "\n", 334 | "α_d = np.array([[0.1]])\n", 335 | "\n", 336 | "k = 7\n", 337 | "λ_1 = np.ones((1, k)) * ε_1\n", 338 | "l_λ = np.hstack((α_d, λ_1))\n", 339 | "d1 = np.vstack((δ_n, np.zeros((k - 1, 1))))\n", 340 | "d2 = np.hstack((d1, np.eye(k)))\n", 341 | "δ_h = np.vstack((d2, np.zeros((1, k+1))))\n", 342 | "θ_h = np.vstack((np.zeros((k, 1)),\n", 343 | " np.ones((1, 1))))\n", 344 | "\n", 345 | "Pref3 = Preferences(β, l_λ, π_h, δ_h, θ_h)\n", 346 | "econ3 = DLE(info1, tech1, Pref3)\n", 347 | "\n", 348 | "k = 10\n", 349 | "λ_1 = np.ones((1, k)) * ε_1\n", 350 | "l_λ = np.hstack((α_d, λ_1))\n", 351 | "d1 = np.vstack((δ_n, np.zeros((k - 1, 1))))\n", 352 | "d2 = np.hstack((d1, np.eye(k)))\n", 353 | "δ_h = np.vstack((d2, np.zeros((1, k + 1))))\n", 354 | "θ_h = np.vstack((np.zeros((k, 1)),\n", 355 | " np.ones((1, 1))))\n", 356 | "\n", 357 | "pref4 = Preferences(β, l_λ, π_h, δ_h, θ_h)\n", 358 | "econ4 = DLE(info1, tech1, pref4)\n", 359 | "\n", 360 | "shock_demand = np.array([[0], [1]])\n", 361 | "\n", 362 | "econ1.irf(ts_length=25, shock=shock_demand)\n", 363 | "econ2.irf(ts_length=25, shock=shock_demand)\n", 364 | "econ3.irf(ts_length=25, shock=shock_demand)\n", 365 | "econ4.irf(ts_length=25, shock=shock_demand)" 366 | ] 367 | }, 368 | { 369 | "cell_type": "markdown", 370 | "metadata": {}, 371 | "source": [ 372 | "The first figure plots the impulse response of $ n_t $ (on the left)\n", 373 | "and $ N_t $ (on the right) to a positive demand shock, for\n", 374 | "$ \\alpha_d = 0.1 $ and $ \\alpha_d = 2 $.\n", 375 | "\n", 376 | "When $ \\alpha_d = 2 $, the number of new students $ n_t $ rises\n", 377 | "initially, but the response then turns negative.\n", 378 | "\n", 379 | "A positive demand shock raises wages, drawing new students into the\n", 380 | "profession.\n", 381 | "\n", 382 | "However, these new students raise $ N_t $.\n", 383 | "\n", 384 | "The higher is $ \\alpha_d $, the larger the effect of this rise in\n", 385 | "$ N_t $ on wages.\n", 386 | "\n", 387 | "This counteracts the demand shock’s positive effect on wages, reducing\n", 388 | "the number of new students in subsequent periods.\n", 389 | "\n", 390 | "Consequently, when $ \\alpha_d $ is lower, the effect of a demand\n", 391 | "shock on $ N_t $ is larger" 392 | ] 393 | }, 394 | { 395 | "cell_type": "code", 396 | "execution_count": null, 397 | "metadata": { 398 | "hide-output": false 399 | }, 400 | "outputs": [], 401 | "source": [ 402 | "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))\n", 403 | "ax1.plot(econ1.c_irf,label='$\\\\alpha_d = 0.1$')\n", 404 | "ax1.plot(econ2.c_irf,label='$\\\\alpha_d = 2$')\n", 405 | "ax1.legend()\n", 406 | "ax1.set_title('Response of $n_t$ to a demand shock')\n", 407 | "\n", 408 | "ax2.plot(econ1.h_irf[:, 0], label='$\\\\alpha_d = 0.1$')\n", 409 | "ax2.plot(econ2.h_irf[:, 0], label='$\\\\alpha_d = 24$')\n", 410 | "ax2.legend()\n", 411 | "ax2.set_title('Response of $N_t$ to a demand shock')\n", 412 | "plt.show()" 413 | ] 414 | }, 415 | { 416 | "cell_type": "markdown", 417 | "metadata": {}, 418 | "source": [ 419 | "The next figure plots the impulse response of $ n_t $ (on the left)\n", 420 | "and $ N_t $ (on the right) to a positive demand shock, for\n", 421 | "$ k=4 $, $ k=7 $ and $ k=10 $ (with $ \\alpha_d = 0.1 $)" 422 | ] 423 | }, 424 | { 425 | "cell_type": "code", 426 | "execution_count": null, 427 | "metadata": { 428 | "hide-output": false 429 | }, 430 | "outputs": [], 431 | "source": [ 432 | "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))\n", 433 | "ax1.plot(econ1.c_irf, label='$k=4$')\n", 434 | "ax1.plot(econ3.c_irf, label='$k=7$')\n", 435 | "ax1.plot(econ4.c_irf, label='$k=10$')\n", 436 | "ax1.legend()\n", 437 | "ax1.set_title('Response of $n_t$ to a demand shock')\n", 438 | "\n", 439 | "ax2.plot(econ1.h_irf[:,0], label='$k=4$')\n", 440 | "ax2.plot(econ3.h_irf[:,0], label='$k=7$')\n", 441 | "ax2.plot(econ4.h_irf[:,0], label='$k=10$')\n", 442 | "ax2.legend()\n", 443 | "ax2.set_title('Response of $N_t$ to a demand shock')\n", 444 | "plt.show()" 445 | ] 446 | }, 447 | { 448 | "cell_type": "markdown", 449 | "metadata": {}, 450 | "source": [ 451 | "Both panels in the above figure show that raising k lowers the effect of\n", 452 | "a positive demand shock on entry into the engineering profession.\n", 453 | "\n", 454 | "Increasing the number of periods of schooling lowers\n", 455 | "the number of new students in response to a demand shock.\n", 456 | "\n", 457 | "This occurs because with longer required schooling, new students ultimately benefit less from the impact of that shock on wages." 458 | ] 459 | } 460 | ], 461 | "metadata": { 462 | "date": 1584334756.6926937, 463 | "filename": "rosen_schooling_model.rst", 464 | "kernelspec": { 465 | "display_name": "Python", 466 | "language": "python3", 467 | "name": "python3" 468 | }, 469 | "title": "Rosen Schooling Model" 470 | }, 471 | "nbformat": 4, 472 | "nbformat_minor": 2 473 | } -------------------------------------------------------------------------------- /schelling.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "
\n", 10 | " \n", 11 | " \"QuantEcon\"\n", 12 | " \n", 13 | "
" 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "metadata": {}, 19 | "source": [ 20 | "# Schelling’s Segregation Model\n", 21 | "\n", 22 | "\n", 23 | "" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "## Contents\n", 31 | "\n", 32 | "- [Schelling’s Segregation Model](#Schelling’s-Segregation-Model) \n", 33 | " - [Outline](#Outline) \n", 34 | " - [The Model](#The-Model) \n", 35 | " - [Results](#Results) \n", 36 | " - [Exercises](#Exercises) \n", 37 | " - [Solutions](#Solutions) " 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "## Outline\n", 45 | "\n", 46 | "In 1969, Thomas C. Schelling developed a simple but striking model of racial segregation [[Sch69]](https://python.quantecon.org/zreferences.html#schelling1969).\n", 47 | "\n", 48 | "His model studies the dynamics of racially mixed neighborhoods.\n", 49 | "\n", 50 | "Like much of Schelling’s work, the model shows how local interactions can lead to surprising aggregate structure.\n", 51 | "\n", 52 | "In particular, it shows that relatively mild preference for neighbors of similar race can lead in aggregate to the collapse of mixed neighborhoods, and high levels of segregation.\n", 53 | "\n", 54 | "In recognition of this and other research, Schelling was awarded the 2005 Nobel Prize in Economic Sciences (joint with Robert Aumann).\n", 55 | "\n", 56 | "In this lecture, we (in fact you) will build and run a version of Schelling’s model.\n", 57 | "\n", 58 | "Let’s start with some imports:" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": null, 64 | "metadata": { 65 | "hide-output": false 66 | }, 67 | "outputs": [], 68 | "source": [ 69 | "from random import uniform, seed\n", 70 | "from math import sqrt\n", 71 | "import matplotlib.pyplot as plt\n", 72 | "%matplotlib inline" 73 | ] 74 | }, 75 | { 76 | "cell_type": "markdown", 77 | "metadata": {}, 78 | "source": [ 79 | "## The Model\n", 80 | "\n", 81 | "We will cover a variation of Schelling’s model that is easy to program and captures the main idea." 82 | ] 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "metadata": {}, 87 | "source": [ 88 | "### Set-Up\n", 89 | "\n", 90 | "Suppose we have two types of people: orange people and green people.\n", 91 | "\n", 92 | "For the purpose of this lecture, we will assume there are 250 of each type.\n", 93 | "\n", 94 | "These agents all live on a single unit square.\n", 95 | "\n", 96 | "The location of an agent is just a point $ (x, y) $, where $ 0 < x, y < 1 $." 97 | ] 98 | }, 99 | { 100 | "cell_type": "markdown", 101 | "metadata": {}, 102 | "source": [ 103 | "### Preferences\n", 104 | "\n", 105 | "We will say that an agent is *happy* if half or more of her 10 nearest neighbors are of the same type.\n", 106 | "\n", 107 | "Here ‘nearest’ is in terms of [Euclidean distance](https://en.wikipedia.org/wiki/Euclidean_distance).\n", 108 | "\n", 109 | "An agent who is not happy is called *unhappy*.\n", 110 | "\n", 111 | "An important point here is that agents are not averse to living in mixed areas.\n", 112 | "\n", 113 | "They are perfectly happy if half their neighbors are of the other color." 114 | ] 115 | }, 116 | { 117 | "cell_type": "markdown", 118 | "metadata": {}, 119 | "source": [ 120 | "### Behavior\n", 121 | "\n", 122 | "Initially, agents are mixed together (integrated).\n", 123 | "\n", 124 | "In particular, the initial location of each agent is an independent draw from a bivariate uniform distribution on $ S = (0, 1)^2 $.\n", 125 | "\n", 126 | "Now, cycling through the set of all agents, each agent is now given the chance to stay or move.\n", 127 | "\n", 128 | "We assume that each agent will stay put if they are happy and move if unhappy.\n", 129 | "\n", 130 | "The algorithm for moving is as follows\n", 131 | "\n", 132 | "1. Draw a random location in $ S $ \n", 133 | "1. If happy at new location, move there \n", 134 | "1. Else, go to step 1 \n", 135 | "\n", 136 | "\n", 137 | "In this way, we cycle continuously through the agents, moving as required.\n", 138 | "\n", 139 | "We continue to cycle until no one wishes to move." 140 | ] 141 | }, 142 | { 143 | "cell_type": "markdown", 144 | "metadata": {}, 145 | "source": [ 146 | "## Results\n", 147 | "\n", 148 | "Let’s have a look at the results we got when we coded and ran this model.\n", 149 | "\n", 150 | "As discussed above, agents are initially mixed randomly together.\n", 151 | "\n", 152 | "\n", 153 | "\n", 154 | " \n", 155 | "But after several cycles, they become segregated into distinct regions.\n", 156 | "\n", 157 | "\n", 158 | "\n", 159 | " \n", 160 | "\n", 161 | "\n", 162 | " \n", 163 | "\n", 164 | "\n", 165 | " \n", 166 | "In this instance, the program terminated after 4 cycles through the set of\n", 167 | "agents, indicating that all agents had reached a state of happiness.\n", 168 | "\n", 169 | "What is striking about the pictures is how rapidly racial integration breaks down.\n", 170 | "\n", 171 | "This is despite the fact that people in the model don’t actually mind living mixed with the other type.\n", 172 | "\n", 173 | "Even with these preferences, the outcome is a high degree of segregation." 174 | ] 175 | }, 176 | { 177 | "cell_type": "markdown", 178 | "metadata": {}, 179 | "source": [ 180 | "## Exercises\n", 181 | "\n", 182 | "\n", 183 | "" 184 | ] 185 | }, 186 | { 187 | "cell_type": "markdown", 188 | "metadata": {}, 189 | "source": [ 190 | "### Exercise 1\n", 191 | "\n", 192 | "Implement and run this simulation for yourself.\n", 193 | "\n", 194 | "Consider the following structure for your program.\n", 195 | "\n", 196 | "Agents can be modeled as [objects](https://python.quantecon.org/python_oop.html).\n", 197 | "\n", 198 | "Here’s an indication of how they might look" 199 | ] 200 | }, 201 | { 202 | "cell_type": "markdown", 203 | "metadata": { 204 | "hide-output": false 205 | }, 206 | "source": [ 207 | "```text\n", 208 | "* Data:\n", 209 | "\n", 210 | " * type (green or orange)\n", 211 | " * location\n", 212 | "\n", 213 | "* Methods:\n", 214 | "\n", 215 | " * determine whether happy or not given locations of other agents\n", 216 | "\n", 217 | " * If not happy, move\n", 218 | "\n", 219 | " * find a new location where happy\n", 220 | "```\n" 221 | ] 222 | }, 223 | { 224 | "cell_type": "markdown", 225 | "metadata": {}, 226 | "source": [ 227 | "And here’s some pseudocode for the main loop" 228 | ] 229 | }, 230 | { 231 | "cell_type": "markdown", 232 | "metadata": { 233 | "hide-output": false 234 | }, 235 | "source": [ 236 | "```text\n", 237 | "while agents are still moving\n", 238 | " for agent in agents\n", 239 | " give agent the opportunity to move\n", 240 | "```\n" 241 | ] 242 | }, 243 | { 244 | "cell_type": "markdown", 245 | "metadata": {}, 246 | "source": [ 247 | "Use 250 agents of each type." 248 | ] 249 | }, 250 | { 251 | "cell_type": "markdown", 252 | "metadata": {}, 253 | "source": [ 254 | "## Solutions" 255 | ] 256 | }, 257 | { 258 | "cell_type": "markdown", 259 | "metadata": {}, 260 | "source": [ 261 | "### Exercise 1\n", 262 | "\n", 263 | "Here’s one solution that does the job we want.\n", 264 | "\n", 265 | "If you feel like a further exercise, you can probably speed up some of the computations and\n", 266 | "then increase the number of agents." 267 | ] 268 | }, 269 | { 270 | "cell_type": "code", 271 | "execution_count": null, 272 | "metadata": { 273 | "hide-output": false 274 | }, 275 | "outputs": [], 276 | "source": [ 277 | "seed(10) # For reproducible random numbers\n", 278 | "\n", 279 | "class Agent:\n", 280 | "\n", 281 | " def __init__(self, type):\n", 282 | " self.type = type\n", 283 | " self.draw_location()\n", 284 | "\n", 285 | " def draw_location(self):\n", 286 | " self.location = uniform(0, 1), uniform(0, 1)\n", 287 | "\n", 288 | " def get_distance(self, other):\n", 289 | " \"Computes the euclidean distance between self and other agent.\"\n", 290 | " a = (self.location[0] - other.location[0])**2\n", 291 | " b = (self.location[1] - other.location[1])**2\n", 292 | " return sqrt(a + b)\n", 293 | "\n", 294 | " def happy(self, agents):\n", 295 | " \"True if sufficient number of nearest neighbors are of the same type.\"\n", 296 | " distances = []\n", 297 | " # distances is a list of pairs (d, agent), where d is distance from\n", 298 | " # agent to self\n", 299 | " for agent in agents:\n", 300 | " if self != agent:\n", 301 | " distance = self.get_distance(agent)\n", 302 | " distances.append((distance, agent))\n", 303 | " # == Sort from smallest to largest, according to distance == #\n", 304 | " distances.sort()\n", 305 | " # == Extract the neighboring agents == #\n", 306 | " neighbors = [agent for d, agent in distances[:num_neighbors]]\n", 307 | " # == Count how many neighbors have the same type as self == #\n", 308 | " num_same_type = sum(self.type == agent.type for agent in neighbors)\n", 309 | " return num_same_type >= require_same_type\n", 310 | "\n", 311 | " def update(self, agents):\n", 312 | " \"If not happy, then randomly choose new locations until happy.\"\n", 313 | " while not self.happy(agents):\n", 314 | " self.draw_location()\n", 315 | "\n", 316 | "\n", 317 | "def plot_distribution(agents, cycle_num):\n", 318 | " \"Plot the distribution of agents after cycle_num rounds of the loop.\"\n", 319 | " x_values_0, y_values_0 = [], []\n", 320 | " x_values_1, y_values_1 = [], []\n", 321 | " # == Obtain locations of each type == #\n", 322 | " for agent in agents:\n", 323 | " x, y = agent.location\n", 324 | " if agent.type == 0:\n", 325 | " x_values_0.append(x)\n", 326 | " y_values_0.append(y)\n", 327 | " else:\n", 328 | " x_values_1.append(x)\n", 329 | " y_values_1.append(y)\n", 330 | " fig, ax = plt.subplots(figsize=(8, 8))\n", 331 | " plot_args = {'markersize': 8, 'alpha': 0.6}\n", 332 | " ax.set_facecolor('azure')\n", 333 | " ax.plot(x_values_0, y_values_0, 'o', markerfacecolor='orange', **plot_args)\n", 334 | " ax.plot(x_values_1, y_values_1, 'o', markerfacecolor='green', **plot_args)\n", 335 | " ax.set_title(f'Cycle {cycle_num-1}')\n", 336 | " plt.show()\n", 337 | "\n", 338 | "# == Main == #\n", 339 | "\n", 340 | "num_of_type_0 = 250\n", 341 | "num_of_type_1 = 250\n", 342 | "num_neighbors = 10 # Number of agents regarded as neighbors\n", 343 | "require_same_type = 5 # Want at least this many neighbors to be same type\n", 344 | "\n", 345 | "# == Create a list of agents == #\n", 346 | "agents = [Agent(0) for i in range(num_of_type_0)]\n", 347 | "agents.extend(Agent(1) for i in range(num_of_type_1))\n", 348 | "\n", 349 | "\n", 350 | "count = 1\n", 351 | "# == Loop until none wishes to move == #\n", 352 | "while True:\n", 353 | " print('Entering loop ', count)\n", 354 | " plot_distribution(agents, count)\n", 355 | " count += 1\n", 356 | " no_one_moved = True\n", 357 | " for agent in agents:\n", 358 | " old_location = agent.location\n", 359 | " agent.update(agents)\n", 360 | " if agent.location != old_location:\n", 361 | " no_one_moved = False\n", 362 | " if no_one_moved:\n", 363 | " break\n", 364 | "\n", 365 | "print('Converged, terminating.')" 366 | ] 367 | } 368 | ], 369 | "metadata": { 370 | "date": 1584334757.4135983, 371 | "filename": "schelling.rst", 372 | "kernelspec": { 373 | "display_name": "Python", 374 | "language": "python3", 375 | "name": "python3" 376 | }, 377 | "title": "Schelling’s Segregation Model" 378 | }, 379 | "nbformat": 4, 380 | "nbformat_minor": 2 381 | } -------------------------------------------------------------------------------- /tax_smoothing_3.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "
\n", 10 | " \n", 11 | " \"QuantEcon\"\n", 12 | " \n", 13 | "
\n", 14 | "\n", 15 | "\n", 16 | "" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# How to Pay for a War: Part 3" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "## Contents\n", 31 | "\n", 32 | "- [How to Pay for a War: Part 3](#How-to-Pay-for-a-War:-Part-3) \n", 33 | " - [Another Application of Markov Jump Linear Quadratic Dynamic Programming](#Another-Application-of-Markov-Jump-Linear-Quadratic-Dynamic-Programming) \n", 34 | " - [Roll-Over Risk](#Roll-Over-Risk) \n", 35 | " - [A Dead End](#A-Dead-End) \n", 36 | " - [Better Representation of Roll-Over Risk](#Better-Representation-of-Roll-Over-Risk) " 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "metadata": {}, 42 | "source": [ 43 | "In addition to what’s in Anaconda, this lecture deploys the quantecon library:" 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": null, 49 | "metadata": { 50 | "hide-output": true 51 | }, 52 | "outputs": [], 53 | "source": [ 54 | "!pip install --upgrade quantecon" 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "metadata": {}, 60 | "source": [ 61 | "## Another Application of Markov Jump Linear Quadratic Dynamic Programming\n", 62 | "\n", 63 | "This is another [sequel to an earlier lecture](https://python.quantecon.org/tax_smoothing_1.html).\n", 64 | "\n", 65 | "We again use a method introduced in lecture [Markov Jump LQ dynamic programming](https://python.quantecon.org/markov_jump_lq.html)\n", 66 | "to implement some ideas Barro (1999 [[Bar99]](https://python.quantecon.org/zreferences.html#barro1999determinants), 2003 [[BM03]](https://python.quantecon.org/zreferences.html#barro2003religion)) that\n", 67 | "extend his classic 1979 [[Bar79]](https://python.quantecon.org/zreferences.html#barro1979) model of tax smoothing.\n", 68 | "\n", 69 | "Barro’s 1979 [[Bar79]](https://python.quantecon.org/zreferences.html#barro1979) model is about a government that borrows and lends in order\n", 70 | "to help it minimize an intertemporal measure of distortions caused by\n", 71 | "taxes.\n", 72 | "\n", 73 | "Technically, Barro’s 1979 [[Bar79]](https://python.quantecon.org/zreferences.html#barro1979) model looks a lot like a consumption-smoothing model.\n", 74 | "\n", 75 | "Our generalizations of his 1979 model will also look\n", 76 | "like souped-up consumption-smoothing models.\n", 77 | "\n", 78 | "In this lecture, we describe a tax-smoothing problem of a\n", 79 | "government that faces **roll-over risk**.\n", 80 | "\n", 81 | "Let’s start with some standard imports:" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": null, 87 | "metadata": { 88 | "hide-output": false 89 | }, 90 | "outputs": [], 91 | "source": [ 92 | "import quantecon as qe\n", 93 | "import numpy as np\n", 94 | "import matplotlib.pyplot as plt\n", 95 | "%matplotlib inline" 96 | ] 97 | }, 98 | { 99 | "cell_type": "markdown", 100 | "metadata": {}, 101 | "source": [ 102 | "## Roll-Over Risk\n", 103 | "\n", 104 | "Let $ T_t $ denote tax collections, $ \\beta $ a discount factor,\n", 105 | "$ b_{t,t+1} $ time $ t+1 $ goods that the government promises to\n", 106 | "pay at $ t $, $ G_t $ government purchases, $ p^t_{t+1} $\n", 107 | "the number of time $ t $ goods received per time $ t+1 $ goods\n", 108 | "promised.\n", 109 | "\n", 110 | "The stochastic process of government expenditures is\n", 111 | "exogenous.\n", 112 | "\n", 113 | "The government’s problem is to choose a plan for borrowing\n", 114 | "and tax collections $ \\{b_{t+1}, T_t\\}_{t=0}^\\infty $ to minimize\n", 115 | "\n", 116 | "$$\n", 117 | "E_0 \\sum_{t=0}^\\infty \\beta^t T_t^2\n", 118 | "$$\n", 119 | "\n", 120 | "subject to the constraints\n", 121 | "\n", 122 | "$$\n", 123 | "T_t + p^t_{t+1} b_{t,t+1} = G_t + b_{t-1,t}\n", 124 | "$$\n", 125 | "\n", 126 | "$$\n", 127 | "G_t = U_{g,t} z_t\n", 128 | "$$\n", 129 | "\n", 130 | "$$\n", 131 | "z_{t+1} = A_{22,t} z_t + C_{2,t} w_{t+1}\n", 132 | "$$\n", 133 | "\n", 134 | "where $ w_{t+1} \\sim {\\cal N}(0,I) $. The variables\n", 135 | "$ T_t, b_{t, t+1} $ are *control* variables chosen at $ t $,\n", 136 | "while $ b_{t-1,t} $ is an endogenous state variable inherited from\n", 137 | "the past at time $ t $ and $ p^t_{t+1} $ is an exogenous state\n", 138 | "variable at time $ t $.\n", 139 | "\n", 140 | "This is the same set-up as used [in this\n", 141 | "lecture](https://python.quantecon.org/tax_smoothing_1.html).\n", 142 | "\n", 143 | "We will consider a situation in which the government faces “roll-over\n", 144 | "risk”.\n", 145 | "\n", 146 | "Specifically, we shut down the government’s ability to borrow in\n", 147 | "one of the Markov states." 148 | ] 149 | }, 150 | { 151 | "cell_type": "markdown", 152 | "metadata": {}, 153 | "source": [ 154 | "## A Dead End\n", 155 | "\n", 156 | "A first thought for how to implement this might be to allow\n", 157 | "$ p^t_{t+1} $ to vary over time with:\n", 158 | "\n", 159 | "$$\n", 160 | "p^t_{t+1} = \\beta\n", 161 | "$$\n", 162 | "\n", 163 | "in Markov state 1 and\n", 164 | "\n", 165 | "$$\n", 166 | "p^t_{t+1} = 0\n", 167 | "$$\n", 168 | "\n", 169 | "in Markov state 2.\n", 170 | "\n", 171 | "Consequently, in the second Markov state, the\n", 172 | "government is unable to borrow, and the budget constraint becomes\n", 173 | "$ T_t = G_t + b_{t-1,t} $.\n", 174 | "\n", 175 | "However, if this is the only adjustment we make in our linear-quadratic\n", 176 | "model, the government will not set $ b_{t,t+1} = 0 $, which is the\n", 177 | "outcome we want to express *roll-over* risk in period $ t $.\n", 178 | "\n", 179 | "Instead, the government would have an incentive to set $ b_{t,t+1} $\n", 180 | "to a large negative number in state 2 – it would accumulate large\n", 181 | "amounts of *assets* to bring into period $ t+1 $ because that is\n", 182 | "cheap (Our Riccati equations will discover this for us!).\n", 183 | "\n", 184 | "Thus, we must represent “roll-over risk” some other way." 185 | ] 186 | }, 187 | { 188 | "cell_type": "markdown", 189 | "metadata": {}, 190 | "source": [ 191 | "## Better Representation of Roll-Over Risk\n", 192 | "\n", 193 | "To force the government to set $ b_{t,t+1} = 0 $, we can instead\n", 194 | "extend the model to have four Markov states:\n", 195 | "\n", 196 | "1. Good today, good yesterday \n", 197 | "1. Good today, bad yesterday \n", 198 | "1. Bad today, good yesterday \n", 199 | "1. Bad today, bad yesterday \n", 200 | "\n", 201 | "\n", 202 | "where good is a state in which effectively the government can issue debt\n", 203 | "and bad is a state in which effectively the government can’t issue debt.\n", 204 | "\n", 205 | "We’ll explain what *effectively* means shortly.\n", 206 | "\n", 207 | "We now set\n", 208 | "\n", 209 | "$$\n", 210 | "p^t_{t+1} = \\beta\n", 211 | "$$\n", 212 | "\n", 213 | "in all states.\n", 214 | "\n", 215 | "In addition – and this is important because it defines what we mean by\n", 216 | "*effectively* – we put a large penalty on the $ b_{t-1,t} $\n", 217 | "element of the state vector in states 2 and 4.\n", 218 | "\n", 219 | "This will prevent the\n", 220 | "government from wishing to issue any debt in states 3 or 4 because it\n", 221 | "would experience a large penalty from doing so in the next period.\n", 222 | "\n", 223 | "The transition matrix for this formulation is:\n", 224 | "\n", 225 | "$$\n", 226 | "\\Pi = \\begin{bmatrix} 0.95 & 0 & 0.05 & 0 \\\\\n", 227 | " 0.95 & 0 & 0.05 & 0 \\\\\n", 228 | " 0 & 0.9 & 0 & 0.1 \\\\\n", 229 | " 0 & 0.9 & 0 & 0.1 \\\\\n", 230 | "\\end{bmatrix}\n", 231 | "$$\n", 232 | "\n", 233 | "This transition matrix ensures that the Markov state cannot move, for\n", 234 | "example, from state 3 to state 1.\n", 235 | "\n", 236 | "Because state 3 is “bad today”, the next period cannot have “good yesterday”." 237 | ] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": null, 242 | "metadata": { 243 | "hide-output": false 244 | }, 245 | "outputs": [], 246 | "source": [ 247 | "# Model parameters\n", 248 | "β, Gbar, ρ, σ = 0.95, 5, 0.8, 1\n", 249 | "\n", 250 | "# Basic model matrices\n", 251 | "A22 = np.array([[1, 0], [Gbar, ρ], ])\n", 252 | "C2 = np.array([[0], [σ]])\n", 253 | "Ug = np.array([[0, 1]])\n", 254 | "\n", 255 | "# LQ framework matrices\n", 256 | "A_t = np.zeros((1, 3))\n", 257 | "A_b = np.hstack((np.zeros((2, 1)), A22))\n", 258 | "A = np.vstack((A_t, A_b))\n", 259 | "\n", 260 | "B = np.zeros((3, 1))\n", 261 | "B[0, 0] = 1\n", 262 | "\n", 263 | "C = np.vstack((np.zeros((1, 1)), C2))\n", 264 | "\n", 265 | "Sg = np.hstack((np.zeros((1, 1)), Ug))\n", 266 | "S1 = np.zeros((1, 3))\n", 267 | "S1[0, 0] = 1\n", 268 | "S = S1 + Sg\n", 269 | "\n", 270 | "R = S.T @ S\n", 271 | "\n", 272 | "# Large penalty on debt in R2 to prevent borrowing in a bad state\n", 273 | "R1 = np.copy(R)\n", 274 | "R2 = np.copy(R)\n", 275 | "R1[0, 0] = R[0, 0] + 1e-9\n", 276 | "R2[0, 0] = R[0, 0] + 1e12\n", 277 | "\n", 278 | "M = np.array([[-β]])\n", 279 | "Q = M.T @ M\n", 280 | "W = M.T @ S\n", 281 | "\n", 282 | "Π = np.array([[0.95, 0, 0.05, 0],\n", 283 | " [0.95, 0, 0.05, 0],\n", 284 | " [0, 0.9, 0, 0.1],\n", 285 | " [0, 0.9, 0, 0.1]])\n", 286 | "\n", 287 | "# Construct lists of matrices that correspond to each state\n", 288 | "As = [A, A, A, A]\n", 289 | "Bs = [B, B, B, B]\n", 290 | "Cs = [C, C, C, C]\n", 291 | "Rs = [R1, R2, R1, R2]\n", 292 | "Qs = [Q, Q, Q, Q]\n", 293 | "Ws = [W, W, W, W]\n", 294 | "\n", 295 | "lqm = qe.LQMarkov(Π, Qs, Rs, As, Bs, Cs=Cs, Ns=Ws, beta=β)\n", 296 | "lqm.stationary_values();" 297 | ] 298 | }, 299 | { 300 | "cell_type": "markdown", 301 | "metadata": {}, 302 | "source": [ 303 | "This model is simulated below, using the same process for $ G_t $ as\n", 304 | "in [this lecture](https://python.quantecon.org/tax_smoothing_2.html).\n", 305 | "\n", 306 | "When $ p^t_{t+1} = \\beta $\n", 307 | "government debt fluctuates around zero.\n", 308 | "\n", 309 | "The spikes in the series for\n", 310 | "taxation show periods when the government is unable to access financial\n", 311 | "markets: positive spikes occur when debt is positive, and the government\n", 312 | "must raise taxes in the current period.\n", 313 | "\n", 314 | "Negative spikes occur when the government has positive asset holdings.\n", 315 | "\n", 316 | "An inability to use financial markets in the next period means that the\n", 317 | "government uses those assets to lower taxation today." 318 | ] 319 | }, 320 | { 321 | "cell_type": "code", 322 | "execution_count": null, 323 | "metadata": { 324 | "hide-output": false 325 | }, 326 | "outputs": [], 327 | "source": [ 328 | "x0 = np.array([[0, 1, 25]])\n", 329 | "T = 300\n", 330 | "x, u, w, state = lqm.compute_sequence(x0, ts_length=T)\n", 331 | "\n", 332 | "# Calculate taxation each period from the budget constraint and the Markov state\n", 333 | "tax = np.zeros([T, 1])\n", 334 | "for i in range(T):\n", 335 | " tax[i, :] = S @ x[:, i] + M @ u[:, i]\n", 336 | "\n", 337 | "# Plot of debt issuance and taxation\n", 338 | "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 4))\n", 339 | "ax1.plot(x[0, :])\n", 340 | "ax1.set_title('One-period debt issuance')\n", 341 | "ax1.set_xlabel('Time')\n", 342 | "ax2.plot(tax)\n", 343 | "ax2.set_title('Taxation')\n", 344 | "ax2.set_xlabel('Time')\n", 345 | "plt.show()" 346 | ] 347 | }, 348 | { 349 | "cell_type": "markdown", 350 | "metadata": {}, 351 | "source": [ 352 | "We can adjust the model so that, rather than having debt fluctuate\n", 353 | "around zero, the government is a debtor in every period we allow it to\n", 354 | "borrow.\n", 355 | "\n", 356 | "To accomplish this, we simply raise $ p^t_{t+1} $ to\n", 357 | "$ \\beta + 0.02 = 0.97 $." 358 | ] 359 | }, 360 | { 361 | "cell_type": "code", 362 | "execution_count": null, 363 | "metadata": { 364 | "hide-output": false 365 | }, 366 | "outputs": [], 367 | "source": [ 368 | "M = np.array([[-β - 0.02]])\n", 369 | "\n", 370 | "Q = M.T @ M\n", 371 | "W = M.T @ S\n", 372 | "\n", 373 | "# Construct lists of matrices\n", 374 | "As = [A, A, A, A]\n", 375 | "Bs = [B, B, B, B]\n", 376 | "Cs = [C, C, C, C]\n", 377 | "Rs = [R1, R2, R1, R2]\n", 378 | "Qs = [Q, Q, Q, Q]\n", 379 | "Ws = [W, W, W, W]\n", 380 | "\n", 381 | "lqm2 = qe.LQMarkov(Π, Qs, Rs, As, Bs, Cs=Cs, Ns=Ws, beta=β)\n", 382 | "x, u, w, state = lqm2.compute_sequence(x0, ts_length=T)\n", 383 | "\n", 384 | "# Calculate taxation each period from the budget constraint and the\n", 385 | "# Markov state\n", 386 | "tax = np.zeros([T, 1])\n", 387 | "for i in range(T):\n", 388 | " tax[i, :] = S @ x[:, i] + M @ u[:, i]\n", 389 | "\n", 390 | "# Plot of debt issuance and taxation\n", 391 | "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 4))\n", 392 | "ax1.plot(x[0, :])\n", 393 | "ax1.set_title('One-period debt issuance')\n", 394 | "ax1.set_xlabel('Time')\n", 395 | "ax2.plot(tax)\n", 396 | "ax2.set_title('Taxation')\n", 397 | "ax2.set_xlabel('Time')\n", 398 | "plt.show()" 399 | ] 400 | }, 401 | { 402 | "cell_type": "markdown", 403 | "metadata": {}, 404 | "source": [ 405 | "With a lower interest rate, the government has an incentive to\n", 406 | "increase debt over time.\n", 407 | "\n", 408 | "However, with “roll-over risk”, debt is\n", 409 | "recurrently reset to zero and taxes spike up.\n", 410 | "\n", 411 | "Consequently, the\n", 412 | "government is wary of letting debt get too high, due to the high costs of\n", 413 | "a “sudden stop”." 414 | ] 415 | } 416 | ], 417 | "metadata": { 418 | "date": 1584334758.924878, 419 | "filename": "tax_smoothing_3.rst", 420 | "kernelspec": { 421 | "display_name": "Python", 422 | "language": "python3", 423 | "name": "python3" 424 | }, 425 | "title": "How to Pay for a War: Part 3" 426 | }, 427 | "nbformat": 4, 428 | "nbformat_minor": 2 429 | } -------------------------------------------------------------------------------- /troubleshooting.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "
\n", 10 | " \n", 11 | " \"QuantEcon\"\n", 12 | " \n", 13 | "
" 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "metadata": {}, 19 | "source": [ 20 | "# Troubleshooting" 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "## Contents\n", 28 | "\n", 29 | "- [Troubleshooting](#Troubleshooting) \n", 30 | " - [Fixing Your Local Environment](#Fixing-Your-Local-Environment) \n", 31 | " - [Reporting an Issue](#Reporting-an-Issue) " 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "This page is for readers experiencing errors when running the code from the lectures." 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": {}, 44 | "source": [ 45 | "## Fixing Your Local Environment\n", 46 | "\n", 47 | "The basic assumption of the lectures is that code in a lecture should execute whenever\n", 48 | "\n", 49 | "1. it is executed in a Jupyter notebook and \n", 50 | "1. the notebook is running on a machine with the latest version of Anaconda Python. \n", 51 | "\n", 52 | "\n", 53 | "You have installed Anaconda, haven’t you, following the instructions in [this lecture](https://python.quantecon.org/getting_started.html)?\n", 54 | "\n", 55 | "Assuming that you have, the most common source of problems for our readers is that their Anaconda distribution is not up to date.\n", 56 | "\n", 57 | "[Here’s a useful article](https://www.anaconda.com/keeping-anaconda-date/)\n", 58 | "on how to update Anaconda.\n", 59 | "\n", 60 | "Another option is to simply remove Anaconda and reinstall.\n", 61 | "\n", 62 | "You also need to keep the external code libraries, such as [QuantEcon.py](https://quantecon.org/quantecon-py) up to date.\n", 63 | "\n", 64 | "For this task you can either\n", 65 | "\n", 66 | "- use pip install –upgrade quantecon on the command line, or \n", 67 | "- execute !pip install –upgrade quantecon within a Jupyter notebook. \n", 68 | "\n", 69 | "\n", 70 | "If your local environment is still not working you can do two things.\n", 71 | "\n", 72 | "First, you can use a remote machine instead, by clicking on the Launch Notebook icon available for each lecture\n", 73 | "\n", 74 | "\n", 75 | "\n", 76 | "Second, you can report an issue, so we can try to fix your local set up.\n", 77 | "\n", 78 | "We like getting feedback on the lectures so please don’t hesitate to get in\n", 79 | "touch." 80 | ] 81 | }, 82 | { 83 | "cell_type": "markdown", 84 | "metadata": {}, 85 | "source": [ 86 | "## Reporting an Issue\n", 87 | "\n", 88 | "One way to give feedback is to raise an issue through our [issue tracker](https://github.com/QuantEcon/lecture-source-py/issues).\n", 89 | "\n", 90 | "Please be as specific as possible. Tell us where the problem is and as much\n", 91 | "detail about your local set up as you can provide.\n", 92 | "\n", 93 | "Another feedback option is to use our [discourse forum](https://discourse.quantecon.org/).\n", 94 | "\n", 95 | "Finally, you can provide direct feedback to [contact@quantecon.org](mailto:contact@quantecon.org)" 96 | ] 97 | } 98 | ], 99 | "metadata": { 100 | "date": 1584334758.9779892, 101 | "filename": "troubleshooting.rst", 102 | "kernelspec": { 103 | "display_name": "Python", 104 | "language": "python3", 105 | "name": "python3" 106 | }, 107 | "title": "Troubleshooting" 108 | }, 109 | "nbformat": 4, 110 | "nbformat_minor": 2 111 | } --------------------------------------------------------------------------------