diff --git a/doc/manual/source/examples.rst b/doc/manual/source/examples.rst index 7a367d82b803d49a010d64f01f5d547b8cab2fd3..f5acea2b497ec5112cc8e4d93e3a5e9026bd9406 100644 --- a/doc/manual/source/examples.rst +++ b/doc/manual/source/examples.rst @@ -79,3 +79,10 @@ description, please refer to the comments inside the files themselves. File demonstrating how to conduct optimal policy experiments in a simple New Keynesian model under commitment (Ramsey) with a user-defined conditional steady state file + +``rbc_irf_matching.mod`` + + Baseline RBC model with government spending shocks estimated via impulse response function (IRF) matching. + Both Frequentist (Maximum Likelihood) and Bayesian (Slice Sampling) approaches are presented. + Additionally, it is shown how to estimate an AR(2)-process + by working with the roots of the autoregressive process instead of the coefficients diff --git a/examples/rbc_irf_matching.mod b/examples/rbc_irf_matching.mod new file mode 100644 index 0000000000000000000000000000000000000000..27aecaa5322b2c6b0608bfe797b5ba814324c61f --- /dev/null +++ b/examples/rbc_irf_matching.mod @@ -0,0 +1,265 @@ +/* + * This file presents a baseline RBC model with government spending shocks where the persistence of the + * government spending shock is estimated via impulse response function (IRF) matching. + * + * Notes: + * - The empirical IRFs were estimated using the Blanchard/Perotti (2002) approach, see + * https://github.com/JohannesPfeifer/DSGE_mod/blob/master/RBC_IRF_matching/get_empirical_IRFs.m + * - They are given in the csv file rbc_irf_matching_data.csv, the first two columns contain + * the empirical IRFs of G and Y, while the third and fourth column contain the corresponding + * variances of the IRFs from a bootstrap approach. + * Importantly: this mod file does not show how to get the empirical IRFs from a SVAR model, + * but takes these as "data". + * - Of course the RBC model is not capable of generating the consumption increase + * after a government spending shock. For that reason, this mod-file only targets the IRFs for G and Y. + * - The weighting matrix uses a diagonal matrix with the inverse of the pointwise IRF variances on the main diagonal. + * - The empirical IRFs and model IRFs use an impulse size of 1 percent. Thus, there is no uncertainty about the + * initial impact. The IRF matching therefore only targets the G-response starting in the second period. + * - Note that for the current model, the number of IRFs exceeds the number of VAR parameters. Therefore, + * the distribution of the estimator will be non-standard, see Guerron-Quintana/Inoue/Kilian (2016), + * http://dx.doi.org/10.1016/j.jeconom.2016.09.009 + * - The mod-file also shows how to estimate an AR(2)-process by working with the roots of the autoregressive + * process instead of the coefficients. This allows for easily restricting the process to the stability region and + * would allow specifying e.g. a beta prior for both roots as was done in Born/Peter/Pfeifer (2013), Fiscal news + * and macroeconomic volatility, https://doi.org/10.1016/j.jedc.2013.06.011 + * + * Please note that the following copyright notice only applies to this Dynare + * implementation of the model. + */ + +/* + * Copyright (C) 2016-17 Johannes Pfeifer, + * Copyright (C) 2024 Dynare Team + * + * This file is part of Dynare. + * + * Dynare is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Dynare is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Dynare. If not, see <https://www.gnu.org/licenses/>. + */ + +%---------------------------------------------------------------- +% define variables +%---------------------------------------------------------------- +@#define IRF_periods=80 + +var y ${y}$ (long_name='output') + c ${c}$ (long_name='consumption') + k ${k}$ (long_name='capital') + l ${l}$ (long_name='hours') + z ${z}$ (long_name='TFP') + ghat ${\hat g}$ (long_name='government spending') + r ${r}$ (long_name='annualized interest rate') + w ${w}$ (long_name='real wage') + invest ${i}$ (long_name='investment') + log_y ${\log(y)}$ (long_name='log output') + log_k ${\log(k)}$ (long_name='log capital stock') + log_c ${\log(c)}$ (long_name='log consumption') + log_l ${\log(l)}$ (long_name='log labor') + log_w ${\log(w)}$ (long_name='log real wage') + log_invest ${\log(i)}$ (long_name='log investment') +; + +varexo eps_z ${\varepsilon_z}$ (long_name='TFP shock') + eps_g ${\varepsilon_g}$ (long_name='government spending shock') +; + +%---------------------------------------------------------------- +% define parameters +%---------------------------------------------------------------- + +parameters + beta ${\beta}$ (long_name='discount factor') + psi ${\psi}$ (long_name='labor disutility parameter') + sigma ${\sigma}$ (long_name='risk aversion') + delta ${\delta}$ (long_name='depreciation rate') + alpha ${\alpha}$ (long_name='capital share') + rhoz ${\rho_z}$ (long_name='persistence TFP shock') + root_g_1 ${\rho_g}$ (long_name='first root of AR(2) G process') + root_g_2 ${\rho_g}$ (long_name='second root of AR(2) G process') + gammax ${\gamma_x}$ (long_name='composite growth rate') + gshare ${\frac{G}{Y}}$ (long_name='government spending share') + n ${n}$ (long_name='population growth') + x ${x}$ (long_name='technology growth (per capita output growth)') + i_y ${\frac{I}{Y}}$ (long_name='investment-output ratio') + k_y ${\frac{K}{Y}}$ (long_name='capital-output ratio') + g_ss ${\bar G}$ (long_name='government spending in steady state') + l_ss ${\bar L}$ (long_name='labor in steady state') +; + +%---------------------------------------------------------------- +% model equations +%---------------------------------------------------------------- +model; +# rho_g_1= (root_g_1+root_g_2); +# rho_g_2= - root_g_1*root_g_2; +[name='Euler equation'] +c^(-sigma)=beta/gammax*c(+1)^(-sigma)* + (alpha*exp(z(+1))*(k/l(+1))^(alpha-1)+(1-delta)); +[name='Labor FOC'] +psi*c^sigma*1/(1-l)=w; +[name='Law of motion capital'] +gammax*k=(1-delta)*k(-1)+invest; +[name='resource constraint'] +y=invest+c+g_ss*exp(ghat); +[name='production function'] +y=exp(z)*k(-1)^alpha*l^(1-alpha); +[name='real wage/firm FOC labor'] +w=(1-alpha)*y/l; +[name='annualized real interst rate/firm FOC capital'] +r=4*alpha*y/k(-1); +[name='exogenous TFP process'] +z=rhoz*z(-1)+eps_z; +[name='government spending process'] +ghat=rho_g_1*ghat(-1)+rho_g_2*ghat(-2)+eps_g; +[name='Definition log output'] +log_y = log(y); +[name='Definition log capital'] +log_k = log(k); +[name='Definition log consumption'] +log_c = log(c); +[name='Definition log hours'] +log_l = log(l); +[name='Definition log wage'] +log_w = log(w); +[name='Definition log investment'] +log_invest = log(invest); +end; + +%---------------------------------------------------------------- +% set steady state values +%--------------------------------------------------------------- + +steady_state_model; + gammax = (1+n)*(1+x); + delta = i_y/k_y-x-n-n*x; + beta = (1+x)*(1+n)/(alpha/k_y+(1-delta)); + l = l_ss; + k = ((1/beta*(1+n)*(1+x)-(1-delta))/alpha)^(1/(alpha-1))*l; + invest = (x+n+delta+n*x)*k; + y = k^alpha*l^(1-alpha); + g = gshare*y; + g_ss = g; + c = (1-gshare)*k^(alpha)*l^(1-alpha)-invest; + psi = (1-alpha)*(k/l)^alpha*(1-l)/c^sigma; + w = (1-alpha)*y/l; + r = 4*alpha*y/k; + log_y = log(y); + log_k = log(k); + log_c = log(c); + log_l = log(l); + log_w = log(w); + log_invest = log(invest); + z = 0; + ghat =0; +end; + +%---------------------------------------------------------------- +% calibration +%---------------------------------------------------------------- +sigma = 1; +alpha = 0.33; +i_y = 0.25; +k_y = 10.4; +x = 0.0055; +n = 0.0027; +rhoz = 0.97; +root_g_1 = 0.9602; +root_g_2 = 0; +gshare = 0.2038; +l_ss = 1/3; + +shocks; +var eps_g = 1; +end; +steady; +check; + +varobs ghat log_y y; // you need to specify observables + +%---------------------------------------------------------------- +% IRF matching example 1: +% - different ways to MANUALLY enter values and weights +% - Maximum likelihood estimation +%---------------------------------------------------------------- +estimated_params; +root_g_1 , 0.90 , 0, 1; +root_g_2 , 0.10 , 0, 1; +end; + +xx = [1.007,1.117,1.092]; +ww = [51,52]; + +matched_irfs; +var log_y ; varexo eps_g ; periods 1, 2 ; values 0.20, 0.17 ; weights 360, 140 ; +var ghat ; varexo eps_g ; periods 2 3:5 ; values 1.01, (xx) ; weights 50, 20 ; +var y ; varexo eps_g ; periods 10:11 ; values (log(1.05)) ; weights (ww) ; +end; + +method_of_moments(mom_method = irf_matching, mode_compute = 5, additional_optimizer_steps=[4]); + + +%---------------------------------------------------------------- +% IRF matching example 2 +% - use all IRFs given in MATLAB objects +% - use Bayesian Slice sampler +%---------------------------------------------------------------- +estimated_params(overwrite); +root_g_1 , 0.50 , 0, 1, beta_pdf , 0.50 , 0.20; +root_g_2 , 0.10 , 0, 1, beta_pdf , 0.50 , 0.20; +end; + +% get data +irfs_data = importdata('rbc_irf_matching_data.csv'); +irfs_ghat_eps_g = irfs_data.data(2:80,1); % start in t=2 due to identification restrictions in SVAR +irfs_log_y_eps_g = irfs_data.data(1:80,2); +weights_ghat_eps_g = 1./irfs_data.data(2:80,3); +weights_log_y_eps_g = 1./irfs_data.data(1:80,4); + +matched_irfs(overwrite); +var ghat ; varexo eps_g; periods 2:80; values (irfs_ghat_eps_g); weights (weights_ghat_eps_g); +var log_y; varexo eps_g; periods 1:80; values (irfs_log_y_eps_g); weights (weights_log_y_eps_g); +end; + +method_of_moments(mom_method = irf_matching + ,order = 1 + ,mh_nblocks = 2, mh_replic = 50 + ,posterior_sampling_method = 'slice' + ,plot_priors = 1 + ); + +%---------------------------------------------------------------- +% IRF matching example 3: +% - use anonymous function to access IRFs more flexibly +% - showcase how to use irf_matching_file +% - find posterior mode +%---------------------------------------------------------------- + +% get data +irfs_data = importdata('rbc_irf_matching_data.csv'); + +% use anonymous function (or MATLAB function) to have more flexibility, but inputs can only be numerical +% we also take 100 just for illustration that you can do any required transformation in an irf_matching_file +irfs_vals = @(j) 100.*(irfs_data.data(2:80,j)); +irfs_weights = @(j) 1./(irfs_data.data(2:80,j)); + +matched_irfs(overwrite); +var ghat ; varexo eps_g; periods 2:80; values (irfs_vals(1)); weights (irfs_weights(3)); +var log_y; varexo eps_g; periods 2:80; values (irfs_vals(2)); weights (irfs_weights(4)); +end; + +% we use the irf_matching_file to transform variable y to log(y) so the model +% variable aligns with the variable from the given empirical SVAR +method_of_moments(mom_method = irf_matching + ,irf_matching_file = rbc_irf_matching_transformations + ,mh_replic = 0,plot_priors = 0 + ); \ No newline at end of file diff --git a/examples/rbc_irf_matching_data.csv b/examples/rbc_irf_matching_data.csv new file mode 100644 index 0000000000000000000000000000000000000000..91647e6e15123fd59309037c2d4a3de6db69e66e --- /dev/null +++ b/examples/rbc_irf_matching_data.csv @@ -0,0 +1,81 @@ +G,Y,var_G,var_Y +1,0.208070478344545,1.12054105855257e-33,0.0027602236508546 +1.01463693816715,0.166450236530301,0.00583152879723266,0.00679133276154495 +1.00764238152471,0.230433660500946,0.0111184998994349,0.00952654639548326 +1.11696510115769,0.215252336067127,0.0164663222282161,0.0113464752654877 +1.09223998892147,0.222958847463141,0.0216966728235886,0.013533420700953 +1.03736643322521,0.243972174559692,0.0257004687001329,0.0151053406229588 +1.01711112212948,0.261016995864984,0.0303544421773506,0.0162405771811019 +0.967577038730636,0.269060130173636,0.0339076793971577,0.0171352445593892 +0.912649802559854,0.278584624341349,0.03620212016322,0.0179592573395723 +0.867058516612021,0.283001682449059,0.038151205713992,0.0187783728830758 +0.820597806619289,0.283598412003388,0.0396511019185971,0.0194594651103199 +0.77563492323912,0.281760898055785,0.0403347277351183,0.0198713886600475 +0.735846344956036,0.277110769410598,0.0407036832985301,0.0198800923047385 +0.698850036380633,0.269931336693529,0.0407917065478011,0.0194569744071588 +0.664596916513962,0.261143278620547,0.0405012612908696,0.0186271529903141 +0.633528960929983,0.251064751428521,0.0400022455114944,0.0174559567202935 +0.604912703413876,0.240132445806634,0.0393594337883548,0.0160603819816583 +0.578360605178466,0.228823340604282,0.0385445703756185,0.0145721875285327 +0.55371549942988,0.217458827167635,0.0376075435183867,0.0130962012473614 +0.530621264922238,0.206298301306342,0.0365729915386994,0.0117094186557471 +0.508813730835084,0.195562831928213,0.0354403165776896,0.010461528435305 +0.488125279535286,0.185390333897221,0.0342268285355491,0.00937102041748079 +0.468386758403429,0.175863201796663,0.0329491563166573,0.00843340667968603 +0.449471041462416,0.167022878990409,0.0316223984500399,0.00763260719022832 +0.431296406103216,0.158870322365946,0.0302644814355948,0.00694575471751527 +0.413799596231625,0.151377829877172,0.0288934660918837,0.00634988691182681 +0.396937751823371,0.144499570770831,0.0275270293690654,0.00582564616104379 +0.380685985677042,0.13817717429653,0.0261806418593218,0.00535836547483349 +0.365028340579903,0.132346351995696,0.0248665732796567,0.00493799567463183 +0.349954881191496,0.126942318129237,0.0235951459469029,0.0045584177486503 +0.335459383987806,0.121903145354258,0.022373467574597,0.00421578980579863 +0.321536118675061,0.117172332783573,0.021205727363848,0.00390754150917342 +0.308178316488601,0.112700463782387,0.0200943664605458,0.00363147379277453 +0.295377351869768,0.108445858384018,0.019040123479836,0.00338513596160304 +0.283122066100135,0.104374632848495,0.0180423053448312,0.00316565728079348 +0.271398650164465,0.100460305211796,0.0170995738403303,0.0029698495549103 +0.260190863606074,0.0966830386847356,0.0162100638803249,0.00279435029276752 +0.249480370591311,0.0930286987898092,0.0153715252985084,0.00263589300567087 +0.239247213436084,0.0894878338463341,0.0145815957210218,0.002491545439791 +0.229470346306504,0.0860546497623421,0.0138378615720872,0.00235884935269597 +0.220128148976686,0.0827260491927552,0.0131378639605267,0.00223588384965084 +0.211198902955524,0.0795007779016462,0.0124791808709379,0.00212125323555392 +0.20266120682353,0.0763786992809964,0.0118594333328108,0.0020139945677632 +0.194494311443246,0.0733602078340912,0.0112762767066973,0.00191345670528973 +0.186678374172779,0.0704457804639186,0.0107274179119509,0.0018191767154505 +0.179194635081175,0.0676356552603192,0.0102106211287206,0.00173077210770515 +0.172025520775263,0.064929622999291,0.00972370794405955,0.0016478667536602 +0.165154686254735,0.0623269135604257,0.00926457432688479,0.00157005669764952 +0.158567006362608,0.0598261581740075,0.00883120737460965,0.00149690646906453 +0.152248528236286,0.0574254089705774,0.00842170119327602,0.00142796690804853 +0.146186396016794,0.0551221987689224,0.00803427530290723,0.0013628024472437 +0.140368757967879,0.0529136261066764,0.00766728912012237,0.00130101642649392 +0.134784664597338,0.0507964530245216,0.00731924890008266,0.00124226770384004 +0.129423964825334,0.0487672057100314,0.00698880917814805,0.00118627695274624 +0.124277205618631,0.046822270602385,0.00667476765058639,0.00113282353216918 +0.119335538941298,0.0449579808540134,0.0063760543634253,0.0010817364372413 +0.11459063850232,0.0431706900378893,0.00609171803409054,0.00103288330782315 +0.110034627608638,0.0414568316344016,0.00582091131964085,0.000986160390158817 +0.105660018476945,0.0398129641266707,0.00556287623442419,0.000941484872060258 +0.101459662633845,0.0382358024894679,0.00531693108962639,0.000898789756847698 +0.0974267115198392,0.0367222375053657,0.00508245926485931,0.000858020371449084 +0.0935545860830807,0.0352693447261226,0.00485889955647229,0.000819131356725285 +0.0898369539782651,0.0338743850644921,0.00464573784815541,0.00078208329876107 +0.0862677129419094,0.0325347989994978,0.00444249975285543,0.000746838714885712 +0.0828409789666302,0.0312481962526895,0.00424874389794858,0.000713357679487274 +0.0795510780159448,0.0300123425850257,0.00406405581698042,0.000681593780987298 +0.076392540182423,0.0288251451088667,0.00388804253930626,0.000651491166504331 +0.0733600953745436,0.0276846372357925,0.00372032800246882,0.000622983230006533 +0.070448669804769,0.0265889641106603,0.00356054943074244,0.000595993138422716 +0.0676533827305797,0.0255363691313685,0.0034083547518209,0.00057043599416774 +0.064969543062731,0.024525181932661,0.00326340099829315,0.00054622212266834 +0.0623926455954874,0.0235538080267355,0.00312535355830137,0.000523260827093126 +0.0599183667294525,0.0226207201454146,0.00299388608378455,0.000501463968548093 +0.0575425596484649,0.0217244512173301,0.00286868083997892,0.000480748874949654 +0.055261248979131,0.0208635888360229,0.00274942930127684,0.000461040295246497 +0.0530706250072852,0.0200367710268393,0.00263583284298659,0.000442271333040507 +0.0509670375530574,0.0192426830970757,0.00252760342283966,0.000424383467067322 +0.0489469896186406,0.0184800553498327,0.00242446418777184,0.000407325873359123 +0.0470071309236527,0.0177476614525368,0.0023261499716701,0.000391054302991331 +0.0451442514353558,0.0170443172715253,0.00223240766511842,0.000375529754828271 diff --git a/examples/rbc_irf_matching_transformations.m b/examples/rbc_irf_matching_transformations.m new file mode 100644 index 0000000000000000000000000000000000000000..f29572090255563d30450f86c66dbb64a5013333 --- /dev/null +++ b/examples/rbc_irf_matching_transformations.m @@ -0,0 +1,50 @@ +function [modelIrf, error_indicator] = rbc_irf_matching_transformations(modelIrf, M_, options_mom_, ys_) +% ------------------------------------------------------------------------- +% This file manipulates model IRFs to be consistent with empirical IRFS +% ------------------------------------------------------------------------- +% INPUTS +% - modelIrf: [options_mom_.irf by M_.endo_nbr by M_.exo_nbr] +% array of IRFs for all model variables and all shocks +% - M_: [structure] Dynare model structure +% - options_mom_: [structure] Dynare options structure +% - ys_: [double] steady state values of all endogenous variables +% ------------------------------------------------------------------------- +% OUTPUTS +% - modelIrf: [options_mom_.irf by M_.endo_nbr by M_.exo_nbr] +% modified array of IRFs for all model variables and all shocks +% - error_indicator: [boolean] indicator of success (0) or failure (1) +% ------------------------------------------------------------------------- +% This function is called by +% - mom.run +% ------------------------------------------------------------------------- + +% Copyright © 2024 Dynare Team +% +% This file is part of Dynare. +% +% Dynare is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% Dynare is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with Dynare. If not, see <https://www.gnu.org/licenses/>. + +% initialize error indicator +error_indicator = 0; + +% get indices of variables +idx_ghat = find(ismember(M_.endo_names,'ghat')); +idx_log_y = find(ismember(M_.endo_names,'log_y')); +idx_eps_g = find(ismember(M_.exo_names,'eps_g')); + +% manipulate the model IRFs to match the empirical IRFs (e.g. cumsum, common scaling, trends, ratios, etc.) +modelIrf(:,idx_ghat,idx_eps_g) = 100.*modelIrf(:,idx_ghat,idx_eps_g); +modelIrf(:,idx_log_y,idx_eps_g) = 100.*modelIrf(:,idx_log_y,idx_eps_g); + +end \ No newline at end of file