{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "
\n", " \n", " \"QuantEcon\"\n", " \n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Additive Functionals\n", "\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Contents\n", "\n", "- [Additive Functionals](#Additive-Functionals) \n", " - [Overview](#Overview) \n", " - [A Particular Additive Functional](#A-Particular-Additive-Functional) \n", " - [Dynamics](#Dynamics) \n", " - [Code](#Code) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Co-authored with Chase Coleman and Balint Szoke" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Overview\n", "\n", "Some time series are nonstationary\n", "\n", "For example, output, prices, and dividends are typically nonstationary, due to irregular but persistent growth\n", "\n", "Which kinds of models are useful for studying such time series?\n", "\n", "Hansen and Scheinkman [[HS09]](zreferences.ipynb#hans-scheink-2009) analyze two classes of time series models that accommodate growth\n", "\n", "They are:\n", "\n", "1. **additive functionals** that display random “arithmetic growth” \n", "1. **multiplicative functionals** that display random “geometric growth” \n", "\n", "\n", "These two classes of processes are closely connected\n", "\n", "For example, if a process $ \\{y_t\\} $ is an additive functional and $ \\phi_t = \\exp(y_t) $, then $ \\{\\phi_t\\} $ is a multiplicative functional\n", "\n", "Hansen and Sargent [[HS17]](zreferences.ipynb#hans-sarg-book-2016) (chs. 5 and 6) describe discrete time versions of additive and multiplicative functionals\n", "\n", "In this lecture we discuss the former (i.e., additive functionals)\n", "\n", "In the [next lecture](multiplicative_functionals.ipynb) we discuss multiplicative functionals\n", "\n", "We also consider fruitful decompositions of additive and multiplicative processes, a more in depth discussion of which can be found in Hansen and Sargent [[HS17]](zreferences.ipynb#hans-sarg-book-2016)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## A Particular Additive Functional\n", "\n", "This lecture focuses on a particular type of additive functional: a scalar process $ \\{y_t\\}_{t=0}^\\infty $ whose increments are driven by a Gaussian vector autoregression\n", "\n", "It is simple to construct, simulate, and analyze\n", "\n", "This additive functional consists of two components, the first of which is a **first-order vector autoregression** (VAR)\n", "\n", "\n", "\n", "$$\n", "x_{t+1} = A x_t + B z_{t+1} \\tag{1}\n", "$$\n", "\n", "Here\n", "\n", "- $ x_t $ is an $ n \\times 1 $ vector, \n", "- $ A $ is an $ n \\times n $ stable matrix (all eigenvalues lie within the open unit circle), \n", "- $ z_{t+1} \\sim {\\cal N}(0,I) $ is an $ m \\times 1 $ i.i.d. shock, \n", "- $ B $ is an $ n \\times m $ matrix, and \n", "- $ x_0 \\sim {\\cal N}(\\mu_0, \\Sigma_0) $ is a random initial condition for $ x $ \n", "\n", "\n", "The second component is an equation that expresses increments\n", "of $ \\{y_t\\}_{t=0}^\\infty $ as linear functions of\n", "\n", "- a scalar constant $ \\nu $, \n", "- the vector $ x_t $, and \n", "- the same Gaussian vector $ z_{t+1} $ that appears in the VAR [(1)](#equation-old1-additive-functionals) \n", "\n", "\n", "In particular,\n", "\n", "\n", "\n", "$$\n", "y_{t+1} - y_{t} = \\nu + D x_{t} + F z_{t+1} \\tag{2}\n", "$$\n", "\n", "Here $ y_0 \\sim {\\cal N}(\\mu_{y0}, \\Sigma_{y0}) $ is a random\n", "initial condition\n", "\n", "The nonstationary random process $ \\{y_t\\}_{t=0}^\\infty $ displays\n", "systematic but random *arithmetic growth*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### A linear state space representation\n", "\n", "One way to represent the overall dynamics is to use a [linear state space system](tools_and_techniques/linear_models.ipynb)\n", "\n", "To do this, we set up state and observation vectors\n", "\n", "$$\n", "\\hat{x}_t = \\begin{bmatrix} 1 \\\\ x_t \\\\ y_t \\end{bmatrix}\n", "\\quad \\text{and} \\quad\n", "\\hat{y}_t = \\begin{bmatrix} x_t \\\\ y_t \\end{bmatrix}\n", "$$\n", "\n", "Now we construct the state space system\n", "\n", "$$\n", "\\begin{bmatrix}\n", " 1 \\\\\n", " x_{t+1} \\\\\n", " y_{t+1}\n", " \\end{bmatrix}\n", " =\n", " \\begin{bmatrix}\n", " 1 & 0 & 0 \\\\\n", " 0 & A & 0 \\\\\n", " \\nu & D' & 1 \\\\\n", "\\end{bmatrix}\n", "\\begin{bmatrix}\n", " 1 \\\\\n", " x_t \\\\\n", " y_t\n", "\\end{bmatrix} +\n", "\\begin{bmatrix}\n", " 0 \\\\ B \\\\ F'\n", "\\end{bmatrix}\n", "z_{t+1}\n", "$$\n", "\n", "$$\n", "\\begin{bmatrix}\n", " x_t \\\\\n", " y_t\n", "\\end{bmatrix}\n", "= \\begin{bmatrix}\n", " 0 & I & 0 \\\\\n", " 0 & 0 & 1\n", "\\end{bmatrix}\n", "\\begin{bmatrix}\n", " 1 \\\\ x_t \\\\ y_t\n", "\\end{bmatrix}\n", "$$\n", "\n", "This can be written as\n", "\n", "$$\n", "\\begin{aligned}\n", " \\hat{x}_{t+1} &= \\hat{A} \\hat{x}_t + \\hat{B} z_{t+1} \\\\\n", " \\hat{y}_{t} &= \\hat{D} \\hat{x}_t\n", "\\end{aligned}\n", "$$\n", "\n", "which is a standard linear state space system\n", "\n", "To study it, we could map it into an instance of [LSS](https://github.com/QuantEcon/QuantEcon.jl/blob/master/src/lss.jl) from [QuantEcon.jl](http://quantecon.org/julia_index.html)\n", "\n", "We will in fact use a different set of code for simulation, for reasons described below" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Dynamics\n", "\n", "Let’s run some simulations to build intuition\n", "\n", "\n", "\n", "In doing so we’ll assume that $ z_{t+1} $ is scalar and that $ \\tilde x_t $ follows a 4th-order scalar autoregession\n", "\n", "\n", "\n", "$$\n", "\\tilde x_{t+1} = \\phi_1 \\tilde x_{t} + \\phi_2 \\tilde x_{t-1} +\n", "\\phi_3 \\tilde x_{t-2} +\n", "\\phi_4 \\tilde x_{t-3} + \\sigma z_{t+1} \\tag{3}\n", "$$\n", "\n", "Let the increment in $ \\{y_t\\} $ obey\n", "\n", "$$\n", "y_{t+1} - y_t = \\nu + \\tilde x_t + \\sigma z_{t+1}\n", "$$\n", "\n", "with an initial condition for $ y_0 $\n", "\n", "While [(3)](#equation-ftaf) is not a first order system like [(1)](#equation-old1-additive-functionals), we know that it can be mapped into a first order system\n", "\n", "- for an example of such a mapping, see [this example](tools_and_techniques/linear_models.ipynb#lss-sode) \n", "\n", "\n", "In fact this whole model can be mapped into the additive functional system definition in [(1)](#equation-old1-additive-functionals) – [(2)](#equation-old2-additive-functionals) by appropriate selection of the matrices $ A, B, D, F $\n", "\n", "You can try writing these matrices down now as an exercise — the correct expressions will appear in the code below" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Simulation\n", "\n", "When simulating we embed our variables into a bigger system\n", "\n", "This system also constructs the components of the decompositions of $ y_t $ and of $ \\exp(y_t) $ proposed by Hansen and Scheinkman [[HS09]](zreferences.ipynb#hans-scheink-2009)\n", "\n", "All of these objects are computed using the code below" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Setup" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide-output": true }, "outputs": [], "source": [ "using InstantiateFromURL\n", "github_project(\"QuantEcon/quantecon-notebooks-julia\", version = \"0.2.0\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide-output": false }, "outputs": [], "source": [ "using LinearAlgebra, Statistics, Compat" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide-output": false }, "outputs": [], "source": [ "using Distributions, Parameters, Plots, QuantEcon\n", "gr(fmt = :png);" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide-output": false }, "outputs": [], "source": [ "function AMF_LSS_VAR(A, B, D, F = nothing; ν = nothing)\n", "\n", " if B isa AbstractVector\n", " B = reshape(B, length(B), 1)\n", " end\n", " # unpack required elements\n", " nx, nk = size(B)\n", "\n", " # checking the dimension of D (extended from the scalar case)\n", " if ndims(D) > 1\n", " nm = size(D, 1)\n", " if D isa Union{Adjoint, Transpose}\n", " D = convert(Matrix, D)\n", " end\n", " else\n", " nm = 1\n", " D = reshape(D, 1, length(D))\n", " end\n", "\n", " # set F\n", " if isnothing(F)\n", " F = zeros(nk, 1)\n", " elseif ndims(F) == 1\n", " F = reshape(F, length(F), 1)\n", " end\n", "\n", " # set ν\n", " if isnothing(ν)\n", " ν = zeros(nm, 1)\n", " elseif ndims(ν) == 1\n", " ν = reshape(ν, length(ν), 1)\n", " else\n", " throw(ArgumentError(\"ν must be column vector!\"))\n", " end\n", "\n", " if size(ν, 1) != size(D, 1)\n", " error(\"The size of ν is inconsistent with D!\")\n", " end\n", "\n", " # construct BIG state space representation\n", " lss = construct_ss(A, B, D, F, ν, nx, nk, nm)\n", "\n", " return (A = A, B = B, D = D, F = F, ν = ν, nx = nx, nk = nk, nm = nm, lss = lss)\n", "end\n", "\n", "AMF_LSS_VAR(A, B, D) =\n", " AMF_LSS_VAR(A, B, D, nothing, ν=nothing)\n", "AMF_LSS_VAR(A, B, D, F, ν) =\n", " AMF_LSS_VAR(A, B, D, [F], ν=[ν])\n", "\n", "function construct_ss(A, B, D, F,\n", " ν, nx, nk, nm)\n", "\n", " H, g = additive_decomp(A, B, D, F, nx)\n", "\n", " # auxiliary blocks with 0's and 1's to fill out the lss matrices\n", " nx0c = zeros(nx, 1)\n", " nx0r = zeros(1, nx)\n", " nx1 = ones(1, nx)\n", " nk0 = zeros(1, nk)\n", " ny0c = zeros(nm, 1)\n", " ny0r = zeros(1, nm)\n", " ny1m = I + zeros(nm, nm)\n", " ny0m = zeros(nm, nm)\n", " nyx0m = similar(D)\n", "\n", " # build A matrix for LSS\n", " # order of states is: [1, t, xt, yt, mt]\n", " A1 = hcat(1, 0, nx0r, ny0r, ny0r) # transition for 1\n", " A2 = hcat(1, 1, nx0r, ny0r, ny0r) # transition for t\n", " A3 = hcat(nx0c, nx0c, A, nyx0m', nyx0m') # transition for x_{t+1}\n", " A4 = hcat(ν, ny0c, D, ny1m, ny0m) # transition for y_{t+1}\n", " A5 = hcat(ny0c, ny0c, nyx0m, ny0m, ny1m) # transition for m_{t+1}\n", " Abar = vcat(A1, A2, A3, A4, A5)\n", "\n", " # build B matrix for LSS\n", " Bbar = vcat(nk0, nk0, B, F, H)\n", "\n", " # build G matrix for LSS\n", " # order of observation is: [xt, yt, mt, st, tt]\n", " G1 = hcat(nx0c, nx0c, I, nyx0m', nyx0m') # selector for x_{t}\n", " G2 = hcat(ny0c, ny0c, nyx0m, ny1m, ny0m) # selector for y_{t}\n", " G3 = hcat(ny0c, ny0c, nyx0m, ny0m, ny1m) # selector for martingale\n", " G4 = hcat(ny0c, ny0c, -g, ny0m, ny0m) # selector for stationary\n", " G5 = hcat(ny0c, ν, nyx0m, ny0m, ny0m) # selector for trend\n", " Gbar = vcat(G1, G2, G3, G4, G5)\n", "\n", " # build LSS type\n", " x0 = hcat(1, 0, nx0r, ny0r, ny0r)\n", " S0 = zeros(length(x0), length(x0))\n", " lss = LSS(Abar, Bbar, Gbar, zeros(nx+4nm, 1), x0, S0)\n", "\n", " return lss\n", "end\n", "\n", "function additive_decomp(A, B, D, F, nx)\n", " A_res = \\(I - A, I)\n", " g = D * A_res\n", " H = F .+ D * A_res * B\n", "\n", " return H, g\n", "end\n", "\n", "function multiplicative_decomp(A, B, D, F, ν, nx)\n", " H, g = additive_decomp(A, B, D, F, nx)\n", " ν_tilde = ν .+ 0.5 * diag(H * H')\n", "\n", " return H, g, ν_tilde\n", "end\n", "\n", "function loglikelihood_path(amf, x, y)\n", " @unpack A, B, D, F = amf\n", " k, T = size(y)\n", " FF = F * F'\n", " FFinv = inv(FF)\n", " temp = y[:, 2:end]-y[:, 1:end-1] - D*x[:, 1:end-1]\n", " obs = temp .* FFinv .* temp\n", " obssum = cumsum(obs)\n", " scalar = (logdet(FF) + k * log(2π)) * (1:T)\n", "\n", " return -(obssum + scalar) / 2\n", "end\n", "\n", "function loglikelihood(amf, x, y)\n", " llh = loglikelihood_path(amf, x, y)\n", "\n", " return llh[end]\n", "end\n", "\n", "function plot_additive(amf, T; npaths = 25, show_trend = true)\n", "\n", " # pull out right sizes so we know how to increment\n", " @unpack nx, nk, nm = amf\n", "\n", " # allocate space (nm is the number of additive functionals - we want npaths for each)\n", " mpath = zeros(nm*npaths, T)\n", " mbounds = zeros(2nm, T)\n", " spath = zeros(nm*npaths, T)\n", " sbounds = zeros(2nm, T)\n", " tpath = zeros(nm*npaths, T)\n", " ypath = zeros(nm*npaths, T)\n", "\n", " # simulate for as long as we wanted\n", " moment_generator = moment_sequence(amf.lss)\n", "\n", " # pull out population moments\n", " for (t, x) in enumerate(moment_generator)\n", " ymeans = x[2]\n", " yvar = x[4]\n", "\n", " # lower and upper bounds - for each additive functional\n", " for ii in 1:nm\n", " li, ui = 2(ii - 1) + 1, 2ii\n", " if sqrt(yvar[nx + nm + ii, nx + nm + ii]) != 0.0\n", " madd_dist = Normal(ymeans[nx + nm + ii], sqrt(yvar[nx + nm + ii, nx + nm + ii]))\n", " mbounds[li, t] = quantile(madd_dist, 0.01)\n", " mbounds[ui, t] = quantile(madd_dist, 0.99)\n", " elseif sqrt(yvar[nx + nm + ii, nx + nm + ii]) == 0.0\n", " mbounds[li, t] = ymeans[nx + nm + ii]\n", " mbounds[ui, t] = ymeans[nx + nm + ii]\n", " else\n", " error(\"standard error is negative\")\n", " end\n", "\n", " if sqrt(yvar[nx + 2nm + ii, nx + 2nm + ii]) != 0.0\n", " sadd_dist = Normal(ymeans[nx + 2nm + ii], sqrt(yvar[nx + 2nm + ii, nx + 2nm + ii]))\n", " sbounds[li, t] = quantile(sadd_dist, 0.01)\n", " sbounds[ui, t] = quantile(sadd_dist, 0.99)\n", " elseif sqrt(yvar[nx + 2nm + ii, nx + 2nm + ii]) == 0.0\n", " sbounds[li, t] = ymeans[nx + 2nm + ii]\n", " sbounds[ui, t] = ymeans[nx + 2nm + ii]\n", " else\n", " error(\"standard error is negative\")\n", " end\n", " end\n", " t == T && break\n", " end\n", "\n", " # pull out paths\n", " for n in 1:npaths\n", " x, y = simulate(amf.lss,T)\n", " for ii in 0:nm - 1\n", " ypath[npaths * ii + n, :] = y[nx + ii + 1, :]\n", " mpath[npaths * ii + n, :] = y[nx + nm + ii + 1, :]\n", " spath[npaths * ii + n, :] = y[nx + 2nm + ii + 1, :]\n", " tpath[npaths * ii + n, :] = y[nx + 3nm + ii + 1, :]\n", " end\n", " end\n", "\n", " add_figs = []\n", "\n", " for ii in 0:nm-1\n", " li, ui = npaths*(ii), npaths*(ii + 1)\n", " LI, UI = 2ii, 2(ii + 1)\n", " push!(add_figs,\n", " plot_given_paths(T, ypath[li + 1:ui, :], mpath[li + 1:ui, :], spath[li + 1:ui, :],\n", " tpath[li + 1:ui, :], mbounds[LI + 1:UI, :], sbounds[LI + 1:UI, :],\n", " show_trend = show_trend))\n", " end\n", " return add_figs\n", "end\n", "\n", "function plot_multiplicative(amf, T, npaths = 25, show_trend = true)\n", " # pull out right sizes so we know how to increment\n", " @unpack nx, nk, nm = amf\n", " # matrices for the multiplicative decomposition\n", " H, g, ν_tilde = multiplicative_decomp(A, B, D, F, ν, nx)\n", "\n", " # allocate space (nm is the number of functionals - we want npaths for each)\n", " mpath_mult = zeros(nm * npaths, T)\n", " mbounds_mult = zeros(2nm, T)\n", " spath_mult = zeros(nm * npaths, T)\n", " sbounds_mult = zeros(2nm, T)\n", " tpath_mult = zeros(nm * npaths, T)\n", " ypath_mult = zeros(nm * npaths, T)\n", "\n", " # simulate for as long as we wanted\n", " moment_generator = moment_sequence(amf.lss)\n", "\n", " # pull out population moments\n", " for (t, x) in enumerate(moment_generator)\n", " ymeans = x[2]\n", " yvar = x[4]\n", "\n", " # lower and upper bounds - for each multiplicative functional\n", " for ii in 1:nm\n", " li, ui = 2(ii - 1)+1, 2ii\n", " if yvar[nx + nm + ii, nx + nm + ii] != 0.0\n", " Mdist = LogNormal(ymeans[nx + nm + ii]- 0.5t * diag(H * H')[ii],\n", " sqrt(yvar[nx + nm + ii, nx + nm + ii]))\n", " mbounds_mult[li, t] = quantile(Mdist, 0.01)\n", " mbounds_mult[ui, t] = quantile(Mdist, 0.99)\n", " elseif yvar[nx + nm + ii, nx + nm + ii] == 0.0\n", " mbounds_mult[li, t] = exp.(ymeans[nx + nm + ii] - 0.5t * diag(H * H')[ii])\n", " mbounds_mult[ui, t] = exp.(ymeans[nx + nm + ii] - 0.5t * diag(H * H')[ii])\n", " else\n", " error(\"standard error is negative\")\n", " end\n", " if yvar[nx + 2nm + ii, nx + 2nm + ii] != 0.0\n", " Sdist = LogNormal(-ymeans[nx + 2nm + ii],\n", " sqrt(yvar[nx + 2nm + ii, nx + 2nm + ii]))\n", " sbounds_mult[li, t] = quantile(Sdist, 0.01)\n", " sbounds_mult[ui, t] = quantile(Sdist, 0.99)\n", " elseif yvar[nx + 2nm + ii, nx + 2nm + ii] == 0.0\n", " sbounds_mult[li, t] = exp.(-ymeans[nx + 2nm + ii])\n", " sbounds_mult[ui, t] = exp.(-ymeans[nx + 2nm + ii])\n", " else\n", " error(\"standard error is negative\")\n", " end\n", " end\n", " t == T && break\n", " end\n", "\n", " # pull out paths\n", " for n in 1:npaths\n", " x, y = simulate(amf.lss,T)\n", " for ii in 0:nm-1\n", " ypath_mult[npaths * ii + n, :] = exp.(y[nx+ii+1, :])\n", " mpath_mult[npaths * ii + n, :] =\n", " exp.(y[nx+nm + ii+1, :] - collect(1:T)*0.5*diag(H * H')[ii+1])\n", " spath_mult[npaths * ii + n, :] = 1 ./exp.(-y[nx+2*nm + ii+1, :])\n", " tpath_mult[npaths * ii + n, :] =\n", " exp.(y[nx + 3nm + ii+1, :] + (1:T) * 0.5 * diag(H * H')[ii + 1])\n", " end\n", " end\n", "\n", " mult_figs = []\n", "\n", " for ii in 0:nm-1\n", " li, ui = npaths * ii, npaths * (ii + 1)\n", " LI, UI = 2ii, 2(ii + 1)\n", " push!(mult_figs,\n", " plot_given_paths(T, ypath_mult[li+1:ui, :], mpath_mult[li+1:ui, :],\n", " spath_mult[li+1:ui, :], tpath_mult[li+1:ui, :],\n", " mbounds_mult[LI+1:UI, :], sbounds_mult[LI+1:UI, :],\n", " horline = 1.0, show_trend=show_trend))\n", " end\n", "\n", " return mult_figs\n", "end\n", "\n", "function plot_martingales(amf, T, npaths = 25)\n", "\n", " # pull out right sizes so we know how to increment\n", " @unpack A, B, D, F, ν, nx, nk, nm = amf\n", " # matrices for the multiplicative decomposition\n", " H, g, ν_tilde = multiplicative_decomp(A, B, D, F, ν, nx)\n", "\n", " # allocate space (nm is the number of functionals - we want npaths for each)\n", " mpath_mult = zeros(nm * npaths, T)\n", " mbounds_mult = zeros(2nm, T)\n", "\n", " # simulate for as long as we wanted\n", " moment_generator = moment_sequence(amf.lss)\n", " # pull out population moments\n", " for (t, x) in enumerate(moment_generator)\n", " ymeans = x[2]\n", " yvar = x[4]\n", "\n", " # lower and upper bounds - for each functional\n", " for ii in 1:nm\n", " li, ui = 2(ii - 1) + 1, 2ii\n", " if yvar[nx + nm + ii, nx + nm + ii] != 0.0\n", " Mdist = LogNormal(ymeans[nx + nm + ii] - 0.5^2 * t * diag(H * H')[ii],\n", " sqrt(yvar[nx + nm + ii, nx + nm + ii]))\n", " mbounds_mult[li, t] = quantile(Mdist, 0.01)\n", " mbounds_mult[ui, t] = quantile(Mdist, 0.99)\n", " elseif yvar[nx + nm + ii, nx + nm + ii] == 0.0\n", " mbounds_mult[li, t] = ymeans[nx + nm + ii] - 0.5^2 * t * diag(H * H')[ii]\n", " mbounds_mult[ui, t] = ymeans[nx + nm + ii]- 0.5t * diag(H * H')[ii]\n", " else\n", " error(\"standard error is negative\")\n", " end\n", " end\n", " t == T && break\n", " end\n", "\n", " # pull out paths\n", " for n in 1:npaths\n", " x, y = simulate(amf.lss, T)\n", " for ii in 0:nm-1\n", " mpath_mult[npaths * ii + n, :] =\n", " exp.(y[nx+nm + ii+1, :] - (1:T) * 0.5 * diag(H * H')[ii+1])\n", " end\n", " end\n", "\n", " mart_figs = []\n", "\n", " for ii in 0:nm-1\n", " li, ui = npaths*(ii), npaths*(ii + 1)\n", " LI, UI = 2ii, 2(ii + 1)\n", " push!(mart_figs,\n", " plot_martingale_paths(T, mpath_mult[li + 1:ui, :],\n", " mbounds_mult[LI + 1:UI, :], horline = 1))\n", " plot!(mart_figs[ii + 1], title = \"Martingale components for many paths of y_(ii + 1)\")\n", " end\n", "\n", " return mart_figs\n", "end\n", "\n", "function plot_given_paths(T, ypath, mpath, spath, tpath, mbounds, sbounds;\n", " horline = 0.0, show_trend = true)\n", "\n", " # allocate space\n", " trange = 1:T\n", "\n", " # allocate transpose\n", " mpathᵀ = Matrix(mpath')\n", "\n", " # create figure\n", " plots=plot(layout = (2, 2), size = (800, 800))\n", "\n", " # plot all paths together\n", "\n", " plot!(plots[1], trange, ypath[1, :], label = \"y_t\", color = :black)\n", " plot!(plots[1], trange, mpath[1, :], label = \"m_t\", color = :magenta)\n", " plot!(plots[1], trange, spath[1, :], label = \"s_t\", color = :green)\n", " if show_trend\n", " plot!(plots[1], trange, tpath[1, :], label = \"t_t\", color = :red)\n", " end\n", " plot!(plots[1], seriestype = :hline, [horline], color = :black, linestyle=:dash, label = \"\")\n", " plot!(plots[1], title = \"One Path of All Variables\", legend=:topleft)\n", "\n", " # plot martingale component\n", " plot!(plots[2], trange, mpath[1, :], color = :magenta, label = \"\")\n", " plot!(plots[2], trange, mpathᵀ, alpha = 0.45, color = :magenta, label = \"\")\n", " ub = mbounds[2, :]\n", " lb = mbounds[1, :]\n", " plot!(plots[2], ub, fill_between = (lb, ub), alpha = 0.25, color = :magenta, label = \"\")\n", " plot!(plots[2], seriestype = :hline, [horline], color = :black, linestyle =:dash, label = \"\")\n", " plot!(plots[2], title = \"Martingale Components for Many Paths\")\n", "\n", " # plot stationary component\n", " plot!(plots[3], spath[1, :], color = :green, label = \"\")\n", " plot!(plots[3], Matrix(spath'), alpha = 0.25, color = :green, label = \"\")\n", " ub = sbounds[2, :]\n", " lb = sbounds[1, :]\n", " plot!(plots[3], ub, fill_between = (lb, ub), alpha = 0.25, color = :green, label = \"\")\n", " plot!(plots[3], seriestype = :hline, [horline], color = :black, linestyle=:dash, label = \"\")\n", " plot!(plots[3], title = \"Stationary Components for Many Paths\")\n", "\n", " # plot trend component\n", " if show_trend == true\n", " plot!(plots[4], Matrix(tpath'), color = :red, label = \"\")\n", " end\n", " plot!(plots[4], seriestype = :hline, [horline], color = :black, linestyle =:dash, label = \"\")\n", " plot!(plots[4], title = \"Trend Components for Many Paths\")\n", "\n", " return plots\n", "end\n", "\n", "function plot_martingale_paths(T, mpath, mbounds;\n", " horline = 1, show_trend = false)\n", " # allocate space\n", " trange = 1:T\n", "\n", " # create the plot\n", " plt = plot()\n", "\n", " # plot martingale component\n", " ub = mbounds[2, :]\n", " lb = mbounds[1, :]\n", " plot!(plt, lb, fill_between = (lb, ub), alpha = 0.25, color = :magenta, label = \"\")\n", " plot!(plt, seriestype = :hline, [horline], color = :black, linestyle =:dash, label = \"\")\n", " plot!(plt, trange, Matrix(mpath'), linewidth=0.25, color = :black, label = \"\")\n", "\n", " return plt\n", "end" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For now, we just plot $ y_t $ and $ x_t $, postponing until later a description of exactly how we compute them\n", "\n", "\n", "" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide-output": false }, "outputs": [], "source": [ "ϕ_1, ϕ_2, ϕ_3, ϕ_4 = 0.5, -0.2, 0, 0.5\n", "σ = 0.01\n", "ν = 0.01 # growth rate\n", "\n", "# A matrix should be n x n\n", "A = [ϕ_1 ϕ_2 ϕ_3 ϕ_4;\n", " 1 0 0 0;\n", " 0 1 0 0;\n", " 0 0 1 0]\n", "\n", "# B matrix should be n x k\n", "B = [σ, 0, 0, 0]\n", "\n", "D = [1 0 0 0] * A\n", "F = [1, 0, 0, 0] ⋅ vec(B)\n", "\n", "amf = AMF_LSS_VAR(A, B, D, F, ν)\n", "\n", "T = 150\n", "x, y = simulate(amf.lss, T)\n", "\n", "plots = plot(layout = (2, 1))\n", "\n", "plot!(plots[1], 1:T, y[amf.nx + 1, :], color = :black, lw = 2, label = \"\")\n", "plot!(plots[1], title = \"A particular path of y_t\")\n", "plot!(plots[2], 1:T, y[1, :], color = :green, lw = 2, label = \"\")\n", "plot!(plots[2], seriestype = :hline, [0], color = :black, lw = 2, linestyle=:dashdot,\n", " label = \"\")\n", "plot!(plots[2], title = \"Associated path of x_t\")\n", "\n", "plot(plots)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice the irregular but persistent growth in $ y_t $" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Decomposition\n", "\n", "Hansen and Sargent [[HS17]](zreferences.ipynb#hans-sarg-book-2016) describe how to construct a decomposition of\n", "an additive functional into four parts:\n", "\n", "- a constant inherited from initial values $ x_0 $ and $ y_0 $ \n", "- a linear trend \n", "- a martingale \n", "- an (asymptotically) stationary component \n", "\n", "\n", "To attain this decomposition for the particular class of additive\n", "functionals defined by [(1)](#equation-old1-additive-functionals) and [(2)](#equation-old2-additive-functionals), we first construct the matrices\n", "\n", "$$\n", "\\begin{aligned}\n", " H & := F + B'(I - A')^{-1} D\n", " \\\\\n", " g & := D' (I - A)^{-1}\n", "\\end{aligned}\n", "$$\n", "\n", "Then the Hansen-Scheinkman [[HS09]](zreferences.ipynb#hans-scheink-2009) decomposition is\n", "\n", "$$\n", "\\begin{aligned}\n", " y_t\n", " &= \\underbrace{t \\nu}_{\\text{trend component}} +\n", " \\overbrace{\\sum_{j=1}^t H z_j}^{\\text{Martingale component}} -\n", " \\underbrace{g x_t}_{\\text{stationary component}} +\n", " \\overbrace{g x_0 + y_0}^{\\text{initial conditions}}\n", "\\end{aligned}\n", "$$\n", "\n", "At this stage you should pause and verify that $ y_{t+1} - y_t $ satisfies [(2)](#equation-old2-additive-functionals)\n", "\n", "It is convenient for us to introduce the following notation:\n", "\n", "- $ \\tau_t = \\nu t $ , a linear, deterministic trend \n", "- $ m_t = \\sum_{j=1}^t H z_j $, a martingale with time $ t+1 $ increment $ H z_{t+1} $ \n", "- $ s_t = g x_t $, an (asymptotically) stationary component \n", "\n", "\n", "We want to characterize and simulate components $ \\tau_t, m_t, s_t $ of the decomposition.\n", "\n", "A convenient way to do this is to construct an appropriate instance of a [linear state space system](tools_and_techniques/linear_models.ipynb) by using [LSS](https://github.com/QuantEcon/QuantEcon.jl/blob/master/src/lss.jl) from [QuantEcon.jl](http://quantecon.org/julia_index.html)\n", "\n", "This will allow us to use the routines in [LSS](https://github.com/QuantEcon/QuantEcon.jl/blob/master/src/lss.jl) to study dynamics\n", "\n", "To start, observe that, under the dynamics in [(1)](#equation-old1-additive-functionals) and [(2)](#equation-old2-additive-functionals) and with the\n", "definitions just given,\n", "\n", "$$\n", "\\begin{bmatrix}\n", " 1 \\\\\n", " t+1 \\\\\n", " x_{t+1} \\\\\n", " y_{t+1} \\\\\n", " m_{t+1}\n", "\\end{bmatrix}\n", "=\n", "\\begin{bmatrix}\n", " 1 & 0 & 0 & 0 & 0 \\\\\n", " 1 & 1 & 0 & 0 & 0 \\\\\n", " 0 & 0 & A & 0 & 0 \\\\\n", " \\nu & 0 & D' & 1 & 0 \\\\\n", " 0 & 0 & 0 & 0 & 1\n", "\\end{bmatrix}\n", "\\begin{bmatrix}\n", " 1 \\\\\n", " t \\\\\n", " x_t \\\\\n", " y_t \\\\\n", " m_t\n", "\\end{bmatrix}\n", "+\n", "\\begin{bmatrix}\n", " 0 \\\\\n", " 0 \\\\\n", " B \\\\\n", " F' \\\\\n", " H'\n", "\\end{bmatrix}\n", "z_{t+1}\n", "$$\n", "\n", "and\n", "\n", "$$\n", "\\begin{bmatrix}\n", " x_t \\\\\n", " y_t \\\\\n", " \\tau_t \\\\\n", " m_t \\\\\n", " s_t\n", "\\end{bmatrix}\n", "=\n", "\\begin{bmatrix}\n", " 0 & 0 & I & 0 & 0 \\\\\n", " 0 & 0 & 0 & 1 & 0 \\\\\n", " 0 & \\nu & 0 & 0 & 0 \\\\\n", " 0 & 0 & 0 & 0 & 1 \\\\\n", " 0 & 0 & -g & 0 & 0\n", "\\end{bmatrix}\n", "\\begin{bmatrix}\n", " 1 \\\\\n", " t \\\\\n", " x_t \\\\\n", " y_t \\\\\n", " m_t\n", "\\end{bmatrix}\n", "$$\n", "\n", "With\n", "\n", "$$\n", "\\tilde{x} := \\begin{bmatrix} 1 \\\\ t \\\\ x_t \\\\ y_t \\\\ m_t \\end{bmatrix}\n", "\\quad \\text{and} \\quad\n", "\\tilde{y} := \\begin{bmatrix} x_t \\\\ y_t \\\\ \\tau_t \\\\ m_t \\\\ s_t \\end{bmatrix}\n", "$$\n", "\n", "we can write this as the linear state space system\n", "\n", "$$\n", "\\begin{aligned}\n", " \\tilde{x}_{t+1} &= \\tilde{A} \\tilde{x}_t + \\tilde{B} z_{t+1} \\\\\n", " \\tilde{y}_{t} &= \\tilde{D} \\tilde{x}_t\n", "\\end{aligned}\n", "$$\n", "\n", "By picking out components of $ \\tilde y_t $, we can track all variables of\n", "interest" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Code\n", "\n", "The type [AMF_LSS_VAR](https://github.com/QuantEcon/QuantEcon.lectures.code/blob/master/additive_functionals/amflss.jl) mentioned above does all that we want to study our additive functional\n", "\n", "In fact [AMF_LSS_VAR](https://github.com/QuantEcon/QuantEcon.lectures.code/blob/master/additive_functionals/amflss.jl) does more, as we shall explain below\n", "\n", "(A hint that it does more is the name of the type – here AMF stands for\n", "“additive and multiplicative functional” – the code will do things for\n", "multiplicative functionals too)\n", "\n", "Let’s use this code (embedded above) to explore the [example process described above](#addfunc-eg1)\n", "\n", "If you run [the code that first simulated that example](#addfunc-egcode) again and then the method call\n", "you will generate (modulo randomness) the plot" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide-output": false }, "outputs": [], "source": [ "plt = plot_additive(amf, T)\n", "plt[1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When we plot multiple realizations of a component in the 2nd, 3rd, and 4th panels, we also plot population 95% probability coverage sets computed using the LSS type\n", "\n", "We have chosen to simulate many paths, all starting from the *same* nonrandom initial conditions $ x_0, y_0 $ (you can tell this from the shape of the 95% probability coverage shaded areas)\n", "\n", "Notice tell-tale signs of these probability coverage shaded areas\n", "\n", "- the purple one for the martingale component $ m_t $ grows with\n", " $ \\sqrt{t} $ \n", "- the green one for the stationary component $ s_t $ converges to a\n", " constant band " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### An associated multiplicative functional\n", "\n", "Where $ \\{y_t\\} $ is our additive functional, let $ M_t = \\exp(y_t) $\n", "\n", "As mentioned above, the process $ \\{M_t\\} $ is called a **multiplicative functional**\n", "\n", "Corresponding to the additive decomposition described above we have the multiplicative decomposition of the $ M_t $\n", "\n", "$$\n", "\\frac{M_t}{M_0}\n", "= \\exp (t \\nu) \\exp \\Bigl(\\sum_{j=1}^t H \\cdot Z_j \\Bigr) \\exp \\biggl( D'(I-A)^{-1} x_0 - D'(I-A)^{-1} x_t \\biggr)\n", "$$\n", "\n", "or\n", "\n", "$$\n", "\\frac{M_t}{M_0} = \\exp\\left( \\tilde \\nu t \\right) \\Biggl( \\frac{\\widetilde M_t}{\\widetilde M_0}\\Biggr) \\left( \\frac{\\tilde e (X_0)} {\\tilde e(x_t)} \\right)\n", "$$\n", "\n", "where\n", "\n", "$$\n", "\\tilde \\nu = \\nu + \\frac{H \\cdot H}{2} ,\n", "\\quad\n", "\\widetilde M_t = \\exp \\biggl( \\sum_{j=1}^t \\biggl(H \\cdot z_j -\\frac{ H \\cdot H }{2} \\biggr) \\biggr), \\quad \\widetilde M_0 =1\n", "$$\n", "\n", "and\n", "\n", "$$\n", "\\tilde e(x) = \\exp[g(x)] = \\exp \\bigl[ D' (I - A)^{-1} x \\bigr]\n", "$$\n", "\n", "An instance of type [AMF_LSS_VAR](https://github.com/QuantEcon/QuantEcon.lectures.code/blob/master/additive_functionals/amflss.jl) includes this associated multiplicative functional as an attribute\n", "\n", "Let’s plot this multiplicative functional for our example\n", "\n", "If you run [the code that first simulated that example](#addfunc-egcode) again and then the method call" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide-output": false }, "outputs": [], "source": [ "plt = plot_multiplicative(amf, T)\n", "plt[1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As before, when we plotted multiple realizations of a component in the 2nd, 3rd, and 4th panels, we also plotted population 95% confidence bands computed using the LSS type\n", "\n", "Comparing this figure and the last also helps show how geometric growth differs from\n", "arithmetic growth" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### A peculiar large sample property\n", "\n", "Hansen and Sargent [[HS17]](zreferences.ipynb#hans-sarg-book-2016) (ch. 6) note that the martingale component\n", "$ \\widetilde M_t $ of the multiplicative decomposition has a peculiar property\n", "\n", "- While $ E_0 \\widetilde M_t = 1 $ for all $ t \\geq 0 $,\n", " nevertheless $ \\ldots $ \n", "- As $ t \\rightarrow +\\infty $, $ \\widetilde M_t $ converges to\n", " zero almost surely \n", "\n", "\n", "The following simulation of many paths of $ \\widetilde M_t $ illustrates this property" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide-output": false }, "outputs": [], "source": [ "plt = plot_martingales(amf, 12000)\n", "plt[1]" ] } ], "metadata": { "filename": "additive_functionals.rst", "kernelspec": { "display_name": "Julia 1.2", "language": "julia", "name": "julia-1.2" }, "title": "Additive Functionals" }, "nbformat": 4, "nbformat_minor": 2 }