├── .gitignore ├── AK_Fixed_Point_Solver.ipynb ├── AKsolve.py ├── DSGE_LinApp.ipynb ├── DSGE_grid.ipynb ├── DSGEtestdata.csv ├── Euler_Errors.ipynb ├── LICENSE ├── LinApp.py ├── Moment_Calculator.ipynb ├── OLG_DSGE.idx ├── OLG_DSGE.ipynb ├── OLG_DSGE.pdf ├── OLG_DSGE.py ├── OLG_DSGE.tex └── rouwen.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | #Latex Related Files 107 | #################### 108 | *.aux 109 | *.fdb_latexmk 110 | *.nav 111 | *.out 112 | *.snm 113 | *.gz 114 | *.toc 115 | *.pdfsync 116 | *.blg 117 | *.bbl 118 | *.log 119 | *.fls 120 | -------------------------------------------------------------------------------- /AK_Fixed_Point_Solver.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Using the Auberbach-Kotlikoff Fixed-Point Solver with Adaptive Dampening\n", 8 | "\n", 9 | "### by [Kerk L. Phillips](https://sites.google.com/site/kerkphillips/home), July 2018\n", 10 | "\n", 11 | "The code in this Jupyter notebook was written using Python 3.6." 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "This notebook explains how to use the Auberbach-Kotlikoff fixed-point solver where the dampeing parameter changes as one iterates. This code and examples can be downloaded at the following Github site. [https://github.com/kerkphil/DSGE-Utilities](https://github.com/kerkphil/DSGE-Utilities). Alternatively, this notebook can be found in the public GitHub repository [https://github.com/kerkphil/Jupyter_Notebooks](https://github.com/kerkphil/Jupyter_Notebooks)." 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "Auerbach and Kiotlikoff (1987) showed how to solve a deterministic overlapping generations (OLG) model using a fixed-point solver on the time path of aggregate capital for an economy. Their algorithm proceeds as follows:\n", 26 | "\n", 27 | "1) Set the counter $i=0$.\n", 28 | "\n", 29 | "2) Take an initial guess for the time path of aggregate capital over a long sample, $\\{K^i_t\\}_{t=1}^T$. $T$ needs to be large enough that the economy is effectively at the steady state by time $T$.\n", 30 | "\n", 31 | "3) Calculate the time paths for wages and interest rates $\\{w_t, r_t\\}_{t=1}^T$ given aggregate capital.\n", 32 | "\n", 33 | "4) For all households in all periods, calculate optimal savings given these prices.\n", 34 | "\n", 35 | "5) Aggregate the savings of all households each period to get a new measure of the capital stock each period, $\\{\\hat K_t\\}_{t=1}^T$.\n", 36 | "\n", 37 | "6) Calculate the difference between $\\{K^i_t\\}_{t=1}^T$ and $\\{\\hat K_t\\}_{t=1}^T$.\n", 38 | "\n", 39 | "7) If the difference is close to zero, end the solver, the transition path has been found. Otherwise update the guess for the time path using $\\{K^{i+1}_t\\}_{t=1}^T = \\xi \\{\\hat K_t\\}_{t=1}^T + (1-\\xi) \\{K^i_t\\}_{t=1}^T$, increment $i = i + 1$ and return to step 2)" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": {}, 45 | "source": [ 46 | "It is well-known that for a value of $0 < \\xi \\le 1$ sufficiently small this proceedure will eventually converge to a fixed-point.\n", 47 | "\n", 48 | "However, the smaller $\\xi$ is the longer the algorithm takes to converge. If $\\xi$ is too large, the algorithm may diverge.\n", 49 | "\n", 50 | "One way to speed up convergence is to adopt a value of $xi$ that changes with each iteration. A simple way to do this is to examine the difference $\\Delta^i \\equiv || \\{K^i_t\\}_{t=1}^T - \\{\\hat K_t\\}_{t=1}^T ||$ each iteration. If $\\Delta$ rises from one iteration to the next, we will reduce the dampener as this is signal that the algorithm may be diverging. If the value of $\\Delta$ falls, we can increase the dampener slightly to speed up convergence.\n", 51 | "\n", 52 | "$$ \\xi^{i+1} = \\left\\{ \\begin{matrix} \\lambda_1 \\xi^i & \\text{if } \\Delta^i > \\Delta^{i-1} \\\\ \\max(\\lambda_2 \\xi^i, 1) & \\text{if } \\Delta^i \\le \\Delta^{i-1} \\end{matrix} \\right.;\\; \\lambda_1 < 1 < \\lambda_2 $$" 53 | ] 54 | }, 55 | { 56 | "cell_type": "markdown", 57 | "metadata": {}, 58 | "source": [ 59 | "The following function implements this idea.\n", 60 | "\n", 61 | "The code for this is available at [https://github.com/kerkphil/DSGE-Utilities](https://github.com/kerkphil/DSGE-Utilities), but we reproduce that code in the cell below." 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": 1, 67 | "metadata": {}, 68 | "outputs": [], 69 | "source": [ 70 | "import numpy as np\n", 71 | "\n", 72 | "def AKsolve(Xguess, funcname, fparams, ccrit, damp, maxiter, shrinkon, \\\n", 73 | " shrink, expandon, expand, disttype, display):\n", 74 | " '''\n", 75 | " This function performs the Auerbach-Kotlikoff contraction mapping on a \n", 76 | " function.\n", 77 | " \n", 78 | " The inputs are:\n", 79 | " Xguess: An initial guess for the fixed point. Can be a scalar or\n", 80 | " matrix.\n", 81 | " funcname: Ahe name of the python function. It must take Xvalue as an\n", 82 | " argument with the same dimensions as Xguess, with fparams as \n", 83 | " parameters and return a new value for X, Xnew. \n", 84 | " fparams: A list of parameters used by funcname\n", 85 | " ccrit: The value for distance between Xvalue and Xnew that indicates\n", 86 | " convergence to the fixed point\n", 87 | " damp: The weight put on Xnew relative to Xvalue when moving to the\n", 88 | " next iteration; Xvalue = damp*Xnew + (1-damp)*Xvalue.\n", 89 | " maxiter: The maximum number of iterations allowed\n", 90 | " shrinkon: If true, the value of damp is scaled down when the distance\n", 91 | " between values of X in an iteration increases.\n", 92 | " shrink: The factor by which damp shrinks.\n", 93 | " expandon: If true, the value of damp is scaled up when the distance\n", 94 | " between values of X in an iteration does not increase.\n", 95 | " expand: The factor by which damp expands.\n", 96 | " disttype: Indicator variable for the method used to compute distance\n", 97 | " between Xvalue and Xnew\n", 98 | " 1: root mean squared differences (default)\n", 99 | " 2: mean absolute deviation\n", 100 | " 3: maximum absolute deviation\n", 101 | " display: If true, display iterations.\n", 102 | " \n", 103 | " The outputs are the fixed point, the last iteration's distanceand the\n", 104 | " number of iterations performed\n", 105 | " '''\n", 106 | " # initialize Xvalue\n", 107 | " Xvalue = Xguess\n", 108 | " # set initial distance measures\n", 109 | " dist = 1.0\n", 110 | " distold = 2.0\n", 111 | " # set counter\n", 112 | " count = 0\n", 113 | " # begin AK iterations\n", 114 | " print('Performing AK contraction mapping')\n", 115 | " while dist > ccrit:\n", 116 | " if count > maxiter:\n", 117 | " break\n", 118 | " Xnew = funcname(Xvalue, fparams)\n", 119 | " diff = Xnew - Xvalue\n", 120 | " if disttype == 2:\n", 121 | " dist = np.mean(np.absolute(diff))\n", 122 | " elif disttype == 3:\n", 123 | " dist = np.amax(np.absolute(diff))\n", 124 | " else:\n", 125 | " dist = (np.mean(diff**2))**.5\n", 126 | " # check if dist is falling, if not lower value of damp\n", 127 | " if (dist > distold) and (shrinkon):\n", 128 | " # shrink damp and redo with same Xvalue, do not update count\n", 129 | " damp = damp * shrink\n", 130 | " Xvalue = damp*Xnew + (1-damp)*Xvalue\n", 131 | " distold = dist\n", 132 | " else:\n", 133 | " # update Xvalue and count\n", 134 | " count = count + 1\n", 135 | " if expandon:\n", 136 | " # expand damp if it is < 1.0\n", 137 | " if damp < 1.0:\n", 138 | " damp = damp * expand\n", 139 | " else:\n", 140 | " damp = 1.0\n", 141 | " # take convex combination for new guess\n", 142 | " Xvalue = damp*Xnew + (1-damp)*Xvalue\n", 143 | " # replace old dist value\n", 144 | " distold = dist\n", 145 | " # show progress\n", 146 | " if display:\n", 147 | " print ('count: ', count, 'distance: ', dist, 'damp: ', damp)\n", 148 | " \n", 149 | " return Xvalue, dist, count" 150 | ] 151 | }, 152 | { 153 | "cell_type": "markdown", 154 | "metadata": {}, 155 | "source": [ 156 | "## Implementing the Code for a Solow Growth Model's Steady State" 157 | ] 158 | }, 159 | { 160 | "cell_type": "markdown", 161 | "metadata": {}, 162 | "source": [ 163 | "Below is a function that implements the known transition function for the Solow growth model. Here $\\delta$ is the depreciation rate, $\\gamma$ is the savings rate, and $\\alpha$ is the capital share in GDP. These values are included in the list `fparams`." 164 | ] 165 | }, 166 | { 167 | "cell_type": "code", 168 | "execution_count": 2, 169 | "metadata": {}, 170 | "outputs": [], 171 | "source": [ 172 | "def example(X, fparams):\n", 173 | " # An example using the Solow growth model\n", 174 | " Xnew = (1-delta)*X + gamma*X**alpha\n", 175 | " \n", 176 | " return Xnew" 177 | ] 178 | }, 179 | { 180 | "cell_type": "markdown", 181 | "metadata": {}, 182 | "source": [ 183 | "The following program implements the AK fixed-point solver for this simple model. We solve for the steady state value of capital $\\bar X$." 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": 3, 189 | "metadata": {}, 190 | "outputs": [ 191 | { 192 | "name": "stdout", 193 | "output_type": "stream", 194 | "text": [ 195 | "Performing AK contraction mapping\n", 196 | "Xfixed: 0.495858909362753\n", 197 | "Xbar 0.4958419986580077\n", 198 | "distance: 9.577551448036736e-07\n", 199 | "iterations: 249\n" 200 | ] 201 | } 202 | ], 203 | "source": [ 204 | "import numpy as np\n", 205 | "import scipy.optimize as opt\n", 206 | "import matplotlib.pyplot as plt\n", 207 | "\n", 208 | "# set parameter values for AKsolve \n", 209 | "ccrit = 1e-6 # convegence criterion for A-K solution\n", 210 | "conv = .25 # initital weight on new values in convexifier\n", 211 | "maxiter = 10000 # maximum number of iterations allowed in A-K solver\n", 212 | "shrinkon = 1 # binary flag to implement shrinking conv value\n", 213 | "shrink = .75 # factor to reduce conv if A-K not converging\n", 214 | "expandon = 1 # binary flag to implement expanding conv value\n", 215 | "expand = 1.01 # factor to expand conv if A-K is converging\n", 216 | "disttype = 1 # distance measure formula\n", 217 | "display = 0 # display iterations on or off\n", 218 | "\n", 219 | "# set parameter values for example\n", 220 | "delta = .08\n", 221 | "gamma = .05\n", 222 | "alpha = .33\n", 223 | "fparams = {delta, gamma, alpha}\n", 224 | "\n", 225 | "# Use AK method to find fixed point\n", 226 | "Xfixed, distance, count = AKsolve(1.0, example, fparams, ccrit, conv, \\\n", 227 | " maxiter, shrinkon, shrink, expandon, expand, disttype, display)\n", 228 | " \n", 229 | "# find closed form solution for SS value\n", 230 | "Xbar = (gamma/delta)**(1/(1-alpha))\n", 231 | "\n", 232 | "print('Xfixed: ', Xfixed)\n", 233 | "print('Xbar ', Xbar)\n", 234 | "print('distance: ', distance)\n", 235 | "print('iterations:', count)" 236 | ] 237 | }, 238 | { 239 | "cell_type": "markdown", 240 | "metadata": {}, 241 | "source": [ 242 | "Try varying the values of `expand` and `shrink` to see how the number of iterations changes." 243 | ] 244 | }, 245 | { 246 | "cell_type": "markdown", 247 | "metadata": {}, 248 | "source": [ 249 | "## Implementing the Code for an OLG Model's Steady State" 250 | ] 251 | }, 252 | { 253 | "cell_type": "markdown", 254 | "metadata": {}, 255 | "source": [ 256 | "Consider a model where a household of age $s$ solves the following dyanamic program.\n", 257 | "\n", 258 | "$$ V^s(k_{st}, \\Theta_t) = \\max_{k_{s+1,t+1}, n_{st}} \\frac{c_{st}^{1-\\gamma} - 1}{1-\\gamma} + \\chi_n \\left( 1 - n_{st}^\\upsilon \\right)^{\\frac{1}{\\upsilon}} + \\beta E \\left\\{ V^{s+1}(k_{s+1,t+1}, \\Theta_{t+1}) \\right\\} $$\n", 259 | "\n", 260 | "Here we use an elliptical utility function for leisure as discussed in Evans and Phillips (2018). This guarantees an interior solution where $0 < n_{st} < 1$\n", 261 | "\n", 262 | "The household budget constraint is:\n", 263 | "$$ c_{st} = w_t n_{st} + (1+r_t-\\delta)k_{st} - k_{s+1,t+1} $$\n", 264 | "\n", 265 | "The Euler equations are:\n", 266 | "$$ c_{st}^{-\\gamma} = \\beta E \\left\\{ c_{s+1,t+1}^{-\\gamma} (1+r_{t+1}-\\delta) \\right\\} $$\n", 267 | "$$ c_{st}^{-\\gamma} w_t = \\chi_n n_{st}^{\\upsilon-1}(1-n_{st}^{\\upsilon})^{\\frac{1-\\upsilon}{\\upsilon}} $$\n", 268 | "\n", 269 | "Suppose also that in the final period of life there is a bequest motive so that households are willing to die with positive assets. That problem will be:\n", 270 | "$$ V^S(k_{St}, \\Theta_t) = \\max_{k_{S+1,t+1}, n_{St}} \\frac{c_{st}^{1-\\gamma} - 1}{1-\\gamma} + \\chi_n \\left( 1 - n_{St}^\\upsilon \\right)^{\\frac{1}{\\upsilon}} + \\chi_b \\frac{k_{S+1,t}^{1-\\gamma}-1}{1-\\gamma} $$\n", 271 | "\n", 272 | "This gives a final intertemporal Euler equation.\n", 273 | "$$ c_{St}^{-\\gamma} = \\chi_b k_{S+1,t+1}^{-\\gamma} $$\n", 274 | "\n", 275 | "From the firm's problem we get:\n", 276 | "$$ Y_t = K_t^\\alpha L_t^{1-\\alpha} $$\n", 277 | "$$ r_t = \\alpha \\frac{Y_t}{K_t} $$\n", 278 | "$$ w_t = (1-\\alpha) \\frac{Y_t}{L_t} $$\n", 279 | "\n", 280 | "Market clearing gives:\n", 281 | "$$ K_t = \\sum_{s=1}^S k_{st} $$\n", 282 | "$$ L_t = \\sum_{s=1}^S n_{st} $$" 283 | ] 284 | }, 285 | { 286 | "cell_type": "markdown", 287 | "metadata": {}, 288 | "source": [ 289 | "To solve for the steady state we need to solve for the steady-state holdings of capital and labor for each cohort. Given a set of guesses for $\\bar w$ and $\\bar r$, we can solve for the optimal steady state consumptions and labors by age, $\\{\\bar c_s, \\bar n_s\\}_{s=1}^S$. The budget constraint then gives us $\\{\\bar k_s\\}_{s=1}^S$, and we can aggregate this and $\\{\\bar n_s\\}_{s=1}^S$ to get aggregate capital and labor. From there we can update our guesses for $\\bar w$ and $\\bar r$.\n", 290 | "\n", 291 | "We need to be able to solve for the value of $\\bar c_1$ that sets $\\bar k_{S+1} = 0$ and in order to do this we have to be able to solve jointly for $\\bar c_s$ and \\bar n_s$ for each age.\n", 292 | "\n", 293 | "The function below takes values of $c$ and $n$ and returns tge labor/leisure Euler equation deviation." 294 | ] 295 | }, 296 | { 297 | "cell_type": "code", 298 | "execution_count": 12, 299 | "metadata": {}, 300 | "outputs": [], 301 | "source": [ 302 | "# This is the labor-leisure Euler equation set up to be zero by definition\n", 303 | "def LLEuler(n, c, *HHparams):\n", 304 | " # unpack HHparams\n", 305 | " wbar = HHparams[0]\n", 306 | " \n", 307 | " return wbar*c**(-gamma) - chin*n**(ups-1)*(1-n**ups)**((1-ups)/ups)" 308 | ] 309 | }, 310 | { 311 | "cell_type": "markdown", 312 | "metadata": {}, 313 | "source": [ 314 | "We use this function to help in solving for the optimal $\\bar c_1$ in the functions below." 315 | ] 316 | }, 317 | { 318 | "cell_type": "code", 319 | "execution_count": 13, 320 | "metadata": {}, 321 | "outputs": [], 322 | "source": [ 323 | "def conshist(c1, *HHparams):\n", 324 | " # unpack HHparams\n", 325 | " wbar = HHparams[0]\n", 326 | " rbar = HHparams[1]\n", 327 | " # initialize vectors for consumption, labor and savings\n", 328 | " chist = np.zeros(S)\n", 329 | " nhist = np.zeros(S)\n", 330 | " bhist = np.zeros(S+1)\n", 331 | " # set intitial consumption value\n", 332 | " chist[0] = c1\n", 333 | " for t in range(0, S):\n", 334 | " # set up lambda function for fsolve with n as the input\n", 335 | " f1 = lambda n: LLEuler(n, chist[t], *HHparams)\n", 336 | " # solve LLEuler for value of n given c\n", 337 | " nhist[t] = opt.fsolve(f1, .99)\n", 338 | " if printcheck:\n", 339 | " # check that LLEuler is close to zero and report\n", 340 | " check = f1(nhist[t])\n", 341 | " print(\"nhist\", t, \": \", nhist[t], \" check-n: \", check)\n", 342 | " # solve for b given c and n\n", 343 | " bhist[t+1] = wbar*nhist[t] + (1.+rbar)*bhist[t] - chist[t]\n", 344 | " # if not the final period solve for next period's c from interpemporal\n", 345 | " # Euler equation\n", 346 | " if t< S-1:\n", 347 | " chist[t+1] = chist[t]*(bet*(1.+rbar))**(1/gamma)\n", 348 | " \n", 349 | " return chist, nhist, bhist\n", 350 | "\n", 351 | "\n", 352 | "# parameters \n", 353 | "def findc1(c1, *HHparams):\n", 354 | " # This function is for fsolve it takes initial consumption and returns \n", 355 | " # the final IT Euler error.\n", 356 | " chist, nhist, bhist = conshist(c1, *HHparams)\n", 357 | " \n", 358 | " return chist[S-1] - chib**(-1.0/gamma)*bhist[S]" 359 | ] 360 | }, 361 | { 362 | "cell_type": "markdown", 363 | "metadata": {}, 364 | "source": [ 365 | "Lastly we use these functions to update our values of $\\bar w$ and $\\bar r$." 366 | ] 367 | }, 368 | { 369 | "cell_type": "code", 370 | "execution_count": 14, 371 | "metadata": {}, 372 | "outputs": [], 373 | "source": [ 374 | "# find updated wbar and rbar from initial guesses\n", 375 | "def updatebar(bar, UPparams):\n", 376 | " # unpack the bar vector\n", 377 | " wbar = bar[0]\n", 378 | " rbar = bar[1]\n", 379 | " # set parameters to pass to findc1 in fsolve\n", 380 | " HHparams = (wbar, rbar, gamma, chin, chib, ups, bet, S, printcheck)\n", 381 | " # solve findc1 for value of c1 \n", 382 | " c1opt = opt.fsolve(findc1, .1, args=HHparams)\n", 383 | " # check that final savings is close to zero and report\n", 384 | " # check = findc1(c1opt, *HHparams)\n", 385 | " # print \"check-c: \", check, \"wbar & rbar: \", wbar, rbar\n", 386 | " # get the consumer's full history\n", 387 | " chist, nhist, bhist = conshist(c1opt, *HHparams)\n", 388 | " # sum savings and labor to get aggregate capital annd labor inputs\n", 389 | " Kbar = np.sum(bhist)\n", 390 | " if Kbar < .01:\n", 391 | " Kbar = .01\n", 392 | " Lbar = np.sum(nhist)\n", 393 | " # solve for the implied values of wages and interest rates\n", 394 | " wbarnew = (1-alf)*(Kbar/Lbar)**alf\n", 395 | " rbarnew = alf*(Lbar/Kbar)**(1-alf) - delta\n", 396 | " # put into barnew array\n", 397 | " barnew = np.array([wbarnew, rbarnew])\n", 398 | " \n", 399 | " return barnew" 400 | ] 401 | }, 402 | { 403 | "cell_type": "markdown", 404 | "metadata": {}, 405 | "source": [ 406 | "We can now proceed to implement the fixed-point solver." 407 | ] 408 | }, 409 | { 410 | "cell_type": "code", 411 | "execution_count": 15, 412 | "metadata": { 413 | "scrolled": true 414 | }, 415 | "outputs": [ 416 | { 417 | "name": "stdout", 418 | "output_type": "stream", 419 | "text": [ 420 | "Performing AK contraction mapping\n" 421 | ] 422 | }, 423 | { 424 | "name": "stderr", 425 | "output_type": "stream", 426 | "text": [ 427 | "C:\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:6: RuntimeWarning: invalid value encountered in power\n", 428 | " \n", 429 | "C:\\Anaconda3\\lib\\site-packages\\scipy\\optimize\\minpack.py:161: RuntimeWarning: The iteration is not making good progress, as measured by the \n", 430 | " improvement from the last ten iterations.\n", 431 | " warnings.warn(msg, RuntimeWarning)\n" 432 | ] 433 | }, 434 | { 435 | "name": "stdout", 436 | "output_type": "stream", 437 | "text": [ 438 | "count: 1 distance: 0.2171964689195677 damp: 0.2525\n", 439 | "count: 2 distance: 0.05182142178578554 damp: 0.255025\n", 440 | "count: 2 distance: 0.17733081239204207 damp: 0.19126875\n", 441 | "count: 3 distance: 0.017236860082718814 damp: 0.1931814375\n", 442 | "count: 3 distance: 0.10166602565831412 damp: 0.14488607812499998\n", 443 | "count: 4 distance: 0.029324178992136355 damp: 0.14633493890625\n", 444 | "count: 4 distance: 0.043770236021735014 damp: 0.10975120417968749\n", 445 | "count: 5 distance: 0.03222890973879605 damp: 0.11084871622148437\n", 446 | "count: 6 distance: 0.0291893258194466 damp: 0.11195720338369922\n", 447 | "count: 7 distance: 0.02584698506286097 damp: 0.1130767754175362\n", 448 | "count: 8 distance: 0.022924448676721547 damp: 0.11420754317171157\n", 449 | "count: 9 distance: 0.020298586201267583 damp: 0.11534961860342868\n", 450 | "count: 10 distance: 0.017952307977991768 damp: 0.11650311478946297\n", 451 | "count: 11 distance: 0.015856831290687982 damp: 0.1176681459373576\n", 452 | "count: 12 distance: 0.013987925342548342 damp: 0.11884482739673118\n", 453 | "count: 13 distance: 0.01232314378681462 damp: 0.12003327567069849\n", 454 | "count: 14 distance: 0.010842102891462693 damp: 0.12123360842740548\n", 455 | "count: 15 distance: 0.009526238562741892 damp: 0.12244594451167953\n", 456 | "count: 16 distance: 0.008358677672592834 damp: 0.12367040395679633\n", 457 | "count: 17 distance: 0.007324098470657398 damp: 0.1249071079963643\n", 458 | "count: 18 distance: 0.006408605491831989 damp: 0.12615617907632795\n", 459 | "count: 19 distance: 0.005599612299933493 damp: 0.12741774086709123\n", 460 | "count: 20 distance: 0.004885732865881902 damp: 0.12869191827576215\n", 461 | "count: 21 distance: 0.004256680655257835 damp: 0.12997883745851976\n", 462 | "count: 22 distance: 0.0037031750206853904 damp: 0.13127862583310496\n", 463 | "count: 23 distance: 0.0032168544078454383 damp: 0.13259141209143602\n", 464 | "count: 24 distance: 0.002790195959124682 damp: 0.1339173262123504\n", 465 | "count: 25 distance: 0.002416441117127145 damp: 0.1352564994744739\n", 466 | "count: 26 distance: 0.0020895268576678065 damp: 0.13660906446921864\n", 467 | "count: 27 distance: 0.0018040222050744186 damp: 0.1379751551139108\n", 468 | "count: 28 distance: 0.0015550696990500033 damp: 0.13935490666504993\n", 469 | "count: 29 distance: 0.001338331501609776 damp: 0.14074845573170044\n", 470 | "count: 30 distance: 0.00114993984784601 damp: 0.14215594028901746\n", 471 | "count: 31 distance: 0.000986451557177134 damp: 0.14357749969190764\n", 472 | "count: 32 distance: 0.0008448063373331728 damp: 0.14501327468882672\n", 473 | "count: 33 distance: 0.0007222886256830513 damp: 0.14646340743571498\n", 474 | "count: 34 distance: 0.0006164927231406875 damp: 0.14792804151007213\n", 475 | "count: 35 distance: 0.0005252909914503322 damp: 0.14940732192517286\n", 476 | "count: 36 distance: 0.00044680489134309626 damp: 0.1509013951444246\n", 477 | "count: 37 distance: 0.0003793786564347294 damp: 0.15241040909586887\n", 478 | "count: 38 distance: 0.0003215554012153618 damp: 0.15393451318682755\n", 479 | "count: 39 distance: 0.0002720554811706116 damp: 0.1554738583186958\n", 480 | "count: 40 distance: 0.00022975692351706473 damp: 0.15702859690188278\n", 481 | "count: 41 distance: 0.00019367776779132188 damp: 0.15859888287090163\n", 482 | "count: 42 distance: 0.00016296015457524727 damp: 0.16018487169961065\n", 483 | "count: 43 distance: 0.00013685602138535795 damp: 0.16178672041660677\n", 484 | "count: 44 distance: 0.00011471426340985696 damp: 0.16340458762077284\n", 485 | "count: 45 distance: 9.596923469282903e-05 damp: 0.16503863349698056\n", 486 | "count: 46 distance: 8.01304682267989e-05 damp: 0.16668901983195036\n", 487 | "count: 47 distance: 6.67735040882687e-05 damp: 0.16835591003026987\n", 488 | "count: 48 distance: 5.5531723784212544e-05 damp: 0.17003946913057258\n", 489 | "count: 49 distance: 4.608909271863567e-05 damp: 0.1717398638218783\n", 490 | "count: 50 distance: 3.817372623065395e-05 damp: 0.1734572624600971\n", 491 | "count: 51 distance: 3.155219402129549e-05 damp: 0.17519183508469807\n", 492 | "count: 52 distance: 2.6024492070110045e-05 damp: 0.17694375343554505\n", 493 | "count: 53 distance: 2.141961031389702e-05 damp: 0.17871319096990052\n", 494 | "count: 54 distance: 1.75916363291065e-05 damp: 0.18050032287959952\n", 495 | "count: 55 distance: 1.4416335451187893e-05 damp: 0.18230532610839553\n", 496 | "count: 56 distance: 1.1788157463247465e-05 damp: 0.18412837936947948\n", 497 | "count: 57 distance: 9.617620946635752e-06 damp: 0.1859696631631743\n", 498 | "count: 58 distance: 7.829033708107654e-06 damp: 0.18782935979480603\n", 499 | "count: 59 distance: 6.3585103954147885e-06 damp: 0.18970765339275408\n", 500 | "count: 60 distance: 5.152251612973279e-06 damp: 0.19160472992668162\n", 501 | "count: 61 distance: 4.165055444034738e-06 damp: 0.19352077722594843\n", 502 | "count: 62 distance: 3.3590303664264097e-06 damp: 0.1954559849982079\n", 503 | "count: 63 distance: 2.7024876105670052e-06 damp: 0.19741054484818998\n", 504 | "count: 64 distance: 2.1689878970715242e-06 damp: 0.19938465029667188\n", 505 | "count: 65 distance: 1.736524999977242e-06 damp: 0.2013784967996386\n", 506 | "count: 66 distance: 1.3868260826641255e-06 damp: 0.203392281767635\n", 507 | "count: 67 distance: 1.1047563939112341e-06 damp: 0.20542620458531136\n", 508 | "count: 68 distance: 8.778103940342298e-07 damp: 0.20748046663116448\n", 509 | "distance: 8.778103940342298e-07\n", 510 | "iterations: 68\n" 511 | ] 512 | } 513 | ], 514 | "source": [ 515 | "# set model parameter values\n", 516 | "S = 100 # max age\n", 517 | "alf = .33 # capital share\n", 518 | "bet = .99 # annual subjective discount factor\n", 519 | "delta = .08 # annual depreciation rate\n", 520 | "gamma = 3.0 # intertemporal elasticity of substitution\n", 521 | "chin = 10.0 # utility weight on leisure\n", 522 | "ups = 2.2926 # curvature in elliptical utility\n", 523 | "chib = .1 # utility eight on bequest in last period of life\n", 524 | "printcheck = 0 # if 1 display each of the labor/leisure Euler deviations\n", 525 | "\n", 526 | "# set AKsolve parameter values\n", 527 | "ccrit = 1e-6 # convegence criterion for A-K solution\n", 528 | "conv = .25 # initital weight on new values in convexifier\n", 529 | "maxiter = 200 # maximum number of iterations allowed in A-K solver\n", 530 | "shrinkon = 1 # binary flag to implement shrinking conv value\n", 531 | "shrink = .75 # factor to reduce conv if A-K not converging\n", 532 | "expandon = 1 # binary flag to implement expanding conv value\n", 533 | "expand = 1.01 # factor to expand conv if A-K is converging\n", 534 | "disttype = 1 # distance measure formula\n", 535 | "display = 1 # display iterations on or off\n", 536 | "\n", 537 | "# convert beta and delta to per period values\n", 538 | "bet = bet**(100./S)\n", 539 | "delta = 1. - (1. - delta)**(100./S)\n", 540 | "\n", 541 | "# set paramters to pass to updatebar\n", 542 | "UPparams = (gamma, chin, chib, ups, bet, S, printcheck)\n", 543 | "\n", 544 | "# set initial guess for wbar and rbar\n", 545 | "wbar = 1\n", 546 | "rbar = .02\n", 547 | "bar = np.array([wbar, rbar])\n", 548 | "\n", 549 | "# set parameters to pass to findc1 in fsolve\n", 550 | "HHparams = (wbar, rbar, gamma, chin, chib, ups, bet, S, printcheck)\n", 551 | "\n", 552 | "# run the solver\n", 553 | "bar, distance, count = AKsolve(bar, updatebar, UPparams, ccrit, conv, maxiter, shrinkon, \\\n", 554 | " shrink, expandon, expand, disttype, display)\n", 555 | "print('distance: ', distance)\n", 556 | "print('iterations:', count)" 557 | ] 558 | }, 559 | { 560 | "cell_type": "markdown", 561 | "metadata": {}, 562 | "source": [ 563 | "Display the results" 564 | ] 565 | }, 566 | { 567 | "cell_type": "code", 568 | "execution_count": 16, 569 | "metadata": {}, 570 | "outputs": [ 571 | { 572 | "name": "stdout", 573 | "output_type": "stream", 574 | "text": [ 575 | "wbar: 1.2276001938785823 rbar: 0.016511666209647027\n", 576 | "nhist 0 : 0.5882775319264427 check-n: -4.440892098500626e-14\n", 577 | "nhist 1 : 0.5862515532169315 check-n: -4.796163466380676e-14\n", 578 | "nhist 2 : 0.584225892358793 check-n: -5.1514348342607263e-14\n", 579 | "nhist 3 : 0.582200625138234 check-n: -5.595524044110789e-14\n", 580 | "nhist 4 : 0.5801758269435954 check-n: -6.039613253960852e-14\n", 581 | "nhist 5 : 0.5781515727549874 check-n: -6.483702463810914e-14\n", 582 | "nhist 6 : 0.5761279371341351 check-n: -7.016609515630989e-14\n", 583 | "nhist 7 : 0.5741049942144345 check-n: -7.549516567451064e-14\n", 584 | "nhist 8 : 0.5720828176912234 check-n: -8.171241461241152e-14\n", 585 | "nhist 9 : 0.5700614808122659 check-n: -8.615330671091215e-14\n", 586 | "nhist 10 : 0.5680410563684551 check-n: -9.414691248821327e-14\n", 587 | "nhist 11 : 0.5660216166847301 check-n: -1.021405182655144e-13\n", 588 | "nhist 12 : 0.5640032336112137 check-n: -1.092459456231154e-13\n", 589 | "nhist 13 : 0.5619859785145693 check-n: -1.1546319456101628e-13\n", 590 | "nhist 14 : 0.5599699222695758 check-n: -1.2256862191861728e-13\n", 591 | "nhist 15 : 0.5579551352509249 check-n: -1.3233858453531866e-13\n", 592 | "nhist 16 : 0.5559416873252387 check-n: -1.4210854715202004e-13\n", 593 | "nhist 17 : 0.5539296478433092 check-n: -1.5276668818842154e-13\n", 594 | "nhist 18 : 0.5519190856325581 check-n: -1.616484723854228e-13\n", 595 | "nhist 19 : 0.5499100689897203 check-n: -1.723066134218243e-13\n", 596 | "nhist 20 : 0.5479026656737478 check-n: -1.8740564655672642e-13\n", 597 | "nhist 21 : 0.5458969428989346 check-n: -1.9806378759312793e-13\n", 598 | "nhist 22 : 0.5438929673282656 check-n: -2.1405099914773018e-13\n", 599 | "nhist 23 : 0.5418908050669831 check-n: -2.2737367544323206e-13\n", 600 | "nhist 24 : 0.5398905216563761 check-n: -2.389199948993337e-13\n", 601 | "nhist 25 : 0.5378921820677891 check-n: -2.5490720645393594e-13\n", 602 | "nhist 26 : 0.5358958506968492 check-n: -2.708944180085382e-13\n", 603 | "nhist 27 : 0.5339015913579127 check-n: -2.886579864025407e-13\n", 604 | "nhist 28 : 0.5319094672787286 check-n: -3.055333763768431e-13\n", 605 | "nhist 29 : 0.5299195410953186 check-n: -3.277378368693462e-13\n", 606 | "nhist 30 : 0.5279318748470729 check-n: -3.4638958368304884e-13\n", 607 | "nhist 31 : 0.5259465299720603 check-n: -3.6770586575585185e-13\n", 608 | "nhist 32 : 0.5239635673025497 check-n: -3.8813396940895473e-13\n", 609 | "nhist 33 : 0.5219830470607459 check-n: -4.1389114358025836e-13\n", 610 | "nhist 34 : 0.5200050288547325 check-n: -4.3787196091216174e-13\n", 611 | "nhist 35 : 0.5180295716745965 check-n: 0.0\n", 612 | "nhist 36 : 0.5160567338889027 check-n: 0.0\n", 613 | "nhist 37 : 0.5140865732410883 check-n: 0.0\n", 614 | "nhist 38 : 0.5121191468463433 check-n: 8.881784197001252e-16\n", 615 | "nhist 39 : 0.5101545111885527 check-n: -8.881784197001252e-16\n", 616 | "nhist 40 : 0.5081927221174652 check-n: -8.881784197001252e-16\n", 617 | "nhist 41 : 0.5062338348460617 check-n: -8.881784197001252e-16\n", 618 | "nhist 42 : 0.5042779039481161 check-n: -1.7763568394002505e-15\n", 619 | "nhist 43 : 0.5023249833559524 check-n: 8.881784197001252e-16\n", 620 | "nhist 44 : 0.5003751263583921 check-n: 0.0\n", 621 | "nhist 45 : 0.4984283855988888 check-n: 0.0\n", 622 | "nhist 46 : 0.4964848130738524 check-n: 8.881784197001252e-16\n", 623 | "nhist 47 : 0.49454446013115616 check-n: -1.7763568394002505e-15\n", 624 | "nhist 48 : 0.4926073774688249 check-n: 8.881784197001252e-16\n", 625 | "nhist 49 : 0.49067361513390473 check-n: 0.0\n", 626 | "nhist 50 : 0.4887432225215076 check-n: -8.881784197001252e-16\n", 627 | "nhist 51 : 0.4868162483740317 check-n: 0.0\n", 628 | "nhist 52 : 0.4848927407805539 check-n: -8.881784197001252e-16\n", 629 | "nhist 53 : 0.48297274717639 check-n: -8.881784197001252e-16\n", 630 | "nhist 54 : 0.48105631434282337 check-n: -8.881784197001252e-16\n", 631 | "nhist 55 : 0.47914348840699633 check-n: 0.0\n", 632 | "nhist 56 : 0.4772343148419639 check-n: -8.881784197001252e-16\n", 633 | "nhist 57 : 0.4753288384669045 check-n: -8.881784197001252e-16\n", 634 | "nhist 58 : 0.47342710344748845 check-n: 0.0\n", 635 | "nhist 59 : 0.4715291532963982 check-n: -8.881784197001252e-16\n", 636 | "nhist 60 : 0.4696350308739988 check-n: 0.0\n", 637 | "nhist 61 : 0.46774477838915657 check-n: 0.0\n", 638 | "nhist 62 : 0.46585843740020133 check-n: 0.0\n", 639 | "nhist 63 : 0.4639760488160321 check-n: 0.0\n", 640 | "nhist 64 : 0.46209765289735977 check-n: 0.0\n", 641 | "nhist 65 : 0.46022328925808725 check-n: 0.0\n", 642 | "nhist 66 : 0.4583529968668218 check-n: -8.881784197001252e-16\n", 643 | "nhist 67 : 0.4564868140485188 check-n: -8.881784197001252e-16\n", 644 | "nhist 68 : 0.4546247784862524 check-n: -4.440892098500626e-16\n", 645 | "nhist 69 : 0.4527669272231107 check-n: -4.440892098500626e-16\n", 646 | "nhist 70 : 0.4509132966642127 check-n: 4.440892098500626e-16\n", 647 | "nhist 71 : 0.4490639225788447 check-n: 0.0\n", 648 | "nhist 72 : 0.4472188401027118 check-n: 8.881784197001252e-16\n", 649 | "nhist 73 : 0.4453780837403032 check-n: -4.440892098500626e-16\n", 650 | "nhist 74 : 0.4435416873673675 check-n: 4.440892098500626e-16\n", 651 | "nhist 75 : 0.44170968423349577 check-n: 4.440892098500626e-16\n", 652 | "nhist 76 : 0.43988210696480917 check-n: -8.881784197001252e-16\n", 653 | "nhist 77 : 0.4380589875667476 check-n: 8.881784197001252e-16\n", 654 | "nhist 78 : 0.436240357426959 check-n: 0.0\n", 655 | "nhist 79 : 0.4344262473182829 check-n: 4.440892098500626e-16\n", 656 | "nhist 80 : 0.43261668740182946 check-n: -4.440892098500626e-16\n", 657 | "nhist 81 : 0.4308117072301472 check-n: 0.0\n", 658 | "nhist 82 : 0.42901133575048045 check-n: 0.0\n", 659 | "nhist 83 : 0.42721560130811037 check-n: 0.0\n", 660 | "nhist 84 : 0.42542453164978017 check-n: -4.440892098500626e-16\n", 661 | "nhist 85 : 0.423638153927199 check-n: -8.881784197001252e-16\n", 662 | "nhist 86 : 0.4218564947006233 check-n: -4.440892098500626e-16\n", 663 | "nhist 87 : 0.4200795799425132 check-n: -8.881784197001252e-16\n", 664 | "nhist 88 : 0.4183074350412603 check-n: 0.0\n", 665 | "nhist 89 : 0.41654008480498494 check-n: 4.440892098500626e-16\n", 666 | "nhist 90 : 0.41477755346540124 check-n: -4.440892098500626e-16\n", 667 | "nhist 91 : 0.4130198646817447 check-n: 0.0\n", 668 | "nhist 92 : 0.4112670415447634 check-n: 4.440892098500626e-16\n", 669 | "nhist 93 : 0.4095191065807674 check-n: 0.0\n", 670 | "nhist 94 : 0.40777608175573565 check-n: 0.0\n", 671 | "nhist 95 : 0.40603798847947753 check-n: -4.440892098500626e-16\n", 672 | "nhist 96 : 0.4043048476098453 check-n: 4.440892098500626e-16\n", 673 | "nhist 97 : 0.4025766794569988 check-n: -4.440892098500626e-16\n", 674 | "nhist 98 : 0.4008535037877148 check-n: 0.0\n", 675 | "nhist 99 : 0.3991353398297435 check-n: -4.440892098500626e-16\n" 676 | ] 677 | }, 678 | { 679 | "name": "stderr", 680 | "output_type": "stream", 681 | "text": [ 682 | "C:\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:6: RuntimeWarning: invalid value encountered in power\n", 683 | " \n", 684 | "C:\\Anaconda3\\lib\\site-packages\\scipy\\optimize\\minpack.py:161: RuntimeWarning: The iteration is not making good progress, as measured by the \n", 685 | " improvement from the last ten iterations.\n", 686 | " warnings.warn(msg, RuntimeWarning)\n" 687 | ] 688 | } 689 | ], 690 | "source": [ 691 | "# recover wbar and rbar and print\n", 692 | "wbar = bar[0]\n", 693 | "rbar = bar[1]\n", 694 | "print(\"wbar: \", wbar, \"rbar: \", rbar)\n", 695 | "HHparams = (wbar, rbar, gamma, chin, chib, ups, bet, S, printcheck)\n", 696 | "\n", 697 | "# check the equations have solved\n", 698 | "c1opt = opt.fsolve(findc1, .1, args=HHparams)\n", 699 | "printcheck = 1\n", 700 | "chist, nhist, khist = conshist(c1opt, *HHparams)\n", 701 | "\n", 702 | "# drop last period for savings (it is now zero anyway)\n", 703 | "khist = khist[0:S]" 704 | ] 705 | }, 706 | { 707 | "cell_type": "markdown", 708 | "metadata": {}, 709 | "source": [ 710 | "Plot the steady state values over ages" 711 | ] 712 | }, 713 | { 714 | "cell_type": "code", 715 | "execution_count": 17, 716 | "metadata": {}, 717 | "outputs": [ 718 | { 719 | "data": { 720 | "image/png": "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\n", 721 | "text/plain": [ 722 | "" 723 | ] 724 | }, 725 | "metadata": {}, 726 | "output_type": "display_data" 727 | } 728 | ], 729 | "source": [ 730 | "# plot steady state values for consumption, savings and labor\n", 731 | "plt.subplot(3, 1, 1)\n", 732 | "plt.plot(chist)\n", 733 | "plt.title('Consumption', y=.92)\n", 734 | "plt.xlabel('age')\n", 735 | "plt.xticks([])\n", 736 | "\n", 737 | "plt.subplot(3, 1, 2)\n", 738 | "plt.plot(nhist)\n", 739 | "plt.title('Labor', y=.92)\n", 740 | "plt.xlabel('age')\n", 741 | "plt.xticks([])\n", 742 | "\n", 743 | "plt.subplot(3, 1, 3)\n", 744 | "plt.plot(khist)\n", 745 | "plt.title('Capital', y=.92)\n", 746 | "plt.xlabel('age')\n", 747 | "\n", 748 | "plt.show()" 749 | ] 750 | } 751 | ], 752 | "metadata": { 753 | "celltoolbar": "Raw Cell Format", 754 | "kernelspec": { 755 | "display_name": "Python 3", 756 | "language": "python", 757 | "name": "python3" 758 | }, 759 | "language_info": { 760 | "codemirror_mode": { 761 | "name": "ipython", 762 | "version": 3 763 | }, 764 | "file_extension": ".py", 765 | "mimetype": "text/x-python", 766 | "name": "python", 767 | "nbconvert_exporter": "python", 768 | "pygments_lexer": "ipython3", 769 | "version": "3.6.10" 770 | } 771 | }, 772 | "nbformat": 4, 773 | "nbformat_minor": 2 774 | } 775 | -------------------------------------------------------------------------------- /AKsolve.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sat Jan 28 13:31:47 2017 4 | Updated on Mon Oct 4 15:14 2017 5 | @author: Kerk Phillips 6 | """ 7 | import numpy as np 8 | 9 | def AKsolve(Xguess, funcname, fparams, ccrit, damp, maxiter, shrinkon, \ 10 | shrink, expandon, expand, disttype, display): 11 | ''' 12 | This function performs the Auerbach-Kotlikoff contraction mapping on a 13 | function. 14 | 15 | The inputs are: 16 | Xguess: An initial guess for the fixed point. Can be a scalar or 17 | matrix. 18 | funcname: Ahe name of the python function. It must take Xvalue as an 19 | argument with the same dimensions as Xguess, with fparams as 20 | parameters and return a new value for X, Xnew. 21 | fparams: A list of parameters used by funcname 22 | ccrit: The value for distance between Xvalue and Xnew that indicates 23 | convergence to the fixed point 24 | damp: The weight put on Xnew relative to Xvalue when moving to the 25 | next iteration; Xvalue = damp*Xnew + (1-damp)*Xvalue. 26 | maxiter: The maximum number of iterations allowed 27 | shrinkon: If true, the value of damp is scaled down when the distance 28 | between values of X in an iteration increases. 29 | shrink: The factor by which damp shrinks. 30 | expandon: If true, the value of damp is scaled up when the distance 31 | between values of X in an iteration does not increase. 32 | expand: The factor by which damp expands. 33 | disttype: Indicator variable for the method used to compute distance 34 | between Xvalue and Xnew 35 | 1: root mean squared differences (default) 36 | 2: mean absolute deviation 37 | 3: maximum absolute deviation 38 | display: If true, display iterations. 39 | 40 | The outputs are the fixed point, the last iteration's distanceand the 41 | number of iterations performed 42 | ''' 43 | # initialize Xvalue 44 | Xvalue = Xguess 45 | # set initial distance measures 46 | dist = 1.0 47 | distold = 2.0 48 | # set counter 49 | count = 0 50 | # begin AK iterations 51 | print('Performing AK contraction mapping') 52 | while dist > ccrit: 53 | if count > maxiter: 54 | break 55 | Xnew = funcname(Xvalue, fparams) 56 | diff = Xnew - Xvalue 57 | if disttype == 2: 58 | dist = np.mean(np.absolute(diff)) 59 | elif disttype == 3: 60 | dist = np.amax(np.absolute(diff)) 61 | else: 62 | dist = (np.mean(diff**2))**.5 63 | # check if dist is falling, if not lower value of damp 64 | if (dist > distold) and (shrinkon): 65 | # shrink damp and redo with same Xvalue, do not update count 66 | damp = damp * shrink 67 | Xvalue = damp*Xnew + (1-damp)*Xvalue 68 | distold = dist 69 | else: 70 | # update Xvalue and count 71 | count = count + 1 72 | if expandon: 73 | # expand damp if it is < 1.0 74 | if damp < 1.0: 75 | damp = damp * expand 76 | else: 77 | damp = 1.0 78 | # take convex combination for new guess 79 | Xvalue = damp*Xnew + (1-damp)*Xvalue 80 | # replace old dist value 81 | distold = dist 82 | # show progress 83 | if display: 84 | print ('count: ', count, 'distance: ', dist, 'damp: ', damp) 85 | 86 | return Xvalue, dist, count -------------------------------------------------------------------------------- /DSGEtestdata.csv: -------------------------------------------------------------------------------- 1 | quarter,RGDP,RCON,RINV,RGOV,NWAGE,DEFL,EMP 2 | 17168,1934.5,1199.4,222.7,478.7,118.8,12.566,43569 3 | 17258,1932.3,1219.3,205.6,482.8,121.2,12.745,43646 4 | 17349,1930.3,1223.3,199.6,485.9,123.9,12.957,43968 5 | 17441,1960.7,1223.6,238.2,482.5,128.2,13.276,44494 6 | 17533,1989.5,1229.8,262.6,488.6,131.6,13.379,44633 7 | 17624,2021.9,1244.1,278.9,505,133.3,13.497,44733 8 | 17715,2033.2,1245.9,281.7,515,138,13.747,45210 9 | 17807,2035.3,1255.8,268.3,533.8,139,13.789,45158 10 | 17899,2007.5,1257.9,228,548.6,136.7,13.717,44470 11 | 17989,2000.8,1277.1,197.7,572.5,134.9,13.579,43984 12 | 18080,2022.8,1280,214.1,577.6,133.9,13.509,43645 13 | 18172,2004.7,1298.8,203.6,565.8,133.1,13.518,43237 14 | 18264,2084.6,1320.4,251.9,557.1,136.8,13.49,43593 15 | 18354,2147.6,1342.1,278.9,566.6,143,13.538,44726 16 | 18445,2230.4,1411,302.9,557.3,150.9,13.832,46028 17 | 18537,2273.4,1368.4,341.3,597.2,158,14.09,46782 18 | 18629,2304.5,1401.5,306.5,660.9,165.3,14.596,47579 19 | 18719,2344.5,1361.9,313.6,748.8,171,14.692,47959 20 | 18810,2392.8,1377.7,290.5,830.9,173.5,14.701,48009 21 | 18902,2398.1,1385.8,267.3,874.8,176.6,14.869,48155 22 | 18994,2423.5,1388.9,274.3,900.5,181,14.863,48441 23 | 19085,2428.5,1416.1,253.6,930.7,182.1,14.882,48516 24 | 19176,2446.1,1423,267.2,940,186,15.048,48795 25 | 19268,2526.4,1473.3,286.5,955.6,193.5,15.091,49859 26 | 19360,2573.4,1490.8,292.6,985.5,197.1,15.096,50320 27 | 19450,2593.5,1499.8,294.3,1005.9,200,15.125,50482 28 | 19541,2578.9,1496.3,288.1,995.2,200.2,15.188,50463 29 | 19633,2539.8,1486.4,267.3,992.4,198.7,15.219,49950 30 | 19725,2528,1491.8,265.4,967.3,196.5,15.266,49336 31 | 19815,2530.7,1511.3,264.8,934.3,196,15.281,49013 32 | 19906,2559.4,1531.8,277.6,914.3,196.4,15.3,48847 33 | 19998,2609.3,1564,289.7,908.6,200.4,15.343,49151 34 | 20090,2683.8,1599.1,318.7,909.2,204.1,15.417,49701 35 | 20180,2727.5,1629.7,337.9,900.5,209.9,15.481,50516 36 | 20271,2764.1,1649.8,343.1,906.1,215.3,15.59,51119 37 | 20363,2780.8,1670.5,351.1,888.3,219.5,15.743,51609 38 | 20455,2770,1673.2,341.1,888.1,223.4,15.902,52146 39 | 20546,2792.9,1678.8,338.4,905.9,227.6,15.997,52488 40 | 20637,2790.6,1682.6,335.4,898.3,230,16.197,52395 41 | 20729,2836.2,1705.8,332.2,920.7,235.4,16.264,52844 42 | 20821,2854.5,1717.5,327.1,940.7,238.3,16.485,53047 43 | 20911,2848.2,1720.5,326.8,935.7,239.7,16.601,53151 44 | 21002,2875.9,1734.1,334.2,943.5,241.9,16.701,53060 45 | 21094,2846.4,1734.9,308.5,959.3,240.2,16.711,52570 46 | 21186,2772.7,1711.1,287.7,950.8,236.8,16.892,51651 47 | 21276,2790.9,1725.1,281.9,974.7,236.3,16.94,50951 48 | 21367,2855.5,1753.5,303.5,980.6,243.9,17.043,51258 49 | 21459,2922.3,1777.1,329.4,1000.7,248.5,17.123,51839 50 | 21551,2976.6,1809.4,347.4,989.4,254.1,17.169,52728 51 | 21641,3049,1837.3,374.4,1001.7,260.6,17.194,53516 52 | 21732,3043.1,1856.5,350.2,1010.3,261,17.258,53522 53 | 21824,3055.1,1858.6,361.6,1002.1,264,17.326,53723 54 | 21916,3123.2,1876.3,398,985.2,270.9,17.397,54415 55 | 22007,3111.3,1900.1,360.9,995.8,273.6,17.443,54544 56 | 22098,3119.1,1892.5,360,1020,274.1,17.506,54268 57 | 22190,3081.3,1894.9,320.1,1026.8,273.5,17.56,53950 58 | 22282,3102.3,1894.4,328.4,1042,273.9,17.598,53634 59 | 22372,3159.9,1922.6,351.4,1044.4,277.8,17.641,53796 60 | 22463,3212.6,1932,378.7,1066.4,282.4,17.687,54270 61 | 22555,3277.7,1970.7,385,1089.7,288.5,17.745,54712 62 | 22647,3336.8,1991.7,405.7,1110.7,293.4,17.837,55118 63 | 22737,3372.7,2016.1,402.5,1116,298.8,17.866,55624 64 | 22828,3404.8,2032.5,409.4,1141.7,301.3,17.903,55854 65 | 22920,3418,2061.3,397.4,1149.6,304.3,17.938,56042 66 | 23012,3456.1,2075.2,418.3,1134.1,308,18.017,56223 67 | 23102,3501.1,2095.1,425,1135.1,312.4,18.047,56618 68 | 23193,3569.5,2123.7,438,1185.4,316.9,18.069,56927 69 | 23285,3595,2141.4,443.4,1173.7,322.3,18.216,57300 70 | 23377,3672.7,2183.6,460,1177.3,328.3,18.274,57712 71 | 23468,3716.4,2222,458.3,1187.9,334.9,18.318,58077 72 | 23559,3766.9,2262.8,469,1189.4,341.5,18.392,58645 73 | 23651,3780.2,2269.2,473.5,1189,346.7,18.476,59144 74 | 23743,3873.5,2319.8,518.6,1187.7,352.8,18.569,59795 75 | 23833,3926.4,2345.5,520,1202,358.9,18.652,60480 76 | 23924,4006.2,2385.9,538.1,1241.7,366.2,18.726,61227 77 | 24016,4100.6,2452.9,541.6,1265.4,377.1,18.853,62012 78 | 24108,4201.9,2489.1,584.9,1289,385.7,18.975,62839 79 | 24198,4219.1,2495.4,576.2,1313.4,395.9,19.131,63752 80 | 24289,4249.2,2523.8,572,1349.1,406.1,19.317,64484 81 | 24381,4285.6,2534.2,575.3,1372.4,413.5,19.481,65024 82 | 24473,4324.9,2548.9,561.2,1429.8,418.8,19.562,65455 83 | 24563,4328.7,2583.7,540.9,1424.2,423.6,19.661,65612 84 | 24654,4366.1,2596.9,556.8,1440.2,432,19.849,66064 85 | 24746,4401.2,2612.7,568.8,1451.4,441.6,20.067,66609 86 | 24838,4490.6,2674.8,580.2,1477.2,454.2,20.29,67105 87 | 24929,4566.4,2715.6,602.4,1485,465.9,20.504,67704 88 | 25020,4599.3,2766.6,586,1489.7,478.3,20.706,68313 89 | 25112,4619.8,2779.1,592.3,1491,489.4,20.999,68984 90 | 25204,4691.6,2810.2,627.2,1494.7,499,21.217,69681 91 | 25294,4706.7,2828.2,623.5,1490,511.4,21.488,70345 92 | 25385,4736.1,2841.9,636.2,1493.5,526.4,21.79,70884 93 | 25477,4715.5,2864.6,605.5,1473.9,536.4,22.071,71149 94 | 25569,4707.1,2882.3,587.4,1466.9,545.1,22.382,71311 95 | 25659,4715.4,2895.6,588.7,1450.2,549,22.694,71167 96 | 25750,4757.2,2921.1,598.3,1456.5,555.7,22.88,70978 97 | 25842,4708.3,2913.1,566.5,1457.2,556.3,23.182,70573 98 | 25934,4834.3,2968.9,632.5,1436.1,570.5,23.536,70844 99 | 26024,4861.9,2996.1,650.5,1432.8,580.4,23.846,71179 100 | 26115,4900,3020,658.4,1432.4,588.8,24.088,71434 101 | 26207,4914.3,3070.2,640.6,1422.6,598.4,24.288,71865 102 | 26299,5002.4,3110.8,682.9,1429.3,618.5,24.664,72681 103 | 26390,5118.3,3170.2,721.6,1438,630.4,24.815,73463 104 | 26481,5165.4,3219.1,731.9,1409.3,642.3,25.048,74036 105 | 26573,5251.2,3294.6,736.5,1420.1,664,25.366,74970 106 | 26665,5380.5,3354.8,779.6,1431.6,683.4,25.661,75974 107 | 26755,5441.5,3353.4,812.9,1424.5,700.2,26.052,76663 108 | 26846,5411.9,3365.3,783.4,1406.4,716.2,26.549,77118 109 | 26938,5462.4,3355.5,811.3,1415.8,735.4,27.077,77851 110 | 27030,5417,3326.2,765,1442.4,748.2,27.592,78218 111 | 27120,5431.3,3337.9,761.9,1451.6,765.3,28.248,78510 112 | 27211,5378.7,3351.6,722.4,1453.5,783.2,29.067,78622 113 | 27303,5357.2,3302.5,726.8,1459.9,792.5,29.923,78182 114 | 27395,5292.4,3330.1,609.7,1476.1,792,30.601,76955 115 | 27485,5333.2,3385.7,591.6,1466.2,800.4,31.059,76535 116 | 27576,5421.4,3434.1,637.5,1489.5,821.3,31.612,77051 117 | 27668,5494.4,3470.5,655.2,1503.4,845.8,32.139,77744 118 | 27760,5618.5,3539.9,718.5,1506.5,871.3,32.473,78791 119 | 27851,5661,3572.4,746.9,1491.4,889.4,32.803,79326 120 | 27942,5689.8,3610.3,749.5,1483.9,908.5,33.226,79714 121 | 28034,5732.5,3657.5,755.1,1484.4,930,33.815,80197 122 | 28126,5799.2,3699.3,790.1,1497.3,950.1,34.359,81024 123 | 28216,5913,3719.7,846.8,1512,981,34.841,82102 124 | 28307,6017.6,3755.2,889.6,1515.4,1007.6,35.27,83147 125 | 28399,6018.2,3811.8,867.3,1512.1,1038.2,36.036,84125 126 | 28491,6039.2,3833.8,884.2,1513.9,1064.3,36.573,85001 127 | 28581,6274,3915.6,941.6,1554.1,1106.1,37.242,86541 128 | 28672,6335.3,3932,969.1,1566.4,1137.2,37.865,87435 129 | 28764,6420.3,3963.5,991.5,1580.6,1175.1,38.661,88339 130 | 28856,6433,3983.6,993.1,1566.9,1208.4,39.352,89115 131 | 28946,6440.8,3981.3,992.2,1583,1234.1,40.304,89773 132 | 29037,6487.1,4020.4,975.5,1585.1,1268.3,41.165,90279 133 | 29129,6503.9,4031.2,958.2,1595.4,1302.8,41.986,90577 134 | 29221,6524.9,4025,951.6,1620.2,1335,42.859,90893 135 | 29312,6392.6,3934.5,870.7,1625.9,1351.1,43.8,90456 136 | 29403,6382.9,3976.9,813.3,1601.9,1376.2,44.808,90048 137 | 29495,6501.2,4029.6,889.2,1601.8,1431.8,46.046,90727 138 | 29587,6635.7,4050.8,971.7,1622.8,1469.2,47.196,91117 139 | 29677,6587.3,4050.1,931.3,1627.9,1496.4,48.081,91355 140 | 29768,6662.9,4066.4,983.5,1621.6,1528.9,48.946,91549 141 | 29860,6585.1,4035.9,948.4,1639.9,1551.7,49.863,91148 142 | 29952,6475,4062.6,854.9,1638.2,1567.4,50.561,90520 143 | 30042,6510.2,4077.6,853.8,1648.9,1581.1,51.17,90041 144 | 30133,6486.8,4109.1,845.7,1659.3,1596.3,51.907,89356 145 | 30225,6493.1,4184.1,780.3,1685.8,1606,52.483,88819 146 | 30317,6578.2,4224.8,807.5,1701.9,1623.2,52.907,89000 147 | 30407,6728.3,4308.4,879.1,1719.1,1655.3,53.265,89677 148 | 30498,6860,4384,934.2,1747.3,1692,53.823,90606 149 | 30590,7001.5,4453.1,1025.1,1718,1740.3,54.219,91872 150 | 30682,7140.6,4490.9,1124.2,1738.1,1785.4,54.796,93085 151 | 30773,7266,4554.9,1160.7,1777.1,1828.4,55.257,94124 152 | 30864,7337.5,4589.9,1185.8,1791.8,1866.9,55.705,95057 153 | 30956,7396,4650.6,1170.4,1826,1899.7,56.079,95905 154 | 31048,7469.5,4729.7,1138.3,1848,1934,56.724,96571 155 | 31138,7537.9,4774.1,1157.7,1891,1963.5,57.075,97270 156 | 31229,7655.2,4865.8,1149.8,1935.4,1996.3,57.406,97845 157 | 31321,7712.6,4878.3,1192.2,1941.8,2037.3,57.738,98428 158 | 31413,7784.1,4919.6,1191.9,1958,2065.5,58.02,98837 159 | 31503,7819.8,4974.6,1171,1997.8,2083.7,58.252,99175 160 | 31594,7898.6,5064.7,1139.5,2043.4,2113.4,58.487,99665 161 | 31686,7939.5,5097.1,1143,2031.5,2153.9,58.813,100312 162 | 31778,7995,5097.9,1173.8,2044.3,2195.3,59.24,100921 163 | 31868,8084.7,5168.6,1174.4,2062.9,2231.6,59.637,101710 164 | 31959,8158,5228.5,1174.6,2067.7,2271.8,60.07,102437 165 | 32051,8292.7,5239.5,1254.6,2092.8,2331.8,60.567,103391 166 | 32143,8339.3,5332.7,1194.4,2078.6,2368.2,61.043,104152 167 | 32234,8449.5,5371.8,1222.9,2086.1,2423,61.633,105006 168 | 32325,8498.3,5417.7,1229.7,2087.5,2463.7,62.359,105742 169 | 32417,8610.9,5479.7,1248.4,2126.8,2507.7,62.859,106600 170 | 32509,8697.7,5505,1290.7,2117.2,2543.2,63.55,107404 171 | 32599,8766.1,5530.9,1278.3,2151.8,2564.6,64.207,107909 172 | 32690,8831.5,5585.9,1266.9,2169.8,2593.3,64.672,108182 173 | 32782,8850.2,5610.5,1257.7,2181.5,2636.2,65.122,108693 174 | 32874,8947.1,5658.7,1270,2215.8,2689,65.841,109421 175 | 32964,8981.7,5676.4,1270.4,2221.2,2738.1,66.52,109796 176 | 33055,8983.9,5699.3,1245.6,2219.9,2771,67.114,109656 177 | 33147,8907.4,5656.2,1176.3,2240.2,2775.9,67.622,109247 178 | 33239,8865.6,5636.7,1137.1,2251.2,2778.3,68.296,108784 179 | 33329,8934.4,5684,1137.2,2259.2,2803.9,68.764,108315 180 | 33420,8977.3,5711.6,1159.8,2250.8,2829.3,69.269,108315 181 | 33512,9016.4,5710.1,1201,2242.3,2857.4,69.643,108327 182 | 33604,9123,5817.3,1178.9,2259.7,2916.4,69.942,108353 183 | 33695,9223.5,5857.2,1245.7,2256.8,2955.8,70.388,108634 184 | 33786,9313.2,5920.6,1255.8,2268.4,2979,70.723,108896 185 | 33878,9406.5,5991.1,1294.2,2263.5,3022.8,71.201,109309 186 | 33970,9424.1,6013.8,1324.6,2237.8,3021.6,71.606,109950 187 | 34060,9480.1,6067.8,1332.1,2240.3,3068.8,72.041,110544 188 | 34151,9526.3,6134.8,1323.1,2245.1,3096.6,72.475,111239 189 | 34243,9653.5,6189.1,1392.5,2250,3143.6,72.853,112016 190 | 34335,9748.2,6260.1,1446.2,2222.1,3156.7,73.206,112871 191 | 34425,9881.4,6308.6,1517.1,2235.1,3228.7,73.571,113925 192 | 34516,9939.7,6357.5,1492.2,2272.7,3262,73.969,114925 193 | 34608,10052.5,6425.9,1553.5,2252.2,3314.9,74.376,115839 194 | 34700,10086.9,6442.9,1570.3,2256.8,3364.6,74.803,116698 195 | 34790,10122.1,6500.7,1537.7,2268.6,3399.3,75.132,117143 196 | 34881,10208.8,6560.3,1528.6,2262.4,3442.3,75.489,117640 197 | 34973,10281.2,6606.4,1566.7,2242.1,3482.2,75.861,118184 198 | 35065,10348.7,6667.7,1590.6,2246.8,3529.8,76.272,118680 199 | 35156,10529.4,6740.1,1667.7,2282.8,3594.7,76.562,119475 200 | 35247,10626.8,6780.7,1744.5,2285.2,3650.8,76.778,120217 201 | 35339,10739.1,6834,1743.9,2301.9,3707.2,77.168,120933 202 | 35431,10820.9,6906.1,1781.6,2301.3,3781.5,77.647,121688 203 | 35521,10984.2,6937.4,1880,2325.3,3839.9,77.857,122554 204 | 35612,11124,7056.1,1913.6,2329,3908.2,78.135,123274 205 | 35704,11210.3,7139.9,1940.7,2332.5,3995.5,78.395,124250 206 | 35796,11321.2,7213.6,2027.1,2319,4080.7,78.523,125011 207 | 35886,11431,7341,2013.4,2366,4150.6,78.687,125799 208 | 35977,11580.6,7437.5,2067.2,2387.6,4221.4,78.981,126511 209 | 36069,11770.7,7546.8,2125.5,2409.4,4291.9,79.228,127276 210 | 36161,11864.7,7618.7,2186.1,2418.1,4375.9,79.624,128036 211 | 36251,11962.5,7731.5,2188,2431.7,4418,79.891,128847 212 | 36342,12113.1,7819.3,2242.8,2460.3,4479.2,80.18,129595 213 | 36434,12323.3,7934.1,2308.6,2496.7,4587.7,80.547,130485 214 | 36526,12359.1,8054.9,2287.8,2476.2,4759.3,81.163,131253 215 | 36617,12592.5,8132.2,2424.5,2506.4,4786.7,81.623,132031 216 | 36708,12607.7,8211.3,2394.1,2501.2,4879.2,82.152,132290 217 | 36800,12679.3,8284.4,2395.6,2509,4904.6,82.593,132561 218 | 36892,12643.3,8319.4,2285.3,2546.3,4989.8,83.112,132745 219 | 36982,12710.3,8340.8,2277.1,2596.4,4970.9,83.699,132402 220 | 37073,12670.1,8371.2,2236.6,2594.6,4943.9,83.973,132005 221 | 37165,12705.3,8499.1,2126.9,2632.4,4942,84.227,131216 222 | 37257,12822.3,8524.6,2202.8,2671.3,4960.2,84.497,130771 223 | 37347,12893,8568.1,2224.9,2696.9,5008.7,84.812,130648 224 | 37438,12955.8,8628,2224.6,2717.8,5018.4,85.19,130570 225 | 37530,12964,8674.4,2220.7,2737.1,5029.6,85.651,130606 226 | 37622,13031.2,8712.5,2239.5,2728.3,5039.2,86.179,130427 227 | 37712,13152.1,8809.5,2251.3,2771.2,5110,86.455,130192 228 | 37803,13372.4,8939.4,2330.9,2771.2,5175.1,86.934,130226 229 | 37895,13528.7,9008.8,2413.1,2786.3,5260,87.346,130531 230 | 37987,13606.5,9096.4,2414.5,2793.9,5290.1,88.108,130921 231 | 38078,13706.2,9155.5,2500.9,2809.9,5393,88.875,131638 232 | 38169,13830.8,9243,2539.4,2820.7,5501.2,89.422,131970 233 | 38261,13950.4,9337.8,2590.6,2808.2,5540.3,90.049,132552 234 | 38353,14099.1,9409.2,2664.4,2814.1,5590.7,90.883,132999 235 | 38443,14172.7,9511.5,2630.5,2818.9,5650.8,91.543,133732 236 | 38534,14291.8,9585.2,2657.9,2841,5748.5,92.399,134483 237 | 38626,14373.4,9621.3,2737.6,2830.7,5822.3,93.1,134956 238 | 38718,14546.1,9729.2,2773.8,2853.5,5987.3,93.832,135756 239 | 38808,14589.6,9781,2755.7,2864.1,6026.7,94.587,136275 240 | 38899,14602.6,9838.1,2727.6,2870.4,6072.1,95.247,136717 241 | 38991,14716.9,9938.4,2663,2889.1,6189,95.58,137083 242 | 39083,14726,9990.7,2638.5,2882.7,6358.1,96.654,137629 243 | 39173,14838.7,10024.6,2674.7,2907,6381.8,97.194,137985 244 | 39264,14938.5,10069.2,2658.1,2928,6404.2,97.531,138065 245 | 39356,14991.8,10081.8,2605.2,2939.8,6478.6,97.956,138310 246 | 39448,14889.5,10061,2517.5,2952,6551.5,98.516,138349 247 | 39539,14963.4,10077.9,2472.6,2975,6543.1,98.995,137880 248 | 39630,14891.6,10005.1,2403.8,3016.2,6555.2,99.673,137171 249 | 39722,14577,9884.7,2190,3035.9,6524.5,99.815,135564 250 | 39814,14375,9850.8,1937.7,3040.5,6240.2,100.062,133310 251 | 39904,14355.6,9806.4,1820.5,3096,6265.2,99.895,131450 252 | 39995,14402.5,9865.9,1804.7,3113,6247.2,99.873,130477 253 | 40087,14541.9,9864.8,1949.6,3106.8,6287.7,100.169,129962 254 | 40179,14604.8,9917.7,2012.9,3084.3,6247,100.522,129810 255 | 40269,14745.9,9998.4,2116.9,3106.2,6373.6,100.968,130443 256 | 40360,14845.5,10063.1,2185.7,3103.5,6434.8,101.429,130418 257 | 40452,14939,10166.1,2166.1,3071.5,6486.8,101.949,130740 258 | 40544,14881.3,10217.1,2125.9,3012.2,6591.3,102.399,131082 259 | 40634,14989.6,10237.7,2208,3009,6623.5,103.145,131768 260 | 40725,15021.1,10282.2,2214,2990,6697.8,103.768,132172 261 | 40817,15190.3,10316.8,2373.7,2978.3,6652.4,103.917,132740 262 | 40909,15291,10379,2429.6,2963.7,6849.5,104.466,133516 263 | 41000,15362.4,10396.6,2489.1,2949.4,6887.6,104.943,133942 264 | 41091,15380.8,10424.1,2482,2940.9,6915.8,105.508,134368 265 | 41183,15384.3,10453.2,2462.2,2912.3,7102.8,105.935,134864 266 | 41275,15491.9,10502.3,2543,2880.6,7008.7,106.349,135518 267 | 41365,15521.6,10523.9,2574.3,2866.2,7111.5,106.57,136098 268 | 41456,15641.3,10573.1,2656.8,2852,7157.8,107.084,136649 269 | 41548,15793.9,10662.2,2692,2831.5,7226.3,107.636,137260 270 | 41640,15747,10712.8,2646.4,2824.3,7360,108.117,137777 271 | 41730,15900.8,10813.3,2717.5,2825.1,7416.1,108.709,138568 272 | 41821,16094.5,10912.9,2776.3,2842.6,7527,109.165,139316 273 | 41913,16186.7,11036.4,2794.1,2840,7643.2,109.3,140097 274 | 42005,16269,11102.4,2860.8,2858,7702.5,109.31,140828 275 | 42095,16374.2,11181.3,2867.7,2880.7,7819.6,109.919,141481 276 | 42186,16454.9,11255.9,2882.2,2894.4,7905.2,110.253,142151 277 | 42278,16490.7,11319.3,2865.4,2901.7,8036.1,110.504,142872 278 | 42370,16525,11365.2,2841.5,2913.2,8023.3,110.63,143531 279 | 42461,16583.1,11484.9,2783.8,2900.9,8116.7,111.258,143983 280 | -------------------------------------------------------------------------------- /Euler_Errors.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Two Examples of Calculating Euler Errors in a DSGE Model\n", 8 | "\n", 9 | "### by [Kerk L. Phillips](https://sites.google.com/site/kerkphillips/home), July 2018\n", 10 | "\n", 11 | "The code in this Jupyter notebook was written using Python 3.6." 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "This notebook explains how to caclualte the Euler errors for a simple DSGE model. The model is solved and simulated two different ways: 1) using linearization about the steady state, amnd 2) using value-function iteration on a full cartesian grid. This notebook uses a variety of downloadable code that can be found at the following Github site. [https://github.com/kerkphil/DSGE-Utilities](https://github.com/kerkphil/DSGE-Utilities).\n", 19 | "\n", 20 | "All the necessary files and this notebook can also be found in the public GitHub repository [https://github.com/kerkphil/Jupyter_Notebooks](https://github.com/kerkphil/Jupyter_Notebooks)." 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "## The Model" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": {}, 33 | "source": [ 34 | "Consider a model where an infinitely-lived representative agent solves the following dynamic program:\n", 35 | "$$ V(k_t,z_t) = \\max_{k_{t+1}} \\frac{c_t^{1-\\gamma} - 1}{1-\\gamma} + \\beta E \\left\\{ V(k_{t+1},z_{t+1}) \\right\\} $$\n", 36 | "Subject to the following budget constraint:\n", 37 | "$$ c_t = w_t + (1+r_t-\\delta)k_t - k_{t+1} $$\n", 38 | "The Euler equation from this optimization problem is:\n", 39 | "$$ c_t^{-\\gamma} = \\beta E \\left\\{ c_{t+1}^{-\\gamma} (1+r_{t+1}-\\delta) \\right\\} $$\n", 40 | "\n", 41 | "The representative firm solves the following static problem each period:\n", 42 | "$$ \\max_{K_t,L_t} \\Pi = K_t^\\alpha (e^{z_t} L_t)^{1-\\alpha} - r_t K_t - w_t L_t $$\n", 43 | "The solution to this problems yields the following:\n", 44 | "$$ Y_t = K_t^\\alpha (e^{z_t} L_t)^{1-\\alpha} $$\n", 45 | "$$ r_t = \\alpha \\frac{Y_t}{K_t} $$\n", 46 | "$$ w_t = (1-\\alpha) \\frac{Y_t}{L_t} $$\n", 47 | "\n", 48 | "The market clearing conditions are:\n", 49 | "$$ k_t = K_t $$\n", 50 | "$$ 1 = L_t $$\n", 51 | "\n", 52 | "The law of motion for the technology deviations is:\n", 53 | "$$ z_t = \\rho z_{t-1} + \\epsilon_t;\\; \\epsilon_t \\sim iid(0,\\sigma^2) $$\n", 54 | "\n", 55 | "The state variables in this model are $k_t$ and $z_t$." 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "### The Definitions Function" 63 | ] 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "metadata": {}, 68 | "source": [ 69 | "We first define a definitions function that gives the non-state variables now as functions of the state variables now and last period. Note that for notational purposes we have listed the current capital stock as $k_t$, even though this was chosen in the previous period. $k_{t+1}$ is chosen in the current period." 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": 1, 75 | "metadata": {}, 76 | "outputs": [], 77 | "source": [ 78 | "def example_def(kp, k, z, param):\n", 79 | " # calculate definitions for GDP, wages, rental rates, consumption\n", 80 | " np.exp((1-alpha)*z)\n", 81 | " y = k**alpha*np.exp((1-alpha)*z)\n", 82 | " w = (1-alpha)*y\n", 83 | " r = alpha*y/k\n", 84 | " c = w + (1+r-delta)*k - kp\n", 85 | " i = y - c\n", 86 | " return y, c, i, r, w" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "### The Characterizing Equations" 94 | ] 95 | }, 96 | { 97 | "cell_type": "markdown", 98 | "metadata": {}, 99 | "source": [ 100 | "Next, we define an Euler equation written in the form:\n", 101 | "$$ E \\{ \\Gamma(k_{t+2}, k_{t+1}, k_t, z_{t+1}, z_t) \\} = 0 $$" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": 2, 107 | "metadata": {}, 108 | "outputs": [], 109 | "source": [ 110 | "def example_dyn(invec, param):\n", 111 | " # unpack invec\n", 112 | " kplus = invec[0]\n", 113 | " know = invec[1]\n", 114 | " kminus = invec[2]\n", 115 | " zplus = invec[3]\n", 116 | " znow = invec[4]\n", 117 | "\n", 118 | " # get definitions each period\n", 119 | " ynow, cnow, inow, rnow, wnow = example_def(know, kminus, znow, param)\n", 120 | " yplus, cplus, iplus, rplus, wplus = example_def(kplus, know, zplus, param)\n", 121 | "\n", 122 | " # calculate Gamma function\n", 123 | " Gamma = cnow**(-theta) / (beta*(cplus**(-theta)*(1+rplus-delta))) - 1.0\n", 124 | " \n", 125 | " return Gamma" 126 | ] 127 | }, 128 | { 129 | "cell_type": "markdown", 130 | "metadata": {}, 131 | "source": [ 132 | "In order to simulate and to calculate the Euler error we need a function for the law of motion for $z_t$" 133 | ] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "execution_count": 3, 138 | "metadata": {}, 139 | "outputs": [], 140 | "source": [ 141 | "def example_lfunc(z, eps, lpars):\n", 142 | " zp = rho*z + sigma*eps\n", 143 | " return zp" 144 | ] 145 | }, 146 | { 147 | "cell_type": "markdown", 148 | "metadata": {}, 149 | "source": [ 150 | "Lastly, we define a function that takes the set $\\{ k_{t+2}, k_{t+1}, k_t, z_{t+1}, z_t \\} $ as individual items, rather than a vector, and returns the value of $\\Gamma$ from above. We will use this in calculating our Euler errors." 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": 4, 156 | "metadata": {}, 157 | "outputs": [], 158 | "source": [ 159 | "def example_efunc(kpp, kp, k, zp, z, epars):\n", 160 | " invec = np.array([kpp, kp, k[0], zp[0], z[0]])\n", 161 | " outvec = example_dyn(invec, epars)\n", 162 | " return outvec" 163 | ] 164 | }, 165 | { 166 | "cell_type": "markdown", 167 | "metadata": {}, 168 | "source": [ 169 | "## Euler Error Calculator" 170 | ] 171 | }, 172 | { 173 | "cell_type": "markdown", 174 | "metadata": {}, 175 | "source": [ 176 | "The Euler error is the devaition of the $\\Gamma$ function from zero in a given period for the simulation. Note that this function requires taking an expected value.\n", 177 | "\n", 178 | "$$ E \\{ \\Gamma(k_{t+2}, k_{t+1}, k_t, z_{t+1}, z_t) \\} = 0 $$\n", 179 | "\n", 180 | "In order to calculate the Euler error a policy function for $k_{t+1}$. The functional form will depend on the method we use to approximate it. We write this function generally as:\n", 181 | "$$ k_{t+1} = \\Phi(k_t, z_t) $$\n", 182 | "\n", 183 | "To calculate the Euler error we must use some form of quadrature to integrate over the possible values of $\\epsilon_{t+1}$. We denote the node values and their associated probabilites for this quadrature as $ \\{\\varepsilon_j, \\phi_j\\}_{j=1}^J $.\n", 184 | "\n", 185 | "Since $k_t$, $z_t$ and $k_{t+1} are known today we need only substitute in the law of motion and the policy function to evaluate the Euler error\n", 186 | "\n", 187 | "$$ e_t = \\sum_{j=1}^J \\phi_j \\Gamma(\\Phi(k_{t+1}, \\rho z_t + \\varepsilon_j), k_{t+1}, k_t, \\rho z_t + \\varepsilon_j, z_t) \\} $$\n", 188 | "\n", 189 | "We now load Python code that calculates Euler errors. This code is available at [https://github.com/kerkphil/DSGE-Utilities](https://github.com/kerkphil/DSGE-Utilities). However, we recreate it here to illustrate how the Euler errors are calculated along the lines discussed above." 190 | ] 191 | }, 192 | { 193 | "cell_type": "code", 194 | "execution_count": 5, 195 | "metadata": {}, 196 | "outputs": [], 197 | "source": [ 198 | "import numpy as np\n", 199 | "from scipy.stats import norm\n", 200 | "\n", 201 | "def EEcalc(Xdata, Zdata, efunc, epars, tfunc, tpars, lfunc, lpars):\n", 202 | " '''\n", 203 | " This function calculates Euler Errors for a DSGE model.\n", 204 | " It takes the following as inputs:\n", 205 | " 1) Xdata: an nobs-by-nx matrix of endogenous state variable data with with \n", 206 | " nobs indexing the observations in rows and nx indexing the variables in \n", 207 | " columns.\n", 208 | " 2) Zdata: an nobs-by-nz matrix of exogenous state variable data with with \n", 209 | " nobs indexing the observations in rows and nz indexing the variables in \n", 210 | " columns.\n", 211 | " 3) efunc: the name of a function which takes a single observation of data \n", 212 | " and returns the Euler error for a given realization of future exogenous \n", 213 | " variables. This function must take 3 nx-element vectors of endogenous\n", 214 | " state variables and and 2 nz-element vector of exogenous state \n", 215 | " variables as inputs and output an neq-element vector of Euler equation \n", 216 | " errors. The order of input is X(t+2), X(t+1), X(t), Z(t+1), Z(t),\n", 217 | " epars\n", 218 | " 4) epars: a list of parameters passed to efunc.\n", 219 | " 5) tfunc: the name of a transition function which takes a single \n", 220 | " observation of the state variables and returns next period's value of \n", 221 | " the endogenous state variables. This function must take an nx-element \n", 222 | " vector of endogenous state variables and and nz-element vector of \n", 223 | " exogenous state variables as inputs and output an nz-element vector of \n", 224 | " next-period endogenous state variables. The order of inputs is X(t), \n", 225 | " Z(t), tpars\n", 226 | " 6) tpars: a list of parameters passed to tfunc.\n", 227 | " 7) lfunc: the name of a law-of-motion function which takes a single \n", 228 | " observation of the exogenous state variables and returns next period's \n", 229 | " value of the exogenous state variables. This function must take an \n", 230 | " nz-element of exogenous state and an scalar iid shock as inputs \n", 231 | " and output an nz-element vector of next-period endogenous state \n", 232 | " variables. The order of inputs is Z(t), Eps(t+1), epars\n", 233 | " 8) lpars: a list of parameters passed to lfunc.\n", 234 | " \n", 235 | " The function returns the following outputs:\n", 236 | " 1) Eerr: an nobs-by-neq matrix of Euler errors with nobs indexing the \n", 237 | " observations in rows and neq indexing the elements from the function \n", 238 | " efunc in columns.\n", 239 | " \n", 240 | " Notes:\n", 241 | " Xdata and Zdata must have the same number of rows.\n", 242 | " Neither Xdata nor Zdata may have missing, nan, or complex values. \n", 243 | " Innovations to the law of motion are drawn from a standard normal \n", 244 | " distribution.\n", 245 | " Currently this function only works with one innovation shock, i.e. ne=1\n", 246 | "\n", 247 | " To Do:\n", 248 | " 1) Allow for more than one shock process. May require the use of sparse \n", 249 | " grids for quadrature.\n", 250 | " 2) Use a more efficient quadrature method. Gaussian?\n", 251 | " '''\n", 252 | " \n", 253 | " # set parameter values\n", 254 | " npts = 10 # number of point for rectangular quadrature\n", 255 | " \n", 256 | " # check sizes of data matrices\n", 257 | " (Xnobs, nx) = Xdata.shape\n", 258 | " (Znobs, nz) = Zdata.shape\n", 259 | " if Xnobs == Znobs:\n", 260 | " nobs = Xnobs\n", 261 | " else:\n", 262 | " print ('Data matrices have different numbers of observations')\n", 263 | " nobs = min(Xnobs, Znobs)\n", 264 | " Xdata = Xdata[0:nobs]\n", 265 | " Zdata = Zdata[0:nobs]\n", 266 | " \n", 267 | " # generate discret support for epsilon to be used in Euler error\n", 268 | " # Eps are the central values\n", 269 | " # Phi are the associated probabilities\n", 270 | " Eps = np.zeros(npts);\n", 271 | " Cum = np.linspace(0.0, 1.0, num=npts+1)+.5/npts\n", 272 | " Cum = Cum[0:npts]\n", 273 | " Phi = np.ones(npts)/npts\n", 274 | " Eps = norm.ppf(Cum)\n", 275 | "\n", 276 | " neq = nx\n", 277 | " \n", 278 | " # initialize matrix of Euler errors\n", 279 | " Eerr = np.zeros((nobs,neq))\n", 280 | " # begin loop over time periods\n", 281 | " for t in range(0, nobs):\n", 282 | " # begin loop over possible va,lues of shock next period\n", 283 | " for i in range(0, npts):\n", 284 | " # find value of next period Z\n", 285 | " Zp = lfunc(Zdata[t,:],Eps[i],lpars)\n", 286 | " # find the value of X next period\n", 287 | " Xp = tfunc(Xdata[t,:],Zdata[t,:],tpars)\n", 288 | " # find the value of X in two periods\n", 289 | " Xpp = tfunc(Xp,Zp,tpars)\n", 290 | " # find the Euler errors\n", 291 | " Eerr[t,:] = Eerr[t,:] + Phi[i]*efunc(Xpp,Xp,Xdata[t,:], \\\n", 292 | " Zp,Zdata[t,:],epars)\n", 293 | " return Eerr" 294 | ] 295 | }, 296 | { 297 | "cell_type": "markdown", 298 | "metadata": {}, 299 | "source": [ 300 | "## Solving and Simulating Using Linearization" 301 | ] 302 | }, 303 | { 304 | "cell_type": "markdown", 305 | "metadata": {}, 306 | "source": [ 307 | "To linearize we use the LinApp package available at [https://github.com/kerkphil/DSGE-Utilities](https://github.com/kerkphil/DSGE-Utilities).\n", 308 | "\n", 309 | "The LinApp package includes the following functions:\n", 310 | "\n", 311 | "LinApp_FindSS - Takes a function, funcname.py, and a steady state value for the exogenous state variables as inputs. Finds the steady state for the model's endogenous state and jump variables.\n", 312 | "\n", 313 | "LinApp_Deriv - Takes a function, funcname.py, as an input. Generates the derivative matrices needed for the Uhlig toolkit.\n", 314 | "\n", 315 | "LinApp_Solve - Takes the derivative matrices as inputs. Uses the code from the Uhlig toolkit to generate the coefficients for the linearized policy function(s).\n", 316 | "\n", 317 | "LinApp_Sim - Takes the policy function coefficients and current state as inputs. Generates the value(s) of the endogenous state variables for the next period.\n", 318 | "\n", 319 | "LinApp_SSL - Takes a history of exogenous state variables and the policy function coefficients as inputs. Generates a history of state and jump variables using linearization about the steady state." 320 | ] 321 | }, 322 | { 323 | "cell_type": "markdown", 324 | "metadata": {}, 325 | "source": [ 326 | "We first define our policy or transition function for the linearized case. This is:\n", 327 | "\n", 328 | "$$ k_{t+1} = \\bar k + P (k_t - \\bar k) + Q z_t $$\n", 329 | "\n", 330 | "The LinApp package will find the values of $\\bar k$, $P$ and $Q$." 331 | ] 332 | }, 333 | { 334 | "cell_type": "code", 335 | "execution_count": 9, 336 | "metadata": {}, 337 | "outputs": [], 338 | "source": [ 339 | " def example_tfunc(k, z, tpars):\n", 340 | " kp = PP*(k-kbar) + QQ*z + kbar\n", 341 | " return kp" 342 | ] 343 | }, 344 | { 345 | "cell_type": "markdown", 346 | "metadata": {}, 347 | "source": [ 348 | "We now proceed with our main program" 349 | ] 350 | }, 351 | { 352 | "cell_type": "code", 353 | "execution_count": 10, 354 | "metadata": {}, 355 | "outputs": [ 356 | { 357 | "name": "stdout", 358 | "output_type": "stream", 359 | "text": [ 360 | "kbar is 2.259808539186245\n", 361 | "check should be close to zero and is 2.220446049250313e-16\n", 362 | "P is [[0.90121425]]\n", 363 | "Q is [[0.40395128]]\n" 364 | ] 365 | } 366 | ], 367 | "source": [ 368 | "from LinApp import LinApp_FindSS, LinApp_Deriv, LinApp_Solve\n", 369 | "\n", 370 | "# set parameter values\n", 371 | "# model parameters\n", 372 | "delta = .08\n", 373 | "alpha = .33\n", 374 | "theta = 2.5\n", 375 | "beta = .9\n", 376 | "rho = .9\n", 377 | "sigma = .0075\n", 378 | "params = [delta, alpha, theta, rho, sigma, beta]\n", 379 | "\n", 380 | "# other parameters\n", 381 | "nobs = 300 # number of periods in simulatipon\n", 382 | "kstart = 1 # starting value for simulation (proportional to kbar)\n", 383 | "nx = 1 # number of endogenous state variables\n", 384 | "ny = 0 # number of jump variables\n", 385 | "nz = 1 # number of exogenous state variables\n", 386 | "takelogs = False # if True log-linearize, otherwise simple linearization\n", 387 | "useSylv = False # if ture use a built-in Sylvester equation solver\n", 388 | "\n", 389 | "# find the steady state\n", 390 | "guessk= np.array([1.])\n", 391 | "zbar = np.array([0.])\n", 392 | "kbar = LinApp_FindSS(example_dyn, params, guessk, zbar, nx, ny)\n", 393 | "# convert from numpy array to real\n", 394 | "kbar = kbar[0]\n", 395 | "# check that the solution works\n", 396 | "invec = np.array([kbar, kbar, kbar, 0., 0.])\n", 397 | "check = example_dyn(invec, params)\n", 398 | "print('kbar is ', kbar)\n", 399 | "print('check should be close to zero and is ', check)\n", 400 | "\n", 401 | "# find derivatives\n", 402 | "AA, BB, CC, DD, FF, GG, HH, JJ, KK, LL, MM = \\\n", 403 | " LinApp_Deriv(example_dyn, params, invec, nx, ny, nz, takelogs)\n", 404 | "\n", 405 | "# find policy function coefficients\n", 406 | "PP, QQ, RR, SS = \\\n", 407 | " LinApp_Solve(AA, BB, CC, DD, FF, GG, HH, JJ, KK, LL, MM, \\\n", 408 | " rho, zbar, useSylv)\n", 409 | "\n", 410 | "print('P is ', PP)\n", 411 | "print('Q is ', QQ)" 412 | ] 413 | }, 414 | { 415 | "cell_type": "markdown", 416 | "metadata": {}, 417 | "source": [ 418 | "We now simulate our model" 419 | ] 420 | }, 421 | { 422 | "cell_type": "code", 423 | "execution_count": 11, 424 | "metadata": {}, 425 | "outputs": [], 426 | "source": [ 427 | "# perform simulation\n", 428 | "tpars = (PP, QQ, kbar)\n", 429 | "lpars = (rho)\n", 430 | "eps = np.random.randn(nobs)*sigma\n", 431 | "z = np.zeros((nobs+1))\n", 432 | "k = np.zeros((nobs+1))\n", 433 | "y = np.zeros(nobs)\n", 434 | "r = np.zeros(nobs)\n", 435 | "w = np.zeros(nobs)\n", 436 | "i = np.zeros(nobs)\n", 437 | "c = np.zeros(nobs)\n", 438 | "k[0] = kbar*kstart\n", 439 | "z[0] = eps[0]\n", 440 | "for t in range(0, nobs):\n", 441 | " z[t+1] = example_lfunc(z[t], eps[t], lpars)\n", 442 | " k[t+1] = example_tfunc(k[t], z[t], tpars)\n", 443 | " y[t], c[t], i[t], r[t], w[t] = example_def(k[t+1], k[t], z[t], params)\n", 444 | "k = k[0:nobs]\n", 445 | "z = z[0:nobs]" 446 | ] 447 | }, 448 | { 449 | "cell_type": "markdown", 450 | "metadata": {}, 451 | "source": [ 452 | "Finally, we calculate our Euler errors using the `EEcalc` function from above." 453 | ] 454 | }, 455 | { 456 | "cell_type": "code", 457 | "execution_count": 12, 458 | "metadata": {}, 459 | "outputs": [ 460 | { 461 | "name": "stdout", 462 | "output_type": "stream", 463 | "text": [ 464 | "Euler Error Summary Statistics\n", 465 | "Maximum Absolute Euler Error: 4.1307840607639895e-05\n", 466 | "Mean Absolute Euler Error: 4.129482169021037e-05\n", 467 | "Root Mean Squared Euler Error: 4.129482309669719e-05\n" 468 | ] 469 | } 470 | ], 471 | "source": [ 472 | "# find Euler Errors\n", 473 | "Xdata = k.reshape(len(k), 1)\n", 474 | "Zdata = z.reshape(len(z), 1)\n", 475 | "efunc = example_efunc\n", 476 | "epars = params\n", 477 | "tfunc = example_tfunc\n", 478 | "lfunc = example_lfunc\n", 479 | "EErrs = EEcalc(Xdata, Zdata, efunc, epars, tfunc, tpars, lfunc, lpars)\n", 480 | "\n", 481 | "MaxAbsEE = np.max(np.abs(EErrs))\n", 482 | "MeanAbsEE = np.mean(np.abs(EErrs))\n", 483 | "RootMeanSqEE = (np.mean(EErrs**2))**.5\n", 484 | "\n", 485 | "print('Euler Error Summary Statistics')\n", 486 | "print('Maximum Absolute Euler Error:', MaxAbsEE)\n", 487 | "print('Mean Absolute Euler Error:', MeanAbsEE)\n", 488 | "print('Root Mean Squared Euler Error:', RootMeanSqEE)" 489 | ] 490 | }, 491 | { 492 | "cell_type": "markdown", 493 | "metadata": {}, 494 | "source": [ 495 | "## Solving and Simulating Using Value-Function Iteration" 496 | ] 497 | }, 498 | { 499 | "cell_type": "markdown", 500 | "metadata": {}, 501 | "source": [ 502 | "The policy or transtion function in this case could be to take values straight from the discrete verision of the policy function calculated over the grid. Or we could use a continuous polynomial function fitted to that. This is shown below with the option `gridsim` indicating which is used." 503 | ] 504 | }, 505 | { 506 | "cell_type": "code", 507 | "execution_count": 10, 508 | "metadata": {}, 509 | "outputs": [], 510 | "source": [ 511 | "def example_tfunc2(k, z, tpars):\n", 512 | " k = np.reshape(k,(1))\n", 513 | " z = np.reshape(z,(1))\n", 514 | " if gridsim:\n", 515 | " # perform simulation with grid\n", 516 | " kidx = np.argmin(np.abs(kvec-k)) # index of closest value for k\n", 517 | " zidx = np.argmin(np.abs(zvec-z)) # index of closest value for z\n", 518 | " kp = trans[zidx,kidx];\n", 519 | " else:\n", 520 | " # perform simulation with polynomial fit\n", 521 | " temp = np.stack(([1.0], k, k**2, k**3, z, z**2, z**3, k*z, k**2*z, \\\n", 522 | " k*z**2))\n", 523 | " kp = np.dot(coeffs,temp)\n", 524 | " return kp" 525 | ] 526 | }, 527 | { 528 | "cell_type": "markdown", 529 | "metadata": {}, 530 | "source": [ 531 | "We use many of the same model parameters as before, but must define new ones specific to value-function iteration" 532 | ] 533 | }, 534 | { 535 | "cell_type": "code", 536 | "execution_count": 11, 537 | "metadata": {}, 538 | "outputs": [], 539 | "source": [ 540 | "low = .2 # low end of k grid (proportional to kbar)\n", 541 | "high = 5 # high end of k grid (proportional to kbar)\n", 542 | "spread = 3 # spread of the z grid (proportional to sigma)\n", 543 | "nptsk = 21 # number of points in the k grid\n", 544 | "nptsz = 21 # number of points in the z grid\n", 545 | "converge = .0001; # convergence criterion for value-function iteration\n", 546 | "gridsim = 0 # set to 1 to use grid, 0 to use polynomial fit" 547 | ] 548 | }, 549 | { 550 | "cell_type": "markdown", 551 | "metadata": {}, 552 | "source": [ 553 | "We now find the policy function" 554 | ] 555 | }, 556 | { 557 | "cell_type": "code", 558 | "execution_count": 12, 559 | "metadata": {}, 560 | "outputs": [ 561 | { 562 | "name": "stderr", 563 | "output_type": "stream", 564 | "text": [ 565 | "C:\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:44: RuntimeWarning: invalid value encountered in double_scalars\n" 566 | ] 567 | }, 568 | { 569 | "name": "stdout", 570 | "output_type": "stream", 571 | "text": [ 572 | "count = 1 distance = 1.0\n", 573 | "count = 2 distance = 0.5452517012577935\n", 574 | "count = 3 distance = 0.3558578751497489\n", 575 | "count = 4 distance = 0.6402419193387543\n", 576 | "count = 5 distance = 0.18632670588729233\n", 577 | "count = 6 distance = 0.457206920739312\n", 578 | "count = 7 distance = 0.27937124710057004\n", 579 | "count = 8 distance = 0.11249655568784568\n", 580 | "count = 9 distance = 0.06774281340580439\n", 581 | "count = 10 distance = 0.05504814003122724\n", 582 | "count = 11 distance = 0.054319684882198786\n", 583 | "count = 12 distance = 0.1882708196999667\n", 584 | "count = 13 distance = 0.06565295655067123\n", 585 | "count = 14 distance = 0.06296436620907432\n", 586 | "count = 15 distance = 0.04568130780380501\n", 587 | "count = 16 distance = 0.5817832636324972\n", 588 | "count = 17 distance = 0.02512202815731057\n", 589 | "count = 18 distance = 0.021323751656452176\n", 590 | "count = 19 distance = 0.020008745300104862\n", 591 | "count = 20 distance = 0.016689417863437788\n", 592 | "count = 21 distance = 0.01384304130664234\n", 593 | "count = 22 distance = 0.04043552605459304\n", 594 | "count = 23 distance = 0.01179425830371814\n", 595 | "count = 24 distance = 0.010269306761934221\n", 596 | "count = 25 distance = 0.010690571033560836\n", 597 | "count = 26 distance = 0.025526080251059652\n", 598 | "count = 27 distance = 0.02281341004859364\n", 599 | "count = 28 distance = 0.011624130044963033\n", 600 | "count = 29 distance = 0.051698897214070165\n", 601 | "count = 30 distance = 0.00836513795432216\n", 602 | "count = 31 distance = 0.00817206192486026\n", 603 | "count = 32 distance = 0.020646933896586058\n", 604 | "count = 33 distance = 0.0059615592616783725\n", 605 | "count = 34 distance = 0.004746123775527513\n", 606 | "count = 35 distance = 0.004398992470708536\n", 607 | "count = 36 distance = 0.004855450416478893\n", 608 | "count = 37 distance = 0.014909188612209927\n", 609 | "count = 38 distance = 0.004948484044399965\n", 610 | "count = 39 distance = 0.003091286890129275\n", 611 | "count = 40 distance = 0.002438408202784564\n", 612 | "count = 41 distance = 0.0020222196325331843\n", 613 | "count = 42 distance = 0.0016079210612918095\n", 614 | "count = 43 distance = 0.001396214139516988\n", 615 | "count = 44 distance = 0.0012242864108945172\n", 616 | "count = 45 distance = 0.0010548614822109195\n", 617 | "count = 46 distance = 0.0008695726835235689\n", 618 | "count = 47 distance = 0.0007793475886318042\n", 619 | "count = 48 distance = 0.0007001949984184134\n", 620 | "count = 49 distance = 0.0006295645414008359\n", 621 | "count = 50 distance = 0.0005663993215903701\n", 622 | "count = 51 distance = 0.0005098092032884781\n", 623 | "count = 52 distance = 0.0004582016198447428\n", 624 | "count = 53 distance = 0.00039701654024634043\n", 625 | "count = 54 distance = 0.000356072071861924\n", 626 | "count = 55 distance = 0.0003206711053411534\n", 627 | "count = 56 distance = 0.00028908705571369634\n", 628 | "count = 57 distance = 0.00026062965063489255\n", 629 | "count = 58 distance = 0.0002349639712529274\n", 630 | "count = 59 distance = 0.00021181356175402826\n", 631 | "count = 60 distance = 0.0001909308318576549\n", 632 | "count = 61 distance = 0.00017209355498468346\n", 633 | "count = 62 distance = 0.00015510191427396596\n", 634 | "count = 63 distance = 0.00013977598787201997\n", 635 | "count = 64 distance = 0.0001259535892149283\n", 636 | "count = 65 distance = 0.00011348839663551855\n", 637 | "count = 66 distance = 0.00010224832093755675\n", 638 | "count = 67 distance = 9.211407060160057e-05\n" 639 | ] 640 | } 641 | ], 642 | "source": [ 643 | "# set up grid for k\n", 644 | "klow = low*kbar # low end of grid\n", 645 | "khigh = high*kbar # high end of grid\n", 646 | "kincr = np.log(khigh/klow)/(nptsk-1);\n", 647 | "kvec = np.zeros(nptsk)\n", 648 | "kvec[0] = klow\n", 649 | "for i in range (1, nptsk):\n", 650 | " kvec[i] = kvec[i-1]*(1+kincr)\n", 651 | "\n", 652 | "# set up grid for z\n", 653 | "zlow = -spread*max(sigma, .001)\n", 654 | "zhigh = spread*max(sigma, .001)\n", 655 | "zincr = (zhigh-zlow)/(nptsz-1);\n", 656 | "zvec = np.zeros(nptsz)\n", 657 | "zvec[0] = zlow\n", 658 | "for i in range (1, nptsz):\n", 659 | " zvec[i] = zvec[i-1] + zincr\n", 660 | "\n", 661 | "# create meshgrid\n", 662 | "kmesh, zmesh = np.meshgrid(kvec, zvec)\n", 663 | "\n", 664 | "# find value function and transition function\n", 665 | "distance = 1.0;\n", 666 | "maxwhile = 1000;\n", 667 | "count = 0;\n", 668 | "value = np.zeros((nptsz,nptsk));\n", 669 | "newval = np.zeros((nptsz,nptsk));\n", 670 | "trans = np.zeros((nptsz,nptsk));\n", 671 | "while distance > converge:\n", 672 | " count = count + 1\n", 673 | " if count > maxwhile:\n", 674 | " break\n", 675 | " for i in range(0, nptsz): # for all values of z(t)\n", 676 | " # find index of closest value for E{z(t+1)}\n", 677 | " m = np.argmin(np.abs(zvec - zvec[i]*rho))\n", 678 | " for j in range(0, nptsk): # for all values of k(t)\n", 679 | " maxval = -10000000000;\n", 680 | " for l in range(0, nptsk): # search over all values of k(t+1)\n", 681 | " if theta == 1:\n", 682 | " temp = np.log(kvec[j]**alpha*np.exp((1-alpha)*zvec[i]) \n", 683 | " +(1-delta)*kvec[j]-kvec[l]) + beta*value[m,l]\n", 684 | " else:\n", 685 | " temp = (((kvec[j]**alpha*np.exp((1-alpha)*zvec[i]) \n", 686 | " +(1-delta)*kvec[j]-kvec[l])**(1-theta)-1)) \\\n", 687 | " / (1-theta) + beta*value[m,l]\n", 688 | " # print i, j, temp\n", 689 | " if np.iscomplex(temp):\n", 690 | " temp = -100000000\n", 691 | " if np.isnan(temp):\n", 692 | " temp = -100000000\n", 693 | " if temp > maxval:\n", 694 | " maxval = temp\n", 695 | " newval[i,j] = temp\n", 696 | " trans[i,j] = kvec[l]\n", 697 | " # print newval\n", 698 | " distance = np.mean(np.abs(value/newval - 1.0))\n", 699 | " print('count = ', count, 'distance = ', distance)\n", 700 | " for i in range(0, nptsz):\n", 701 | " for j in range(0, nptsk):\n", 702 | " value[i,j] = newval[i,j]" 703 | ] 704 | }, 705 | { 706 | "cell_type": "markdown", 707 | "metadata": {}, 708 | "source": [ 709 | "Fit the policy function with a polynomial" 710 | ] 711 | }, 712 | { 713 | "cell_type": "code", 714 | "execution_count": 13, 715 | "metadata": {}, 716 | "outputs": [ 717 | { 718 | "name": "stdout", 719 | "output_type": "stream", 720 | "text": [ 721 | "R-squared 0.999335409097344\n" 722 | ] 723 | } 724 | ], 725 | "source": [ 726 | " # fit a polynomial\n", 727 | "Y = trans.flatten()\n", 728 | "\n", 729 | "X = np.ones(nptsk*nptsz)\n", 730 | "\n", 731 | "temp = kmesh.flatten()\n", 732 | "X = np.vstack((X,temp))\n", 733 | "\n", 734 | "temp = kmesh**2\n", 735 | "temp = temp.flatten()\n", 736 | "X = np.vstack((X,temp))\n", 737 | "\n", 738 | "temp = kmesh**3\n", 739 | "temp = temp.flatten()\n", 740 | "X = np.vstack((X,temp))\n", 741 | "\n", 742 | "temp = zmesh.flatten()\n", 743 | "X = np.vstack((X,temp))\n", 744 | "\n", 745 | "temp = zmesh**2\n", 746 | "temp = temp.flatten()\n", 747 | "X = np.vstack((X,temp))\n", 748 | "\n", 749 | "temp = zmesh**3\n", 750 | "temp = temp.flatten()\n", 751 | "X = np.vstack((X,temp))\n", 752 | "\n", 753 | "temp = kmesh*zmesh\n", 754 | "temp = temp.flatten()\n", 755 | "X = np.vstack((X,temp))\n", 756 | "\n", 757 | "temp = kmesh**2*zmesh\n", 758 | "temp = temp.flatten()\n", 759 | "X = np.vstack((X,temp))\n", 760 | "\n", 761 | "temp = kmesh*zmesh**2\n", 762 | "temp = temp.flatten()\n", 763 | "X = np.vstack((X,temp))\n", 764 | "\n", 765 | "XtX = np.dot(X,np.transpose(X))\n", 766 | "XtY = np.dot(X,Y)\n", 767 | "coeffs = np.dot(np.linalg.inv(XtX),XtY)\n", 768 | "tpoly = np.zeros((nptsz,nptsk))\n", 769 | "for i in range(0, nptsz):\n", 770 | " for j in range(0, nptsk):\n", 771 | " tpoly[i,j] = np.dot(np.stack((1, kvec[j], kvec[j]**2, kvec[j]**3, \\\n", 772 | " zvec[i], zvec[i]**2, zvec[i]**3, \\\n", 773 | " kvec[j]*zvec[i], kvec[j]**2*zvec[i], kvec[j]*zvec[i]**2)),coeffs)\n", 774 | "\n", 775 | "# calcuate R-squared\n", 776 | "Rsq = 1 - np.sum((trans-tpoly)**2)/np.sum(trans**2)\n", 777 | "print('R-squared', Rsq)" 778 | ] 779 | }, 780 | { 781 | "cell_type": "markdown", 782 | "metadata": {}, 783 | "source": [ 784 | "We now simulate our model" 785 | ] 786 | }, 787 | { 788 | "cell_type": "code", 789 | "execution_count": 14, 790 | "metadata": {}, 791 | "outputs": [], 792 | "source": [ 793 | "# perform simulation\n", 794 | "eps = np.random.randn(nobs)*sigma\n", 795 | "z = np.zeros(nobs+1)\n", 796 | "k = np.zeros(nobs+1)\n", 797 | "k[0] = kstart*kbar\n", 798 | "z[0] = eps[0]\n", 799 | "tpars = [kvec, zvec, trans, coeffs]\n", 800 | "lpars = [rho, sigma]\n", 801 | "for t in range(0, nobs):\n", 802 | " k[t+1] = example_tfunc(k[t], z[t], tpars)\n", 803 | " z[t+1] = example_lfunc(z[t], eps[t], lpars)\n", 804 | " \n", 805 | "# remove final k & z\n", 806 | "k = k[0:nobs]\n", 807 | "z = z[0:nobs]" 808 | ] 809 | }, 810 | { 811 | "cell_type": "markdown", 812 | "metadata": {}, 813 | "source": [ 814 | "Finally, we again calculate our Euler errors using the `EEcalc` function from above." 815 | ] 816 | }, 817 | { 818 | "cell_type": "code", 819 | "execution_count": 15, 820 | "metadata": {}, 821 | "outputs": [ 822 | { 823 | "name": "stdout", 824 | "output_type": "stream", 825 | "text": [ 826 | "Euler Error Summary Statistics\n", 827 | "Maximum Absolute Euler Error: 0.019506309755123973\n", 828 | "Mean Absolute Euler Error: 0.01899616624415117\n", 829 | "Root Mean Squared Euler Error: 0.01899640982371943\n" 830 | ] 831 | } 832 | ], 833 | "source": [ 834 | "# find Euler Errors\n", 835 | "Xdata = k.reshape(len(k), 1)\n", 836 | "Zdata = z.reshape(len(z), 1)\n", 837 | "efunc = example_efunc\n", 838 | "epars = params\n", 839 | "tfunc = example_tfunc2\n", 840 | "lfunc = example_lfunc\n", 841 | "EErrs = EEcalc(Xdata, Zdata, efunc, epars, tfunc, tpars, lfunc, lpars)\n", 842 | "\n", 843 | "MaxAbsEE = np.max(np.abs(EErrs))\n", 844 | "MeanAbsEE = np.mean(np.abs(EErrs))\n", 845 | "RootMeanSqEE = (np.mean(EErrs**2))**.5\n", 846 | "\n", 847 | "print('Euler Error Summary Statistics')\n", 848 | "print('Maximum Absolute Euler Error:', MaxAbsEE)\n", 849 | "print('Mean Absolute Euler Error:', MeanAbsEE)\n", 850 | "print('Root Mean Squared Euler Error:', RootMeanSqEE)" 851 | ] 852 | } 853 | ], 854 | "metadata": { 855 | "celltoolbar": "Raw Cell Format", 856 | "kernelspec": { 857 | "display_name": "Python 3", 858 | "language": "python", 859 | "name": "python3" 860 | }, 861 | "language_info": { 862 | "codemirror_mode": { 863 | "name": "ipython", 864 | "version": 3 865 | }, 866 | "file_extension": ".py", 867 | "mimetype": "text/x-python", 868 | "name": "python", 869 | "nbconvert_exporter": "python", 870 | "pygments_lexer": "ipython3", 871 | "version": "3.7.3" 872 | } 873 | }, 874 | "nbformat": 4, 875 | "nbformat_minor": 4 876 | } 877 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /LinApp.py: -------------------------------------------------------------------------------- 1 | ''' 2 | MATLAB version 1.0 written by Kerk Phillips, April 2014 3 | 4 | PYTHON version adapted by Yulong Li, November 2015 5 | 6 | updated 20 Nov 2017 by Kerk Phillips 7 | 8 | additional updates 22 May 2020 by Kerk Phillips 9 | 10 | more updates 3 June 2021 by Kerk Phillips 11 | replaced scipy.optimize.fsolve with scipy.optimize.root in the steady 12 | state solution code 13 | ''' 14 | 15 | import numpy as np 16 | import scipy as sp 17 | import scipy.optimize as opt 18 | from numpy import tile, array, zeros, log, exp, hstack, vstack, dot, eye, kron 19 | from scipy import linalg as la 20 | from numpy import linalg as npla 21 | 22 | 23 | def steady(XYbar, Zbar, funcname, param, nx, ny): 24 | Xbar = XYbar[0:nx] 25 | Ybar = XYbar[nx:nx+ny] 26 | Zbar = np.array(Zbar) 27 | if ny==0: 28 | In = np.concatenate((Xbar, Xbar, Xbar, Zbar, Zbar)) 29 | else: 30 | In = np.concatenate((Xbar, Xbar, Xbar, Ybar, Ybar, Zbar, Zbar)) 31 | In = np.concatenate((Xbar, Xbar, Xbar, Ybar, Ybar, Zbar, Zbar)) 32 | Out = funcname(In, param) 33 | return Out 34 | 35 | 36 | def LinApp_FindSS(funcname, param, guessXY, Zbar, nx, ny): 37 | # ''' 38 | # Finds the steady state for a DSGE model numerically 39 | # 40 | # Parameters 41 | # ----------- 42 | # funcname: function 43 | # the name of the function which generates a column vector 44 | # from ny+nx dynamic equations. 45 | # The ny equations to be linearized into the form below in the first 46 | # ny rows. 47 | # A X(t) + B X(t-1) + C Y(t) + D Z(t) = 0 48 | # The function must be written so as to evaluate to zero for all rows 49 | # in the steady state. 50 | # 51 | # param: array, dtype=float 52 | # a vector of parameter values to be passed to funcname. 53 | # 54 | # guessXY: array, dtype=float 55 | # guess for the steady state values of X and Y 56 | # 57 | # Zbar: array, dtype=float 58 | # nz vector of Z steady state values 59 | # 60 | # nx: number, dtype=int 61 | # number of X variables 62 | # 63 | # ny: number, dtype=int 64 | # number of Y variables 65 | # 66 | # Returns 67 | # -------- 68 | # XYbar: array, dtype=float 69 | # 1-by-(nx+ny) vector of X and Y steady state values, with the X 70 | # values in positions 1 - nx and the Y values in nx+1 - nx+ny. 71 | # ''' 72 | f = lambda XYbar: steady(XYbar, Zbar, funcname, param, nx, ny) 73 | output = opt.root(f, guessXY, method='hybr') 74 | 75 | XYbar = output.x 76 | 77 | return XYbar 78 | 79 | 80 | #------------------------------------------------------------------------------ 81 | 82 | def LinApp_Deriv(funcname, param, theta0, nx, ny, nz, logX): 83 | """ 84 | This function computes the matricies AA-MM in the log-linearization of 85 | the equations in the function 'func'. 86 | 87 | Parameters 88 | ---------- 89 | func: function 90 | The function that generates a vector from the dynamic equations that 91 | are to be linearized. This must be written to evaluate to zero in the 92 | steady state. Often these equations are the Euler equations defining 93 | the model 94 | 95 | theta0: array, dtype=float 96 | A vector of steady state values for state parameters. Place the values 97 | of X in the front, then the Y values, followed by the Z's. 98 | 99 | nx: number, dtype=int 100 | The number of elements in X 101 | 102 | ny: number, dtype=nt 103 | The number of elements in Y 104 | 105 | nz: number, dtype=int 106 | The number of elements in Z 107 | 108 | logX: binary, dtype=int 109 | true if log-linearizing the X & Y variables, false for simple linearization 110 | 111 | Returns 112 | ------- 113 | AA - MM : 2D-array, dtype=float: 114 | The equaitons described by Uhlig in the log-linearization. 115 | """ 116 | # calculate of derivative matrix 117 | length = 3 * nx + 2 * (ny + nz) 118 | height = nx + ny 119 | 120 | # set vaue for epsilon 121 | # eps = 2.2E-16 # machine epsilon for double-precision 122 | eps = 1.0E-6 123 | 124 | # Constant term, T0, should be very close to zero if linearizing about SS 125 | T0 = funcname(theta0, param) 126 | 127 | # set up plus and minus deviations matrices, disturb each input one-by-one 128 | devplus = np.tile(theta0.reshape(1, theta0.size), (length, 1)) 129 | devminus = np.tile(theta0.reshape(1, theta0.size), (length, 1)) 130 | for i in range(length): 131 | devplus[i, i] += eps 132 | devminus[i, i] -= eps 133 | 134 | # initialize first derivative matrix 135 | dGammaMat = np.zeros((height,length)) 136 | 137 | # find first derivatives 138 | for i in range(0,length): 139 | if i < 3 * nx + 2 * ny: 140 | if logX: 141 | dGammaMat[:,i] = \ 142 | (theta0[i]*(funcname(devplus[i, :], param)-T0)/(1.0+T0) \ 143 | - theta0[i]*(funcname(devminus[i, :], param)-T0)/(1.0+T0)) \ 144 | / (2.0 * eps) 145 | else: 146 | dGammaMat[:,i] = \ 147 | (funcname(devplus[i, :], param) \ 148 | -funcname(devminus[i, :], param)) / (2.0 * eps) 149 | else: 150 | dGammaMat[:,i] = \ 151 | (funcname(devplus[i, :], param) \ 152 | -funcname(devminus[i, :], param)) / (2.0 * eps) 153 | 154 | # partition into parts as labeled by Uhlig 155 | AA = np.array(dGammaMat[0:ny, nx:2 * nx]) 156 | BB = np.array(dGammaMat[0:ny, 2 * nx:3 * nx]) 157 | CC = np.array(dGammaMat[0:ny, 3 * nx + ny:3 * nx + 2 * ny]) 158 | DD = np.array(dGammaMat[0:ny, 3 * nx + 2 * ny + nz:length]) 159 | FF = np.array(dGammaMat[ny:ny + nx, 0:nx]) 160 | GG = np.array(dGammaMat[ny:ny + nx, nx:2 * nx]) 161 | HH = np.array(dGammaMat[ny:ny + nx, 2 * nx:3 * nx]) 162 | JJ = np.array(dGammaMat[ny:ny + nx, 3 * nx:3 * nx + ny]) 163 | KK = np.array(dGammaMat[ny:ny + nx, 3 * nx + ny:3 * nx + 2 * ny]) 164 | LL = np.array(dGammaMat[ny:ny + nx, 3 * nx + 2 * ny:3 * nx + 2 * ny + nz]) 165 | MM = np.array(dGammaMat[ny:ny + nx, 3 * nx + 2 * ny + nz:length]) 166 | 167 | return [AA, BB, CC, DD, FF, GG, HH, JJ, KK, LL, MM] 168 | 169 | 170 | #------------------------------------------------------------------------------ 171 | 172 | def _nullSpaceBasis(A): 173 | """ 174 | This funciton will find the basis of the null space of the matrix A. 175 | 176 | Parameters 177 | ---------- 178 | A : array_like, dtype=float 179 | The matrix you want the basis for 180 | 181 | Returns 182 | ------- 183 | vecs : array_like, dtype=float 184 | A numpy matrix containing the vectors as row vectors. 185 | 186 | Notes 187 | ----- 188 | If A is an empty matrix, an empty matrix is returned. 189 | 190 | """ 191 | if A.any(): 192 | U, s, Vh = la.svd(A) 193 | vecs = np.array([]) 194 | toAppend = A.shape[1] - s.size 195 | s = np.append(s, zeros((1, toAppend))) 196 | for i in range(0, s.size): 197 | if s[i] == 0: 198 | vecs = Vh[-toAppend:, :] 199 | if vecs.size == 0: 200 | vecs = zeros((1, A.shape[1])) 201 | return np.mat(vecs) 202 | else: 203 | return zeros((0, 0)) 204 | 205 | 206 | def qzswitch(i, A, B, Q, Z): 207 | ''' 208 | Takes U.T. matrices A, B, orthonormal matrices Q,Z, interchanges 209 | diagonal elements i and i+1 of both A and B, while maintaining 210 | Q'AZ' and Q'BZ' unchanged. Does nothing if ratios of diagonal elements 211 | in A and B at i and i+1 are the same. Aborts if diagonal elements of 212 | both A and B are zero at either position. 213 | 214 | Parameters 215 | ---------- 216 | i : number, dtype=int 217 | Index (>=1) of the diagonal element to be interchanged 218 | A : array_like, dtype=float 219 | The upper triangular matrix of which some diagonal elements are to 220 | be interchanged 221 | B : array_like, dtype=float 222 | The other upper triangular matrix of which some diagonal elements are 223 | to be interchanged 224 | Q : array_like, dtype=float 225 | An orthonormal matrix from the QZ decomposition 226 | Z : array_like, dtype=float 227 | An orthonormal matrix from the QZ decomposition 228 | Returns 229 | ------- 230 | A : array_like, dtype=float 231 | Altered A matrix 232 | B : array_like, dtype=float 233 | Altered A matrix 234 | Q : array_like, dtype=float 235 | Altered Q matrix 236 | Z : array_like, dtype=float 237 | Altered Z matrix 238 | Notes 239 | ----- 240 | Copyright: C.A. Sims, 1996, Yale University. 241 | ''' 242 | a = A[i-1,i-1] 243 | d = B[i-1,i-1] 244 | b = A[i-1,i] 245 | e = B[i-1,i] 246 | c = A[i,i] 247 | f = B[i,i] 248 | 249 | wz = hstack((dot(c,e)-dot(f,b), (dot(c,d)-dot(f,a)).conj().T)) 250 | xy = hstack(((dot(b,d)-dot(e,a)).conj().T, (dot(c,d)-dot(f,a)).conj().T)) 251 | 252 | n = np.sqrt(dot(wz,wz.conj().T)) 253 | m = np.sqrt(dot(xy,xy.conj().T)) 254 | 255 | if n == 0: 256 | print ("qzswitch(): Inputs unchanged!") 257 | return A, B, Q, Z 258 | else: 259 | wz = wz/n 260 | xy = xy/m 261 | wz = vstack(( wz, hstack((-wz[1].conj().T, wz[0].conj().T)) )) 262 | xy = vstack(( xy, hstack((-xy[1].conj().T, xy[0].conj().T)) )) 263 | A[i-1:i+1,:] = xy.dot(A[i-1:i+1,:]) 264 | B[i-1:i+1,:] = xy.dot(B[i-1:i+1,:]) 265 | A[:,i-1:i+1] = A[:,i-1:i+1].dot(wz) 266 | B[:,i-1:i+1] = B[:,i-1:i+1].dot(wz) 267 | Z[:,i-1:i+1] = Z[:,i-1:i+1].dot(wz) 268 | Q[i-1:i+1,:] = xy.dot(Q[i-1:i+1,:]) 269 | return A, B, Q, Z 270 | 271 | 272 | def qzdiv(stake, A, B, Q, Z): 273 | ''' 274 | Takes U.T. matrices A, B, orthonormal matrices Q,Z, rearranges them 275 | so that all cases of abs(B(i,i)/A(i,i))>stake are in lower right 276 | corner, while preserving U.T. and orthonormal properties and Q'AZ' and Q'BZ'. 277 | 278 | Parameters 279 | ---------- 280 | stake : number, dtype=float 281 | A : array_like, dtype=float 282 | An upper triangular matrix 283 | B : array_like, dtype=float 284 | An upper triangular matrix 285 | Q : array_like, dtype=float 286 | An orthonormal matrix from the QZ decomposition 287 | Z : array_like, dtype=float 288 | An orthonormal matrix from the QZ decomposition 289 | Returns 290 | ------- 291 | A : array_like, dtype=float 292 | Rearranged A matrix 293 | B : array_like, dtype=float 294 | Rearranged B matrix 295 | Q : array_like, dtype=float 296 | Rearranged Q matrix 297 | Z : array_like, dtype=float 298 | Rearranged Z matrix 299 | Notes 300 | ----- 301 | Copyright: C.A. Sims, 1996, Yale University. 302 | ''' 303 | n, jnk = A.shape 304 | 305 | root = abs(vstack((np.diag(A), np.diag(B))).T) 306 | tmp = (root[:,0]<1.e-13).astype(int) 307 | root[:,0] = root[:,0]- tmp *(root[:,0]+root[:,1]) 308 | root[:,1] = root[:,1]/root[:,0] 309 | for i in range(n,0,-1): 310 | m=0 311 | for j in range(i,0,-1): 312 | if (root[j-1,1] > stake or root[j-1,1] < -.1): 313 | m=j 314 | break 315 | if m==0: 316 | print ("qzdiv(): Inputs unchanged!") 317 | return A, B, Q, Z 318 | for k in range(m,i,1): 319 | A, B, Q, Z = qzswitch(k,A,B,Q,Z) 320 | tmp = root[k-1,1] 321 | root[k-1,1] = root[k,1] 322 | root[k,1] = tmp 323 | return A, B, Q, Z 324 | 325 | 326 | def LinApp_Solve(AA, BB, CC, DD, FF, GG, HH, JJ, KK, LL, MM, NN, Z0, Sylv): 327 | """ 328 | This code takes Uhlig's original code and puts it in the form of a 329 | function. This version outputs the policy function coefficients: PP, 330 | QQ and UU for X, and RR, SS and VV for Y. 331 | 332 | Inputs overview: 333 | The matrices of derivatives: AA - MM. 334 | The autoregression coefficient matrix NN from the law of motion for Z. 335 | Z0 is the Z-point about which the linearization is taken. For 336 | linearizing about the steady state this is Zbar and normally Zbar = 0. 337 | Sylv is an indicator variable telling the program to use the built-in 338 | function sylvester() to solve for QQ and SS, if possible. Default is 339 | to use Sylv=1. This option is now disabled and we always set Sylv=1. 340 | 341 | Parameters 342 | ---------- 343 | AA : array_like, dtype=float, shape=(ny, nx) 344 | The matrix represented above by :math:`A`. It is the matrix of 345 | derivatives of the Y equations with repsect to :math:`X_t` 346 | BB : array_like, dtype=float, shape=(ny, nx) 347 | The matrix represented above by :math:`B`. It is the matrix of 348 | derivatives of the Y equations with repsect to 349 | :math:`X_{t-1}`. 350 | CC : array_like, dtype=float, shape=(ny, ny) 351 | The matrix represented above by :math:`C`. It is the matrix of 352 | derivatives of the Y equations with repsect to :math:`Y_t` 353 | DD : array_like, dtype=float, shape=(ny, nz) 354 | The matrix represented above by :math:`C`. It is the matrix of 355 | derivatives of the Y equations with repsect to :math:`Z_t` 356 | FF : array_like, dtype=float, shape=(nx, nx) 357 | The matrix represetned above by :math:`F`. It is the matrix of 358 | derivatives of the model's characterizing equations with 359 | respect to :math:`X_{t+1}` 360 | GG : array_like, dtype=float, shape=(nx, nx) 361 | The matrix represetned above by :math:`G`. It is the matrix of 362 | derivatives of the model's characterizing equations with 363 | respect to :math:`X_t` 364 | HH : array_like, dtype=float, shape=(nx, nx) 365 | The matrix represetned above by :math:`H`. It is the matrix of 366 | derivatives of the model's characterizing equations with 367 | respect to :math:`X_{t-1}` 368 | JJ : array_like, dtype=float, shape=(nx, ny) 369 | The matrix represetned above by :math:`J`. It is the matrix of 370 | derivatives of the model's characterizing equations with 371 | respect to :math:`Y_{t+1}` 372 | KK : array_like, dtype=float, shape=(nx, ny) 373 | The matrix represetned above by :math:`K`. It is the matrix of 374 | derivatives of the model's characterizing equations with 375 | respect to :math:`Y_t` 376 | LL : array_like, dtype=float, shape=(nx, nz) 377 | The matrix represetned above by :math:`L`. It is the matrix of 378 | derivatives of the model's characterizing equations with 379 | respect to :math:`Z_{t+1}` 380 | MM : array_like, dtype=float, shape=(nx, nz) 381 | The matrix represetned above by :math:`M`. It is the matrix of 382 | derivatives of the model's characterizing equations with 383 | respect to :math:`Z_t` 384 | NN : array_like, dtype=float, shape=(nz, nz) 385 | The autocorrelation matrix for the exogenous state vector z. 386 | Z0 : array, dtype=float, shape=(nz,) 387 | the Z-point about which the linearization is taken. For linearizing 388 | about the steady state this is Zbar and normally Zbar = 0. 389 | QQ if true. 390 | Sylv: binary, dtype=int 391 | an indicator variable telling the program to use the built-in 392 | function sylvester() to solve for QQ and SS, if possible. Default is 393 | to use Sylv=1. 394 | 395 | Returns 396 | ------- 397 | P : 2D-array, dtype=float, shape=(nx, nx) 398 | The matrix :math:`P` in the law of motion for endogenous state 399 | variables described above. 400 | Q : 2D-array, dtype=float, shape=(nx, nz) 401 | The matrix :math:`Q` in the law of motion for exogenous state 402 | variables described above. 403 | R : 2D-array, dtype=float, shape=(ny, nx) 404 | The matrix :math:`R` in the law of motion for endogenous state 405 | variables described above. 406 | S : 2D-array, dtype=float, shape=(ny, nz) 407 | The matrix :math:`S` in the law of motion for exogenous state 408 | variables described above. 409 | 410 | References 411 | ---------- 412 | .. [1] Uhlig, H. (1999): "A toolkit for analyzing nonlinear dynamic 413 | stochastic models easily," in Computational Methods for the Study 414 | of Dynamic Economies, ed. by R. Marimon, pp. 30-61. Oxford 415 | University Press. 416 | 417 | """ 418 | # The coding for Uhlig's solution for QQ and SS gives incorrect results 419 | # So we will use numpy's Sylvester equation solver regardless of the value 420 | # chosen for Sylv 421 | 422 | #The original coding we did used the np.matrix form for our matrices so we 423 | #make sure to set our inputs to numpy matrices. 424 | AA = np.matrix(AA) 425 | BB = np.matrix(BB) 426 | CC = np.matrix(CC) 427 | DD = np.matrix(DD) 428 | FF = np.matrix(FF) 429 | GG = np.matrix(GG) 430 | HH = np.matrix(HH) 431 | JJ = np.matrix(JJ) 432 | KK = np.matrix(KK) 433 | LL = np.matrix(LL) 434 | MM = np.matrix(MM) 435 | NN = np.matrix(NN) 436 | Z0 = np.array(Z0) 437 | #Tolerance level to use 438 | TOL = .000001 439 | 440 | # Here we use matrices to get pertinent dimensions. 441 | nx = FF.shape[1] 442 | l_equ = CC.shape[0] 443 | ny = CC.shape[1] 444 | nz = min(NN.shape) 445 | 446 | # The following if and else blocks form the 447 | # Psi, Gamma, Theta Xi, Delta mats 448 | if l_equ == 0: 449 | if CC.any(): 450 | # This blcok makes sure you don't throw an error with an empty CC. 451 | CC_plus = la.pinv(CC) 452 | CC_0 = _nullSpaceBasis(CC.T) 453 | else: 454 | CC_plus = np.mat([]) 455 | CC_0 = np.mat([]) 456 | Psi_mat = FF 457 | Gamma_mat = -GG 458 | Theta_mat = -HH 459 | Xi_mat = np.mat(vstack((hstack((Gamma_mat, Theta_mat)), 460 | hstack((eye(nx), zeros((nx, nx))))))) 461 | Delta_mat = np.mat(vstack((hstack((Psi_mat, zeros((nx, nx)))), 462 | hstack((zeros((nx, nx)), eye(nx)))))) 463 | 464 | else: 465 | CC_plus = la.pinv(CC) 466 | CC_0 = _nullSpaceBasis(CC.T) 467 | if l_equ != ny: 468 | Psi_mat = vstack((zeros((l_equ - ny, nx)), FF \ 469 | - dot(dot(JJ, CC_plus), AA))) 470 | Gamma_mat = vstack((dot(CC_0, AA), dot(dot(JJ, CC_plus), BB) \ 471 | - GG + dot(dot(KK, CC_plus), AA))) 472 | Theta_mat = vstack((dot(CC_0, BB), dot(dot(KK, CC_plus), BB) - HH)) 473 | else: 474 | CC_inv = la.inv(CC) 475 | Psi_mat = FF - dot(JJ.dot(CC_inv), AA) 476 | Gamma_mat = dot(JJ.dot(CC_inv), BB) - GG + dot(dot(KK, CC_inv), AA) 477 | Theta_mat = dot(KK.dot(CC_inv), BB) - HH 478 | Xi_mat = vstack((hstack((Gamma_mat, Theta_mat)), \ 479 | hstack((eye(nx), zeros((nx, nx)))))) 480 | Delta_mat = vstack((hstack((Psi_mat, np.mat(zeros((nx, nx))))),\ 481 | hstack((zeros((nx, nx)), eye(nx))))) 482 | 483 | # Now we need the generalized eigenvalues/vectors for Xi with respect to 484 | # Delta. That is eVals and eVecs below. 485 | 486 | eVals, eVecs = la.eig(Xi_mat, Delta_mat) 487 | if npla.matrix_rank(eVecs) < nx: 488 | print("Error: Xi is not diagonalizable, stopping...") 489 | 490 | # From here to line 158 we Diagonalize Xi, form Lambda/Omega and find P. 491 | else: 492 | Xi_sortindex = np.argsort(abs(eVals)) 493 | Xi_sortedVec = np.array([eVecs[:, i] for i in Xi_sortindex]).T 494 | Xi_sortval = eVals[Xi_sortindex] 495 | Xi_select = np.arange(0, nx) 496 | if np.imag(Xi_sortval[nx - 1]).any(): 497 | if (abs(Xi_sortval[nx - 1] - sp.conj(Xi_sortval[nx])) < TOL): 498 | drop_index = 1 499 | cond_1 = (abs(np.imag(Xi_sortval[drop_index-1])) > TOL) 500 | cond_2 = drop_index < nx 501 | while cond_1 and cond_2: 502 | drop_index += 1 503 | if drop_index >= nx: 504 | print("There is an error. Too many complex eigenvalues." 505 | +" Quitting...") 506 | else: 507 | print("Droping the lowest real eigenvalue. Beware of" + 508 | " sunspots!") 509 | Xi_select = np.array([np.arange(0, drop_index - 1),\ 510 | np.arange(drop_index, nx + 1)]) 511 | # Here Uhlig computes stuff if user chose "Manual roots" I skip it. 512 | if max(abs(Xi_sortval[Xi_select])) > 1 + TOL: 513 | print("It looks like we have unstable roots. This might not work...") 514 | if abs(max(abs(Xi_sortval[Xi_select])) - 1) < TOL: 515 | print("Check the model to make sure you have a unique steady" + 516 | " state we are having problems with convergence.") 517 | Lambda_mat = np.diag(Xi_sortval[Xi_select]) 518 | Omega_mat = Xi_sortedVec[nx:2 * nx, Xi_select] 519 | 520 | if npla.matrix_rank(Omega_mat) < nx: 521 | print("Omega matrix is not invertible, Can't solve for P; we" + 522 | " proceed with QZ-method instead.") 523 | 524 | #~~~~~~~~~ QZ-method codes from SOLVE_QZ ~~~~~~~~# 525 | Delta_up,Xi_up,UUU,VVV=la.qz(Delta_mat,Xi_mat, output='complex') 526 | UUU=UUU.T 527 | Xi_eigval = np.diag( np.diag(Xi_up)/np.maximum(np.diag(Delta_up),TOL)) 528 | Xi_sortindex= np.argsort(abs(np.diag(Xi_eigval))) 529 | Xi_sortval = Xi_eigval[Xi_sortindex, Xi_sortindex] 530 | Xi_select = np.arange(0, nx) 531 | stake = max(abs(Xi_sortval[Xi_select])) + TOL 532 | 533 | Delta_up, Xi_up, UUU, VVV = qzdiv(stake,Delta_up,Xi_up,UUU,VVV) 534 | 535 | #Check conditions from line 49-109 536 | if np.imag(Xi_sortval[nx - 1]).any(): 537 | if (abs(Xi_sortval[nx - 1] - sp.conj(Xi_sortval[nx])) < TOL): 538 | print("Problem: You have complex eigenvalues! And this means"+ 539 | " PP matrix will contain complex numbers by this method." ) 540 | drop_index = 1 541 | cond_1 = (abs(np.imag(Xi_sortval[drop_index-1])) > TOL) 542 | cond_2 = drop_index < nx 543 | while cond_1 and cond_2: 544 | drop_index += 1 545 | if drop_index >= nx: 546 | print("There is an error. Too many complex eigenvalues." 547 | +" Quitting...") 548 | else: 549 | print("Dropping the lowest real eigenvalue. Beware of" + 550 | " sunspots!") 551 | for i in range(drop_index,nx+1): 552 | Delta_up,Xi_up,UUU,VVV = qzswitch(i,Delta_up,Xi_up,UUU,VVV) 553 | Xi_select1 = np.arange(0,drop_index-1) 554 | Xi_select = np.append(Xi_select1, np.arange(drop_index,nx+1)) 555 | 556 | if Xi_sortval[max(Xi_select)] < 1 - TOL: 557 | print('There are stable roots NOT used. Proceeding with the' + 558 | ' smallest root.') 559 | if max(abs(Xi_sortval[Xi_select])) > 1 + TOL: 560 | print("It looks like we have unstable roots. This might not work...") 561 | if abs(max(abs(Xi_sortval[Xi_select])) - 1) < TOL: 562 | print("Check the model to make sure you have a unique steady" + 563 | " state we are having problems with convergence.") 564 | #End of checking conditions 565 | #Lambda_mat = np.diag(Xi_sortval[Xi_select]) # to help sol_out.m 566 | 567 | VVV=VVV.conj().T 568 | VVV_2_1 = VVV[nx : 2*nx, 0 : nx] 569 | VVV_2_2 = VVV[nx : 2*nx, nx :2*nx] 570 | UUU_2_1 = UUU[nx : 2*nx, 0 : nx] 571 | VVV = VVV.conj().T 572 | 573 | if abs(la.det(UUU_2_1))< TOL: 574 | print("One necessary condition for computing P is NOT satisfied,"+ 575 | " but we proceed anyways...") 576 | if abs(la.det(VVV_2_1))< TOL: 577 | print("VVV_2_1 matrix, used to compute for P, is not invertible; we"+ 578 | " are in trouble but we proceed anyways...") 579 | 580 | PP = np.matrix( la.solve(- VVV_2_1, VVV_2_2) ) 581 | PP_imag = np.imag(PP) 582 | PP = np.real(PP) 583 | if (sum(sum(abs(PP_imag))) / sum(sum(abs(PP))) > .000001).any(): 584 | print("A lot of P is complex. We will continue with the" + 585 | " real part and hope we don't lose too much information.") 586 | #~~~~~~~~~ End of QZ-method ~~~~~~~~~# 587 | 588 | #This follows the original uhlig.py file 589 | else: 590 | PP = dot(dot(Omega_mat, Lambda_mat), la.inv(Omega_mat)) 591 | PP_imag = np.imag(PP) 592 | PP = np.real(PP) 593 | if (sum(sum(abs(PP_imag))) / sum(sum(abs(PP))) > .000001).any(): 594 | print("A lot of P is complex. We will continue with the" + 595 | " real part and hope we don't lose too much information.") 596 | 597 | # The if and else below make RR depending on our model's setup. 598 | if l_equ == 0: 599 | RR = zeros((0, nx)) #empty matrix 600 | else: 601 | RR = - dot(CC_plus, (dot(AA, PP) + BB)) 602 | 603 | # Now we use Sylvester equation solver to find QQ and SS matrices. 604 | ''' 605 | This code written by Kerk Phillips 2020 606 | updated in July 2021 607 | ''' 608 | 609 | CCinv = npla.inv(CC) 610 | # if ny>0: 611 | # PM = npla.inv(FF-np.matmul(np.matmul(JJ,CCinv), AA)) 612 | # if npla.matrix_rank(PM)< nx+ny: 613 | # print("Sylvester equation solver condition is not satisfied") 614 | # else: 615 | # PM = npla.inv(FF) 616 | # if npla.matrix_rank(FF)< nx: 617 | # print("Sylvester equation solver condition is not satisfied") 618 | if ny>0: 619 | JCAP = np.matmul(np.matmul(JJ,CCinv), np.matmul(AA,PP)) 620 | JCB = np.matmul(np.matmul(JJ,CCinv), BB) 621 | KCA = np.matmul(np.matmul(KK,CCinv), AA) 622 | KCD = np.matmul(np.matmul(KK,CCinv), DD) 623 | JCDN = np.matmul(np.matmul(JJ,CCinv), np.matmul(DD,NN)) 624 | Dnew = FF.dot(PP) + GG - JCAP - JCB - KCA 625 | Fnew = FF-np.matmul(np.matmul(JJ,CCinv), AA) 626 | Gnew = NN 627 | Hnew = KCD - LL.dot(NN) + JCDN - MM 628 | Asyl = npla.inv(Dnew).dot(Fnew) 629 | Bsyl = npla.inv(Gnew) 630 | Csyl = np.matmul(npla.inv(Dnew).dot(Hnew), npla.inv(Gnew)) 631 | QQ = la.solve_sylvester(Asyl,Bsyl,Csyl) 632 | SS = la.solve(-CC, (AA.dot(QQ)+DD)) 633 | else: 634 | Dnew = FF.dot(PP) + GG 635 | Fnew = FF 636 | Gnew = NN 637 | Hnew = - LL.dot(NN) - MM 638 | Asyl = npla.inv(Dnew).dot(Fnew) 639 | Bsyl = npla.inv(Gnew) 640 | Csyl = np.matmul(npla.inv(Dnew).dot(Hnew), npla.inv(Gnew)) 641 | QQ = la.solve_sylvester(Asyl,Bsyl,Csyl) 642 | SS = np.zeros((0,nz)) #empty matrix 643 | 644 | return np.array(PP), np.array(QQ), np.array(RR), np.array(SS) 645 | 646 | 647 | #------------------------------------------------------------------------------ 648 | 649 | def LinApp_Sim(Xm, Z, PP, QQ, RR, SS): 650 | ''' 651 | Uses the coefficients from a linear approximation to generate data for 652 | next period given today's state. The set of endogenous state variables 653 | known today is Xm and the set of exogenous state variables is Z. 654 | This program generates X. 655 | 656 | The input and output values are in deviation from the linearization point 657 | (almost always the steady state, but not necessarily so). This means 658 | you will need to add back the steady state or other values after you have 659 | called this function. How you do this depends on whether you used 660 | log-linearization or simple linearization in deriving the values of the 661 | input coefficients. 662 | 663 | Parameters 664 | ----------- 665 | Xm: array, dtype=float 666 | nx vector of X(t-1) values 667 | 668 | Z: array, dtype=float 669 | nz vector of Z(t) values 670 | 671 | PP: 2D-array, dtype=float 672 | nx-by-nx matrix of X(t-1) on X(t) coefficients 673 | 674 | QQ: 2D-array, dtype=float 675 | nx-by-nz matrix of Z(t) on X(t) coefficients 676 | 677 | RR: 2D-array, dtype=float 678 | ny-by-nx matrix of X(t-1) on Y(t) coefficients 679 | 680 | SS: 2D-array, dtype=float 681 | ny-by-nz matrix of Z(t) on Y(t) coefficients 682 | 683 | Returns 684 | -------- 685 | X: array, dtype=float 686 | nx vector containing the value of the endogenous 687 | state variables for next period 688 | 689 | Y: array, dtype=float 690 | ny vector containing the value of the endogenous 691 | non-state variables for the current period 692 | ''' 693 | # Find the number of each kind of state variable 694 | # Using Xm find nx 695 | if len(Xm.shape)!=1: 696 | print('Xm must be a one-dimensional array') 697 | else: 698 | nx = Xm.shape[0] 699 | # Using RR find ny 700 | ny = RR.shape[0] 701 | 702 | # Using Z find nz 703 | if len(Z.shape)!=1: 704 | print('Z must be a one-dimensional array') 705 | else: 706 | nz = Z.shape[0] 707 | 708 | # Check conformity of input coefficient matrices 709 | d1,d2 = PP.shape 710 | if d1 != nx or d2 != nx: 711 | print('Dimensions of PP incorrect') 712 | 713 | d1,d2 = QQ.shape 714 | if d1 != nx or d2 != nz: 715 | print('dimensions of QQ incorrect') 716 | 717 | # Generate data for next period, one equation at a time 718 | X = PP.dot(Xm) + QQ.dot(Z) 719 | 720 | if ny>0: 721 | Y = RR.dot(Xm) + SS.dot(Z) 722 | else: 723 | Y = [] 724 | 725 | return np.array(X), np.array(Y) 726 | 727 | 728 | #------------------------------------------------------------------------------ 729 | 730 | def LinApp_SSL(X0, Z, XYbar, logX, PP, QQ, RR, SS): 731 | ''' 732 | Generates a history of X & Y variables by linearizing the policy function 733 | about the steady state as in Uhlig's toolkit. 734 | 735 | Parameters 736 | ----------- 737 | X0: array, dtype=float 738 | nx vector of X(1) starting values values 739 | 740 | Z: 2D-array, dtype=float 741 | nobs-by-nz matrix of Z values 742 | 743 | XYbar: array, dtype=float 744 | nx+ny vector of X and Y steady state values 745 | 746 | logX: binary, dtype=int 747 | an indicator that determines if the X & Y variables are 748 | log-linearized (true) or simply linearized (false). Z variables 749 | are always simply linearized. 750 | 751 | PP: 2D-array, dtype=float 752 | nx-by-nx matrix of X(t-1) on X(t) coefficients 753 | 754 | QQ: 2D-array, dtype=float 755 | nx-by-nz matrix of Z(t) on X(t) coefficients 756 | 757 | Y0: array, dtype=float 758 | ny vector of Y(1) starting values values. 759 | 760 | RR: 2D-array, dtype=float 761 | ny-by-nx matrix of X(t-1) on Y(t) coefficients 762 | 763 | SS: 2D-array, dtype=float 764 | ny-by-nz matrix of Z(t) on Y(t) coefficients 765 | 766 | Returns 767 | -------- 768 | X: 2D-array, dtype=float 769 | nobs-by-nx matrix containing the value of the endogenous 770 | state variables 771 | 772 | Y: 2D-array, dtype=float 773 | nobs-by-ny matrix vector containing the value of the endogenous 774 | non-state variables 775 | ''' 776 | # Formating 777 | X0 = array(X0) 778 | 779 | # get values for nx, ny, nz and nobs 780 | nobs,nz = Z.shape 781 | nx = X0.shape[0] 782 | nxy = XYbar.shape[0] 783 | ny = nxy - nx 784 | 785 | # get Xbar and Ybar 786 | Xbar = XYbar[0:nx] 787 | Ybar = XYbar[nx:nx+ny] 788 | 789 | # Generate a history of X's and Y's 790 | X = zeros((nobs,nx)) 791 | Y = zeros((nobs,ny)) 792 | Xtil = zeros((nobs,nx)) 793 | Ytil = zeros((nobs,ny)) 794 | 795 | # set starting values 796 | if logX: 797 | Xtil[0,:] = log(X0/Xbar) 798 | else: 799 | Xtil[0,:] = X0 - Xbar 800 | 801 | # simulate 802 | for t in range(0, nobs-1): 803 | Xtemp, Ytemp = LinApp_Sim(Xtil[t,:], Z[t,:], PP, QQ, RR, SS) 804 | Xtil[t+1,:] = Xtemp 805 | if ny>0: 806 | Ytil[t,:] = Ytemp 807 | 808 | # Convert to levels 809 | if logX: 810 | X = tile(Xbar,(nobs,1))*exp(Xtil) 811 | if ny> 0: 812 | Y = tile(Ybar,(nobs,1))*exp(Ytil) 813 | else: 814 | X = tile(Xbar,(nobs,1))+Xtil 815 | if ny>0: 816 | Y = tile(Ybar,(nobs,1))+Ytil 817 | 818 | return X, Y #Note if ny=0, Y is a nobs by 0 empty matrix 819 | -------------------------------------------------------------------------------- /Moment_Calculator.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Quickly and Easily Calculate Business Cycle Moments\n", 8 | "\n", 9 | "### by [Kerk L. Phillips](https://sites.google.com/site/kerkphillips/home), July 2018\n", 10 | "\n", 11 | "The code in this Jupyter notebook was written using Python 3.6." 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "This notebook shows how to quickly and easily calculate a set of commonly reported moments from a set of data. This data could be real world data, or data from a simulated model. The function used, `calcmom`, can be downloaded at the following Github site. [https://github.com/kerkphil/DSGE-Utilities](https://github.com/kerkphil/DSGE-Utilities). For the example in this notebook we use data stored in a csv spreadsheet, `DSGEtestdata.csv`. That data files and this notebook can be found in the public GitHub repository [https://github.com/kerkphil/Jupyter_Notebooks](https://github.com/kerkphil/Jupyter_Notebooks)." 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "## Moment Calculator Code" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": {}, 31 | "source": [ 32 | "The code below can be downloaded from the repository shown above, however we reproduce it here in order to see how the moments are calculated.\n", 33 | "\n", 34 | "Note that the data must be organized as follows:\n", 35 | "\n", 36 | "data: an nobs-by-nvar matrix of data with with nobs indexing the time-series observations in rows and nvar indexing the variables in columns. If GDP is included it should be in the first column." 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": 2, 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "import pandas as pd\n", 46 | "import numpy as np\n", 47 | "\n", 48 | "def calcmom(data, means = False, stds = True, relstds = True, \n", 49 | " corrs = True, autos = True, cvars = False):\n", 50 | " '''\n", 51 | " This function calculates a user controlled set of moments from data\n", 52 | " It takes the following as inputs:\n", 53 | " 1) data: an nobs-by-nvar matrix of data with with nobs indexing the \n", 54 | " time-series observations in rows and nvar indexing the variables in \n", 55 | " columns. If GDP is included it should be in the first column.\n", 56 | " \n", 57 | " The function caculates and returns the following outputs in a single\n", 58 | " matrix with rows for each type of momemnt and nvar columns . The moments,\n", 59 | " if calculated are reported in the following order. Each column can be\n", 60 | " turned off or on by setting the appropriate flags.\n", 61 | " 1) means - means of the variables\n", 62 | " 2) stdevs - standard deviations of variables\n", 63 | " 3) relstds - standard deviations of variables relative to GDP\n", 64 | " 4) correls - correlations of variables with GDP\n", 65 | " 5) autocoors - autocorrelations of variables\n", 66 | " 6) coefvars - coefficients of variation (stdev/mean)\n", 67 | " \n", 68 | " Notes:\n", 69 | " \n", 70 | " '''\n", 71 | " # find the number of variables and observations\n", 72 | " (nobs, nvar) = data.shape\n", 73 | " report = np.zeros(nvar)\n", 74 | " count = 0\n", 75 | " rindex = []\n", 76 | " \n", 77 | " if means or cvars:\n", 78 | " dmeans= np.mean(data,axis=0)\n", 79 | " report = np.vstack((report,dmeans))\n", 80 | " count = count + 1\n", 81 | " rindex.extend(['means'])\n", 82 | " \n", 83 | " if stds or cvars:\n", 84 | " dstds = np.std(data,axis=0)\n", 85 | " report = np.vstack((report,dstds))\n", 86 | " count = count + 1\n", 87 | " rindex.extend(['standard deviations'])\n", 88 | " \n", 89 | " if relstds:\n", 90 | " drelstds = dstds/dstds[0]\n", 91 | " report = np.vstack((report,drelstds))\n", 92 | " count = count + 1\n", 93 | " rindex.extend(['standard deviations relative to GDP'])\n", 94 | " \n", 95 | " if corrs:\n", 96 | " temp = np.corrcoef(np.transpose(data))\n", 97 | " dcorrs = temp[0:nvar,0]\n", 98 | " report = np.vstack((report,dcorrs))\n", 99 | " count = count + 1\n", 100 | " rindex.extend(['corrleations with GDP'])\n", 101 | " \n", 102 | " if autos:\n", 103 | " dlead = np.transpose(data[1:nobs,:])\n", 104 | " dlag = np.transpose(data[0:nobs-1,:])\n", 105 | " temp = np.corrcoef(dlead,dlag)\n", 106 | " dautos = np.diag(temp, -nvar)\n", 107 | " report = np.vstack((report,dautos))\n", 108 | " count = count + 1\n", 109 | " rindex.extend(['autocorrelations'])\n", 110 | " \n", 111 | " if cvars:\n", 112 | " dcvars = dstds/dmeans\n", 113 | " report = np.vstack((report,dcvars))\n", 114 | " count = count + 1\n", 115 | " rindex.extend(['coefficients of variation'])\n", 116 | " \n", 117 | " # appropriately truncate lists\n", 118 | " report = report[1:count+1,:]\n", 119 | " rindex = rindex[0:count+1]\n", 120 | " \n", 121 | " return report, rindex" 122 | ] 123 | }, 124 | { 125 | "cell_type": "markdown", 126 | "metadata": {}, 127 | "source": [ 128 | "## An Example" 129 | ] 130 | }, 131 | { 132 | "cell_type": "code", 133 | "execution_count": 14, 134 | "metadata": {}, 135 | "outputs": [ 136 | { 137 | "data": { 138 | "text/html": [ 139 | "\n", 140 | " \n", 141 | " \n", 142 | " \n", 143 | " \n", 144 | " \n", 145 | " \n", 146 | " \n", 147 | " \n", 148 | " \n", 149 | " \n", 150 | " \n", 151 | " \n", 152 | " \n", 153 | " \n", 154 | " \n", 155 | " \n", 156 | " \n", 157 | " \n", 158 | " \n", 159 | " \n", 160 | " \n", 161 | " \n", 162 | " \n", 163 | " \n", 164 | " \n", 165 | " \n", 166 | " \n", 167 | " \n", 168 | " \n", 169 | " \n", 170 | " \n", 171 | " \n", 172 | " \n", 173 | " \n", 174 | " \n", 175 | " \n", 176 | " \n", 177 | " \n", 178 | " \n", 179 | " \n", 180 | " \n", 181 | " \n", 182 | " \n", 183 | " \n", 184 | " \n", 185 | " \n", 186 | " \n", 187 | " \n", 188 | " \n", 189 | "
ycigwe
standard deviations0.0161980.0125340.0741440.0330720.0182620.014307
standard deviations relative to GDP1.0000000.7737924.5773192.0417231.1273940.883242
corrleations with GDP1.0000000.7708890.8372860.1552060.8624080.820931
autocorrelations0.8504910.8158010.7961250.9057750.8766540.918816
" 190 | ], 191 | "text/plain": [ 192 | "" 193 | ] 194 | }, 195 | "metadata": {}, 196 | "output_type": "display_data" 197 | } 198 | ], 199 | "source": [ 200 | "# read the data from an external csv file\n", 201 | "macrodata = pd.read_csv('DSGEtestdata.csv')\n", 202 | "\n", 203 | "# based on the data in the file calculate the natural logs of:\n", 204 | "y = np.log(macrodata.RGDP) # real GDP\n", 205 | "c = np.log(macrodata.RCON) # real consumption\n", 206 | "i = np.log(macrodata.RINV) # real inbestment\n", 207 | "g = np.log(macrodata.RGOV) # real government purchases\n", 208 | "w = np.log(macrodata.NWAGE/macrodata.DEFL) # real wage\n", 209 | "e = np.log(macrodata.EMP) # employment\n", 210 | "\n", 211 | "# stack this data into a single numpy matrix\n", 212 | "data = np.stack((y,c,i,g,w,e),axis=1)\n", 213 | "\n", 214 | "# assign names for the columns\n", 215 | "varnames = ['y','c','i','g','w','e']\n", 216 | "\n", 217 | "# find number of observations and variables\n", 218 | "(nobs, nvar) = data.shape\n", 219 | "\n", 220 | "# choose a filter to remove the trend\n", 221 | "filtertype = 'HP'\n", 222 | "\n", 223 | "import statsmodels.api as sm\n", 224 | "if filtertype == 'FD': # first-differences\n", 225 | " cyclical = data[1:nobs,:] - data[0:nobs-1,:]\n", 226 | "elif filtertype == 'HP': # Hodrick-Prescott\n", 227 | " cyclical, trend = sm.tsa.filters.hpfilter(data)\n", 228 | "elif filtertype == 'CF': # Christiano-Fitzgerald\n", 229 | " cyclical, trend = sm.tsa.filters.cffilter(data)\n", 230 | "elif filtertype == 'BK': # Baxter-King\n", 231 | " cyclical = sm.tsa.filters.bkfilter(data)\n", 232 | "\n", 233 | "# use calcmom to get the default moments\n", 234 | "moms, momnames = calcmom(cyclical)\n", 235 | "\n", 236 | "# put into a pandas data frame\n", 237 | "table = pd.DataFrame(moms, index = momnames, columns = varnames) \n", 238 | "\n", 239 | "# display on screen\n", 240 | "from IPython.display import display, HTML\n", 241 | "display(HTML(table.to_html()))\n", 242 | "\n", 243 | "# write to an external csv file\n", 244 | "table.to_csv('DSGEmoments.csv')" 245 | ] 246 | } 247 | ], 248 | "metadata": { 249 | "celltoolbar": "Raw Cell Format", 250 | "kernelspec": { 251 | "display_name": "Python 3", 252 | "language": "python", 253 | "name": "python3" 254 | }, 255 | "language_info": { 256 | "codemirror_mode": { 257 | "name": "ipython", 258 | "version": 3 259 | }, 260 | "file_extension": ".py", 261 | "mimetype": "text/x-python", 262 | "name": "python", 263 | "nbconvert_exporter": "python", 264 | "pygments_lexer": "ipython3", 265 | "version": "3.6.5" 266 | } 267 | }, 268 | "nbformat": 4, 269 | "nbformat_minor": 2 270 | } 271 | -------------------------------------------------------------------------------- /OLG_DSGE.idx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kerkphil/Jupyter_Notebooks/24e1f9b85a337c18a9a9ec179df398b42c9dcf41/OLG_DSGE.idx -------------------------------------------------------------------------------- /OLG_DSGE.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kerkphil/Jupyter_Notebooks/24e1f9b85a337c18a9a9ec179df398b42c9dcf41/OLG_DSGE.pdf -------------------------------------------------------------------------------- /OLG_DSGE.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Thu Jul 6 2017 5 | 6 | Updated on Fri May 18 2018 7 | 8 | @author: klp4 9 | 10 | This is a simple OLG model with S-period-lived agents and an aggregate shock 11 | to productivity. Agents have fixed labor supply and no retirement. 12 | 13 | This model is meant soley as a proof-of-concept and works with S=400, i.e. a 14 | quarterly time period. 15 | 16 | """ 17 | 18 | # Overlapping Generations Model 19 | import numpy as np 20 | import matplotlib.pyplot as plt 21 | 22 | # create a definitions function 23 | def Modeldefs(Xp, X, Z, params): 24 | ''' 25 | This function takes vectors of endogenous and exogenous state variables 26 | along with a vector of 'jump' variables and returns explicitly defined 27 | values for consumption, gdp, wages, real interest rates, and transfers 28 | 29 | Inputs are: 30 | Xp: value of capital holdings in next period 31 | X: value of capital holdings this period 32 | Z: value of productivity this period 33 | params: list of parameter values 34 | 35 | Output are: 36 | Y: GDP 37 | w: wage rate 38 | r: rental rate on capital 39 | T: transfer payments 40 | c: consumption 41 | u: utiity 42 | ''' 43 | 44 | # unpack input vectors 45 | kp = np.concatenate([Xp, np.zeros(1)]) 46 | k = np.concatenate([np.zeros(1), X]) 47 | z = Z 48 | 49 | # find definintion values 50 | K = np.sum(k) 51 | Y = K**alpha*(np.exp(z))**(1-alpha) 52 | w = (1-alpha)*Y 53 | r = alpha*Y/K 54 | T = tau*(w + (r - delta)*K) 55 | c = (1-tau)*(w + (r - delta)*k) + k + T - kp 56 | # check to make sure no consumptions are too low 57 | c = np.maximum(c, .0001*np.ones(S)) 58 | u = c**(1-gamma)/(1-gamma) 59 | 60 | return K, Y, w, r, T, c, u 61 | 62 | 63 | def Modeldyn(theta0, params): 64 | ''' 65 | This function takes vectors of endogenous and exogenous state variables 66 | along with a vector of 'jump' variables and returns values from the 67 | characterizing Euler equations. 68 | 69 | Inputs are: 70 | theta: a vector containng (Xpp, Xp, X, Yp, Y, Zp, Z) where: 71 | Xpp: value of capital in two periods 72 | Xp: value of capital in next period 73 | X: value of capital this period 74 | Yp: value of labor in next period 75 | Y: value of labor this period 76 | Zp: value of productivity in next period 77 | Z: value of productivity this period 78 | params: list of parameter values 79 | 80 | Output are: 81 | Euler: a vector of Euler equations written so that they are zero at the 82 | steady state values of X, Y & Z. This is a 2x1 numpy array. 83 | ''' 84 | 85 | # unpack theat0 86 | Xpp = theta0[0 : nx] 87 | Xp = theta0[nx : 2*nx] 88 | X = theta0[2*nx : 3*nx] 89 | Yp = theta0[3*nx : 3*nx + ny] 90 | Y = theta0[3*nx + ny : 3*nx + 2*ny] 91 | Zp = theta0[3*nx + 2*ny : 3*nx + 2*ny + nz] 92 | Z = theta0[3*nx + 2*ny+ nz : 3*nx + 2*ny + 2*nz] 93 | 94 | # find definitions for now and next period 95 | K, Y, w, r, T, c, u = Modeldefs(Xp, X, Z, params) 96 | Kp, Yp, wp, rp, Tp, cp, up = Modeldefs(Xpp, Xp, Zp, params) 97 | 98 | # truncate c vectors for intertemporal Euler equation 99 | c1 = c[0 : S-1] 100 | c1p = cp[1 : S] 101 | E = (c1**(-gamma)) / (beta*c1p**(-gamma)*(1 + (1-tau)*(rp - delta))) - 1. 102 | 103 | return E 104 | 105 | ''' 106 | Now the main program 107 | ''' 108 | # import the modules from LinApp 109 | from LinApp_FindSS import LinApp_FindSS 110 | from LinApp_Deriv import LinApp_Deriv 111 | from LinApp_Solve import LinApp_Solve 112 | from LinApp_SSL import LinApp_SSL 113 | 114 | # set parameter values 115 | S = 80 116 | alpha = .35 117 | beta = .99**(80/S) 118 | gamma = 2.5 119 | delta_ann = .08 120 | delta = 1. - (1. - delta_ann)**(80/S) 121 | tau = .05 122 | rho = .9**(80/S) 123 | sigma = .02 124 | 125 | # make parameter list to pass to functions 126 | params = (S, alpha, beta, gamma, delta, tau, rho, sigma) 127 | 128 | # set LinApp parameters 129 | Zbar = np.array([0.]) 130 | nx = S-1 131 | ny = 0 132 | nz = 1 133 | logX = 0 134 | Sylv = 0 135 | 136 | # take a guess for steady state values of k 137 | kguess = 0.001 138 | guessXY = kguess*np.ones(nx) 139 | 140 | # find the steady state values using LinApp_FindSS 141 | XYbar = LinApp_FindSS(Modeldyn, params, guessXY, Zbar, nx, ny) 142 | kbar = XYbar[0:nx] 143 | # print ('XYbar: ', XYbar) 144 | 145 | Kbar, Ybar, wbar, rbar, Tbar, cbar, ubar = Modeldefs(kbar, kbar, Zbar, params) 146 | Cbar = np.sum(cbar) 147 | 148 | plt.subplot(3, 1, 1) 149 | plt.plot(kbar) 150 | plt.xticks([]) 151 | plt.title('SS Capital by Age', y=.92) 152 | 153 | plt.subplot(3, 1, 2) 154 | plt.plot(cbar) 155 | plt.xticks([]) 156 | plt.title('SS Consumption by Age', y=.92) 157 | 158 | plt.subplot(3, 1, 3) 159 | plt.plot(ubar) 160 | plt.title('SS Utility by Age', y=.92) 161 | 162 | plt.show() 163 | 164 | 165 | # set up steady state input vector 166 | theta0 = np.concatenate([kbar, kbar, kbar, Zbar, Zbar]) 167 | 168 | # check SS solution 169 | check = Modeldyn(theta0, params) 170 | print ('check: ', np.max(np.abs(check))) 171 | if np.max(np.abs(check)) > 1.E-6: 172 | print ('Have NOT found steady state') 173 | 174 | # find the derivatives matrices 175 | [AA, BB, CC, DD, FF, GG, HH, JJ, KK, LL, MM] = \ 176 | LinApp_Deriv(Modeldyn, params, theta0, nx, ny, nz, logX) 177 | 178 | # set value for NN 179 | NN = rho 180 | 181 | # find the policy and jump function coefficients 182 | PP, QQ, RR, SS = \ 183 | LinApp_Solve(AA,BB,CC,DD,FF,GG,HH,JJ,KK,LL,MM,NN,Zbar,Sylv) 184 | #print ('P: ', PP) 185 | #print ('Q: ', QQ) 186 | #print ('R: ', RR) 187 | #print ('S: ', SS) 188 | 189 | 190 | # generate a history of Z's 191 | nobs = 250 192 | Zhist = np.zeros((nobs+1,1)) 193 | for t in range(1, nobs+1): 194 | Zhist[t,0] = rho*Zhist[t,0] + sigma*np.random.normal(0., 1.) 195 | 196 | # put SS values and starting values into numpy vectors 197 | XYbar = kbar 198 | X0 = kbar 199 | 200 | # simulate the model 201 | Xhist, Yhist = \ 202 | LinApp_SSL(X0, Zhist, XYbar, logX, PP, QQ, RR, SS) 203 | 204 | # generate non-state variables 205 | Khist = np.zeros(nobs) 206 | Yhist = np.zeros(nobs) 207 | whist = np.zeros(nobs) 208 | rhist = np.zeros(nobs) 209 | Thist = np.zeros(nobs) 210 | chist = np.zeros((nobs,S)) 211 | Chist = np.zeros(nobs) 212 | uhist = np.zeros((nobs,S)) 213 | 214 | for t in range(0, nobs): 215 | Khist[t], Yhist[t], whist[t], rhist[t], Thist[t], chist[t,:], uhist[t,:] \ 216 | = Modeldefs(Xhist[t+1,:], Xhist[t,:], Zhist[t,:], params) 217 | Chist[t] = np.sum(chist[t,:]) 218 | 219 | 220 | # plot 221 | plt.subplot(3, 2, 1) 222 | plt.plot(Khist) 223 | plt.xticks([]) 224 | plt.title('Capital', y=.92) 225 | 226 | plt.subplot(3, 2, 2) 227 | plt.plot(Yhist) 228 | plt.xticks([]) 229 | plt.title('GDP', y=.92) 230 | 231 | plt.subplot(3, 2, 3) 232 | plt.plot(whist) 233 | plt.xticks([]) 234 | plt.title('Wage', y=.92) 235 | 236 | plt.subplot(3, 2, 4) 237 | plt.plot(rhist) 238 | plt.xticks([]) 239 | plt.title('Interest', y=.92) 240 | 241 | plt.subplot(3, 2, 5) 242 | plt.plot(Thist) 243 | plt.title('Taxes', y=.92) 244 | 245 | plt.subplot(3, 2, 6) 246 | plt.plot(Chist) 247 | plt.title('Consumption', y=.92) 248 | 249 | plt.show() -------------------------------------------------------------------------------- /OLG_DSGE.tex: -------------------------------------------------------------------------------- 1 | \documentclass[letterpaper,12pt]{article} 2 | 3 | \usepackage{amsmath, amsfonts, amscd, amssymb, amsthm} 4 | \usepackage{graphicx} 5 | %\usepackage{import} 6 | \usepackage{versions} 7 | \usepackage{crop} 8 | \usepackage{multicol} 9 | \usepackage{graphicx} 10 | \usepackage{makeidx} 11 | \usepackage{hyperref} 12 | \usepackage{ifthen} 13 | \usepackage[format=hang,font=normalsize,labelfont=bf]{caption} 14 | \usepackage{natbib} 15 | \usepackage{setspace} 16 | \usepackage{placeins} 17 | \usepackage{framed} 18 | \usepackage{enumitem} 19 | \usepackage{threeparttable} 20 | \usepackage{geometry} 21 | \geometry{letterpaper,tmargin=1in,bmargin=1in,lmargin=1in,rmargin=1in} 22 | \usepackage{multirow} 23 | \usepackage[table]{xcolor} 24 | \usepackage{array} 25 | \usepackage{delarray} 26 | \usepackage{lscape} 27 | \usepackage{float,color, colortbl} 28 | %\usepackage[pdftex]{graphicx} 29 | \usepackage{hyperref} 30 | \usepackage{tabu} 31 | \usepackage{appendix} 32 | \usepackage{listings} 33 | 34 | 35 | \include{thmstyle} 36 | %\bibliographystyle{econometrica} 37 | \providecommand{\abs}[1]{\lvert#1\rvert} 38 | \providecommand{\norm}[1]{\lVert#1\rVert} 39 | \newcommand{\ve}{\varepsilon} 40 | \newcommand{\ip}[2]{\langle #1,#2 \rangle} 41 | 42 | \hypersetup{colorlinks,linkcolor=red,urlcolor=blue,citecolor=red} 43 | \theoremstyle{definition} 44 | \newtheorem{theorem}{Theorem} 45 | \newtheorem{acknowledgement}[theorem]{Acknowledgement} 46 | \newtheorem{algorithm}[theorem]{Algorithm} 47 | \newtheorem{axiom}[theorem]{Axiom} 48 | \newtheorem{case}[theorem]{Case} 49 | \newtheorem{claim}[theorem]{Claim} 50 | \newtheorem{conclusion}[theorem]{Conclusion} 51 | \newtheorem{condition}[theorem]{Condition} 52 | \newtheorem{conjecture}[theorem]{Conjecture} 53 | \newtheorem{corollary}[theorem]{Corollary} 54 | \newtheorem{criterion}[theorem]{Criterion} 55 | \newtheorem{definition}{Definition} % Number definitions on their own 56 | \newtheorem{derivation}{Derivation} % Number derivations on their own 57 | \newtheorem{example}[theorem]{Example} 58 | \newtheorem{exercise}[theorem]{Exercise} 59 | \newtheorem{lemma}[theorem]{Lemma} 60 | \newtheorem{notation}[theorem]{Notation} 61 | \newtheorem{problem}[theorem]{Problem} 62 | \newtheorem{proposition}{Proposition} % Number propositions on their own 63 | \newtheorem{remark}[theorem]{Remark} 64 | \newtheorem{solution}[theorem]{Solution} 65 | \newtheorem{summary}[theorem]{Summary} 66 | %\numberwithin{equation}{document} 67 | \graphicspath{{./Figures/}} 68 | \renewcommand\theenumi{\roman{enumi}} 69 | \DeclareMathOperator*{\argmin}{arg\,min} 70 | 71 | \crop 72 | \makeindex 73 | 74 | 75 | \begin{document} 76 | 77 | \begin{titlepage} 78 | \title{Interpreting an OLG Model in a DSGE Framework} 79 | \end{titlepage} 80 | 81 | \begin{spacing}{1.5} 82 | 83 | %section 1 84 | \section{A Simple DSGE Model}\label{Linear_LogLinApprox} 85 | This is a simple DSGE model with infinitely-lived agents. 86 | 87 | %subsection 1.1 88 | \subsection{Household's Problem} 89 | Households in this model hold capital ($k_t$) and an endowment of labor which is normalized by a choice of units to one. They earn a wage rate ($w_t$) payable on the portion of this labor endowment they choose to supply to the market, and generate utility with the remaining labor, which we can think of as leisure. They also earn a rental rate ($r_t$) on their capital, but lose a fraction ($\delta$) to depreciation. There is also a government in our version of the model, which is missing from Hansen's specification. The government taxes household income at a constant marginal rate ($\tau$) and refunds the proceeds lump-sum to the households in the form of a transfer ($T_t$). From this net income, households choose a consumption amount ($c_t$) and an amount of capital to carry over to the next period ($k_{t+1}$). 90 | 91 | The dynamic program for the households is 92 | \begin{equation}\label{VFHousehold} 93 | V(k_t;\theta_t) = \max_{k_{t+1}} u(c_t) + \beta E_t\{V(k_{t+1},\theta_{t+1})\} 94 | \end{equation} 95 | \begin{equation}\label{BCHousehold} 96 | \text{s.t. } (1-\tau) \left[w_t+(r_t-\delta)k_t\right] + k_t + T_t = c_t+k_{t+1} 97 | \end{equation} 98 | 99 | We can dispense with the Lagrangian if we rewrite \eqref{BCHousehold} as 100 | \begin{equation}\label{ConsDef} 101 | c_t = (1-\tau) \left[w_t+(r_t-\delta)k_t\right] + k_t + T_t-k_{t+1} 102 | \end{equation} 103 | and substitute it into the utility function of \eqref{VFHousehold}. 104 | 105 | The first order conditon from the problem is: 106 | \begin{equation}\label{FOC2Household} 107 | -u_c(c_t) + \beta E_t\{V_k(k_{t+1},\theta_{t+1})\} = 0 108 | \end{equation} 109 | 110 | The envelope condition is : 111 | \begin{equation}\label{EnvHousehold} 112 | V_k(k_t;\theta_t) = u_c(c_t)[(r_t-\delta)(1-\tau)+1] 113 | \end{equation} 114 | 115 | Combining \eqref{FOC2Household} and \eqref{EnvHousehold} and rearranging terms gives us the intertemporal Euler equation. 116 | \begin{equation}\label{Euler2Household} 117 | u_c(c_t) = \beta E_t\left\{ u_c(c_{t+1})[(r_{t+1}-\delta)(1-\tau)+1] \right\} 118 | \end{equation} 119 | 120 | %subsection 1.2 121 | \subsection{Firm's Problem} 122 | A unit measure of firms arises spontaneously each period. Each firm rents capital and labor services from households. The objective is to maximize profits as shown. 123 | \begin{equation} 124 | \max_{K_t,L_t} \Pi_t = f(K_t,L_t,z_t) - W_tL_t-R_tK_t \nonumber 125 | \end{equation} 126 | where $K_t$ and $L_t$ are capital and labor hired, $R_t$ and $W_t$ are the factor prices, and $f(.)$ is the production function. 127 | 128 | It yields the following first-order conditions: 129 | \begin{equation} 130 | R_t = f_K(K_t,L_t,z_t) 131 | \end{equation} 132 | \begin{equation} 133 | W_t = f_L(K_t,L_t,z_t) 134 | \end{equation} 135 | 136 | %subsection 1.3 137 | \subsection{Government} 138 | The government collects distortionary taxes and refunds these to the households lump-sum: 139 | \begin{equation}\label{GovtBC2Firm} 140 | \tau \left[w_t\ell_t+(r_t-\delta)k_t\right] = T_t 141 | \end{equation} 142 | 143 | %subsection 1.4 144 | \subsection{Adding-Up and Market Clearing} 145 | Market clearing is: 146 | \begin{equation}\label{LAdd} 147 | 1 = L_t 148 | \end{equation} 149 | \begin{equation}\label{KAdd} 150 | k_t = K_t 151 | \end{equation} 152 | 153 | Price equivalences are: 154 | \begin{equation}\label{WAdd} 155 | w_t = W_t 156 | \end{equation} 157 | \begin{equation}\label{RAdd} 158 | r_t = R_t 159 | \end{equation} 160 | 161 | %subsection 1.5 162 | \subsection{Exogenous Laws of Motion} 163 | The stochastic process for the technology is shown below. 164 | \begin{equation}\label{LoM} 165 | z_t = (1-\rho_z)\bar z + \rho_z z_{t-1}+ \epsilon^z_t ;\quad \epsilon^z_t\sim\text{i.i.d.}(0,\sigma_z^2) 166 | \end{equation} 167 | 168 | %subsection 1.6 169 | \subsection{The Equilibrium} 170 | The dynamic equilibrium for the model is defined by \eqref{ConsDef} and \eqref{Euler2Household} -- \eqref{LoM}, a system of eleven equations in eleven unknowns. We can simplify this, however, by using \eqref{WAdd} and \eqref{RAdd} as definitions to eliminate the variables $W_t$ and $R_t$. Similarly, \eqref{LAdd} and \eqref{KAdd} eliminate $L_t$ and $K_t$. This leaves us with seven equations in seven unknowns, $\{c_t,k_t,\ell_t,w_t,r_t,T_t\>\&\>z_t\}$. The equations are: 171 | 172 | \begin{equation}\label{BC22Household} 173 | c_t = (1-\tau) \left[w_t\ell_t+(r_t-\delta)k_t\right] + k_t + T_t-k_{t+1} 174 | \end{equation} 175 | \begin{equation}\label{Euler22Household} 176 | u_c(c_t) = \beta E_t\left\{ u_c(c_{t+1})[(r_{t+1}-\delta)(1-\tau)+1] \right\} 177 | \end{equation} 178 | \begin{equation}\label{FOC012Firm} 179 | r_t = f_K(k_t,z_t) 180 | \end{equation} 181 | \begin{equation}\label{FOC022Firm} 182 | w_t = f_L(k_t,z_t) 183 | \end{equation} 184 | \begin{equation}\label{GovtTaxes} 185 | \tau \left[w_t+(r_t-\delta)k_t\right] = T_t 186 | \end{equation} 187 | \begin{equation}\label{LoM2} 188 | z_t = \rho_z z_{t-1}+ \epsilon^z_t ;\quad \epsilon^z_t\sim\text{i.i.d.}(0,\sigma_z^2) 189 | \end{equation} 190 | 191 | \subsection{Functional Forms} 192 | We use the following functional form: 193 | \begin{align} 194 | u(c_t) & = \tfrac{1}{1-\sigma}(c_t^{1-\sigma} -1 ) \\ 195 | f(K_t,L_t,z_t) & = K_t^\alpha \left( e^{z_t} L_t \right)^{1-\alpha} 196 | \end{align} 197 | 198 | \subsection{Putting Our Model in a More General Notation} 199 | 200 | The state of the economy is defined by $z_t$ and $k_{t-1}$. All other variables are jump variables. This gives us the following classifications: 201 | \begin{equation}\label{XYZ} 202 | \begin{split} 203 | X_t & = \left[k_{t-1}\right] \\ 204 | Y_t & = \emptyset \\ 205 | Z_t & = \left[z_t\right] \\ 206 | D_t & = \left\{c_t,w_t,r_t,T_t\right\} 207 | \end{split} 208 | \end{equation} 209 | 210 | Here $X_t$ is a vecetor of endogenous state variables, and $Z_t$ is a vector exogenous state variables. $D_t$ is a set of non-state variables for which closed-form solutions can be found defining them as functions of $X_t$ and $Z_t$. $Y_t$ is a vector of non-state variables which are only implicity defined as functions of the state variables. 211 | 212 | Equation \eqref{Euler22Household} can be written as: 213 | \begin{equation}\label{GammaEqn} 214 | E_t\left\{\Gamma\{X_{t+2},X_{t+1},X_{t},Y_{t+1},Y_{t},Z_{t+1},Z_{t}\} \right\}= 0 215 | \end{equation} 216 | 217 | And the law of motion in equation \eqref{LoM2} can be written as: 218 | \begin{equation}\label{Zlom} 219 | Z_{t} = N Z_{t-1}+ E_t ;\quad E_t\sim\text{i.i.d.}(0,\Sigma^2) 220 | \end{equation} 221 | 222 | Our goal is the policy function: 223 | \begin{equation}\label{HEqn} 224 | X_{t+1} = H (X_t,Z_t) 225 | \end{equation} 226 | and the ``jump'' function 227 | \begin{equation}\label{GEqn} 228 | Y_{t} = G (X_t,Z_t) 229 | \end{equation} 230 | 231 | \section{Linearization} 232 | We can take the Taylor-series expansion of equation \eqref{GammaEqn} about the values $\bar X, \bar Y$ and $\bar Z$. Denoting the deviation away from these steady state values with a tilde, so that $\tilde x_t \equiv x_t - \bar x$ this gives: 233 | \begin{align} 234 | & A \tilde X_{t+1} + B \tilde X_t + C \tilde Y_t + D \tilde Z_t = 0 \\ 235 | & E_t\left\{ F \tilde X_{t+2} + G \tilde X_{t+1} + H \tilde X_{t} + J \tilde Y_{t+1} + K \tilde Y_{t} + L \tilde Z_{t+1} + M \tilde Z_{t} \right\} = 0 236 | \end{align} 237 | 238 | These equations along with \eqref{Zlom} can be solved using the methods laid out in Uhlig(1991) for the following linear approximations to \eqref{HEqn} and \eqref{GEqn}. 239 | \begin{align} 240 | \tilde X_{t+1} & = P \tilde X_{t} + Q \tilde Z_{t} \\ 241 | \tilde Y_{t} & = R \tilde X_{t} + S \tilde Z_{t} 242 | \end{align} 243 | 244 | The LinApp toolkit available at https://github.com/kerkphil/DSGE-Utilities implement this solution. 245 | 246 | 247 | 248 | \section{An Overlapping Generations Model} 249 | This model differs from the simple DSGE model above only in its specification of households. 250 | 251 | Now we index households by age, denoted with an $s$ subscript. The typical household problem can be written as: 252 | \begin{equation}\label{VFHouseholdSpecOLG} 253 | V_s(k_{st};\theta_t) = \max_{k_{s+1,t+1}} u(c_{st}) + \beta E_t\{V_{s+1}(k_{s+1,t+1},\theta_{t+1})\} 254 | \end{equation} 255 | \begin{equation}\label{BCHouseholdSpecOLG} 256 | \text{s.t. } (1-\tau) \left[w_t\ell_{s}+(r_t-\delta)k_{st}\right] + k_{st} + T_{st} = c_{st}+k_{s+1,t+1} 257 | \end{equation} 258 | 259 | The first-order conditon from the problem is: 260 | \begin{equation}\label{FOC2HouseholdSpecOLG} 261 | -u_c(c_{st}) + \beta E_t\{V_{sk}(k_{s+1,t+1},\theta_{t+1})\} = 0 262 | \end{equation} 263 | 264 | The envelope condition is : 265 | \begin{equation}\label{EnvHouseholdSpecOLG} 266 | V_{sk}(k_{st};\theta_t) = u_c(c_{st})[(r_t-\delta)(1-\tau)+1] 267 | \end{equation} 268 | 269 | Combining \eqref{FOC2HouseholdSpecOLG} and \eqref{EnvHouseholdSpecOLG} and rearranging terms gives us the intertemporal Euler equation. 270 | \begin{equation}\label{Euler2HouseholdSpecOLG} 271 | u_c(c_{st}) = \beta E_t\left\{ u_c(c_{s+1,t+1})[(r_{t+1}-\delta)(1-\tau)+1] \right\} 272 | \end{equation} 273 | 274 | We can combine the various verisions of equations \eqref{Euler2HouseholdSpecOLG} by defining the following vectors: 275 | \begin{align} 276 | \mathbf{c}_t & \equiv \begin{bmatrix} c_{1t} & c_{2t} & \dots & c_{S-1,t} & c_{St} \end{bmatrix}^{'} \\ 277 | \mathbf{c}^-_t & \equiv \begin{bmatrix} c_{1t} & c_{2t} & \dots & c_{S-1,t} \end{bmatrix}^{'} \\ 278 | \mathbf{c}^+_t & \equiv \begin{bmatrix} c_{2t} & \dots & c_{S-1,t} & c_{St} \end{bmatrix}^{'} \\ 279 | \mathbf{k}_t & \equiv \begin{bmatrix} k_{2t} & \dots & k_{S-1,t} & k_{St} \end{bmatrix}^{'} \\ 280 | \mathbf{k}^-_t & \equiv \begin{bmatrix} 0 & k_{2t} & \dots & k_{S-1,t} & k_{St} \end{bmatrix}^{'} \\ 281 | \mathbf{k}^+_t & \equiv \begin{bmatrix} k_{2t} & \dots & k_{S-1,t} & k_{St} & 0 \end{bmatrix}^{'} \\ 282 | \mathbf{T}_t & \equiv \begin{bmatrix} T_{1t} & T_{2t} & \dots & T_{S-1,t} & T_{St} \end{bmatrix}^{'} \\ 283 | \mathbf{l} & \equiv \begin{bmatrix} \ell_{1} & \ell_{2} & \dots & \ell_{S-1} & \ell_{S} \end{bmatrix}^{'} 284 | \end{align} 285 | 286 | The Euler equation now can be written as: 287 | \begin{align} 288 | \mathbf{U}_c(\mathbf{c}^-_{t}) & = \beta E_t\left\{ \mathbf{u}_c(\mathbf{c}^+_{t+1})[(r_{t+1}-\delta)(1-\tau)+1] \right\} 289 | \end{align} 290 | 291 | The budget constraints can be written as: 292 | \begin{equation} 293 | (1-\tau) \left[w_t \mathbf{l}_{t}+(r_t-\delta)\mathbf{k}^-_{t}\right] + \mathbf{k}^-_{t} + \mathbf{T}_{t} = \mathbf{c}_{t}+\mathbf{k}^+_{t+1} 294 | \end{equation} 295 | 296 | We retain the following equations from the firms and government. 297 | \begin{align} 298 | r_t & = f_K(K_t,L_t,z_t) \\ 299 | w_t & = f_L(K_t,L_t,z_t) 300 | \end{align} 301 | 302 | The government's buget constraint becomes 303 | \begin{equation} 304 | \mathbf{1}_{1 \times S} \tau \left[w_t \mathbf{L}_t+(r_t-\delta)\mathbf{k}^-_t\right] = \mathbf{1}_{1 \times S} \mathbf{T}_t 305 | \end{equation} 306 | 307 | And market clearing conditions are: 308 | \begin{align} 309 | \mathbf{1}_{1 \times (S-1)} \mathbf{k}^-_t = K_t \\ 310 | \mathbf{1}_{1 \times S} \mathbf{l} = L 311 | \end{align} 312 | 313 | Finally, we also need an allocation rule for the lump-sum transfers across ages. A simple one would be to make the same transfer to each age cohort so that: 314 | \begin{equation} 315 | \mathbf{T}_t = \tfrac{1}{S} \mathbf{1}_{S \times 1} T_t 316 | \end{equation} 317 | 318 | This system can be solved and simulated the same as the infintinely-lived-agent DSGE model with the following mappings. 319 | 320 | \begin{equation}\label{XYZolg} 321 | \begin{split} 322 | X_t & = \left[\mathbf{k}_{t-1}\right] \\ 323 | Y_t & = \emptyset \\ 324 | Z_t & = \left[z_t\right] \\ 325 | D_t & = \left\{\mathbf{c}_t,w_t,r_t,T_t\right\} 326 | \end{split} 327 | \end{equation} 328 | 329 | 330 | \end{spacing} 331 | {} 332 | \newpage 333 | {} 334 | \bibliography{BootCampText} 335 | 336 | \end{document} -------------------------------------------------------------------------------- /rouwen.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def rouwen(rho, mu, step, num): 5 | ''' 6 | Adapted from Lu Zhang and Karen Kopecky. Python by Ben Tengelsen. 7 | Construct transition probability matrix for discretizing an AR(1) 8 | process. This procedure is from Rouwenhorst (1995), which works 9 | well for very persistent processes. 10 | 11 | INPUTS: 12 | rho - persistence (close to one) 13 | mu - mean and the middle point of the discrete state space 14 | step - step size of the even-spaced grid 15 | num - number of grid points on the discretized process 16 | 17 | OUTPUT: 18 | dscSp - discrete state space (num by 1 vector) 19 | transP - transition probability matrix over the grid 20 | ''' 21 | 22 | # discrete state space 23 | dscSp = np.linspace(mu -(num-1)/2*step, mu +(num-1)/2*step, num).T 24 | 25 | # transition probability matrix 26 | q = p = (rho + 1)/2. 27 | transP = np.array([[p**2, p*(1-q), (1-q)**2], \ 28 | [2*p*(1-p), p*q+(1-p)*(1-q), 2*q*(1-q)], \ 29 | [(1-p)**2, (1-p)*q, q**2]]).T 30 | 31 | 32 | while transP.shape[0] <= num - 1: 33 | 34 | # see Rouwenhorst 1995 35 | len_P = transP.shape[0] 36 | transP = p * np.vstack((np.hstack((transP, np.zeros((len_P, 1)))), np.zeros((1, len_P+1)))) \ 37 | + (1 - p) * np.vstack((np.hstack((np.zeros((len_P, 1)), transP)), np.zeros((1, len_P+1)))) \ 38 | + (1 - q) * np.vstack((np.zeros((1, len_P+1)), np.hstack((transP, np.zeros((len_P, 1)))))) \ 39 | + q * np.vstack((np.zeros((1, len_P+1)), np.hstack((np.zeros((len_P, 1)), transP)))) 40 | 41 | transP[1:-1] /= 2. 42 | 43 | 44 | # ensure columns sum to 1 45 | if np.max(np.abs(np.sum(transP, axis=1) - np.ones(transP.shape))) >= 1e-12: 46 | print('Problem in rouwen routine!') 47 | return None 48 | else: 49 | return transP.T, dscSp --------------------------------------------------------------------------------