{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "8a2e1506", "metadata": { "execution": { "iopub.execute_input": "2025-03-15T12:20:59.366105Z", "iopub.status.busy": "2025-03-15T12:20:59.365695Z", "iopub.status.idle": "2025-03-15T12:20:59.372400Z", "shell.execute_reply": "2025-03-15T12:20:59.371971Z" } }, "outputs": [], "source": [ "import os\n", "\n", "os.environ[\"OMP_NUM_THREADS\"] = \"4\"\n", "os.environ[\"OPENBLAS_NUM_THREADS\"] = \"4\"\n", "os.environ[\"MKL_NUM_THREADS\"] = \"4\"\n", "os.environ[\"VECLIB_MAXIMUM_THREADS\"] = \"4\"\n", "os.environ[\"NUMEXPR_NUM_THREADS\"] = \"4\"" ] }, { "cell_type": "code", "execution_count": 2, "id": "22ba2087", "metadata": { "execution": { "iopub.execute_input": "2025-03-15T12:20:59.390714Z", "iopub.status.busy": "2025-03-15T12:20:59.390442Z", "iopub.status.idle": "2025-03-15T12:20:59.697852Z", "shell.execute_reply": "2025-03-15T12:20:59.697613Z" } }, "outputs": [], "source": [ "%%capture\n", "try:\n", " from pandas_datareader.fred import FredReader\n", "except ImportError:\n", " !pip install pandas-datareader\n", " from pandas_datareader.fred import FredReader" ] }, { "cell_type": "code", "execution_count": 3, "id": "8a9537f1", "metadata": { "execution": { "iopub.execute_input": "2025-03-15T12:20:59.699244Z", "iopub.status.busy": "2025-03-15T12:20:59.699124Z", "iopub.status.idle": "2025-03-15T12:21:01.357502Z", "shell.execute_reply": "2025-03-15T12:21:01.357170Z" } }, "outputs": [], "source": [ "import arviz as az\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import pandas as pd\n", "import preliz as pz\n", "import pymc as pm\n", "\n", "import gEconpy as ge\n", "import gEconpy.plotting as gp\n", "\n", "gp.set_matplotlib_style()" ] }, { "cell_type": "code", "execution_count": 4, "id": "f4791749", "metadata": { "execution": { "iopub.execute_input": "2025-03-15T12:21:01.359299Z", "iopub.status.busy": "2025-03-15T12:21:01.358945Z", "iopub.status.idle": "2025-03-15T12:21:01.361273Z", "shell.execute_reply": "2025-03-15T12:21:01.361046Z" } }, "outputs": [], "source": [ "RANDOM_SEED = sum(map(ord, \"USA Estimation\"))\n", "rng = np.random.default_rng(RANDOM_SEED)" ] }, { "cell_type": "markdown", "id": "598277cc", "metadata": {}, "source": [ "# Fitting an RBC to US Data\n", "\n", "In this notebook, we go through steps to fit an RBC model to actual US data. This begins with grabbing data (in this case from FRED), doing some light preprocessing, then fitting the model using PyMC." ] }, { "cell_type": "markdown", "id": "217377c9", "metadata": {}, "source": [ "## Get US data\n", "\n", "We want series for consumption, investment, labor, GDP, interest rate, and wages" ] }, { "cell_type": "code", "execution_count": 5, "id": "997ef073", "metadata": { "execution": { "iopub.execute_input": "2025-03-15T12:21:01.362567Z", "iopub.status.busy": "2025-03-15T12:21:01.362484Z", "iopub.status.idle": "2025-03-15T12:21:04.635503Z", "shell.execute_reply": "2025-03-15T12:21:04.635270Z" } }, "outputs": [], "source": [ "indicators = {\n", " \"NAEXKP01USQ652S\": \"Y\", # GDP\n", " \"NAEXKP04USQ652S\": \"I\", # Investment\n", " \"NAEXKP02USQ189S\": \"C\", # HH consumption\n", " \"TOTLQ\": \"L\", # total non-farm hours worked\n", " \"GS10\": \"i\", # 10-year interest rate\n", " \"CES0500000003\": \"w\", # average hourly wage\n", " \"CPIAUCSL\": \"cpi\", # CPI\n", "}\n", "\n", "if not os.path.isfile(\"us_fred_data.csv\"):\n", " data = FredReader(symbols=list(indicators.keys()), start=\"1900\", end=None).read()\n", " data.to_csv(\"us_fred_data.csv\")\n", "else:\n", " data = pd.read_csv(\n", " \"us_fred_data.csv\",\n", " index_col=0,\n", " parse_dates=[\"DATE\"],\n", " )" ] }, { "cell_type": "markdown", "id": "dbc51f3e", "metadata": {}, "source": [ "## Raw Data from FRED\n", "\n", "The first problem we encounter is different frequencies of data. We want everything to be quarterly, so step 1 is to convert everything.\n", "\n", "Well, actually step 1 is to rename these awful columns." ] }, { "cell_type": "code", "execution_count": 6, "id": "f74978ea", "metadata": { "execution": { "iopub.execute_input": "2025-03-15T12:21:04.637436Z", "iopub.status.busy": "2025-03-15T12:21:04.637210Z", "iopub.status.idle": "2025-03-15T12:21:04.647517Z", "shell.execute_reply": "2025-03-15T12:21:04.647174Z" } }, "outputs": [ { "data": { "text/html": [ "
| \n", " | NAEXKP01USQ652S | \n", "NAEXKP04USQ652S | \n", "NAEXKP02USQ189S | \n", "TOTLQ | \n", "GS10 | \n", "CES0500000003 | \n", "CPIAUCSL | \n", "
|---|---|---|---|---|---|---|---|
| DATE | \n", "\n", " | \n", " | \n", " | \n", " | \n", " | \n", " | \n", " |
| 2024-05-01 | \n", "NaN | \n", "NaN | \n", "NaN | \n", "NaN | \n", "4.48 | \n", "34.89 | \n", "313.140 | \n", "
| 2024-06-01 | \n", "NaN | \n", "NaN | \n", "NaN | \n", "NaN | \n", "4.31 | \n", "35.00 | \n", "313.131 | \n", "
| 2024-07-01 | \n", "NaN | \n", "NaN | \n", "NaN | \n", "NaN | \n", "4.25 | \n", "35.07 | \n", "313.566 | \n", "
| 2024-08-01 | \n", "NaN | \n", "NaN | \n", "NaN | \n", "NaN | \n", "3.87 | \n", "35.23 | \n", "314.131 | \n", "
| 2024-09-01 | \n", "NaN | \n", "NaN | \n", "NaN | \n", "NaN | \n", "3.72 | \n", "35.33 | \n", "314.851 | \n", "
| 2024-10-01 | \n", "NaN | \n", "NaN | \n", "NaN | \n", "NaN | \n", "4.10 | \n", "35.48 | \n", "315.564 | \n", "
| 2024-11-01 | \n", "NaN | \n", "NaN | \n", "NaN | \n", "NaN | \n", "4.36 | \n", "35.61 | \n", "316.449 | \n", "
| 2024-12-01 | \n", "NaN | \n", "NaN | \n", "NaN | \n", "NaN | \n", "4.39 | \n", "35.68 | \n", "317.603 | \n", "
| 2025-01-01 | \n", "NaN | \n", "NaN | \n", "NaN | \n", "NaN | \n", "4.63 | \n", "35.83 | \n", "319.086 | \n", "
| 2025-02-01 | \n", "NaN | \n", "NaN | \n", "NaN | \n", "NaN | \n", "4.45 | \n", "35.93 | \n", "319.775 | \n", "
| \n", " | Y | \n", "I | \n", "C | \n", "L | \n", "w | \n", "r | \n", "
|---|---|---|---|---|---|---|
| Time | \n", "\n", " | \n", " | \n", " | \n", " | \n", " | \n", " |
| 2024-01-01 | \n", "NaN | \n", "NaN | \n", "NaN | \n", "NaN | \n", "11.108370 | \n", "3.783503 | \n", "
| 2024-04-01 | \n", "NaN | \n", "NaN | \n", "NaN | \n", "NaN | \n", "11.177431 | \n", "4.329314 | \n", "
| 2024-07-01 | \n", "NaN | \n", "NaN | \n", "NaN | \n", "NaN | \n", "11.221181 | \n", "3.756799 | \n", "
| 2024-10-01 | \n", "NaN | \n", "NaN | \n", "NaN | \n", "NaN | \n", "11.234151 | \n", "3.981176 | \n", "
| 2025-01-01 | \n", "NaN | \n", "NaN | \n", "NaN | \n", "NaN | \n", "11.236025 | \n", "2.770449 | \n", "
\\[A_{ss} = 1\\]
\n", "\\[mc_{ss} = 1\\]
\n", "\\[r_{ss} = \\delta - 1 + \\frac{1}{\\beta}\\]
\n", "\\[w_{ss} = - \\left(\\frac{\\alpha}{r_{ss}}\\right)^{- \\frac{\\alpha}{\\alpha - 1}} \\left(\\alpha - 1\\right)\\]
\n", "\\[Y_{ss} = \\left(w_{ss} \\left(- \\frac{w_{ss}}{\\alpha - 1}\\right)^{\\sigma_{L}}\\right)^{\\frac{1}{\\sigma_{C} + \\sigma_{L}}} \\left(- \\frac{r_{ss}}{\\alpha \\delta - r_{ss}}\\right)^{\\frac{\\sigma_{C}}{\\sigma_{C} + \\sigma_{L}}}\\]
\n", "\\[I_{ss} = \\frac{\\alpha \\delta Y_{ss}}{r_{ss}}\\]
\n", "\\[C_{ss} = Y_{ss}^{\\frac{\\left(-1\\right) \\sigma_{L}}{\\sigma_{C}}} \\left(w_{ss}^{\\sigma_{L} + 1} \\left(1 - \\alpha\\right)^{- \\sigma_{L}}\\right)^{\\frac{1}{\\sigma_{C}}}\\]
\n", "\\[K_{ss} = \\frac{\\alpha Y_{ss} mc_{ss}}{r_{ss}}\\]
\n", "\\[L_{ss} = - \\frac{Y_{ss} mc_{ss} \\left(\\alpha - 1\\right)}{w_{ss}}\\]
\n", "\\[U_{ss} = \\frac{\\frac{C_{ss}^{1 - \\sigma_{C}}}{\\sigma_{C} - 1} + \\frac{L_{ss}^{\\sigma_{L} + 1}}{\\sigma_{L} + 1}}{\\beta - 1}\\]
\n", "\\[\\lambda_{ss} = C_{ss}^{- \\sigma_{C}}\\]
\n", "\\[TC_{ss} = - K_{ss} r_{ss} - L_{ss} w_{ss}\\]
\n", "\\[u_{t} = - \\frac{C_{t}^{1 - \\sigma_{C}}}{\\sigma_{C} - 1} - \\frac{L_{t}^{\\sigma_{L} + 1}}{\\sigma_{L} + 1}\\]
\n", "\\[\\operatorname{Set}\\left(\\left[ C_{t}, \\ L_{t}, \\ I_{t}, \\ K_{t}\\right]\\right)\\]
\n", "\\[U_{t} = \\beta U_{t+1} + u_{t}\\]
\n", "\\[C_{t} + I_{t} = K_{t-1} r_{t} + L_{t} w_{t}\\]
\n", "\\[K_{t} = I_{t} - K_{t-1} \\left(\\delta - 1\\right)\\]
\n", "\\[\\beta = 0.99\\]
\n", "\\[\\delta = 0.02\\]
\n", "\\[\\sigma_{C} = 1.5\\]
\n", "\\[\\sigma_{L} = 2.0\\]
\n", "\\[\\operatorname{Set}\\left(\\left[ K_{t-1}, \\ L_{t}\\right]\\right)\\]
\n", "\\[TC_{t} = - K_{t-1} r_{t} - L_{t} w_{t}\\]
\n", "\\[Y_{t} = A_{t} K_{t-1}^{\\alpha} L_{t}^{1 - \\alpha}\\]
\n", "\\[mc_{t} = 1\\]
\n", "\\[\\alpha = 0.35\\]
\n", "\\[\\log{\\left(A_{t} \\right)} = \\rho_{A} \\log{\\left(A_{t-1} \\right)} + \\epsilon_{A t}\\]
\n", "\\[\\operatorname{Set}\\left(\\left[ \\epsilon_{A t}\\right]\\right)\\]
\n", "\\[\\rho_{A} = 0.95\\]
\n", "Model Requirements \n", " \n", " Variable Shape Constraints Dimensions \n", " ──────────────────────────────────────────────────── \n", " alpha () None \n", " beta () None \n", " delta () None \n", " rho_A () None \n", " sigma_C () Positive None \n", " sigma_L () Positive None \n", " sigma_epsilon_A () Positive None \n", " error_sigma_Y () None \n", " error_sigma_I () None \n", " error_sigma_C () None \n", " error_sigma_L () None \n", " error_sigma_w () None \n", " error_sigma_r () None \n", " \n", " These parameters should be assigned priors inside a \n", " PyMC model block before calling the \n", " build_statespace_graph method. \n", "\n" ], "text/plain": [ "\u001b[3m Model Requirements \u001b[0m\n", " \n", " \u001b[1m \u001b[0m\u001b[1mVariable \u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1mShape\u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1mConstraints\u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1mDimensions\u001b[0m\u001b[1m \u001b[0m \n", " ──────────────────────────────────────────────────── \n", " alpha \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " beta \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " delta \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " rho_A \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " sigma_C \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m Positive \u001b[3;35mNone\u001b[0m \n", " sigma_L \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m Positive \u001b[3;35mNone\u001b[0m \n", " sigma_epsilon_A \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m Positive \u001b[3;35mNone\u001b[0m \n", " error_sigma_Y \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " error_sigma_I \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " error_sigma_C \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " error_sigma_L \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " error_sigma_w \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " error_sigma_r \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " \n", "\u001b[2;3m These parameters should be assigned priors inside a \u001b[0m\n", "\u001b[2;3m PyMC model block before calling the \u001b[0m\n", "\u001b[2;3m build_statespace_graph method. \u001b[0m\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "ss_mod.configure(\n", " observed_states=df.columns,\n", " measurement_error=df.columns,\n", " mode=\"JAX\",\n", " solver=\"scan_cycle_reduction\",\n", " use_adjoint_gradients=True,\n", " max_iter=20,\n", ")" ] }, { "cell_type": "code", "execution_count": 22, "id": "5dbe4889", "metadata": { "execution": { "iopub.execute_input": "2025-03-15T12:21:09.330961Z", "iopub.status.busy": "2025-03-15T12:21:09.330885Z", "iopub.status.idle": "2025-03-15T12:21:09.332577Z", "shell.execute_reply": "2025-03-15T12:21:09.332391Z" } }, "outputs": [], "source": [ "# Save some groups of variable names for later\n", "all_params = ss_mod.param_names\n", "deep_params = list(ss_mod.param_dict.keys())\n", "shock_params = [f\"sigma_{name}\" for name in ss_mod.shock_names]\n", "error_params = [f\"error_sigma_{name}\" for name in ss_mod.error_states]" ] }, { "cell_type": "markdown", "id": "dd31e109", "metadata": {}, "source": [ "## Building PyMC model\n", "\n", "The `Model Requirements` table tells us what we need to define. We already have priors for the 6 deep parameters. These can be quickly added using `ss_mod.to_pymc()`. Then we have to define the remaining standard deviations: `sigma_epsilon_A`, `error_sigma_Y`, `error_sigma_I`, `error_sigma_C`, `error_sigma_w`, and `error_sigma_r`. \n", "\n", "The model is log-linearized, so all values are in percentage deviation from steady state. This is nice, because we can think about the errors in percentage terms. We can assume a prior that data are at most 5% off, which implies a standard deviation of at most ~5 (2 * sqrt(5) = 4.47, just round back up to 5). \n", "\n", "Probably that huge, but why not. It's just a prior!" ] }, { "cell_type": "code", "execution_count": 23, "id": "32c9af2c", "metadata": { "execution": { "iopub.execute_input": "2025-03-15T12:21:09.333647Z", "iopub.status.busy": "2025-03-15T12:21:09.333589Z", "iopub.status.idle": "2025-03-15T12:21:09.641580Z", "shell.execute_reply": "2025-03-15T12:21:09.641265Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/jessegrabowski/mambaforge/envs/geconpy-dev/lib/python3.12/site-packages/pymc_extras/statespace/utils/data_tools.py:159: ImputationWarning: Provided data contains missing values and will be automatically imputed as hidden states during Kalman filtering.\n", " warnings.warn(impute_message, ImputationWarning)\n" ] } ], "source": [ "with pm.Model(coords=ss_mod.coords) as usa_rbc:\n", " ss_mod.to_pymc()\n", "\n", " # Save the pre-defined priors as a variable we can use to stay organized\n", " prior_dict = ss_mod.param_priors.copy()\n", "\n", " # pz.maxent helps us by finding the distribution in a given family with some percent of total mass between\n", " # two points. Technically infinity distribtuions will satisfy that criteria, so it gives the one with\n", " # maximum entropy. It's much easier to reason about ranges of admissible values than parameters.\n", "\n", " prior_dict[\"sigma_epsilon_A\"] = pz.maxent(pz.Gamma(), lower=0.01, upper=0.1, plot=False)\n", " prior_dict[\"sigma_epsilon_A\"].to_pymc(\"sigma_epsilon_A\")\n", "\n", " # As mentioned above, we'll make the measurement errors between 0% and 5%\n", " for var in ss_mod.error_states:\n", " d = pz.maxent(pz.Gamma(), lower=0.001, upper=0.05, plot=False)\n", " prior_dict[f\"error_sigma_{var}\"] = d\n", " d.to_pymc(f\"error_sigma_{var}\")\n", "\n", " ss_mod.build_statespace_graph(\n", " data=df_detrend[ss_mod.observed_states],\n", " add_norm_check=True,\n", " add_solver_success_check=True,\n", " add_steady_state_penalty=True,\n", " )" ] }, { "cell_type": "code", "execution_count": 24, "id": "ecdd6e30", "metadata": { "execution": { "iopub.execute_input": "2025-03-15T12:21:09.642815Z", "iopub.status.busy": "2025-03-15T12:21:09.642746Z", "iopub.status.idle": "2025-03-15T12:21:10.289526Z", "shell.execute_reply": "2025-03-15T12:21:10.289239Z" } }, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "
Sampler Progress
\n", "Total Chains: 6
\n", "Active Chains: 0
\n", "\n", " Finished Chains:\n", " 6\n", "
\n", "Sampling for 6 minutes
\n", "\n", " Estimated Time to Completion:\n", " now\n", "
\n", "\n", " \n", "| Progress | \n", "Draws | \n", "Divergences | \n", "Step Size | \n", "Gradients/Draw | \n", "
|---|---|---|---|---|
| \n", " \n", " | \n", "1000 | \n", "1 | \n", "0.81 | \n", "3 | \n", "
| \n", " \n", " | \n", "1000 | \n", "0 | \n", "0.79 | \n", "7 | \n", "
| \n", " \n", " | \n", "1000 | \n", "0 | \n", "0.78 | \n", "7 | \n", "
| \n", " \n", " | \n", "1000 | \n", "0 | \n", "0.76 | \n", "7 | \n", "
| \n", " \n", " | \n", "1000 | \n", "0 | \n", "0.75 | \n", "7 | \n", "
| \n", " \n", " | \n", "1000 | \n", "0 | \n", "0.78 | \n", "7 | \n", "
\\[K_{to L ss} = \\left(\\frac{\\alpha A_{ss} mc_{ss}}{r_{ss}}\\right)^{- \\frac{1}{\\alpha - 1}}\\]
\n", "\\[A_{ss} = 1\\]
\n", "\\[shock_{I ss} = 1\\]
\n", "\\[\\beta_{ss} = \\beta\\]
\n", "\\[\\Theta_{ss} = \\Theta\\]
\n", "\\[z_{ss} = 1\\]
\n", "\\[mc_{ss} = 1\\]
\n", "\\[r_{ss} = \\delta - 1 + \\frac{1}{\\beta}\\]
\n", "\\[w_{ss} = - A_{ss} K_{to L ss}^{\\alpha} mc_{ss} \\left(\\alpha - 1\\right)\\]
\n", "\\[L_{ss} = \\left(- \\frac{w_{ss} \\left(1 - \\phi_{H}\\right)^{- \\sigma_{C}} \\left(\\beta \\phi_{H} - 1\\right) \\left(- \\delta K_{to L ss} + A_{ss} K_{to L ss}^{\\alpha}\\right)^{- \\sigma_{C}}}{\\Theta}\\right)^{\\frac{1}{\\sigma_{C} + \\sigma_{L}}}\\]
\n", "\\[K_{ss} = K_{to L ss} L_{ss}\\]
\n", "\\[K_{d ss} = K_{ss} z_{ss}\\]
\n", "\\[Y_{ss} = A_{ss} K_{d ss}^{\\alpha} L_{ss}^{1 - \\alpha}\\]
\n", "\\[I_{ss} = \\delta K_{ss}\\]
\n", "\\[C_{ss} = - I_{ss} + Y_{ss}\\]
\n", "\\[U_{ss} = \\frac{\\frac{C_{ss}^{1 - \\sigma_{C}}}{\\sigma_{C} - 1} + \\frac{L_{ss}^{\\sigma_{L} + 1}}{\\sigma_{L} + 1}}{\\beta - 1}\\]
\n", "\\[\\lambda_{ss} = - \\left(- C_{ss} \\left(\\phi_{H} - 1\\right)\\right)^{- \\sigma_{C}} \\left(\\beta \\phi_{H} - 1\\right)\\]
\n", "\\[q_{ss} = \\lambda_{ss}\\]
\n", "\\[TC_{ss} = - K_{ss} r_{ss} - L_{ss} w_{ss}\\]
\n", "\\[u_{t} = - \\frac{L_{t}^{\\sigma_{L} + 1} \\Theta_{t}}{\\sigma_{L} + 1} - \\frac{\\left(- \\phi_{H} C_{t-1} + C_{t}\\right)^{1 - \\sigma_{C}}}{\\sigma_{C} - 1}\\]
\n", "\\[\\Psi_{z t} = \\frac{\\psi_{z} \\left(z_{t} - 1\\right)^{2}}{2} + \\psi_{z 1} \\left(z_{t} - 1\\right)\\]
\n", "\\[\\operatorname{Set}\\left(\\left[ C_{t}, \\ L_{t}, \\ I_{t}, \\ K_{t}, \\ z_{t}\\right]\\right)\\]
\n", "\\[U_{t} = U_{t+1} \\beta_{t} + u_{t}\\]
\n", "\\[C_{t} + I_{t} + K_{t-1} \\Psi_{z t} = K_{t-1} r_{t} z_{t} + L_{t} w_{t}\\]
\n", "\\[K_{t} = - I_{t} \\left(\\frac{\\gamma_{I} \\left(\\frac{I_{t} shock_{I t}}{I_{t-1}} - 1\\right)^{2}}{2} - 1\\right) - K_{t-1} \\left(\\delta - 1\\right)\\]
\n", "\\[\\log{\\left(\\beta_{t} \\right)} = \\rho_{\\beta} \\log{\\left(\\beta_{t-1} \\right)} + \\epsilon_{\\beta t} - \\left(\\rho_{\\beta} - 1\\right) \\log{\\left(\\beta \\right)}\\]
\n", "\\[\\log{\\left(shock_{I t} \\right)} = \\rho_{I} \\log{\\left(shock_{I t-1} \\right)} + \\epsilon_{I t}\\]
\n", "\\[\\log{\\left(\\Theta_{t} \\right)} = \\rho_{\\Theta} \\log{\\left(\\Theta_{t-1} \\right)} + \\epsilon_{\\Theta t} - \\left(\\rho_{\\Theta} - 1\\right) \\log{\\left(\\Theta \\right)}\\]
\n", "\\[\\operatorname{Set}\\left(\\left[ \\epsilon_{\\beta t}, \\ \\epsilon_{I t}, \\ \\epsilon_{\\Theta t}\\right]\\right)\\]
\n", "\\[\\beta = 0.99\\]
\n", "\\[\\delta = 0.035\\]
\n", "\\[\\sigma_{C} = 3\\]
\n", "\\[\\sigma_{L} = 1.5\\]
\n", "\\[\\Theta = 1.0\\]
\n", "\\[\\gamma_{I} = 6.32\\]
\n", "\\[\\phi_{H} = 0.8\\]
\n", "\\[\\rho_{\\beta} = 0.9\\]
\n", "\\[\\rho_{\\Theta} = 0.9\\]
\n", "\\[\\rho_{I} = 0.9\\]
\n", "\\[\\psi_{z} = 0.169\\]
\n", "\\[\\psi_{z 1} = \\delta - 1 + \\frac{1}{\\beta}\\]
\n", "\\[\\operatorname{Set}\\left(\\left[ K_{d t}, \\ L_{t}\\right]\\right)\\]
\n", "\\[TC_{t} = - K_{d t} r_{t} - L_{t} w_{t}\\]
\n", "\\[Y_{t} = A_{t} K_{d t}^{\\alpha} L_{t}^{1 - \\alpha}\\]
\n", "\\[mc_{t} = 1\\]
\n", "\\[K_{d t} = K_{t-1} z_{t}\\]
\n", "\\[\\alpha = 0.35\\]
\n", "\\[\\log{\\left(A_{t} \\right)} = \\rho_{A} \\log{\\left(A_{t-1} \\right)} + \\epsilon_{A t}\\]
\n", "\\[\\operatorname{Set}\\left(\\left[ \\epsilon_{A t}\\right]\\right)\\]
\n", "\\[\\rho_{A} = 0.95\\]
\n", "Model Requirements \n", " \n", " Variable Shape Constraints Dimensions \n", " ──────────────────────────────────────────────────────── \n", " Theta () None \n", " alpha () None \n", " beta () None \n", " delta () None \n", " gamma_I () None \n", " phi_H () None \n", " psi_z () None \n", " rho_A () None \n", " rho_I () None \n", " rho_Theta () None \n", " rho_beta () None \n", " sigma_C () Positive None \n", " sigma_L () Positive None \n", " sigma_epsilon_A () Positive None \n", " sigma_epsilon_I () Positive None \n", " sigma_epsilon_Theta () Positive None \n", " sigma_epsilon_beta () Positive None \n", " error_sigma_Y () None \n", " error_sigma_I () None \n", " error_sigma_C () None \n", " error_sigma_L () None \n", " error_sigma_w () None \n", " error_sigma_r () None \n", " \n", " These parameters should be assigned priors inside a PyMC \n", " model block before calling the build_statespace_graph \n", " method. \n", "\n" ], "text/plain": [ "\u001b[3m Model Requirements \u001b[0m\n", " \n", " \u001b[1m \u001b[0m\u001b[1mVariable \u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1mShape\u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1mConstraints\u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1mDimensions\u001b[0m\u001b[1m \u001b[0m \n", " ──────────────────────────────────────────────────────── \n", " Theta \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " alpha \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " beta \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " delta \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " gamma_I \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " phi_H \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " psi_z \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " rho_A \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " rho_I \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " rho_Theta \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " rho_beta \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " sigma_C \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m Positive \u001b[3;35mNone\u001b[0m \n", " sigma_L \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m Positive \u001b[3;35mNone\u001b[0m \n", " sigma_epsilon_A \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m Positive \u001b[3;35mNone\u001b[0m \n", " sigma_epsilon_I \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m Positive \u001b[3;35mNone\u001b[0m \n", " sigma_epsilon_Theta \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m Positive \u001b[3;35mNone\u001b[0m \n", " sigma_epsilon_beta \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m Positive \u001b[3;35mNone\u001b[0m \n", " error_sigma_Y \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " error_sigma_I \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " error_sigma_C \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " error_sigma_L \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " error_sigma_w \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " error_sigma_r \u001b[1m(\u001b[0m\u001b[1m)\u001b[0m \u001b[3;35mNone\u001b[0m \n", " \n", "\u001b[2;3m These parameters should be assigned priors inside a PyMC \u001b[0m\n", "\u001b[2;3m model block before calling the build_statespace_graph \u001b[0m\n", "\u001b[2;3m method. \u001b[0m\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "ss_mod_extended.configure(\n", " observed_states=df_detrend.columns,\n", " measurement_error=df_detrend.columns,\n", " mode=\"JAX\",\n", " solver=\"scan_cycle_reduction\",\n", " use_adjoint_gradients=True,\n", " max_iter=20,\n", ")" ] }, { "cell_type": "code", "execution_count": 34, "id": "773a0d47", "metadata": { "execution": { "iopub.execute_input": "2025-03-15T12:29:33.141958Z", "iopub.status.busy": "2025-03-15T12:29:33.141889Z", "iopub.status.idle": "2025-03-15T12:29:33.367116Z", "shell.execute_reply": "2025-03-15T12:29:33.366863Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/jessegrabowski/mambaforge/envs/geconpy-dev/lib/python3.12/site-packages/pymc_extras/statespace/utils/data_tools.py:159: ImputationWarning: Provided data contains missing values and will be automatically imputed as hidden states during Kalman filtering.\n", " warnings.warn(impute_message, ImputationWarning)\n" ] } ], "source": [ "with pm.Model(coords=ss_mod_extended.coords) as usa_rbc_extended:\n", " ss_mod_extended.to_pymc()\n", "\n", " # Save the pre-defined priors as a variable we can use to stay organized\n", " prior_dict = ss_mod_extended.param_priors.copy()\n", "\n", " for shock in ss_mod_extended.shock_names:\n", " prior_dict[f\"sigma_{shock}\"] = pz.maxent(pz.Gamma(), lower=0.01, upper=0.1, plot=False)\n", " prior_dict[f\"sigma_{shock}\"].to_pymc(f\"sigma_{shock}\")\n", "\n", " # As mentioned above, we'll make the measurement errors between 0% and 5%\n", " for var in ss_mod_extended.error_states:\n", " d = pz.maxent(pz.Gamma(), lower=0.01, upper=0.05, plot=False)\n", " prior_dict[f\"error_sigma_{var}\"] = d\n", " d.to_pymc(f\"error_sigma_{var}\")\n", "\n", " ss_mod_extended.build_statespace_graph(\n", " data=df_detrend[ss_mod_extended.observed_states],\n", " add_norm_check=True,\n", " add_solver_success_check=True,\n", " add_steady_state_penalty=True,\n", " )" ] }, { "cell_type": "code", "execution_count": 35, "id": "cf442d9e", "metadata": { "execution": { "iopub.execute_input": "2025-03-15T12:29:33.368378Z", "iopub.status.busy": "2025-03-15T12:29:33.368300Z", "iopub.status.idle": "2025-03-15T12:29:34.295664Z", "shell.execute_reply": "2025-03-15T12:29:34.295371Z" } }, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "
Sampler Progress
\n", "Total Chains: 6
\n", "Active Chains: 0
\n", "\n", " Finished Chains:\n", " 6\n", "
\n", "Sampling for 9 minutes
\n", "\n", " Estimated Time to Completion:\n", " now\n", "
\n", "\n", " \n", "| Progress | \n", "Draws | \n", "Divergences | \n", "Step Size | \n", "Gradients/Draw | \n", "
|---|---|---|---|---|
| \n", " \n", " | \n", "1000 | \n", "1 | \n", "0.58 | \n", "7 | \n", "
| \n", " \n", " | \n", "1000 | \n", "9 | \n", "0.57 | \n", "7 | \n", "
| \n", " \n", " | \n", "1000 | \n", "3 | \n", "0.54 | \n", "7 | \n", "
| \n", " \n", " | \n", "1000 | \n", "3 | \n", "0.56 | \n", "7 | \n", "
| \n", " \n", " | \n", "1000 | \n", "9 | \n", "0.56 | \n", "3 | \n", "
| \n", " \n", " | \n", "1000 | \n", "0 | \n", "0.59 | \n", "7 | \n", "
Sampling ... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00 / 0:00:23\n\n", "text/plain": "Sampling ... \u001b[32m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[35m100%\u001b[0m 0:00:00 / 0:00:23\n" }, "metadata": {}, "output_type": "display_data" } ], "tabbable": null, "tooltip": null } }, "16794a06e8db4407ab7a1c156a19e245": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "2eff8a0852b1495d88682d4aeb1278f0": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "753db7c4e93d4f068d8cd0927d4517ae": { "model_module": "@jupyter-widgets/output", "model_module_version": "1.0.0", "model_name": "OutputModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/output", "_model_module_version": "1.0.0", "_model_name": "OutputModel", "_view_count": null, "_view_module": "@jupyter-widgets/output", "_view_module_version": "1.0.0", "_view_name": "OutputView", "layout": "IPY_MODEL_2eff8a0852b1495d88682d4aeb1278f0", "msg_id": "", "outputs": [ { "data": { "text/html": "
Sampling ... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00 / 0:01:36\n\n", "text/plain": "Sampling ... \u001b[32m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[35m100%\u001b[0m 0:00:00 / 0:01:36\n" }, "metadata": {}, "output_type": "display_data" } ], "tabbable": null, "tooltip": null } }, "9c2ee61dd79a4364869ca9d38ee5440f": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "b371ec7b595c40c3a8c5f5932c27a64d": { "model_module": "@jupyter-widgets/output", "model_module_version": "1.0.0", "model_name": "OutputModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/output", "_model_module_version": "1.0.0", "_model_name": "OutputModel", "_view_count": null, "_view_module": "@jupyter-widgets/output", "_view_module_version": "1.0.0", "_view_name": "OutputView", "layout": "IPY_MODEL_16794a06e8db4407ab7a1c156a19e245", "msg_id": "", "outputs": [ { "data": { "text/html": "
Sampling ... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00 / 0:02:14\n\n", "text/plain": "Sampling ... \u001b[32m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[35m100%\u001b[0m 0:00:00 / 0:02:14\n" }, "metadata": {}, "output_type": "display_data" } ], "tabbable": null, "tooltip": null } } }, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 5 }