diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e141d98 --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +*~ +trash/ + +# Ignore files used in estimation +g1.mat +g2.mat +g3.mat +H.dat + +# Ignore large output files +save/* +!mode_in + +# Ignore directories for user-generate output +figures/*tex +figures/*pdf +graphs/* diff --git a/Main.m b/Main.m new file mode 100644 index 0000000..99564c9 --- /dev/null +++ b/Main.m @@ -0,0 +1,48 @@ +%% Main.m +%% This script produces all output associated with the FRBNY DSGE model. +% +% Copyright Federal Reserve Bank of New York. You may reproduce, use, modify, +% make derivative works of, and distribute and this code in whole or in part +% so long as you keep this notice in the documentation associated with any +% distributed works. Neither the name of the Federal Reserve Bank of New +% York (FRBNY) nor the names of any of the authors may be used to endorse or +% promote works derived from this code without prior written permission. +% Portions of the code attributed to third parties are subject to applicable +% third party licenses and rights. By your use of this code you accept this +% license and any applicable third party license. +% +% THIS CODE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT ANY WARRANTIES OR +% CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +% LIMITATION ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, +% MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, EXCEPT TO THE EXTENT +% THAT THESE DISCLAIMERS ARE HELD TO BE LEGALLY INVALID. FRBNY IS NOT, UNDER +% ANY CIRCUMSTANCES, LIABLE TO YOU FOR DAMAGES OF ANY KIND ARISING OUT OF OR +% IN CONNECTION WITH USE OF OR INABILITY TO USE THE CODE, INCLUDING, BUT NOT +% LIMITED TO DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, PUNITIVE, SPECIAL OR +% EXEMPLARY DAMAGES, WHETHER BASED ON BREACH OF CONTRACT, BREACH OF WARRANTY, +% TORT OR OTHER LEGAL OR EQUITABLE THEORY, EVEN IF FRBNY HAS BEEN ADVISED OF +% THE POSSIBILITY OF SUCH DAMAGES OR LOSS AND REGARDLESS OF WHETHER SUCH +% DAMAGES OR LOSS IS FORESEEABLE. + +%% Initialization +clear +close all +spec_990 % sets important variables and flags +set_paths % adds necessary paths + +%% Estimation +% In this stage we draw from the distribution for the parameters. The modal +% parameters as well as the draws of parameters, are outputted in the /save +% folder. +gibb + + +%% Forecasting +% Here we produce forecasts for our observable variables, one associated +% with each draw of the parameters, and saves them in the /save folder. +forecast_parallel_est_ant + +%% Plotting +forplot % produces series to be plotted +plotPresentation % produces plots of series outputted from forplot, which + % are saved in the /graphs folder diff --git a/README.md b/README.md new file mode 100644 index 0000000..31ef130 --- /dev/null +++ b/README.md @@ -0,0 +1,176 @@ +# FRBNY DSGE Model (Version 990.2) + +MATLAB code to estimate and forecast the model discussed in the Liberty Street Economics blog post "The FRBNY DSGE Model Forecast". + +# Running the Code + +## Running with Default Settings + +All you need to do is run the file `Main.m`. This script will run the entire +set of code, calling + + - `set_paths.m`: Set default directories for input and output; add code + subfolders to MATLAB path. + - `spec_990.m`: Set model specifications and important flags for estimation + and forecasting. + - `gibb_est_ant.m`: Find posterior mode and sample from posterior distribution. + - `forecast_parallel_est_ant.m`: Forecast observables; can run in parallel. + - `forplot.m`: Load forecasts into data structures to prepare for plotting. + - `plotPresentation.m`: Plot forecasts. + +## Running with Modified Settings + +If you would like to change defaults for estimation and forecasts, see +`spec_990.m`. There, you can modify + + - **Estimation Parameters** + - `reoptimize`: Whether to re-optimize and find the mode or use saved mode. + - `CH`: Whether to re-compute the hession or use saved. + - `nsim`: The number of posterior draws per block. + - `nblocks`: The number of blocks. + - `nburn`: Size of the burn-in. + - `jstep`: From the blocks, the forecasting code will only use every + jstep-th element. + - **Forecast Parameters** + - `zerobound`: Whether to incorporate anticipated policy shocks. + - `peachflag`: Whether to condition time T+1 forecasts of observables on + user-provided forecasts of observables (treating the information supplied + by the user as data). + - `distr`: Flag to specify whether to parallelize the forecast procedure. + - `nMaxWorkers`: Number of workers to use in parallel forecast procedure. + +# Directory Structure + +In the main folder, there exist the following directories to house code +components: + + - `data/`: Input data + - `dsgesolv/`: Solving the model; includes `gensys.m` code. + - `estimation/`: Mode-finding and posterior sampling. + - `figures/`: For output including parameter moment-tables and TeX tables. + - `forecast/`: Forecasting programs. + - `graphs/`: For graphs of forecasts. + - `initializaization/`: Loading data, defining model structure, setting up + important model flags. + - `kalman/`: Kalman filtering and smoothing. + - `plotting`: Loading forecast distributions and generating/saving plots. + - `save/`: Input mode and output data generated by the code (output mode, + posterior draws, forecasts). + - `toolbox/`: Supporting programs. + + +# Program Details + +This section describes important programs in greater detail. If the user +is interested only in running the default model and reproducing the forecast +results, this section can be ignored. + +This section focuses on what the code does and why, while the code itself +(including comments) provides detailed information regarding *how* these basic +procedures are implemented. + +## Estimation + +**Main Program**: `estimation/gibb_est_ant.m` + +**Purpose**: Finds modal parameter estimates and samples from posterior +distribution. + +**Main Steps** + +- *Initialization*: Read in transform raw data from `data/`. Load files from + `initialization/` related to model specification, parameter priors, parameter + restrictions. +- *Find Mode*: The main program will call the `csminwel.m` optimization routine + to find modal parameter estimates. Can optionally start estimation from a + starting parameter vector by specifying `data/mode_in.` +- *Sample from Posterior*: Posterior sampling begins from the computed mode, + first computing the Hessian matrix to scale the proposal distribution in the + Metropolis Hastings algorithm. Settings for the number of sampling blocks and + the size of those blocks can be specified in `spec_990.m`. + +*Remark*: In addition to saving each draw of the parameter vector, the +estimation program also saves the resulting posterior value and transition +equation matrices implied by each draw of the parameter vector. This is to save +time in the forecasting step since that code can avoid recomputing those +matrices. In addition, to save space, all files in `save/` are binary files. + +## Forecasting + +**Main Program**: `forecast/forecast_parallel_est_ant.m` + +**Purpose**: Compute forecast distribution for the observables, sampling from +the full posterior distribution of parameters and sampling exogenous shocks. + +**Main Steps** + +- *Load Draws*: Load in posterior distribution blocks that are output from the + estimation stage. +- *Filter and Smooth*: Pass matrices defining the state transition equation + into `forecastFcn_est_ant.m`, which will filter and smooth the states over + the history. +- *Forecast*: Compute forecasts using `getForecast.m`, which takes matrices + corresponding to a posterior draw and uses them to iterate on the time T + state vector to obtain forecasts, adding in draws of exogenous shocks as + well. + +*Remark*: The code can be run in parallel or sequentially. Running in parallel +requires the MATLAB parallel toolbox. + +## Plotting ## + +**Main Programs**: `plotting/forplot.m`, `plotting/plotPresentation.m` + +**Purpose**: Generate plots of observables. + +**Main Steps** + +- *Load Plots*: The program `forplot.m` will load output from the forecast + program into the workspace, computing entries in the data structures `Means` + and `Bands`. +- *Plot*: The program `plotPresentation.m` will plot the forecasts and shock + decompositions, saving the graphs in the `graphs/` folder. + +*Remark*: Each time `forplot.m` is called, it will attempt to recompute the +forecast means and bands, which takes some time. However, these are saved in +`save/` after the very first call to `forplot.m`. To use these saved Means and +Bands structures and avoid recomputing, set `useSavedMB=1` before running +`forplot.m`. + +# Final Notes on MATLAB Versions and Toolboxes + +In certain functions implemented in this program are Toolbox functions provided +by Mathworks. If you are receiving errors in running these programs due to +undefined functions, it is likely because you do not yet have access to these +Toolboxes. For example, to run the forecasts in parallel (the default setting), +you will need the parallel toolbox. Also, `dlyap.m`, a function to solve +discrete-time Lyapunov equations, comes from the Control System Toolbox. + +These programs are meant to be run in Matlab09a. While we have not attempted to +run these programs using a more recent version of Matlab, it is possible that +some of the Matlab-defined functions are not identical and thus may yield +nonidentical results. + +# DISCLAIMER + +Copyright Federal Reserve Bank of New York. You may reproduce, use, modify, +make derivative works of, and distribute and this code in whole or in part so +long as you keep this notice in the documentation associated with any +distributed works. Neither the name of the Federal Reserve Bank of New York +(FRBNY) nor the names of any of the authors may be used to endorse or promote +works derived from this code without prior written permission. Portions of the +code attributed to third parties are subject to applicable third party licenses +and rights. By your use of this code you accept this license and any +applicable third party license. + +THIS CODE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT ANY WARRANTIES OR CONDITIONS +OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY +WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS +FOR A PARTICULAR PURPOSE, EXCEPT TO THE EXTENT THAT THESE DISCLAIMERS ARE HELD +TO BE LEGALLY INVALID. FRBNY IS NOT, UNDER ANY CIRCUMSTANCES, LIABLE TO YOU +FOR DAMAGES OF ANY KIND ARISING OUT OF OR IN CONNECTION WITH USE OF OR +INABILITY TO USE THE CODE, INCLUDING, BUT NOT LIMITED TO DIRECT, INDIRECT, +INCIDENTAL, CONSEQUENTIAL, PUNITIVE, SPECIAL OR EXEMPLARY DAMAGES, WHETHER +BASED ON BREACH OF CONTRACT, BREACH OF WARRANTY, TORT OR OTHER LEGAL OR +EQUITABLE THEORY, EVEN IF FRBNY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES OR LOSS AND REGARDLESS OF WHETHER SUCH DAMAGES OR LOSS IS FORESEEABLE. diff --git a/README.pdf b/README.pdf new file mode 100644 index 0000000..46f1828 Binary files /dev/null and b/README.pdf differ diff --git a/data/ExpFFR_OIS.m b/data/ExpFFR_OIS.m new file mode 100644 index 0000000..a8ef1ac --- /dev/null +++ b/data/ExpFFR_OIS.m @@ -0,0 +1,107 @@ + +%% Loads in expected FFR derived from OIS quotes + + +function [ExpFFR,peachdata_FFR] = ExpFFR_OIS(nant,antlags,psize,zerobound,peachflag) + +% 2008-Q4 expectations (from Jan-2009 BCFF survey, conducted mid-/end- of Dec-2008) +ExpFFR(1,:) = [0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0 2.1 2.2 2.4]; + +% % 2009-Q1 expectations (from Apr-2009 BCFF survey, conducted mid-/end- of Mar-2009) +ExpFFR(2,:) = [0.2 0.3 0.5 0.6 0.8 1.1 1.3 1.5 1.7 2.0 2.2 2.4 2.5]; + +% 2009-Q2 expectations (from Jul-2009 BCFF survey, conducted mid-/end- of Jun-2009) +ExpFFR(3,:) = [0.2 0.4 0.7 1.1 1.4 1.8 2.2 2.6 2.9 3.2 3.5 3.7 4.0]; + +% 2009-Q3 expectations (from Oct-2009 BCFF survey, conducted mid-/end- of Sep-2009) +ExpFFR(4,:) = [0.2 0.4 0.7 1.0 1.4 1.8 2.1 2.4 2.7 2.9 3.1 3.3 3.6]; + +% 2009-Q4 expectations (from Jan-2010 BCFF survey, conducted mid-/end- of Dec-2009) +ExpFFR(5,:) = [0.2 0.4 0.8 1.2 1.6 2.0 2.4 2.7 3.0 3.3 3.5 3.7 4.0]; + +% 2010-Q1 expectations (from Apr-2010 BCFF survey, conducted mid-/end- of Mar-2010) +ExpFFR(6,:) = [0.2 0.4 0.6 0.9 1.2 1.6 1.9 2.3 2.6 2.9 3.1 3.4 3.6]; + +% 2010-Q2 expectations (from Jul-2010 BCFF survey, conducted mid-/end- of Jun-2010) +ExpFFR(7,:) = [0.2 0.3 0.4 0.5 0.6 0.8 1.0 1.2 1.4 1.7 1.9 2.2 2.2]; + +% 2010-Q3 expectations (from Oct-2010 BCFF survey, conducted mid-/end- of Sep-2010) +ExpFFR(8,:) = [0.2 0.2 0.2 0.3 0.4 0.5 0.6 0.8 0.9 1.1 1.3 1.5 1.6]; + +% 2010-Q4 expectations (from Jan-2011 BCFF survey, conducted mid-/end- of Dec-2010) +ExpFFR(9,:) = [0.2 0.2 0.3 0.4 0.6 0.8 1.0 1.3 1.6 1.8 2.1 2.4 2.6]; + +% 2011-Q1 expectations (from Apr-2011 BCFF survey, conducted mid-/end- of Mar-2011) +ExpFFR(10,:) = [0.1 0.2 0.4 0.7 0.9 1.2 1.5 1.8 2.1 2.4 2.7 2.9 3.2]; + +% 2011-Q2 expectations (from Jul-2011 BCFF survey, conducted mid-/end- of Jun-2011) +ExpFFR(11,:) = [0.1 0.2 0.3 0.4 0.5 0.7 0.9 1.2 1.4 1.7 2.0 2.2 2.4]; + +% 2011-Q3 expectations (from Oct-2011 BCFF survey, conducted mid-/end- of Sep-2011) +ExpFFR(12,:) = [0.1 0.1 0.1 0.1 0.2 0.2 0.3 0.4 0.5 0.6 0.8 0.9 1.0]; + +% 2011-Q4 expectations (from 12/30/2011 OIS data) +ExpFFR(13,:) = [0.1 0.1 0.1 0.1 0.2 0.2 0.3 0.4 0.5 0.6 0.7 0.9 1.0]; + +% 2012-Q1 expectations (from 3/30/2012 OIS data) +ExpFFR(14,:) = [0.1 0.1 0.2 0.2 0.3 0.3 0.4 0.5 0.6 0.7 0.9 1.0 1.2]; +% +% % 2012-Q2 expectations (from 6/30/2012 OIS data) +ExpFFR(15,:) = [0.2 0.2 0.2 0.2 0.2 0.3 0.3 0.4 0.4 0.5 0.5 0.6 0.8]; + +% % 2012-Q3 expectations (from 9/30/2012 OIS data) +ExpFFR(16,:) = [0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.3 0.4 0.5 0.6 0.7]; +% +% % 2012-Q4 expectations (from 12/31/2012 OIS data) +ExpFFR(17,:) = [0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.3 0.3 0.4 0.5 0.6 0.8]; + +% 2013-Q1 expectations (from 3/29/2013 OIS data) +ExpFFR(18,:) = [0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.5 0.6 0.7]; + +% 2013-Q2 expectations (from 6/29/2013 OIS data) +ExpFFR(19,:) = [0.1 0.2 0.2 0.3 0.4 0.5 0.7 0.8 1.0 1.2 1.3 1.5 1.7]; + +% 2013-Q3 expectations (from 10/3/2013 OIS data) +ExpFFR(20,:) = [0.1 0.1 0.1 0.2 0.2 0.3 0.4 0.6 0.7 0.9 1.1 1.3 1.5]; + +% 2013-Q4 expectations (from 12/31/2013 OIS data) +ExpFFR(21,:) = [0.1 0.1 0.1 0.2 0.3 0.4 0.6 0.8 1.0 1.2 1.4 1.7 1.9]; + +% 2014-Q1 expectations (from 3/31/2014 OIS data) +ExpFFR(22,:) = [0.1 0.1 0.1 0.2 0.4 0.5 0.7 0.9 1.1 1.4 1.7 1.9 2.2]; + +% 2014-Q2 expectations (from 6/30/2014 OIS data) +ExpFFR(23,:) = [0.1 0.1 0.2 0.3 0.4 0.6 0.8 1.0 1.2 1.4 1.7 1.9 2.2]; + +% 2014-Q3 expectations (from 9/30/2014 OIS data) +ExpFFR(24,:) = [0.1 0.1 0.2 0.4 0.6 0.9 1.1 1.4 1.6 1.9 2.1 2.3 2.5]; + +% 2014-Q4 expectations (from 12/31/2014 OIS Data) +ExpFFR(25,:) = [0.1 0.2 0.4 0.5 0.7 0.9 1.2 1.4 1.6 1.8 1.9 2.1 2.3]; + +if nant <= size(ExpFFR,2) + ExpFFR = ExpFFR(:,1:nant); +else + ExpFFR = [ExpFFR,NaN(antlags+1,nant-size(ExpFFR,2))]; +end + +if peachflag + xpeachdata_FFR(1,:) = [0.16 0.28 0.44 0.61 0.79 0.98 1.17 1.34 1.51 1.67 NaN]; + +% This should start with the OIS value for the first quarter AFTER the +% one you are forecasting. So if you have data until Q2 and you are +% forecating Q3, the first element of the array should be for Q4. The +% conditional peachdata file will supply the Q3 value. + + if nant <= size(xpeachdata_FFR,2) + for t = 1:psize + peachdata_FFR(t,:) = [xpeachdata_FFR(t,1:nant-t),NaN(1,t)]; + end + else + peachdata_FFR = [xpeachdata_FFR,NaN(psize,nant-size(xpeachdata_FFR,2))]; + end + + +else + peachdata_FFR = []; +end diff --git a/data/conddata.mat b/data/conddata.mat new file mode 100644 index 0000000..a15b0a3 Binary files /dev/null and b/data/conddata.mat differ diff --git a/data/rawData_990.mat b/data/rawData_990.mat new file mode 100644 index 0000000..2b285f5 Binary files /dev/null and b/data/rawData_990.mat differ diff --git a/dsgesolv/dsgesolv.m b/dsgesolv/dsgesolv.m new file mode 100644 index 0000000..5eca27f --- /dev/null +++ b/dsgesolv/dsgesolv.m @@ -0,0 +1,190 @@ +% OVERVIEW +% dsgesolv.m finds a solution to the DSGE model with an input parameter vector. +% To help construct the G0, G1, C, PSI, and PIE matrices, which are used to +% express the model in canonical form, the following programs are called +% (1) getpara<>.m: assigns a parameter name to each element of a +% parameter vector. Also assigns values to steady state parameters +% (parameters that are derived from the values of other parameters). +% These paramters are usually used in the steady state component +% (long-term trend, D) of the measurement equation: Y_t = Z*S_t +D +% (2) states.m: Assigns a number to each state. +% (3) eqs.m: Assigns a number to each equation. +% (4) eqcond.m: Expresses the equilibrium conditions in +% canonical form using G0, G1, C, PSI, and PIE matrices. +% +% Using the assigned states and equations in states*.m and eqs*.m, +% coefficients are specified in the proper positions. +% G0 (neq x neq) holds coefficients of current time states. +% G1 (neq x neq) holds coefficients of lagged states. +% PSI (neq x nshocks) holds coefficients of the state corresponding to an iid shock. +% PIE (neq x n expecational states) holds coefficients of expectational states. +% +% INPUTS +% para: a parameter vector +% mspec: model specification number +% nant: number of anticipated shocks +% varargin: Optional non-zero integer value used to specify +% alternative policy rules, which are +% written in eqcond file of the model +% ** 0 should be reserved for "No Changes/Regular Rule" + +% OUTPUTS +% TTT,RRR,CCC: matrices of tht state transition equation: +% S_t = TTT*S_(t-1) + RRR*eps_t + CCC +% valid: If the solution to the model meets any of the various error +% critera in this program, this flag indicates the type of error +% encountered. +% +% See also: Sims(2000), Solving Linear Rational Expectations Models + +function [TTT,RRR,CCC,valid] = dsgesolv(mspec, para, nant) + +valid = 1; +TTT = 0; +RRR = 0; +CCC = 0; + +%% Assign a value to each parameter +getPara_script + +%% Pre-allocate matrices + + +if exist('fzflag','var') + if fzflag < 1 + disp('fzero failed to converge'); + TTT = []; + RRR = []; + valid = -1; + return + end +end + +%% Assign a number to each state + +eval(['states',num2str(mspec)]); + +%% Assign numbers to each equations + +eval(['eqs',num2str(mspec)]); + +%% Express the equilibrium conditions in canonical form + +% Total number of equations, states, shocks, and endogenous variables + +nstate = n_end+n_exo+n_exp; +neq = nstate; + +G0 = zeros(neq,neq); +G1 = zeros(neq,neq); +C = zeros(neq,1); +PSI = zeros(neq,nex); +PIE = zeros(neq,nend); + + +eval(['eqcond',num2str(mspec)]); + +if any(isnan(G0(:))) || any(isnan(G1(:))) + disp('NaN values in G0 or G1'); + %keyboard; + valid = -2; + return +end + + +try + [T1,TC,T0,M,TZ,TY,gev,RC] = gensys(G0,G1,C,PSI,PIE,1+10^(-6)); +catch err + warning('gensys failed to run properly'); + T1 = zeros(nstates,nstates); + T0 = zeros(nstates,2); + TC = zeros(nstates,1); + RC = [1,1]; + valid = -4; +end + +if (RC(1) ~= 1) || (RC(2) ~= 1); + TTT = zeros(nstates,nstates); + RRR = zeros(nstates,2); + valid = - 3; + %keyboard; +end; + +TTT = real( T1 ); +RRR = real( T0 ); +CCC = TC; + +% Some of our observables are growth rates, which is calculated as a +% linear combination of a present and lagged state. To capture the lagged state, +% we assign to it an index. In addition, we also need to expand the +% matrices of the state transition equation to accommodate the extra state. +% In dsgesolv.m, AddTTT is appended to TTT to capture the lagged state +% value in the current state vector, while AddRRR and AddCCC augment +% RRR and CCC with the appropriate number of zeros. + +numAdd = 12; + +% Make the Add matrices +AddTTT = zeros(numAdd,size(TTT,2)); +AddRRR = zeros(numAdd,size(RRR,2)); +AddCCC = zeros(numAdd,size(CCC,2)); + +% Make the Add matrix for new states (onse that aren't just tracking old +% lags); will be used for measurement error shocks +AddTTT_new = zeros(numAdd); + +%% Get extra matrices for E_t{pi_{t+1}} stuff +T2 = TTT^2; +TR = TTT*RRR; +CTC = CCC+TTT*CCC; + +%% AddTTT modifications + +% Track Lags +AddTTT(1,y_t) = 1; +AddTTT(2,c_t) = 1; +AddTTT(3,i_t) = 1; +AddTTT(4,w_t) = 1; +AddTTT(5,pi_t) = 1; +AddTTT(6,L_t) = 1; +AddTTT(12,u_t) = 1; + +% Expected inflation +AddTTT(7,:) = T2(pi_t,:); + +% The 8th column of AddTTT corresponds to "v_lr" which is set equal to +% e_lr --measurements errors for the two real wage observables built in +% as exogenous structural shocks. +AddTTT_new(8,end-4) = rho_lr; +AddTTT_new(9,end-3) = rho_tfp; +AddTTT_new(10,end-2)= rho_gdpdef; +AddTTT_new(11,end-1) = rho_pce; + +%% AddRRR modficiations + +% Expected inflation +AddRRR(7,:) = TR(pi_t,:); + +% Measurement Error on long rate +AddRRR(8,lr_sh) = 1; + +% Measurement Error on TFP +AddRRR(9,tfp_sh) = 1; + +% Measurement Error on GDP Deflator +AddRRR(10,gdpdef_sh) = 1; + +% Measurement Error on Core PCE +AddRRR(11,pce_sh) = 1; + +% AddCCC Modifications + +% Expected inflation +AddCCC(7,:) = CTC(pi_t,:); + +%% Put everything together and expand TTT, RRR, CCC +TTT = [[TTT,zeros(size(TTT,1),numAdd)];[AddTTT,AddTTT_new]]; +RRR = [RRR ; AddRRR]; +CCC = [CCC ; AddCCC]; + + diff --git a/dsgesolv/gensys.m b/dsgesolv/gensys.m new file mode 100644 index 0000000..75671f0 --- /dev/null +++ b/dsgesolv/gensys.m @@ -0,0 +1,215 @@ +function [G1,C,impact,fmat,fwt,ywt,gev,eu]=gensys(g0,g1,c,psi,pi,div) +%function [G1,C,impact,fmat,fwt,ywt,gev,eu]=gensys(g0,g1,c,psi,pi,div) +%System given as +% g0*y(t)=g1*y(t-1)+c+psi*z(t)+pi*eta(t), +%with z an exogenous variable process and eta being endogenously determined +%one-step-ahead expectational errors. Returned system is +% y(t)=G1*y(t-1)+C+impact*z(t)+ywt*inv(I-fmat*inv(L))*fwt*z(t+1) . +% If z(t) is inlags.i.d., the last term drops out. +% If div is omitted from argument list, a div>1 is calculated. +% eu(1)=1 for existence, eu(2)=1 for uniqueness. eu(1)=-1 for +% existence only with not-s.c. z; eu=[-2,-2] for coincident zeros. +% By Christopher A. Sims +% Updated by Marco Del Negro, Vasco Curdia, Daria Finocchiaro and others. + + qzerror_flag = 0; + invwarn_flag = 0; + + eu=[0;0]; + realsmall=1e-6; + fixdiv=(nargin==6); + n=size(g0,1); + + if any(any(isinf(g0))) | any(any(isnan(g0))) | ... + any(any(isinf(g1))) | any(any(isnan(g1))); + + %We have inf or nan in g0, g1 + [inang0,jnang0] = find(~isfinite(g0)) + [inang1,jnang1] = find(~isfinite(g1)) + eu=[-4;-4]; + G1=[]; + C=[]; + impact=[]; + fmat=[]; + fwt=[]; + ywt=[]; + gev=[]; + return + end + + try; + [a b q z v]=qz(g0,g1); + catch exception; + disp(exception.identifier); + disp(exception.message); + disp('QZ did not work '); + qzerror_flag = 1; + end; + + if qzerror_flag; + eu=[-4;-4]; + G1=[]; + C=[]; + impact=[]; + fmat=[]; + fwt=[]; + ywt=[]; + gev=[]; + return + end + + if ~fixdiv + div=1.01; + end + + nunstab=0; + zxz=0; + + for i=1:n + %Div calc + if ~fixdiv + if abs(a(i,i)) > 0 + divhat=abs(b(i,i))/abs(a(i,i)); + if 1+realsmalldiv*abs(a(i,i))); + if abs(a(i,i))realsmall); + ueta=ueta(:,bigev); + veta=veta(:,bigev); + deta=deta(bigev,bigev); + [uz,dz,vz]=svd(zwt); + md=min(size(dz)); + bigev=find(diag(dz(1:md,1:md))>realsmall); + uz=uz(:,bigev); + vz=vz(:,bigev); + dz=dz(bigev,bigev); + if isempty(bigev) + exist=1; + else + exist=norm(uz-ueta*ueta'*uz) < realsmall*n; + end + if ~isempty(bigev) + zwtx0=b2\zwt; + + zwtx=zwtx0; + M=b2\a2; + for i=2:nunstab + zwtx=[M*zwtx zwtx0]; + end + zwtx=b2*zwtx; + + if any(any(isinf(zwtx))) | any(any(isnan(zwtx))); + disp('inf or nan in zwtx') + eu=[-2;-2]; + G1=[]; + C=[]; + impact=[]; + fmat=[]; + fwt=[]; + ywt=[]; + gev=[]; + return + end + + [ux,dx,vx]=svd(zwtx); + md=min(size(dx)); + bigev=find(diag(dx(1:md,1:md))>realsmall); + ux=ux(:,bigev); + vx=vx(:,bigev); + dx=dx(bigev,bigev); + existx=norm(ux-ueta*ueta'*ux) < realsmall*n; + else + existx=1; + end + %---------------------------------------------------- + % Note that existence and uniqueness are not just matters of comparing + % numbers of roots and numbers of endogenous errors. These counts are + % reported below because usually they point to the source of the problem. + %------------------------------------------------------ + + + [ueta1,deta1,veta1]=svd(q1*pi); + md=min(size(deta1)); + bigev=find(diag(deta1(1:md,1:md))>realsmall); + ueta1=ueta1(:,bigev); + veta1=veta1(:,bigev); + deta1=deta1(bigev,bigev); + + if existx | nunstab==0 + %Solution exists + eu(1)=1; + else + %Does solution exist for unforecastable z only? Else, there is + %no solution due to unstable roots and/or endogenous errors. + if exist + eu(1)=-1; + end + end + + if isempty(veta1) + unique=1; + else + unique=norm(veta1-veta*veta'*veta1)stake are in lower right +% corner, while preserving U.T. and orthonormal properties and Q'AZ' and +% Q'BZ'. +% +[n jnk] = size(A); +root = abs([diag(A) diag(B)]); +root(:,1) = root(:,1)-(root(:,1)<1.e-13).*(root(:,1)+root(:,2)); +root(:,2) = root(:,2)./root(:,1); +for i = n:-1:1 + m=0; + for j=i:-1:1 + if (root(j,2) > stake | root(j,2) < -.1) + m=j; + break + end + end + if (m==0) + return + end + for k=m:1:i-1 + [A B Q Z] = qzswitch(k,A,B,Q,Z); + tmp = root(k,2); + root(k,2) = root(k+1,2); + root(k+1,2) = tmp; + end +end diff --git a/dsgesolv/qzswitch.m b/dsgesolv/qzswitch.m new file mode 100644 index 0000000..7af6017 --- /dev/null +++ b/dsgesolv/qzswitch.m @@ -0,0 +1,60 @@ +function [A,B,Q,Z] = qzswitch(i,A,B,Q,Z) +%function [A,B,Q,Z] = qzswitch(i,A,B,Q,Z) +% +% Takes U.T. matrices A, B, orthonormal matrices Q,Z, interchanges +% diagonal elements i and i+1 of both A and B, while maintaining +% Q'AZ' and Q'BZ' unchanged. If diagonal elements of A and B +% are zero at matching positions, the returned A will have zeros at both +% positions on the diagonal. This is natural behavior if this routine is used +% to drive all zeros on the diagonal of A to the lower right, but in this case +% the qz transformation is not unique and it is not possible simply to switch +% the positions of the diagonal elements of both A and B. + realsmall=sqrt(eps)*10; +%realsmall=1e-3; +a = A(i,i); d = B(i,i); b = A(i,i+1); e = B(i,i+1); +c = A(i+1,i+1); f = B(i+1,i+1); + % A(i:i+1,i:i+1)=[a b; 0 c]; + % B(i:i+1,i:i+1)=[d e; 0 f]; +if (abs(c) 1e50, disp('Bad initial parameter.'), return, end +if NumGrad + %%%%if grad is not string, either compute it (if grad=[]) or check whether it is fine) + if length(grad)==0 + [g badg] = numgrad(fcn,x0, varargin{:}); + + + %ARGLIST + %[g badg] = numgrad(fcn,x0,P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13); + else + badg=any(find(grad==0)); + g=grad; + end + %numgrad(fcn,x0,P1,P2,P3,P4); +else + %%%%if grad is a string, compute it + [g badg] = eval([grad '(x0,varargin{:})']); + %ARGLIST + %[g badg] = feval(grad,x0,P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13); +end +retcode3=101; +x=x0; +f=f0; +H=H0; +cliff=0; +while ~done + %%%% iterate until done is positive -while done is zero + g1=[]; g2=[]; g3=[]; + %addition fj. 7/6/94 for control + if Verbose + disp('-----------------') + disp('-----------------') + %disp('f and x at the beginning of new iteration') + disp(sprintf('f at the beginning of new iteration, %20.10f',f)) + %-----------Comment out this line if the x vector is long---------------- + % disp([sprintf('x = ') sprintf('%15.8g',x)]); + %------------------------- + end + itct=itct+1; + + [f1 x1 fc retcode1] = csminit(fcn,x,f,g,badg,H,Verbose,varargin{:}); + %ARGLIST + %[f1 x1 fc retcode1] = csminit(fcn,x,f,g,badg,H,P1,P2,P3,P4,P5,P6,P7,... + % P8,P9,P10,P11,P12,P13); + % itct=itct+1; + fcount = fcount+fc; + % erased on 8/4/94 + % if (retcode == 1) | (abs(f1-f) < crit) + % done=1; + % end + % if itct > nit + % done = 1; + % retcode = -retcode; + % end + if retcode1 ~= 1 + %%%% if retcode1=1 gradient is zero and you are at the peak + if retcode1==2 | retcode1==4 + %%%% if retcode1=2 or 4 you have shrunk or increased lambda as much as you could: exhausted search possibilities + %%%% the csminit step has failed + wall1=1; badg1=1; + else + %%%% if you are not at the peak but the csminit has improved, compute the gradient again to update H + if NumGrad + [g1 badg1] = numgrad(fcn, x1,varargin{:}); + %ARGLIST + %[g1 badg1] = numgrad(fcn, x1,P1,P2,P3,P4,P5,P6,P7,P8,P9,... + % P10,P11,P12,P13); + else + [g1 badg1] = eval([grad '(x1,varargin{:})']); + %ARGLIST + %[g1 badg1] = feval(grad, x1,P1,P2,P3,P4,P5,P6,P7,P8,P9,... + % P10,P11,P12,P13); + end + wall1=badg1; + % g1 + save g1 g1 x1 f1 varargin; + %ARGLIST + %save g1 g1 x1 f1 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13; + end + if wall1 % & (~done) by Jinill + % Bad gradient or back and forth on step length. Possibly at + % cliff edge. Try perturbing search direction. + % + %%%% if stuck, give it another try by perturbing H + + %fcliff=fh;xcliff=xh; + Hcliff=H+diag(diag(H).*(rand(nx,1))); + disp('Cliff. Perturbing search direction.') + [f2 x2 fc retcode2] = csminit(fcn,x,f,g,badg,Hcliff,Verbose,varargin{:}); + %ARGLIST + %[f2 x2 fc retcode2] = csminit(fcn,x,f,g,badg,Hcliff,P1,P2,P3,P4,... + % P5,P6,P7,P8,P9,P10,P11,P12,P13); + fcount = fcount+fc; % put by Jinill + if f2 < f + if retcode2==2 | retcode2==4 + wall2=1; badg2=1; + else + if NumGrad + [g2 badg2] = numgrad(fcn, x2,varargin{:}); + %ARGLIST + %[g2 badg2] = numgrad(fcn, x2,P1,P2,P3,P4,P5,P6,P7,P8,... + % P9,P10,P11,P12,P13); + else + [g2 badg2] = eval([grad '(x2,varargin{:})']); + %ARGLIST + %[g2 badg2] = feval(grad,x2,P1,P2,P3,P4,P5,P6,P7,P8,... + % P9,P10,P11,P12,P13); + end + wall2=badg2; + % g2 + badg2; + save g2 g2 x2 f2 varargin + %ARGLIST + %save g2 g2 x2 f2 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13; + end + if wall2 + disp('Cliff again. Try traversing') + if norm(x2-x1) < 1e-13 + f3=f; x3=x; badg3=1;retcode3=101; + else + gcliff=((f2-f1)/((norm(x2-x1))^2))*(x2-x1); + [f3 x3 fc retcode3] = csminit(fcn,x,f,gcliff,0,eye(nx),Verbose,varargin{:}); + %ARGLIST + %[f3 x3 fc retcode3] = csminit(fcn,x,f,gcliff,0,eye(nx),P1,P2,P3,... + % P4,P5,P6,P7,P8,... + % P9,P10,P11,P12,P13); + fcount = fcount+fc; % put by Jinill + if retcode3==2 | retcode3==4 + wall3=1; badg3=1; + else + if NumGrad + [g3 badg3] = numgrad(fcn, x3,varargin{:}); + %ARGLIST + %[g3 badg3] = numgrad(fcn, x3,P1,P2,P3,P4,P5,P6,P7,P8,... + % P9,P10,P11,P12,P13); + else + [g3 badg3] = eval([grad '(x3,varargin{:})']); + %ARGLIST + %[g3 badg3] = feval(grad,x3,P1,P2,P3,P4,P5,P6,P7,P8,... + % P9,P10,P11,P12,P13); + end + wall3=badg3; + % g3 + badg3 + save g3 g3 x3 f3 varargin; + %ARGLIST + %save g3 g3 x3 f3 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13; + end + end + else + f3=f; x3=x; badg3=1; retcode3=101; + end + else + f3=f; x3=x; badg3=1;retcode3=101; + end + else + % normal iteration, no walls, or else we're finished here. + f2=f; f3=f; badg2=1; badg3=1; retcode2=101; retcode3=101; + end + end + %how to pick gh and xh + if f3 nit + disp('iteration count termination') + done = 1; + elseif stuck + disp('improvement < crit termination') + done = 1; + end + if Verbose + + rc=retcodeh; + if rc == 1 + disp('zero gradient') + elseif rc == 6 + disp('smallest step still improving too slow, reversed gradient') + elseif rc == 5 + disp('largest step still improving too fast') + elseif (rc == 4) | (rc==2) + disp('back and forth on step length never finished') + elseif rc == 3 + disp('smallest step still improving too slow') + elseif rc == 7 + disp('warning: possible inaccuracy in H matrix') + end + end + f=fh; + if Verbose + disp(sprintf('max percentage change in the parameters, %20.10f',100*max(log(abs(xh(find(xh))))-log(abs(x(find(xh))))))) + end + x=xh; + g=gh; + badg=badgh; +end +% what about making an m-file of 10 lines including numgrad.m +% since it appears three times in csminwel.m diff --git a/estimation/dsgelh.m b/estimation/dsgelh.m new file mode 100644 index 0000000..976bed9 --- /dev/null +++ b/estimation/dsgelh.m @@ -0,0 +1,164 @@ +% OVERVIEW +% +% This is a dsge likelihood function that can handle 2-part estimation where +% there is a model switch. +% +% HOWEVER, this program is by and large the same as objfcnmhdsge_2part.m, save +% the bound-checking. Therefore, the code has been substantially consolidated +% and much of the code supporting the operations in this function are shared by +% objfcnmhdsge_2part.m +% +% Note: given the multi-period setup, all relevant matrices will be stored in +% an array structure since they will change over time. As currently +% implemented, there are 3 time periods, which index the structure: presample, +% normal sample, ZB sample. +% +% If there is no model switch, then we filter over the main sample all at once. +% +function pyt = dsgelh(para,YY,YY0,nobs,nlags,nvar,mspec,npara,coint,cointadd,YYcoint0,nant,antlags) + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% STEP 0: Set up structures that will hold all of the transition equation matrices +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Set up the general classes of 2-part estimation models where +% operations/indexing is similar within a particular class. +class2part; + +% Create structure to hold all matrices -- data matrices, state equation matrices, measurement matrices, etc. +[mt, pd] = dsgelh_partition(YY0, YY, nvar, nant, antlags); + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% step 1: solution to DSGE model - delivers transition equation for the state variables S_t +%% transition equation: S_t = TC+TTT S_{t-1} +RRR eps_t, where var(eps_t) = QQ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Solve the model +[mt(pd).TTT, mt(pd).RRR, mt(pd).CCC, valid] = dsgesolv(mspec,para, mt(end).nant{:}); + +%% For models using 2part estimation: Get the normal, no ZB model matrices +if any(mspec == class2part_all) + + % Get the starting indices + [start_ant_state, start_ant_shock, revol_ind] = get_start_ant(mspec, nant); + + [mt(pd-1).TTT, mt(pd-1).RRR, mt(pd-1).CCC] = ... + dsgelh_getNoZB(nant, start_ant_state, start_ant_shock, mt(pd).TTT, mt(pd).RRR, mt(pd).CCC,revol_ind{:}); +end + +if valid < 1; + pyt = -1E10; + return +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% step 2: define the measurement equation: X_t = ZZ*S_t + D + u_t +%% where u_t = eta_t+MM* eps_t with var(eta_t) = EE +%% where var(u_t) = HH = EE+MM QQ MM', cov(eps_t,u_t) = VV = QQ*MM' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Set up some helper functions to create compound matrices by passing the +% period index to access the relevant EE, MM, QQ, RR, VV matrices +makeHH = @(E, M, Q) E + M*Q*M'; +makeVV = @(Q, M) Q*M'; +makeVVall = @(R, Q, V, H) [[R*Q*R', R*V]; ... + [V'*R', H]]; + + +% Get measurement equation matrices set up for all periods that aren't the presample +for p = 2:pd + + % Save measurement equations + [mt(p).ZZ, mt(p).DD, mt(p).DDcointadd, mt(p).QQ, mt(p).EE, mt(p).MM, retcode] = ... + feval(['measur',num2str(mspec)], mt(p).TTT, mt(p).RRR,valid,para,mt(p).nvar,nlags,mspec,npara,coint,cointadd,mt(p).nant{:}); + + if retcode == 0 + % invalid parameterization + pyt = -1E10; + return; + end; + + mt(p).HH = makeHH(mt(p).EE, mt(p).MM, mt(p).QQ); + mt(p).VV = makeVV(mt(p).QQ, mt(p).MM); + mt(p).VVall = makeVVall(mt(p).RRR, mt(p).QQ, mt(p).VV, mt(p).HH); + + if p == 2 && any(mt(p).CCC ~= 0) + mt(p).DD = mt(p).DD + (mt(p).ZZ)*((eye(size(mt(p).TTT))-mt(p).TTT)\mt(p).CCC); + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% step 3: compute log-likelihood using Kalman filter - written by Iskander +%% note that Iskander's program assumes a transition equation written as: +%% S_t = TTT S_{t-1} +eps2_t, where eps2_t = RRReps_t +%% therefore redefine QQ2 = var(eps2_t) = RRR*QQ*RRR' +%% and VV2 = cov(eps2_t,u_u) = RRR*VV +%% define VVall as the joint variance of the two shocks VVall = var([eps2_t;u_t]) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% PRESAMPLE + +% Solve lyapunov with normal period state matrices (i.e. period 2 matrices) +[A0,P0] = lyap_nonstationary(mspec,para,mt(2).TTT,mt(2).RRR,mt(2).QQ); + +% If there is a presample +if ~isempty(mt(1).YY) + + % If number of presample series differ from number of measurement equation + % series, chop off extra measurement equations and recompute HH, VV, VVall + % for presample. Otherwise, HH, VV, VVall same in presample as in normal pd + if size(mt(1).YY,2) ~= size(mt(2).ZZ,1) + nvar0 = size(mt(1).YY,2); + + % Chop off parts from measurement matrices + meas_mats = {'ZZ', 'DD', 'EE', 'MM'}; + for mm = 1:length(meas_mats) + mt(1).(meas_mats{mm}) = mt(2).(meas_mats{mm})(1:nvar0,:); + end + mt(1).EE = mt(1).EE(:,1:nvar0); + + % Recompute + mt(1).HH = makeHH(mt(1).EE, mt(1).MM, mt(2).QQ); + mt(1).VV = makeVV(mt(2).QQ, mt(1).MM); + mt(1).VVall = makeVVall(mt(2).RRR, mt(2).QQ, mt(1).VV, mt(1).HH); + + else + mt(1).ZZ = mt(2).ZZ; + mt(1).DD = mt(2).DD; + mt(1).VVall = mt(2).VVall; + end + + %% run Kalman filter on initial observations + [mt(1).pyt0, mt(1).zend, mt(1).Pend] = ... + kalcvf2NaN( (mt(1).YY)', 1, zeros(size(mt(2).TTT,2),1), mt(2).TTT, ... + mt(1).DD, mt(1).ZZ, mt(1).VVall, A0, P0); +else + + mt(1).zend = A0; + mt(1).Pend = P0; + +end + + +%% MAIN SAMPLE + +% Loop over normal period and extra periods (if any) +for p = 2:pd + if p > 2 + [zprev,Pprev] = augmentStates(mspec, mt(p).nant{:}, size(mt(p).TTT,2), mt(p-1).zend, mt(p-1).Pend); + else + zprev = mt(p-1).zend; + Pprev = mt(p-1).Pend; + end + [mt(p).pyt, mt(p).zend, mt(p).Pend] = ... + kalcvf2NaN( (mt(p).YY)', 1, zeros(size(mt(p).TTT,2),1), mt(p).TTT, ... + mt(p).DD, mt(p).ZZ, mt(p).VVall, zprev, Pprev); +end + +pyt = sum([mt(2:end).pyt]); + + + diff --git a/estimation/dsgelh_2part.m b/estimation/dsgelh_2part.m new file mode 100644 index 0000000..801716c --- /dev/null +++ b/estimation/dsgelh_2part.m @@ -0,0 +1,115 @@ +function pyt = dsgelh_2part(para,YY,nobs,nlags,nvar,mspec,npara,coint,cointadd,nant, antlags) + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% step 1: solution to DSGE model - delivers transition equation for the state variables S_t +%% transition equation: S_t = TC+TTT S_{t-1} +RRR eps_t, where var(eps_t) = QQ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +[TTT,RRR,CCC,valid] = dsgesolv(mspec,para, nant); + +iSplit = getState(mspec,0,'n_end+n_exo'); +nstate = size(TTT,1); +nshocks = size(RRR,2)-nant; + +% For 510,555, TTT/RRR/CCC for 510 are contained within those for 555 +if any(mspec == [555 556 557 5571 558]) + TTT1 = zeros(nstate-(nant+1),nstate-(nant+1)); + TTT1 = [TTT(1:iSplit,1:iSplit), ... + TTT(1:iSplit,iSplit+(nant+1)+1:end);... + TTT(iSplit+(nant+1)+1:end,1:iSplit),... + TTT(iSplit+(nant+1)+1:end,iSplit+(nant+1)+1:end)]; + + RRR1 = zeros(nstate-(nant+1),nshocks); + RRR1 = [RRR(1:iSplit,1:nshocks); RRR(iSplit+(nant+1)+1:end,1:nshocks)]; + + CCC1 = zeros(nstate-(nant+1),1); + CCC1 = [CCC(1:iSplit,1); CCC(iSplit+(nant+1)+1:end,1)]; +else + TTT1 = TTT; + RRR1 = RRR; + CCC1 = CCC; +end + +if valid < 1; + pyt = -1E10; + return +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% step 2: define the measurement equation: X_t = ZZ*S_t + D + u_t +%% where u_t = eta_t+MM* eps_t with var(eta_t) = EE +%% where var(u_t) = HH = EE+MM QQ MM', cov(eps_t,u_t) = VV = QQ*MM' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%keyboard; +eval(['[ZZ,DD,DDcointadd,QQ,EE,MM,retcode] = measur',num2str(mspec),'(TTT1,RRR1,valid,para,nvar-nant,nlags,mspec,npara,coint,cointadd);']); + +if retcode == 0 + % invalid parameterization + pyt = -1E10; + return; +end; + +nstate = size(TTT1,1); +nshocks = size(RRR1,2); + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% step 3: compute log-likelihood using Kalman filter - written by Iskander +%% note that Iskander's program assumes a transition equation written as: +%% S_t = TTT S_{t-1} +eps2_t, where eps2_t = RRReps_t +%% therefore redefine QQ2 = var(eps2_t) = RRR*QQ*RRR' +%% and VV2 = cov(eps2_t,u_u) = RRR*VV +%% define VVall as the joint variance of the two shocks VVall = var([eps2_t;u_t]) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% truncate system matrices - these should NOT include the expectations + +%taking the expectations out of the data +%nvar = nvar-nant; +YY1= YY(:, 1:nvar-nant); + +HH = EE+MM*QQ*MM'; +VV = QQ*MM'; +VVall = [[RRR1*QQ*RRR1',RRR1*VV];[VV'*RRR1',HH]]; + +if any(CCC1 ~= 0) + DDadd = ZZ*((eye(size(TTT1))-TTT1)\CCC1); +else + DDadd = 0; +end + +DD= DD+DDadd; + + +%% Define the initial mean and variance for the state vector +% (deals with nonstationarity on model by model basis) +[A0,P0] = lyap_nonstationary(mspec,para,TTT1,RRR1,QQ); + + zend = A0; + Pend = P0; + + +%% Running Kalman Filter normal model (main sample) + +% First, filter using normal model up to period T-antlags-1. +[pyt1,zend,Pend] = kalcvf2NaN(YY1(1:end-antlags-1,:)',1,zeros(nstate,1),TTT1,DD,ZZ,VVall,zend,Pend); + +% Now change models to incorporate anticipated shocks. +eval(['[ZZ,DD,DDcointadd,QQ,EE,MM,retcode] = measur',num2str(mspec),'(TTT,RRR,valid,para,nvar,nlags,mspec,npara,coint,cointadd, nant);']); + +HH = EE+MM*QQ*MM'; +VV = QQ*MM'; +VVall = [[RRR*QQ*RRR',RRR*VV];[VV'*RRR',HH]]; + +nstate = size(TTT,1); +nshocks = size(RRR,2); + +[zprev,pprev] = augmentStates(mspec,nant,nstate,zend,Pend); +% Next, filter using ZB model for periods T-antlags:T +% These new filtered states include anticipated shocks and +% are consistent with the zero bound. +[pyt2,zend,pend] = kalcvf2NaN(YY(end-antlags:end,:)',1,zeros(nstate,1),TTT,DD,ZZ,VVall,zprev,pprev); + +pyt = pyt1+pyt2; + + diff --git a/estimation/dsgelh_getNoZB.m b/estimation/dsgelh_getNoZB.m new file mode 100644 index 0000000..35baae7 --- /dev/null +++ b/estimation/dsgelh_getNoZB.m @@ -0,0 +1,50 @@ +% OVERVIEW +% +% This function pulls out the state equation matrices for the models WITHOUT +% anticipated policy shocks (model 510, 904, etc), from the state equation +% matrics for the models WITH anticipated policy shocks (e.g. 555, 557, 955). +% This is because the models WITH anticipated shocks contain the models WITHOUT +% anticipated shocks within them (i.e. 510 is embedded in 555 and 904 in 955). +function [ TTT, RRR, CCC ] = dsgelh_getNoZB(nant, start_ant_state, start_ant_shock, TTT, RRR, CCC, varargin) + + if nargin > 6 + revol_ind = varargin{1}; + % This indicates that we need to drop an extra equation for the evolution + % of the monetary shock. + % + % We need to do this because 555, 557 and variants don't normally have an + % equation for the evolution of the contemporaneous monetary policy shock; + % it's assumed iid and is implemented via PSI in the taylor rule equation + % row. But in the model with anticipated policy shocks, an extra equation + % has to be added (and a new state introduced) such that + % + % (time t monetary shock) = (contemp shock) + (ant shocks). + % + % This sum is then what's added into the Taylor rule. BUT if we kick out + % the ant shocks, we don't need this equation, so let's remove it. We will + % just treat the monetary shock as iid as in model 510. + +% TTT(:,revol_ind) = []; +% TTT(revol_ind,:) = []; +% RRR(revol_ind,:) = []; +% CCC(revol_ind,:) = []; + else + revol_ind = []; + + end + + + % Indices corresopnding to ant shock states (which hold exogenous ant shocks) + % and exogenous shocks + ant_state_inds = [revol_ind start_ant_state:(start_ant_state+nant-1)]; + ant_shock_inds = start_ant_shock:(start_ant_shock+nant-1); + + % Remove the ant rows and columns + TTT(:,ant_state_inds) = []; % Ditch the columns that multiply the states that hold the anticipated policy shocks + TTT(ant_state_inds,:) = []; % Ditch the equations for the evolution fo the anticipated policy shocks + RRR(ant_state_inds,:) = []; + CCC(ant_state_inds,:) = []; + RRR(:,ant_shock_inds) = []; % Ditch columns for exogenous anticipated policy shocks + + +end diff --git a/estimation/dsgelh_partition.m b/estimation/dsgelh_partition.m new file mode 100644 index 0000000..e99def0 --- /dev/null +++ b/estimation/dsgelh_partition.m @@ -0,0 +1,26 @@ +% OVERVIEW +% +% This function will partition the sample for estimation purposes, +% accommodating 2-part estimation if relevant. +% +% Returns a structure array where size = number of distinct periods (presample, +% normal, ZB, etc.). The mt struture will hold the relevant matrices for each +% period. +function [mt, pd] = dsgelh_partition(YY0, YY, nvar, nant, antlags) + +% Indicates 2-part estimation +if nant > 0 + if ~isempty(YY0), YY0 = YY0(:,1:nvar-nant); end % Take out expectations + mt = struct('YY', {YY0, YY(1:end-antlags-1, 1:nvar-nant), YY(end-antlags:end,:)}, ... + 'nvar', {nvar-nant, nvar-nant, nvar}, ... % Effective number of variables in each period + 'nant', {{}, {}, {nant}}); % Number of anticipated shocks in each period + pd = 3; % Set number of periods; here, pre-sample, normal, ZB +else + mt = struct('YY', {YY0, YY}, ... + 'nvar', {nvar, nvar}, ... + 'nant', {{}, {}}); + pd = 2; % Set number of periods; here, pre-sample, normal +end + + +end diff --git a/estimation/get_start_ant.m b/estimation/get_start_ant.m new file mode 100644 index 0000000..676b93c --- /dev/null +++ b/estimation/get_start_ant.m @@ -0,0 +1,28 @@ +% OVERVIEW +% +% Returns the starting indices for the anticipated policy shock states and +% shocks. Very model-class specific +function [start_ant_state, start_ant_shock, revol_ind] = get_start_ant(mspec, nant) + + class2part; + + % Set the starting indices for states and shocks corresponding to anticipated + % policy shocks; depends on how eqconds is set up for a particular model + if any(mspec == class2part_555) + str_ant_state = 'n_end+n_exo'; + str_ant_shock = 'n_exo'; + + % Also for the 555 class of models, we need to drop the extra equation for + % the evolution of the monetary shock. See the getNoZBmats.m function. This + % is very model specific. + revol_ind = {getState(mspec, nant, 'n_end+n_exo') - nant}; + + elseif any(mspec == class2part_955) + str_ant_state = 'nstates'; + str_ant_shock = 'nex'; + revol_ind = {}; + end + start_ant_state = getState(mspec,nant,str_ant_state)-nant+1; + start_ant_shock = getState(mspec,nant,str_ant_shock)-nant+1; + +end diff --git a/estimation/gibb.m b/estimation/gibb.m new file mode 100644 index 0000000..267d1e3 --- /dev/null +++ b/estimation/gibb.m @@ -0,0 +1,375 @@ +%% gibb_est_ant.m +% This program produces and saves draws from the posterior distribution of +% the parameters. + +%% Step 1: Initialization %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Basic Initialization (Reads in data and model specifications) +initializePrograms; +marglh = 'marglh'; + +%% Determine whether 2part estimation or not + +if is2part(mspec) + % If 2-part estimation, we want to pass nant and antlags to likelihood and + % objective functions. Also want to pass nant to dsgesolv + args_nant_antlags = {nant, antlags}; + arg_nant = {nant}; +else + % If not 2-part estimation, pass nant and antlags as 0 to likelihood and + % objective functions. Don't want to pass nant to dsgesolv + args_nant_antlags = {0, 0}; + arg_nant = {}; +end + + +%% Configure the Metropolis Algorithm + +% Setting the jump size for sampling +cc0 = 0.01; +cc = .09; +date_q = (1:1:qahead)'; + + +%% Evaluate posterior at a parameter vector, para +% para is set in mspec_parameters.m + +[post_values,like_values,prior_values] = feval(strcat('objfcndsge'),para,... + YY,YY0,nobs,nlags,nvar,mspec,npara,trspec,pmean,pstdd,pshape,para_mask,... + para_fix,marglh,coint,cointadd,cointall,YYcoint0,0,args_nant_antlags{:}); + + + +%% Setting infiles and starting points + +% Here, we detect whether we have already gone through gibb_est_ant.m. If +% not, we start the mode-finding algorithm from the pre-specified 'para' vector. +% Otherwise, we will begin the optimization from where we left off in the last +% round of iterations. + +if(~exist('xh', 'var')); + + % specify starting mode + infile0 = [spath, 'mode_in']; + fid0 = fopen(infile0,'r'); + params = fread(fid0,[npara,1],'single'); + disp('Previous mode found, reading in...') +else + disp('gibb_est_ant was called recursively. Will use parameter vector from last call to find mode.'); +end + +% Inputs to minimization algorithm (csminwel). +x0 = invtrans(params,trspec); +H0 = eye(npara)*1E-4; +nit = 1000; +crit= 1E-10; +MIN = 1; + + +%% Step 2: Finding the posterior mode: re-maximization + +if reoptimize + disp('Re-optimizing') + % We seek the posterior distribution of the parameters. + % We first find the mode of the distribution (i.e., the maximum of its pdf) + % so that once we begin sampling, we can begin from this mode. + + [fh,xh,g,H,itct,fcount,retcode] = csminwel('objfcndsge',x0,H0,[],crit,nit,... + YY,YY0,nobs,nlags,nvar, mspec,npara,trspec,pmean,pstdd,pshape,para_mask,... + para_fix,marglh,coint,cointadd,cointall,YYcoint0, MIN, nant, antlags); + + % Transform modal parameters so they are no longer bounded (i.e., allowed + % to lie anywhere on the real line). + + xh = real(xh); + params = trans(xh,trspec); + + % If we choose to fix any of the parameters (i.e., not estimate them), here + % we reset those parameters to those fixed values. + + params = params.*(1-para_mask)+para_fix.*para_mask; + + % Once we get a mode, we this save the parameter vector in the binary file + % 'outfile0'. + + outfile0 = [spath,'/mode_out']; + fid0 = fopen(outfile0,'w'); + fwrite(fid0,params','single'); + fclose(fid0); + + % If the algorithm stops only because we have exceeded the maximum number of + % iterations,continue improving guess of modal parameters by recursively + % calling gibb. + if itct >= nit + clear infile0; + gibb; + return; + end +end + +%% Step 3: Compute the inverse Hessian %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Once we find and save the posterior mode, we calculate the Hessian +% at the mode. The hessian is used to calculate the variance of the proposal +% distribution,which is used to draw a new parameter in each iteration of +% the algorithm. +%% Step 3a: Calculate Hessian corresponding to the posterior mode +if CH == 1 % if choose to calculate Hessian + disp('Re-computing Hessian') + MIN=0; + %calculate Hessian + hessian = hessizero('objfcndsge',[params,para_mask],1,... + YY,YY0,nobs,nlags,nvar,mspec,npara,trspec,pmean,pstdd,pshape,para_mask,... + para_fix,marglh,coint,cointadd,cointall,YYcoint0,MIN,args_nant_antlags{:}); + % Save computed Hessian in output file + + outfile_hes = [spath,'/hessian']; + fid_hes = fopen(outfile_hes,'w'); + fwrite(fid_hes,hessian,'single'); + fclose(fid_hes); + +else % if don't calculate Hessian, read in pre-calculated Hessian matrix + disp('Using pre-calculated Hessian') + infile_hes = [spath,'/hessian']; + fid = fopen(infile_hes,'r'); + hessian=fread(fid,[npara npara],'single'); +end; + +if any(diag(hessian)<0) + error('negative in diagonal of hessian'); +end + +%% Step 3b: Calculate inverse of Hessian (by Singular Value Decomposition) +% We use singular value decomposition to compute the inverse of the +% Hessian, as the Hessian calculated above is singular +rankhhm = npara; +[u,s,v] = svd(hessian); +sigpropinv = hessian; +md = min(size(s)); +bigev = find(diag(s(1:md,1:md))>1e-6); +sigpropdim = length(bigev); + +sigproplndet = 0; + +for i = 1:npara + if i > sigpropdim + s(i,i) = 0; + else + s(i,i) = 1/s(i,i); + sigproplndet = sigproplndet+log(s(i,i)); + end +end + +invhhm = u*s*u'; +sigscale = u*sqrt(s); + +if length(bigev) ~= (npara-length(find(para_mask))) + disp('problem -- shutting down dimensions') + pause +end + +%% Step 3: Initialize algorithm by drawing para_old from a normal distribution centered on the posterior mode (propdens). + +% para_old is used to solve the model to check for indeterminancy, and it is +% passed through objfcnmhdsge.m to calculate the posterior value. + +% objfcnmhdsge.m is similar to objfcndsge.m, except it also checks that parameters +% are within the bounds specified in mspec_parameters.m. Until the parameters +% are within bounds, or until the posterior value is sufficiently large, gibb.m +% keeps drawing a new para_old (if you see multiple lines of "Initializing..." +% in the command window, this is the problem). + +[TTT,RRR,CCC,valid] = dsgesolv(mspec,params,nant); +retcode = valid; +[lnpost0,lnpy0,zend0,ZZ0,DD0,QQ0] = feval('objfcnmhdsge',params,bounds,YY,YY0,nobs,... + nlags,nvar,mspec,npara,trspec,pmean,pstdd,pshape,... + TTT,RRR,CCC,valid,para_mask,coint,cointadd,cointall,YYcoint0,... + args_nant_antlags{:}); +jc = 1; +valid0 = 0; + +while ~valid0 + jc = jc+1; + + para_old = params + cc0*(sigscale*randn(npara,1)); + para_old = para_old.*(1-para_mask)+para_fix.*para_mask; + + [TTT_old,RRR_old,CCC_old,valid_old] = dsgesolv(mspec,para_old,nant); + nstate = length(TTT_old); + nshocks = size(RRR_old,2); + + retcode = valid_old; + [post_old,like_old,zend_old,ZZ_old,DD_old,QQ_old] = ... + feval('objfcnmhdsge',para_old,bounds,YY,YY0,nobs,nlags,nvar,mspec,npara,trspec,pmean,pstdd,pshape,... + TTT_old,RRR_old,CCC_old,valid_old,para_mask,coint,cointadd,cointall,YYcoint0,args_nant_antlags{:}); + + propdens = -0.5*sigpropdim*log(2*pi) - 0.5*sigproplndet - 0.5*sigpropdim*log(cc0^2) ... + -0.5*(para_old - params)'*sigpropinv*(para_old - params)/cc0^2; + + if post_old > -10000000; + valid0 = 1; + end + + record(jc) = post_old; + disp('Initializing Metropolis-Hastings Algorithm') + +end + +tic +fprintf(1,'\n Time %3.2f ',ti(I)); +fprintf(1,'\n Peak = %2.3f',lnpost0); + +%% Open files for saving +% Once you open files for writing, the original files (if they existed) +% will be overwritten. + +% Parameters draws +outfile1 = [spath,'/params']; +fid1 = fopen(outfile1,'w'); + +% Transition Matrices +outfile2 = [spath,'/post']; +fid2 = fopen(outfile2,'w'); + +outfile3 = [spath,'/TTT']; +fid3 = fopen(outfile3,'w'); + +outfile4 = [spath,'/RRR']; +fid4 = fopen(outfile4,'w'); + +outfile5 = [spath,'/zend']; +fid5 = fopen(outfile5,'w'); + +% Covariance Matrices +outfile6 = [spath,'/cov']; +fid6 = fopen(outfile6,'w'); + +% Initialize some variables (for calculating rejection rate) +Tim = 0; +eT = 0; +reje = 0; + +%% Step 4: For nsim*ntimes iterations within each block, generate a new parameter draw. +%% Decide to accept or reject, and save every ntimes_th draw that is accepted. + +for iblock = 1:nblocks + + if iblock >1; fprintf(1,' block: %2.0f %3.2f ;',[iblock,toc/(iblock-1)]); end; + + parasim = zeros(nsim,npara); + likesim = zeros(nsim,1); + postsim = zeros(nsim,1); + rej = zeros(nsim*ntimes,1); + TTTsim = zeros(nsim,nstate^2); + RRRsim = zeros(nsim,nstate*nshocks); + CCCsim = zeros(nsim,nstate); + zsim = zeros(nsim,nstate); + + for j = 1:nsim*ntimes + + Tim = Tim+1; + + % Draw para_new from the proposal distribution (a multivariate normal + % distribution centered on the previous draw, with standard + % deviation cc*sigscale). + + para_new = para_old + cc*(sigscale*randn(npara,1)); + para_new = para_new.*(1-para_mask)+para_fix.*para_mask; + [TTT_new,RRR_new,CCC_new,valid_new] = dsgesolv(mspec,para_new,nant); + retcode = valid_new; + + % Solve the model, check that parameters are within bounds, and + % evalue the posterior. + + [post_new,like_new,zend_new,ZZ_new,DD_new,QQ_new] = feval('objfcnmhdsge',para_new,bounds,YY,YY0,nobs,... + nlags,nvar,mspec,npara,trspec,pmean,pstdd,pshape,TTT_new,RRR_new,CCC_new,valid_new,para_mask,coint,cointadd,cointall,YYcoint0,args_nant_antlags{:}); + + + % Calculate the multivariate log likelihood of jump from para_old to para_new + propdens = -0.5*sigpropdim*log(2*pi) - 0.5*sigproplndet - 0.5*sigpropdim*log(cc^2) ... + -0.5*(para_new - para_old)'*sigpropinv*(para_new - para_old)/cc^2; + + + % Choose to accept or reject the new parameter by calculating the + % ratio (r) of the new posterior value relative to the old one + % We compare min(1,r) to a number drawn randomly from a + % uniform (0,1) distribution. This allows us to always accept + % the new draw if its posterior value is greater than the previous draw's, + % but it gives some probability to accepting a draw with a smaller posterior value, + % so that we may explore tails and other local modes. + + r = min([1 ; exp( post_new - post_old)]); + + if rand(1,1) < r; + % Accept proposed jump + para_old = para_new; + post_old = post_new; + like_old = like_new; + + TTT_old = TTT_new; + RRR_old = RRR_new; + CCC_old = CCC_new; + valid_old = valid_new; + + zend_old = zend_new; + ZZ_old = ZZ_new; + DD_old = DD_new; + QQ_old = QQ_new; + + else + % Reject proposed jump + rej(j) = 1; + reje = reje+1; + + end + + % Save every (ntime)th draw + if (j/ntimes) == round(j/ntimes) + likesim(j/ntimes,1) = like_old; + postsim(j/ntimes,1) = post_old; + parasim(j/ntimes,:) = para_old'; + TTTsim(j/ntimes,:) = TTT_old(:)'; + RRRsim(j/ntimes,:) = RRR_old(:)'; + CCCsim(j/ntimes,:) = CCC_old(:)'; + zsim(j/ntimes,:) = zend_old(:)'; + end + + if j == nsim*ntimes + fprintf(1,'\nRejection perct %2.4f ',[sum(rej)/j]); + end + + end + + fwrite(fid1,parasim','single'); + fwrite(fid2,postsim','single'); + fwrite(fid3,TTTsim','single'); + fwrite(fid4,RRRsim','single'); + fwrite(fid5,zsim','single'); + +end + +toc + +fprintf(1,'rejection rate = %2.4f',reje/Tim); + +%% Calculate Parameter Covariance Matrix + +num1 = nblocks*nsim*npara*4; % number of bites per file +numb1 = nburn*npara*4; % number of bites to discard + +% read in saved parameter draws +infile_params = [spath,'/params']; +fid = fopen(infile_params,'r'); +status = fseek(fid,numb1,'bof'); + + +% Reshape parameter draws into a matrix so can calculate covariance +theta = []; +while ( ftell(fid1) < num1 ) + theta_add = fread(fid,[npara,nsim],'single')'; + theta = [theta; theta_add]; +end + +% Calculate covariance and save +cov_theta = cov(theta); +fwrite(fid6,cov_theta(:),'single'); +fclose('all'); \ No newline at end of file diff --git a/estimation/gibb_est_ant.m b/estimation/gibb_est_ant.m new file mode 100644 index 0000000..b7cb438 --- /dev/null +++ b/estimation/gibb_est_ant.m @@ -0,0 +1,350 @@ +%% gibb_est_ant.m +% This program produces and saves draws from the posterior distribution of +% the parameters. + +%% Step 1: Initialization %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Basic Initialization (Reads in data and model specifications) +initializePrograms; +marglh = 'marglh'; + +%% Configure the Metropolis-Hastings Algorithm + +% Set jump size parameters for sampling +cc0 = 0.01; +cc = .09; +date_q = (1:1:qahead)'; + + +%% Initialize Mode-Finding Algorithm + +% Here, we detect whether we have already gone through gibb_est_ant.m. If +% not, we start the mode-finding algorithm from the pre-specified 'para' vector. +% Otherwise, we will begin the optimization from where we left off in the last +% round of iterations. + +if(~exist('xh', 'var')); + + % specify starting mode + infile0 = [spath, 'mode_in']; + fid0 = fopen(infile0,'r'); + params = fread(fid0,[npara,1],'single'); + disp('Previous mode found, reading in...') +else + disp('gibb_est_ant was called recursively. Will use parameter vector from last call to find mode'); +end + +% Inputs to minimization algorithm (csminwel). +x0 = invtrans(params,trspec); +H0 = eye(npara)*1E-4; +nit = 1000; +crit= 1E-10; +MIN = 1; + +%% Step 2: Find mode of posterior distribution %%%%%%%%%%%%%%%%%%%%%%%%%%%% + +if reoptimize + disp('Re-optimizing') + % We seek the posterior distribution of the parameters. + % We first find the mode of the distribution (i.e., the maximum of its pdf) + % so that once we begin sampling, we can begin from this mode. + + [fh,xh,g,H,itct,fcount,retcode] = csminwel('objfcndsge_2part',x0,H0,[],crit,nit,... + YY,nobs,nlags,nvar, mspec,npara,trspec,pmean,pstdd,pshape,para_mask,... + para_fix,marglh,coint,cointadd,cointall,MIN, nant, antlags); + + % Transform modal parameters so they are no longer bounded (i.e., allowed + % to lie anywhere on the real line). + + xh = real(xh); + params = trans(xh,trspec); + + % If we choose to fix any of the parameters (i.e., not estimate them), here + % we reset those parameters to those fixed values. + + params = params.*(1-para_mask)+para_fix.*para_mask; + + % Once we get a mode, we this save the parameter vector in the binary file + % 'outfile0'. + + outfile0 = [spath,'/mode_out']; + fid0 = fopen(outfile0,'w'); + fwrite(fid0,params','single'); + fclose(fid0); + + % If the algorithm stops only because we have exceeded the maximum number of + % iterations,continue improving guess of modal parameters by recursively + % calling gibb. + if itct >= nit + clear infile0; + gibb_est_ant; + return; + end +end + + +%% Step 3: Compute the inverse Hessian %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Once we find and save the posterior mode, we calculate the Hessian +% at the mode. The hessian is used to calculate the variance of the proposal +% distribution,which is used to draw a new parameter in each iteration of +% the algorithm. +%% Step 3a: Calculate Hessian corresponding to the posterior mode +if CH == 1 % if choose to calculate Hessian + disp('Re-computing Hessian') + MIN=0; + %calculate Hessian + hessian = hessizero('objfcndsge_2part',[params,para_mask],1,... + YY,nobs,nlags,nvar,mspec,npara,trspec,pmean,pstdd,pshape,para_mask,... + para_fix,marglh,coint,cointadd,cointall,MIN,nant,antlags); + % Save computed Hessian in output file + + outfile_hes = [spath,'/hessian']; + fid_hes = fopen(outfile_hes,'w'); + fwrite(fid_hes,hessian,'single'); + fclose(fid_hes); +else % if don't calculate Hessian, read in pre-calculated Hessian matrix + disp('Using pre-calculated Hessian') + infile_hes = [spath,'/hessian']; + fid = fopen(infile_hes,'r'); + hessian=fread(fid,[npara npara],'single'); +end; + +if any(diag(hessian)<0) + error('negative in diagonal of hessian'); +end + +%% Step 3b: Calculate inverse of Hessian (by Singular Value Decomposition) +% We use singular value decomposition to compute the inverse of the +% Hessian, as the Hessian calculated above is singular +rankhhm = npara; +[u,s,v] = svd(hessian); +sigpropinv = hessian; +md = min(size(s)); +bigev = find(diag(s(1:md,1:md))>1e-6); +sigpropdim = length(bigev); + +sigproplndet = 0; + +for i = 1:npara + if i > sigpropdim + s(i,i) = 0; + else + s(i,i) = 1/s(i,i); + sigproplndet = sigproplndet+log(s(i,i)); + end +end + +invhhm = u*s*u'; +sigscale = u*sqrt(s); + +if length(bigev) ~= (npara-length(find(para_mask))) + disp('problem -- shutting down dimensions') + pause +end + + +%% Step 3: Initialize algorithm by drawing para_old from a normal distribution centered on the posterior mode (propdens). + +% para_old is used to solve the model to check for indeterminancy, and it is +% passed through objfcnmhdsge.m to calculate the posterior value. + +% objfcnmhdsge.m is similar to objfcndsge.m, except it also checks that parameters +% are within the bounds specified in mspec_parameters.m. Until the parameters +% are within bounds, or until the posterior value is sufficiently large, gibb.m +% keeps drawing a new para_old (if you see multiple lines of "Initializing..." +% in the command window, this is the problem). + +[TTT,RRR,CCC,valid] = dsgesolv(mspec,params,nant); +retcode = valid; +[lnpost0,lnpy0,zend0,ZZ0,DD0,QQ0] = feval('objfcnmhdsge_2part',params,bounds,YY,YY0,nobs,... + nlags,nvar,mspec,npara,trspec,pmean,pstdd,pshape,... + TTT,RRR,CCC,valid,para_mask,coint,cointadd,cointall,YYcoint0,nant,antlags,nshocks); + +jc = 1; +valid0 = 0; +while ~valid0 + jc = jc+1; + + para_old = params + cc0*(sigscale*randn(npara,1)); + para_old = para_old.*(1-para_mask)+para_fix.*para_mask; + + [TTT_old,RRR_old,CCC_old,valid_old] = dsgesolv(mspec,para_old,nant); + nstate = length(TTT_old); + nshocks = size(RRR_old,2); + + retcode = valid_old; + [post_old,like_old,zend_old,ZZ_old,DD_old,QQ_old] = feval('objfcnmhdsge_2part',para_old,bounds,YY,YY0,nobs,... + nlags,nvar,mspec,npara,trspec,pmean,pstdd,pshape,... + TTT_old,RRR_old,CCC_old,valid_old,para_mask,coint,cointadd,cointall,YYcoint0,nant,antlags,nshocks-nant); + + propdens = -0.5*sigpropdim*log(2*pi) - 0.5*sigproplndet - 0.5*sigpropdim*log(cc0^2) ... + -0.5*(para_old - params)'*sigpropinv*(para_old - params)/cc0^2; + + if post_old > -10000000; + valid0 = 1; + end + + record(jc) = post_old; + disp('Initializing Metropolis-Hastings Algorithm') + +end + +tic +fprintf(1,'\n Time %3.2f ',ti(I)); +fprintf(1,'\n Peak = %2.3f',lnpost0); + +%% Open files for saving +% Once you open files for writing, the original files (if they existed) +% will be overwritten. + +% Parameters draws +outfile1 = [spath,'/params']; +fid1 = fopen(outfile1,'w'); + +% Transition Matrices +outfile2 = [spath,'/post']; +fid2 = fopen(outfile2,'w'); + +outfile3 = [spath,'/TTT']; +fid3 = fopen(outfile3,'w'); + +outfile4 = [spath,'/RRR']; +fid4 = fopen(outfile4,'w'); + +outfile5 = [spath,'/zend']; +fid5 = fopen(outfile5,'w'); + +% Covariance Matrices +outfile6 = [spath,'/cov']; +fid6 = fopen(outfile6,'w'); + +% Initialize some variables (for calculating rejection rate) +Tim = 0; +eT = 0; +reje = 0; + +%% Step 4: For nsim*ntimes iterations within each block, generate a new parameter draw. +%% Decide to accept or reject, and save every ntimes_th draw that is accepted. + +for iblock = 1:nblocks + + if iblock >1; fprintf(1,' block: %2.0f %3.2f ;',[iblock,toc/(iblock-1)]); end; + + parasim = zeros(nsim,npara); + likesim = zeros(nsim,1); + postsim = zeros(nsim,1); + rej = zeros(nsim*ntimes,1); + TTTsim = zeros(nsim,nstate^2); + RRRsim = zeros(nsim,nstate*nshocks); + CCCsim = zeros(nsim,nstate); + zsim = zeros(nsim,nstate); + + for j = 1:nsim*ntimes + + Tim = Tim+1; + + % Draw para_new from the proposal distribution (a multivariate normal + % distribution centered on the previous draw, with standard + % deviation cc*sigscale). + + para_new = para_old + cc*(sigscale*randn(npara,1)); + para_new = para_new.*(1-para_mask)+para_fix.*para_mask; + [TTT_new,RRR_new,CCC_new,valid_new] = dsgesolv(mspec,para_new,nant); + retcode = valid_new; + + % Solve the model, check that parameters are within bounds, and + % evalue the posterior. + + [post_new,like_new,zend_new,ZZ_new,DD_new,QQ_new] = feval('objfcnmhdsge_2part',para_new,bounds,YY,YY0,nobs,... + nlags,nvar,mspec,npara,trspec,pmean,pstdd,pshape,TTT_new,RRR_new,CCC_new,valid_new,para_mask,coint,cointadd,cointall,YYcoint0,nant,antlags,nshocks-nant); + + + % Calculate the multivariate log likelihood of jump from para_old to para_new + propdens = -0.5*sigpropdim*log(2*pi) - 0.5*sigproplndet - 0.5*sigpropdim*log(cc^2) ... + -0.5*(para_new - para_old)'*sigpropinv*(para_new - para_old)/cc^2; + + + % Choose to accept or reject the new parameter by calculating the + % ratio (r) of the new posterior value relative to the old one + % We compare min(1,r) to a number drawn randomly from a + % uniform (0,1) distribution. This allows us to always accept + % the new draw if its posterior value is greater than the previous draw's, + % but it gives some probability to accepting a draw with a smaller posterior value, + % so that we may explore tails and other local modes. + + r = min([1 ; exp( post_new - post_old)]); + + if rand(1,1) < r; + % Accept proposed jump + para_old = para_new; + post_old = post_new; + like_old = like_new; + + TTT_old = TTT_new; + RRR_old = RRR_new; + CCC_old = CCC_new; + valid_old = valid_new; + + zend_old = zend_new; + ZZ_old = ZZ_new; + DD_old = DD_new; + QQ_old = QQ_new; + + else + % Reject proposed jump + rej(j) = 1; + reje = reje+1; + + end + + % Save every (ntime)th draw + if (j/ntimes) == round(j/ntimes) + likesim(j/ntimes,1) = like_old; + postsim(j/ntimes,1) = post_old; + parasim(j/ntimes,:) = para_old'; + TTTsim(j/ntimes,:) = TTT_old(:)'; + RRRsim(j/ntimes,:) = RRR_old(:)'; + CCCsim(j/ntimes,:) = CCC_old(:)'; + zsim(j/ntimes,:) = zend_old(:)'; + end + + if j == nsim*ntimes + fprintf(1,'\nRejection perct %2.4f ',[sum(rej)/j]); + end + + end + + fwrite(fid1,parasim','single'); + fwrite(fid2,postsim','single'); + fwrite(fid3,TTTsim','single'); + fwrite(fid4,RRRsim','single'); + fwrite(fid5,zsim','single'); + +end + +toc + +fprintf(1,'rejection rate = %2.4f',reje/Tim); + +%% Calculate Parameter Covariance Matrix + +num1 = nblocks*nsim*npara*4; % number of bites per file +numb1 = nburn*npara*4; % number of bites to discard + +% read in saved parameter draws +infile_params = [spath,'/params']; +fid = fopen(infile_params,'r'); +status = fseek(fid,numb1,'bof'); + + +% Reshape parameter draws into a matrix so can calculate covariance +theta = []; +while ( ftell(fid1) < num1 ) + theta_add = fread(fid,[npara,nsim],'single')'; + theta = [theta; theta_add]; +end + +% Calculate covariance and save +cov_theta = cov(theta); +fwrite(fid6,cov_theta(:),'single'); +fclose('all'); diff --git a/estimation/hessizero.m b/estimation/hessizero.m new file mode 100644 index 0000000..8fd4d12 --- /dev/null +++ b/estimation/hessizero.m @@ -0,0 +1,115 @@ +function [hessian,stoph] = hessizero(fcn,x,Verbose,varargin) +% computes hessian of function fcn (string) evaluated at x (vector) +% varargin are the other inputs of fcn +% if Verbose, display error messages , results, etc. +% 11/12/01 translated by Marco DelNegro in matlab from Frank Schorfheide's program in gauss + +%% index of free parameters +para_free = 1-x(:,2); +fpara_free = find(para_free); +nfree = length(fpara_free); + +%% actual max +x = x(:,1); + +npara = length(x); +ndx = 6; +dx = exp(-(6:2:(6+(ndx-1)*2))'); +hessian = zeros( npara, npara ); +gradx = zeros(ndx,1); +grady = zeros(ndx,1); +gradxy = zeros(ndx,1); +hessdiag = zeros(ndx,1); +dxscale = ones(npara,1); + + + +% Compute Diagonal elements first +for seli = fpara_free' + + if Verbose; fprintf(1,'\n Hessian Element: (%2.2g %2.2g)',[seli,seli]); end; + for i=1:ndx; + paradx = x; + parady = x; + paradx(seli) = paradx(seli) + dx(i)*dxscale(seli); + parady(seli) = parady(seli) - dx(i)*dxscale(seli); + paradxdy = paradx; + paradxdy(seli) = paradxdy(seli) - dx(i)*dxscale(seli); +fx = eval([fcn '(x,varargin{:})']); + fdx = eval([fcn '(paradx,varargin{:})']); + fdy = eval([fcn '(parady,varargin{:})']); + fdxdy = eval([fcn '(paradxdy,varargin{:})']); + gradx(i) = -( fx - fdx )/ (dx(i)*dxscale(seli)); + grady(i) = ( fx - fdy )/ (dx(i)*dxscale(seli)); + gradxy(i) = -(fx -fdxdy)/ sqrt( (dx(i)*dxscale(seli))^2 + (dx(i)*dxscale(seli))^2 ); + hessdiag(i) = -( 2*fx - fdx - fdy)/(dx(i)*dxscale(seli))^2; + hessdiag(i) = -( fx - fdx - fdy + fdxdy )/(dx(i)*dx(i)*dxscale(seli)*dxscale(seli)); + end + if Verbose == 2; fprintf(1,'\n Values: %2.6f',-hessdiag); pause; end; + hessian(seli,seli) = -0.5*(hessdiag(3)+hessdiag(4)); + if hessian(seli,seli) <0 + error('negative diagonal in hessian'); + end + if Verbose; fprintf(1,'\n Value Used: %2.6f ',hessian(seli,seli)); end; +end + +% Now compute off-diagonal elements +% Make sure that correlations are between -1 and 1 +% errorij contains the index of elements that are invalid +errorij = [ ]; + +for II = 1:(nfree-1); + seli = fpara_free(II); + for JJ = II+1:nfree; + selj = fpara_free(JJ); + if Verbose; fprintf(1,'\n Hessian Element: (%2.2g %2.2g)',[seli,selj]); end; + for i=1:ndx; + paradx = x; + parady = x; + paradx(seli) = paradx(seli) + dx(i)*dxscale(seli); + parady(selj) = parady(selj) - dx(i)*dxscale(selj); + paradxdy = paradx; + paradxdy(selj) = paradxdy(selj) - dx(i)*dxscale(selj); + fx = eval([fcn '(x,varargin{:})']); + fdx = eval([fcn '(paradx,varargin{:})']); + fdy = eval([fcn '(parady,varargin{:})']); + fdxdy = eval([fcn '(paradxdy,varargin{:})']); + gradx(i) = -( fx - fdx )/ (dx(i)*dxscale(seli)); + grady(i) = ( fx - fdy )/ (dx(i)*dxscale(selj)); + gradxy(i) = -(fx -fdxdy)/ sqrt( (dx(i)*dxscale(selj))^2 + (dx(i)*dxscale(seli))^2 ); + hessdiag(i) = -( 2*fx - fdx - fdy)/(dx(i)*dxscale(seli))^2; + hessdiag(i) = -( fx - fdx - fdy + fdxdy )/(dx(i)*dx(i)*dxscale(seli)*dxscale(selj)); + end + if Verbose == 2; fprintf(1,'\n Values: %2.6f',-hessdiag); pause; end; + %"Values"; ; + + hessian(seli,selj) = -0.5*(hessdiag(3)+hessdiag(4)); + + if ( hessian(seli,selj) == 0 ) | (hessian(selj,selj) == 0) + corrij = 0; + else + corrij = hessian(seli,selj)/sqrt(hessian(seli,seli)*hessian(selj,selj)); + end + + if (corrij < -1) | (corrij > 1) + hessian(seli,selj)=0; + errorij = [errorij;[seli,selj,corrij]]; + end + hessian(selj,seli) = hessian(seli,selj); + + if Verbose + fprintf(1,'\n Value Used: %2.6f ',hessian(seli,seli)); + fprintf(1,'\n Correlation: %2.6f ',corrij); + fprintf(1,'\n Number of errors: %2.2g ',size(errorij,1)); + end + end +end + + stoph = 0; +if ~isempty(errorij) + fprintf(1,'\n Errors: %2.6f %2.6f %2.6f ',errorij'); + stoph = 1; +end + + + diff --git a/estimation/is2part.m b/estimation/is2part.m new file mode 100644 index 0000000..27a54d0 --- /dev/null +++ b/estimation/is2part.m @@ -0,0 +1,7 @@ +% OVERVIEW +% +% Function checks if a model is a two part model +function [ yesno ] = is2part(mspec) + class2part; + yesno = (any(mspec == class2part_all)); +end diff --git a/estimation/mom.m b/estimation/mom.m new file mode 100644 index 0000000..88867ff --- /dev/null +++ b/estimation/mom.m @@ -0,0 +1,109 @@ +% OVERVIEW +% mom.m: Computes moments, tabulates parameter moments, and plots parameter +% draws from the prior and posterior distribution. +% +% IMPORTANT VARIABLES +% PLOTDRAWS: Specify whether or not you want to plot the parameter draws +% (runs momPlot.m) +% percent: In the output laTex table, we report bands for +% parameter draws from the posterior +% +% INPUTS +% infile1: This refers to a an output file (mhparam*) from gibb.m, +% which holds draws from the posterior. +% infile4: This refers to a an output file (post*) from gibb.m, which +% holds the value of the posterior, for each posterior draw. +% theta: (ndraws x npara) matrix holding the posterior draws +% (stored in mhpara*, output from gibb.m) +% post: (ndraws x 1) matrix holding the posterior value +% (stored in post*, output from gibb.m) +% priotheta: (ndraws x npara) matrix holding the prior draws +% (stored in mhNIpriopara*, output from prio.m) +% (optional input) +% +% OUTPUTS +% From momTable.m: 1: (mhpara*Mean): holds the mean parameter across +% draws from the posterior. +% 2: (*Mom_MainParams*): laTex table that lists the +% moments for important parameters. +% 3: (*Mom_PeriphParams*): laTex table that lists the +% moments for less important parameters. +% 4: (*PrioPostMean*) that lists the prior and +% posterior means + +close all; +keepVars; +initializePrograms; + +%% Settings +Verbose = 0; +percent = .90; % Bands + +%% Input files + +% Posterior draws (output from gibb.m) +infile1 = [spath, 'params']; +num1 = nblocks*nsim*npara*4; % number of bites per file +numb1 = nburn*npara*4; % number of bites to dicard +disp(['Infile: ' infile1]); + +% Posterior values file (output from gibb.m) +infile4 = [spath,'/post']; +num4 = nblocks*nsim*1*4; +numb4 = nburn*1*4; + +%% Load in theta (postrior draws), priotheta (prior draws), and post (posterior value) +fid1 = fopen(infile1,'r'); +status = fseek(fid1,numb1,'bof'); + +fid4 = fopen(infile4,'r'); +status = fseek(fid4,numb4,'bof'); + +theta = []; +priotheta = []; +post = []; + +% Read blocks of size nsim +while ( ftell(fid1) < num1 ) + + thetadd = fread(fid1,[npara,nsim],'single')'; + theta = [theta;thetadd]; + clear thetadd; + + postadd = fread(fid4,[nsim,1],'single'); + post = [post;postadd]; + clear postadd; + +end; + +fclose(fid1); +fclose(fid4); + + +ndraws = size(theta,1); + +%% Produce table (Tex) of moments +momTable; + +infile1 = [spath,'params']; +num1 = nblocks*nsim*npara*4; % number of bites per file +numb1 = nburn*npara*4; % number of bites to dicard +fid1 = fopen(infile1,'r'); +status = fseek(fid1,numb1,'bof'); + +theta = []; + +while ( ftell(fid1) < num1 ) % Read blocks of size nsim + theta_add = fread(fid1,[npara,nsim],'single')'; + theta = [theta; theta_add]; +end + +cov_theta = cov(theta); + +outfile100 = [spath,'/cov']; +fid100 = fopen(outfile100,'w'); + +fwrite(fid100,cov_theta(:),'single'); + +fclose('all'); + diff --git a/estimation/momTable.m b/estimation/momTable.m new file mode 100644 index 0000000..40facdc --- /dev/null +++ b/estimation/momTable.m @@ -0,0 +1,200 @@ +% OVERVIEW +% momTable.m: tabulates parameter moments in 3 laTex tables: +% (1) For our MAIN parameters, a list of the prior means, prior +% standard deviations, posterior means and 90% bands for posterior +% draws. +% (2) For LESS IMPORTANT parameters, a list of the prior means, prior +% standard deviations, posterior means and 90% bands for posterior +% draws. +% (3) A list of prior means and posterior means +% +% momTable.m is called on in mom.m +% +% INPUTS +% theta: (ndraws x npara) matrix holding the posterior draws +% (stored in mhpara*, output from gibb.m) +% post: (ndraws x 1) matrix holding the posterior value +% (stored in post*, output from gibb.m) +% priotheta: (ndraws x npara) matrix holding the prior draws +% (stored in mhNIpriopara*, output from prio.m) +% +% OUTPUTS +% outfile0: This refers to a file (mhpara*Mean) that holds the mean +% parameter across draws from the posterior. +% outfile01: This refers to a latex table (*Mom_MainParams*) that lists the +% moments for important parameters. +% outfile02: This refers to a latex table (*Mom_PeriphParams*) that lists the +% moments for less important parameters. +% outfile03: This refers to a latex table (*PrioPostMean*) that lists +% the prior and posterior means + +%% Compute mean, st dev, and 90% bands across draws from the posterior + +% pmean and pstdd (prior mean and st dev are computed in +% initializePrograms.m + +thetahat = mean(theta,1)'; +thetasig = cov(theta,1); +thetabands = hpdint(theta,percent,1)'; + +%% Save posterior mean + +outfile0 = [spath,'/params_mean']; +fid0 = fopen(outfile0,'w'); +fwrite(fid0,thetahat','single'); +fclose(fid0); + +%% Open outfiles for writing + +% Moments for main parameters +outfile01 = [fpath,'Mom_MainParams.tex']; +fid01 = fopen(outfile01,'w'); + +% Moments for peripheral parameters +outfile02 = [fpath,'Mom_PeriphParams.tex']; +fid02 = fopen(outfile02,'w'); + +% Parameter mean across prior draws and posterior draws +outfile03 = [fpath,'PrioPostMean.tex']; +fid03 = fopen(outfile03,'w'); + +%% Create variables used for writing to the output table + +colnames = {'Parameter ',... + 'Prior Mean ',... + 'Prior Stdd ',... + 'Post Mean ',... + [num2str(100*percent),'\% {\tiny Lower Band}'],... + [num2str(100*percent),'\% {\tiny Upper Band}'] }; + +outmat = [pmean,pstdd,thetahat,thetabands]; % prior mean and standard devaition, posterior mean and bands +outmat2 = [pmean thetahat]; % prior mean and posterior mean + +%% Write to Table 1: Prior mean, st dev and posterior mean, bands for IMPORTANT parameters + +fprintf(fid01,'\n \\documentclass[12pt]{article}'); +fprintf(fid01,'\n \\usepackage[dvips]{color}'); +fprintf(fid01,'\n \\begin{document}'); +fprintf(fid01,'\n \\pagestyle{empty}'); +fprintf(fid01,'\n \\begin{table}[h] \\centering'); +fprintf(fid01,'\n \\caption{Parameter Estimates}'); +fprintf(fid01,'\n \\vspace*{.5cm}'); +fprintf(fid01,'\n {\\small \n'); +fprintf(fid01,'\n \\begin{tabular}{lllllll}\\hline \n'); + +fprintf(fid01,' %4.99s & ',colnames{:}); + +% Keep track of the indices for these important parameters within para_names +important_para = []; +for i = 1:length(para_names) + if isempty(regexp(para_names{i},'rho_','once')) && ... + isempty(regexp(para_names{i},'zeta_','once')) && ... + isempty(regexp(para_names{i},'psi_','once')) && ... + isempty(regexp(para_names{i},'nu_l','once')) && ... + isempty(regexp(para_names{i},'pi^*','once')) && ... + (mspec ~= 16 || isempty(regexp(para_names{i},'u^*','once'))) + continue; + end + if strcmp(para_names{i},'\rho_{\chi}') || (isequal(subspec,7) && strcmp(para_names{i},'\rho_{b}')) + continue; + end + fprintf(fid01,'\\\\ \n $%4.99s$ & ',para_names{i}); + fprintf(fid01,' %8.3f & ',outmat(i,:)); + important_para = [important_para, i]; +end + +fprintf(fid01,'\\\\ \\hline'); +fprintf(fid01,'\n \\end{tabular}}'); +fprintf(fid01,'\n \\end{table} \n\n'); +fprintf(fid01,'\n \\end{document}'); +fclose(fid01); + +%% Write to Table 2: Prior mean, st dev and posterior mean, bands for OTHER parameters + +fprintf(fid02,'\n \\documentclass[12pt]{article}'); +fprintf(fid02,'\n \\usepackage[dvips]{color}'); +fprintf(fid02,'\n \\begin{document}'); +fprintf(fid02,'\n \\pagestyle{empty}'); +fprintf(fid02,'\n \\begin{table}[h] \\centering'); +fprintf(fid02,'\n \\caption{Parameter Estimates}'); +fprintf(fid02,'\n \\vspace*{.2cm}'); +fprintf(fid02,'\n {\\small \n'); +fprintf(fid02,'\n \\begin{tabular}{lllllll}\\hline \n'); + +fprintf(fid02,' %4.99s & ',colnames{:}); + +% Counter for parameters to track length of table, number of tables in +% excess of default '1' +other_para = 1; +table_count = 0; +for i = 1:length(para_names) + if ismember(i,important_para) + continue; + end + + if mod(other_para,25) == 0 && ~(i == length(para_names)) + fprintf(fid02,'\\\\ \\hline'); + fprintf(fid02,'\n \\end{tabular}}'); + fprintf(fid02,'\n \\end{table} \n\n'); + fprintf(fid02,'\n \\end{document}'); + + table_count = table_count + 1; + fclose(fid02); + + filename = sprintf('Mom_PeriphParams_%i.tex',table_count); + outfile02 = [fpath,filename]; + fid02 = fopen(outfile02,'w'); + + fprintf(fid02,'\n \\documentclass[12pt]{article}'); + fprintf(fid02,'\n \\usepackage[dvips]{color}'); + fprintf(fid02,'\n \\begin{document}'); + fprintf(fid02,'\n \\pagestyle{empty}'); + + fprintf(fid02,'\n \\begin{table}[h] \\centering'); + fprintf(fid02,'\n \\caption{Parameter Estimates}'); + fprintf(fid02,'\n \\vspace*{.2cm}'); + fprintf(fid02,'\n {\\small \n'); + fprintf(fid02,'\n \\begin{tabular}{lllllll}\\hline \n'); + + fprintf(fid02,' %4.99s & ',colnames{:}); + end + + fprintf(fid02,'\\\\ \n $%4.99s$ & ',para_names{i}); + fprintf(fid02,' %8.3f & ',outmat(i,:)); + other_para = other_para + 1; +end +fprintf(fid02,'\\\\ \\hline'); +fprintf(fid02,'\n \\end{tabular}}'); +fprintf(fid02,'\n \\end{table} \n\n'); +fprintf(fid02,'\n \\end{document}'); +fclose(fid02); +clear parasimm postsim; + +%% Write to Table 3: Prior mean and posterior mean for all parameters + +fprintf(fid03,'\n \\documentclass[12pt]{article}'); +fprintf(fid03,'\n \\usepackage[dvips]{color}'); +fprintf(fid03,'\n \\begin{document}'); +fprintf(fid03,'\n \\pagestyle{empty}'); +fprintf(fid03,'\n \\begin{table}[h] \\centering'); +fprintf(fid03,'\n \\caption{Parameter Estimates: Prior and Posterior Mean}'); +fprintf(fid03,'\n \\vspace*{.5cm}'); +fprintf(fid03,'\n \\begin{tabular}{ccc'); +fprintf(fid03,'}\\hline \n'); +fprintf(fid03,' Parameter & Prior '); +fprintf(fid03,'\\\\ \\hline \n'); + +for i = 1:length(para_names) + fprintf(fid03,' \n $%4.99s$ ',para_names{i}); + fprintf(fid03,' & %8.3f ',outmat2(i,:)); + fprintf(fid03,'\\\\ '); +end +fprintf(fid03,'\\\\ \\hline'); +fprintf(fid03,'\n \\end{tabular}'); +fprintf(fid03,'\n \\end{table} \n\n'); +fprintf(fid03,'\n \\end{document}'); +fclose(fid03); + +close all; + +fprintf('Tables are in %s \n',fpath); diff --git a/estimation/objfcndsge.m b/estimation/objfcndsge.m new file mode 100644 index 0000000..5846934 --- /dev/null +++ b/estimation/objfcndsge.m @@ -0,0 +1,29 @@ +function [obj, varargout] = objfcndsge(para,YY,YY0,nobs,nlags,nvar,mspec,npara,trspec,pmean,pstdd,pshape,para_mask,... + para_fix,marglh,coint,cointadd,cointall,YYcoint0,MIN, nant, antlags) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% obj evaluates the log posterior = log likelihood + log prior +%% MIN takes into account that csminwel minimizes as opposed to max, and that the parameters are rescaled +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +if MIN + para = trans(para,trspec); +end +para = para.*(1-para_mask)+para_fix.*para_mask; + + +%--- Evaluate the Likelihood function: LOG{P[y|theta]} +lnpy = dsgelh(para,YY,YY0,nobs,nlags,nvar,mspec,npara,coint,cointadd,YYcoint0, nant, antlags); +%--- Evaluate the Prior distribution: LOG{P[theta]} +lnprio = priodens(para,pmean,pstdd,pshape); + +%--- Evaluate the Posterior density: LOG{P[theta|y]} +if MIN + obj = real(-lnpy-lnprio); % We minize the inverse of the likelihood fcn +else + obj = real(lnpy+lnprio); +end + +if nargout>1 + varargout(1) = {lnpy}; + varargout(2) = {lnprio}; +end; diff --git a/estimation/objfcndsge_2part.m b/estimation/objfcndsge_2part.m new file mode 100644 index 0000000..1bd6cee --- /dev/null +++ b/estimation/objfcndsge_2part.m @@ -0,0 +1,28 @@ +function [obj, varargout] = objfcndsge_2part(para,YY,nobs,nlags,nvar,mspec,npara,trspec,pmean,pstdd,pshape,para_mask,... + para_fix,marglh,coint,cointadd,cointall,MIN, nant, antlags) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% obj evaluates the log posterior = log likelihood + log prior +%% MIN takes into account that csminwel minimizes as opposed to max, and that the parameters are rescaled +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +if MIN + para = trans(para,trspec); +end +para = para.*(1-para_mask)+para_fix.*para_mask; + +%--- Evaluate the Likelihood function: LOG{P[y|theta]} +lnpy = dsgelh_2part(para,YY,nobs,nlags,nvar,mspec,npara,coint,cointadd,nant, antlags); +%--- Evaluate the Prior distribution: LOG{P[theta]} +lnprio = priodens(para,pmean,pstdd,pshape); + +%--- Evaluate the Posterior density: LOG{P[theta|y]} +if MIN + obj = real(-lnpy-lnprio); % We minize the inverse of the likelihood fcn +else + obj = real(lnpy+lnprio); +end + +if nargout>1 + varargout(1) = {lnpy}; + varargout(2) = {lnprio}; +end; diff --git a/estimation/objfcnmhdsge.m b/estimation/objfcnmhdsge.m new file mode 100644 index 0000000..557f9a2 --- /dev/null +++ b/estimation/objfcnmhdsge.m @@ -0,0 +1,230 @@ +% OVERVIEW +% +% +% This is a dsge likelihood function that can handle 2-part estimation where +% there is a model switch. It also checks that parameters are within certain +% bounds--which is the main difference from dsgelh_2part.m. +% +% HOWEVER, this program is by and large the same as dsgelh_2part.m, save the +% bound-checking. Therefore, the code has been substantially consolidated and +% much of the code supporting the operations in this function are shared by +% dsgelh_2part.m +% +% Note: given the multi-period setup, all relevant matrices will be stored +% in an array structure since they will change over time. As currently +% implemented, there are 3 time periods, which index the structure: presample, +% normal sample, ZB sample. +% +% If there is no model switch, then we filter over the main sample all at once. +% +function [lnpost,lnpy,zend,ZZ,DD,QQ] = objfcnmhdsge(para,bounds,YY,... + YY0,nobs,nlags,nvar,mspec,npara,trspec,pmean,pstdd,pshape,... + TTT,RRR,CCC,valid,para_mask,coint,cointadd,cointall,YYcoint0,nant,antlags) + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% STEP 0: Set up structures that will hold all of the transition equation matrices. Store transition mats +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Set up the general classes of 2-part estimation models where +% operations/indexing is similar within a particular class. +class2part; + + +% Create structure to hold all matrices -- data matrices, state equation matrices, measurement matrices, etc. +[mt, pd] = dsgelh_partition(YY0, YY, nvar, nant, antlags); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% STEP 1: Process the state transition equation matrices +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Put the TTT, RRR, CCC matrices in mt +mt(pd).TTT = TTT; +mt(pd).RRR = RRR; +mt(pd).CCC = CCC; + +%% For models using 2part estimation: Get the normal, no ZB model matrices +if any(mspec == class2part_all) + + % Set the starting indices for states and shocks corresponding to anticipated + % policy shocks; depends on how eqconds is set up for a particular model + if any(mspec == class2part_555) + str_ant_state = 'n_end+n_exo'; + str_ant_shock = 'n_exo'; + + % Also for the 555 class of models, we need to drop the extra equation for + % the evolution of the monetary shock. See the getNoZBmats.m function. This + % is very model specific. + revol_ind = {getState(mspec, nant, 'n_end+n_exo') - nant}; + + elseif any(mspec == class2part_955) + str_ant_state = 'nstates'; + str_ant_shock = 'nex'; + revol_ind = {}; + end + start_ant_state = getState(mspec,nant,str_ant_state)-nant+1; + start_ant_shock = getState(mspec,nant,str_ant_shock)-nant+1; + + [mt(pd-1).TTT, mt(pd-1).RRR, mt(pd-1).CCC] = ... + dsgelh_getNoZB(nant, start_ant_state, start_ant_shock, mt(pd).TTT, mt(pd).RRR, mt(pd).CCC,revol_ind{:}); +end + + +if valid < 1; + lnpost = -1E10; + lnpy = -1E20; + zend = []; + ZZ = []; + DD = []; + QQ = []; + return; +end + +ind1 = (para > bounds(:,2)); +ind1(logical(para_mask)) = []; +ind2 = (para < bounds(:,1)); +ind2(logical(para_mask)) = []; + +if any(ind1) || any(ind2) + + lnpost = -1E10; + lnpy = -1E20; + zend = []; + ZZ = []; + DD = []; + QQ = []; + +else + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% step 2: define the measurement equation: X_t = ZZ S_t +D+u_t + %% where u_t = eta_t+MM* eps_t with var(eta_t) = EE + %% where var(u_t) = HH = EE+MM QQ MM', cov(eps_t,u_t) = VV = QQ*MM' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % Set up some helper functions to create compound matrices by passing the + % period index to access the relevant EE, MM, QQ, RR, VV matrices + makeHH = @(E, M, Q) E + M*Q*M'; + makeVV = @(Q, M) Q*M'; + makeVVall = @(R, Q, V, H) [[R*Q*R', R*V]; ... + [V'*R', H]]; + + + % Get measurement equation matrices set up for all periods that aren't the presample + for p = 2:pd + + % Save measurement equations + [mt(p).ZZ, mt(p).DD, mt(p).DDcointadd, mt(p).QQ, mt(p).EE, mt(p).MM, retcode] = ... + feval(['measur',num2str(mspec)], mt(p).TTT, mt(p).RRR,valid,para,mt(p).nvar,nlags,mspec,npara,coint,cointadd,mt(p).nant{:}); + + if retcode == 0 + % invalid parameterization + pyt = -1E10; + return; + end; + + mt(p).HH = makeHH(mt(p).EE, mt(p).MM, mt(p).QQ); + mt(p).VV = makeVV(mt(p).QQ, mt(p).MM); + mt(p).VVall = makeVVall(mt(p).RRR, mt(p).QQ, mt(p).VV, mt(p).HH); + + if coint ~= 0 && find(mt(p).CCC) ~= nan % Rare, only used for mspec 3; kept for legacy + dfgdfsgdfgdf % if we get this error, we need to fix something + + else % Used for everything else + if p == 2 && any(CCC ~= 0) % If in non-ZB period/model + mt(p).DD = mt(p).DD + mt(p).ZZ*((eye(size(mt(p).TTT))-mt(p).TTT)\mt(p).CCC); + end + end + end + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% step 3: compute log-likelihood using Kalman filter - written by Iskander + %% note that Iskander's program assumes a transition equation written as: + %% S_t = TTT S_{t-1} +eps2_t, where eps2_t = RRReps_t + %% therefore redefine QQ2 = var(eps2_t) = RRR*QQ*RRR' + %% and VV2 = cov(eps2_t,u_u) = RRR*VV + %% define VVall as the joint variance of the two shocks VVall = var([eps2_t;u_t]) + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + %% PRESAMPLE + + %% Define the initial mean and variance for the state vector (deals with + %nonstationarity on model by model basis) + [A0,P0] = lyap_nonstationary(mspec,para, mt(2).TTT, mt(2).RRR, mt(2).QQ); + + + % Set zend and Pend + if ~isempty(mt(1).YY) + if coint == 0 % Usual case + + %% run Kalman filter on initial observations + [xxx,mt(1).zend,mt(1).Pend] = ... + kalcvf2NaN(mt(1).YY',1,zeros(size(mt(2).TTT,2),1),mt(2).TTT,... + mt(2).DD,mt(2).ZZ,mt(2).VVall,A0,P0); + + else % Rare case, only mspec 3, kept for legacy purposes + + %% run Kalman filter for initial observations on extended system + [pytcoint,zend,Pend] = ... + kalcvf2NaN([mt(1).YY(1,:),YYcoint0]',1, zeros(size(mt(2).TTT,2),1), mt(2).TTT, ... + mt(2).DD, mt(2).ZZ, mt(2).VVall,A0,P0); + + %% run Kalman filter on remainder of initialization sample + %% first, remove cointegration component from the system + meas_mats = {'ZZ', 'DD', 'EE', 'MM'}; + for mm = 1:length(meas_mats) + mt(1).(meas_mats{mm}) = mt(2).(meas_mats{mm})(1:nvar,:); + end + mt(1).EE = mt(2).EE(:,1:nvar); + + % Recompute + mt(1).HH = makeHH(mt(1).EE, mt(1).MM, mt(2).QQ); + mt(1).VV = makeVV(mt(2).QQ, mt(1).MM); + mt(1).VVall = makeVVall(mt(2).RRR, mt(2).QQ, mt(1).VV, mt(1).HH); + + if nlags > 1 + [pyt0,mt(1).zend,mt(1).Pend] = ... + kalcvf2NaN(mt(1).YY(2:end,:)',1,zeros(size(mt(2).TTT,2),1),mt(2).TTT,... + mt(1).DD,mt(1).ZZ,mt(1).VVall,zend,Pend); + end + + end + else + mt(1).zend = A0; + mt(1).Pend = P0; + end + + + %% MAIN SAMPLE + + % Loop over normal period and extra periods (if any) + for p = 2:pd + if p > 2 + [zprev,Pprev] = augmentStates(mspec, mt(p).nant{:}, size(mt(p).TTT,2), mt(p-1).zend, mt(p-1).Pend); + else + zprev = mt(p-1).zend; + Pprev = mt(p-1).Pend; + end + [mt(p).pyt, mt(p).zend, mt(p).Pend] = ... + kalcvf2NaN( (mt(p).YY)', 1, zeros(size(mt(p).TTT,2),1), mt(p).TTT, ... + mt(p).DD, mt(p).ZZ, mt(p).VVall, zprev, Pprev); + end + + pyt = sum([mt(2:end).pyt]); + + + %% Stuff to return + lnpy = real(pyt); + lnprio = priodens(para,pmean,pstdd,pshape); + lnpost = lnpy + real(lnprio); + + zend = mt(p).zend; + ZZ = mt(p).ZZ; + DD = mt(p).DD; + QQ = mt(p).QQ; + +end + + +end diff --git a/estimation/objfcnmhdsge_2part.m b/estimation/objfcnmhdsge_2part.m new file mode 100644 index 0000000..b48d418 --- /dev/null +++ b/estimation/objfcnmhdsge_2part.m @@ -0,0 +1,187 @@ +function [lnpost,lnpy,zend,ZZ,DD,QQ] = objfcnmhdsge_2part(para,bounds,YY,... + YY0,nobs,nlags,nvar,mspec,npara,trspec,pmean,pstdd,pshape,... + TTT,RRR,CCC,valid,para_mask,coint,cointadd,cointall,YYcoint0,nant,antlags,nshocks) + +iSplit = getState(mspec,0,'n_end+n_exo'); +nstate = size(TTT,1); + +% For 510,555, TTT/RRR/CCC for 510 are contained within those for 555 +if any(mspec == [555 556 557 5571 558]) + TTT1 = zeros(nstate-(nant+1),nstate-(nant+1)); + TTT1 = [TTT(1:iSplit,1:iSplit), ... + TTT(1:iSplit,iSplit+(nant+1)+1:end);... + TTT(iSplit+(nant+1)+1:end,1:iSplit),... + TTT(iSplit+(nant+1)+1:end,iSplit+(nant+1)+1:end)]; + + RRR1 = zeros(nstate-(nant+1),nshocks); + RRR1 = [RRR(1:iSplit,1:nshocks); RRR(iSplit+(nant+1)+1:end,1:nshocks)]; + + CCC1 = zeros(nstate-(nant+1),1); + CCC1 = [CCC(1:iSplit,1); CCC(iSplit+(nant+1)+1:end,1)]; +end + +if valid < 1; + lnpost = -1E10; + lnpy = -1E20; + zend = []; + ZZ = []; + DD = []; + QQ = []; + return; +end + +ind1 = (para > bounds(:,2)); +%disp([find(ind1) para(find(ind1)) bounds(find(ind1),1)]) +ind1(logical(para_mask)) = []; +ind2 = (para < bounds(:,1)); +%disp([find(ind2) disp(find(ind2)) bounds(find(ind2),2)]) +ind2(logical(para_mask)) = []; + +if any(ind1) || any(ind2) + + lnpost = -1E10; + lnpy = -1E20; + zend = []; + ZZ = []; + DD = []; + QQ = []; + +else + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% step 2: define the measurement equation: X_t = ZZ S_t +D+u_t +%% where u_t = eta_t+MM* eps_t with var(eta_t) = EE +%% where var(u_t) = HH = EE+MM QQ MM', cov(eps_t,u_t) = VV = QQ*MM' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +eval(strcat('[ZZ,DD,DDcointadd,QQ,EE,MM,retcode] = measur',num2str(mspec),'(TTT1,RRR1,valid,para,nvar-nant,nlags,mspec,npara,coint,cointadd);')); +%[ZZ,DD,QQ,EE,MM,retcode] = measur(TTT,RRR,valid,para,nvar,nlags,mspec,npara); + +if retcode == 0 + % invalid parameterization + pyt = -1E10; + return; + +end; + +nstate = size(TTT1,1); +nshocks = size(RRR1,2); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% step 3: compute log-likelihood using Kalman filter - written by Iskander +%% note that Iskander's program assumes a transition equation written as: +%% S_t = TTT S_{t-1} +eps2_t, where eps2_t = RRReps_t +%% therefore redefine QQ2 = var(eps2_t) = RRR*QQ*RRR' +%% and VV2 = cov(eps2_t,u_u) = RRR*VV +%% define VVall as the joint variance of the two shocks VVall = var([eps2_t;u_t]) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +if coint == 0, + + % truncate data + YY1 = YY(:,1:nvar-nant); + + HH = EE+MM*QQ*MM'; + VV = QQ*MM'; + VVall = [[RRR1*QQ*RRR1',RRR1*VV];[VV'*RRR1',HH]]; + + if any(CCC ~= 0) + DDadd = ZZ*((eye(size(TTT1))-TTT1)\CCC1); + else + DDadd = 0; + end + + DD= DD+DDadd; + + %% if you have constant, change the st st of observables and rewrite kalman as deviations from stst + + + %% Define the initial mean and variance for the state vector + % (deals with nonstationarity on model by model basis) + [A0,P0] = lyap_nonstationary(mspec,para,TTT1,RRR1,QQ); + + + if ~isempty(YY0) + YY0 = YY0(:,1:nvar-nant); + %% run Kalman filter on initial observations + [xxx,zend,Pend] = ... + kalcvf2NaN(YY0',1,zeros(nstate,1),TTT1,DD,ZZ,VVall,A0,P0); + + else + zend = A0; + Pend = P0; + end + + %% run Kalman filter on main sample + % First, filter using normal model up to period + [pyt1,zend,Pend] = kalcvf2NaN(YY1(1:end-antlags-1,:)',1,zeros(nstate,1),TTT1,DD,ZZ,VVall,zend,Pend); + + % Change models to incorporate anticipated shocks + eval(strcat('[ZZ,DD,DDcointadd,QQ,EE,MM,retcode] = measur',num2str(mspec),'(TTT,RRR,valid,para,nvar,nlags,mspec,npara,coint,cointadd,nant);')); + + HH = EE+MM*QQ*MM'; + VV = QQ*MM'; + VVall = [[RRR*QQ*RRR',RRR*VV];[VV'*RRR',HH]]; + + nstate = size(TTT,1); + nshocks = size(RRR,2); + + [zprev,pprev] = augmentStates(mspec,nant,nstate,zend,Pend); + [pyt2,zend,pend] = kalcvf2NaN(YY(end-antlags:end,:)',1,zeros(nstate,1),TTT,DD,ZZ,VVall,zprev,pprev); + pyt=pyt1+pyt2; + +else + + %% use system matrices for extended system + + if find(CCC) ~= nan, + dfgdfsgdfgdf % if we get this error, we need to fix something + end; + + DDcoint = DD(nvar+1:nvar+coint,:); + ZZcoint = ZZ(nvar+1:nvar+coint,:); + + HH = EE+MM*QQ*MM'; + VV = QQ*MM'; + VVall = [[RRR*QQ*RRR',RRR*VV];[VV'*RRR',HH]]; + + %% if you have constant, change the st st of observables and rewrite kalman as deviations from stst + % DDadd = ZZ*((eye(size(TTT))-TTT)\CCC); + % DD= DD+DDadd; + + %% Define the initial mean and variance for the state vector + A0 = zeros(nstate,1); + P0 = dlyap(TTT,RRR*QQ*RRR'); + + %% run Kalman filter for initial observations on extended system + [pytcoint,zend,Pend] = ... + kalcvf2NaN([YY0(1,:),YYcoint0]',1,zeros(nstate,1),TTT,DD,ZZ,VVall,A0,P0); + + %% run Kalman filter on remainder of initialization sample + %% first, remove cointegration component from the system + ZZ = ZZ(1:nvar,:); + DD = DD(1:nvar,:); + EE = EE(1:nvar,1:nvar); + MM = MM(1:nvar,:); + + HH = EE+MM*QQ*MM'; + VV = QQ*MM'; + VVall = [[RRR*QQ*RRR',RRR*VV];[VV'*RRR',HH]]; + nstate = size(TTT,1); + + if nlags > 1 + [pyt0,zend,Pend] = ... + kalcvf2NaN(YY0(2:end,:)',1,zeros(nstate,1),TTT,DD,ZZ,VVall,zend,Pend); + end + + %% run Kalman filter on main sample + [pyt,zend,Pend] = ... + kalcvf2NaN(YY',1,zeros(nstate,1),TTT,DD,ZZ,VVall,zend,Pend); + +end; + + lnpy = real(pyt); + lnprio = priodens(para,pmean,pstdd,pshape); + lnpost = lnpy + real(lnprio); + +end diff --git a/figures/.empty b/figures/.empty new file mode 100644 index 0000000..71ef3b1 --- /dev/null +++ b/figures/.empty @@ -0,0 +1 @@ +Exists so Git will track the figures/ folder, but not the contents. diff --git a/forecast/augmentStates.m b/forecast/augmentStates.m new file mode 100644 index 0000000..78bb091 --- /dev/null +++ b/forecast/augmentStates.m @@ -0,0 +1,42 @@ +% OVERVIEW +% +% This function expands the number of states to accomodate extra states for the +% anticipated policy shocks. It does so by taking the zend and Pend for the +% state space without anticipated policy shocks, then shoves in nant (or +% nant+1, see below) zeros in the middle of zend and Pend in the location of +% the anticipated shock entries. +% +% Note, 557 needs to add in a new equation and state for the monetary shock (bc +% it's iid without ant), while 904 doesn't. As a result, 557 needs nant+1 extra +% states/zeros, while 955 needs nant. See dsgelh_getNoZB.m for more detailed +% explanation. + +function [zprev, pprev] = augmentStates(mspec,nant,nstate,zend,Pend) + +class2part; + +% Because money shock named differently in different models; also need to +% specify "adj" -- the number of extra equations beyond nant that are added to +% the system +if any(mspec == [904 class2part_955]) + r_tl1 = getState(mspec,nant,'rm_tl1'); +else + r_tl1 = getState(mspec,nant,'r_tl1'); +end +adj = adj2part(mspec); + +up_to_ant_all = 1:(r_tl1-1-adj); % Indices for all states up to (but not including) ant and (maybe) new monetary shock states +aftr_ant_prev = (r_tl1+nant):nstate; % State indices for everything after ant in the new zprev vector +aftr_ant_ends = (r_tl1-adj):length(zend); % State indices for everything after ant in the old zend vector + +zprev = zeros(nstate,1); +zprev(up_to_ant_all) = zend(up_to_ant_all, end); +zprev(aftr_ant_prev) = zend(aftr_ant_ends, end); + +pprev = zeros([nstate nstate]); +pprev(up_to_ant_all, up_to_ant_all) = Pend(up_to_ant_all, up_to_ant_all, end); % Upper left block +pprev(aftr_ant_prev, up_to_ant_all) = Pend(aftr_ant_ends, up_to_ant_all, end); % Lower left block +pprev(up_to_ant_all, aftr_ant_prev) = Pend(up_to_ant_all, aftr_ant_ends, end); % Upper right block +pprev(aftr_ant_prev, aftr_ant_prev) = Pend(aftr_ant_ends, aftr_ant_ends, end); % Lower right block + + diff --git a/forecast/forecastFcn_est_ant.m b/forecast/forecastFcn_est_ant.m new file mode 100644 index 0000000..0eb8233 --- /dev/null +++ b/forecast/forecastFcn_est_ant.m @@ -0,0 +1,482 @@ +% OVERVIEW +% forecastFcn_est_ant.m: a function called on by forecast_mode_est_ant.m. This +% function takes draws allocated each worker to calculate +% forecasts, counterfactuals, shock decompositions, and +% smoothed +% shock estimates, both unconditional and conditional on +% Dick +% Peach's forecast. +% +% forecastFcn_est_ant.m is broken up into 4 main steps: +% +% STEP 1: Get matrices of the state transition and +% measurement equations. In gibb.m, these +% matrices are computed and condensed, so here we read in and +% reshape the input data. +% STEP 2: Run the Kalman filter. +% STEP 3: Run the Kalman smoother to get a sequence of smoothed states +% (S_0/T,...,S_T/T). In this step, we also get a sequence of +% smoothed +% shocks, which we plot (these figures are referred to as "shock +% histories"). +% STEP 4: Using S_{T/T}, compute forecasts. With S_{0/T}, compute the +% deterministic trend. Using a subset of the sequence of smoothed ... +% states, we can compute the counterfactuals and shock decompositions. +% +% The state transition equation is: S_t = TTT*S_t-1+RRR*eps_t +% The measurement equation is: Y_t = ZZ*S_t+DD +% +% IMPORTANT INPUTS +% k: worker number index (used to ensure workers receive independently +% randomized seeds) +% +% priotheta (npara x nsim): parameter draws +% TTTsim (nstate^2 x nsim), RRRsim (nstate*nshocks x nsim): state transition +% equation matrices +% zendsim (nstate x nsim): end-of-sample smoothed state vector (from gibb.m) +% +% zerobound: flag specifying zerobound model (incorporates anticipated shocks) +% bdd_int_rate: flag specifying bounded interest rate rule +% nant,antlags: number of anticipated shocks, number of past periods in +% which ZB was in effect. +% nshocks_all: total number of shocks (incl. anticipated shocks) +% +% peachflag: (if 0) no conditional data ("unconditional forecast") +% (if 1) use conditional forecasts and data for all observables +% except labor share ("conditional forecast") +% (if 2) use conditional data for spreads and FFR only +% ("semi-conditional forecast") +% peachdata, semi_peachdata (both are nant x (nvar+nant)): conditional, +% semi-conditional data +% +% nobs: length of observable time series +% stime: index for the current quarter, relative to the observable time series +% +% Startdate: Index for counterfactual start date. Also, index for shock +% decomposition figure start date. +% Enddate_forecastfile: total number of quarters in the observable time +% series and the forecast period: stime + qahead + +% OUTPUTS +% For output variable dimensions, see section "Initialize Output Variables" +% below. +% +% fcast: forecast; there are subfields for unconditional, semi-conditional, +% conditional, and (if zerobound) their bounded forecast counterparts +% varargout (optional outputs): +% shocks: smoothed shock histories +% ytrend: steady state, for shock decomposition plots +% dettrend: deterministic trend, for shock decomposition plots +% shockdec_all: shock contributions to forecast, for shock decomposition plots +% counter_all: counterfactual forecasts +% +% IMPORTANT SUBFUNCTIONS +% augmentFilter.m, augmentSmoother.m: augments relevant matrices for the Kalman +% Filter and Smoother +% kalcvf2NaN.m: runs the Kalman Filter +% kalsmth_k93.m: runs the Kalman Smoother using algorithm in (Koopman 1993) + + +function [fcast,varargout] = forecastFcn_est_ant(k,priotheta,TTTsim,RRRsim,zendsim,... + mspec,zerobound,bdd_int_rate,peachflag,plotImp,nimpVar,... + nvar,qahead,qahead_extra,nshocks_all,YY,nobs,peachdata,psize,... + Enddate_forecastfile,Startdate,stime,ShockremoveList,... + nant,antlags,varnames,names_shocks,... + nstate_0,nshocks_0,sflag,YY0,... + valid_para,nlags,npara,coint,cointadd,ExpFFR,nplotstates,varargin) + +% Set new seed (random number sequence) for each worker +rand('state',sum(100*clock+k)) +randn('state',sum(100*clock+k)) + + +% Number of draws distributed. Matrices holding draws have already been indexed +% by jstep in forecast_parallel.m. +nDraws = size(TTTsim,1); + +%% Initialize output variables +fcast.uncond_hist = zeros(nDraws,nvar*stime); +fcast.uncond = zeros(nDraws,nvar*qahead); + +if peachflag + fcast.cond_hist = zeros(nDraws,nvar*stime); + fcast.cond = zeros(nDraws,nvar*qahead); +end + +if zerobound + fcast.uncond_bdd = zeros(nDraws,nvar*qahead); + if peachflag, fcast.cond_bdd = zeros(nDraws,nvar*qahead); end +end + +shocks.data = zeros(nDraws,nshocks_all*size(YY',2)); + +% Non-standardized shocks +shocks.data_ns = zeros(nDraws,nshocks_all*size(YY',2)); +if peachflag + shocks.peach = zeros(nDraws,nshocks_all*(size(peachdata,1))); + shocks.datawpeach = zeros(nDraws,nshocks_all*size(YY,1)); + shocks.peach_ns = zeros(nDraws,nshocks_all*(size(peachdata,1))); + shocks.datawpeach_ns = zeros(nDraws,nshocks_all*size(YY,1)); +end + + +ytrend = zeros(nDraws,nvar); +dettrend = zeros(nDraws,nvar*(Enddate_forecastfile - Startdate + 1),... + peachflag+1); +counter_all = zeros(nDraws,nvar*(Enddate_forecastfile - Startdate),... + peachflag+1,length(ShockremoveList)); +shockdec_all = zeros(nDraws,nvar*(Enddate_forecastfile - Startdate + 1),... + peachflag+1,length(ShockremoveList) - 1); + + +% Load the 2part classes and set up some important information +adj = adj2part(mspec); + +%% Loop through parameter draws +for a = 1:nDraws + + nstate = nstate_0; + nshocks = nshocks_0; + + % state selector + params = priotheta(a,:)'; + [A, C_ss, cum_for, states_names] = mapStates(mspec,nstate,nplotstates,params); + + + %% STEP 1: Reshape inputs to get matrices of the state transition and + %% measurement equations + % State transition: S_t = TTT*S_(t-1) + RRR*eps_t + % Measurement equation: Y_t = ZZ*S_t + DD + + if zerobound && is2part(mspec) + [TTT,RRR,zend] = getmodel(TTTsim,RRRsim,zendsim,a,nstate+nant+adj,nshocks+nant); + else + [TTT,RRR,zend] = getmodel(TTTsim,RRRsim,zendsim,a,nstate,nshocks); + end + + nstate = size(TTT,1); + + if is2part(mspec) + if zerobound + + % Get the starting indices + [start_ant_state, start_ant_shock, revol_ind] = get_start_ant(mspec, nant); + + % Get noZB matrices + [TTT_noZB, RRR_noZB, CCC_noZB] = ... + dsgelh_getNoZB(nant, start_ant_state, start_ant_shock, TTT, RRR, zeros(size(TTT,1),1),revol_ind{:}); + + zend_noZB = zend; + zend_noZB( start_ant_state:(start_ant_state+nant-1) ) = []; % Ditch ant states + if ~isempty(revol_ind) + zend_noZB(revol_ind{:}) = []; % Ditch extra equation + end + + else + TTT_noZB = TTT; + RRR_noZB = RRR; + zend_noZB = zend; + end + + nant_rm = nant; + + else + TTT_noZB = TTT; + RRR_noZB = RRR; + zend_noZB = zend; + nant_rm = 0; + end + + nstate = size(TTT_noZB,1); + [ZZ,DD,DDcointadd,QQ,EE,MM,retcode] = getmeasur(mspec,TTT_noZB,RRR_noZB,valid_para,params,nvar,nlags,npara,coint,cointadd); + + + %% STEP 2 (Unconditional data): Kalman Filter + + % If we are only doing an unconditional forecast we can just skip + % to the end since all we need is zend, which we already loaded in. + + + HH = EE+MM*QQ*MM'; + VV = QQ*MM'; + VVall = [[RRR_noZB*QQ*RRR_noZB',RRR_noZB*VV];[VV'*RRR_noZB',HH]]; + lead = 1; + + % Define the initial mean and variance for the state vector + % (deals with nonstationarity on model by model basis) + [A0,P0] = lyap_nonstationary(mspec,params,TTT_noZB,RRR_noZB,QQ); + + % Kalman filtering over the presample + if ~isempty(YY0) + [pyt0,zend,pend,pred0,vpred0] = kalcvf2NaN(YY0(:,1:nvar-nant_rm)',1,zeros(nstate,1),TTT_noZB,DD,ZZ,VVall,A0,P0); + else + zend = A0; + pend = P0; + pred0 = []; + vpred0 = []; + end + + % Kalman filtering over the main sample. + if zerobound == 1 + + % First, filter using normal model up to period T-antlags-1. + [L,zend,pend,pred,vpred] = kalcvf2NaN(YY(1:end-antlags-1,1:nvar-nant_rm)',lead,zeros(nstate,1),TTT_noZB,DD,ZZ,VVall,zend,pend); + + + % Now change models to incorporate anticipated shocks. + valid_a = valid_para; + [TTT,RRR,CCC,valid_a] = dsgesolv(mspec,params,nant); + + [ZZ,DD,DDcointadd,QQ,EE,MM,retcode] = getmeasur(mspec,TTT,RRR,valid_a,params,nvar,nlags,npara,coint,cointadd,nant); + + % Might need to check that this carries through to + % augmentStates, where there's an if statement + r_tl1 = getState(mspec,nant,'rm_tl1'); + r_tlx = r_tl1+1; + + nstate = length(TTT); + nshocks = size(RRR,2); + + % state selector + [A, C_ss] = mapStates(mspec,nstate,nplotstates,params); + + ind_r = find(strcmp(varnames,'Interest Rate')); + [zprev,pprev,MM_ant,EE_ant,ZZ_e,DD_e,YY_ant] = ... + augmentFilter(r_tl1,r_tlx,nant,antlags,ind_r,zend,pend,... + MM(1:end-nant_rm,:),... + EE(1:end-nant_rm,1:end-nant_rm),... + ZZ(1:end-nant_rm,:),DD(1:end-nant_rm),... + YY(:,1:end-nant_rm),TTT,ExpFFR); + + HH_ant = EE_ant+MM_ant*QQ*MM_ant'; + VV_ant = QQ*MM_ant'; + VVall_ant = [[RRR*QQ*RRR',RRR*VV_ant];[VV_ant'*RRR',HH_ant]]; + + + % Next, filter using ZB model for periods T-antlags:T + % These new filtered states include anticipated shocks and + % are consistent with the zero bound. + [L_ant,zend,pend,pred_ant,vpred_ant] = ... + kalcvf2NaN(YY_ant',lead,zeros(nstate,1),TTT,DD_e,ZZ_e,... + VVall_ant,zprev,pprev); + + else + % Filter over the main sample. + [L,zend,pend,pred,vpred] = ... + kalcvf2NaN(YY',lead,zeros(nstate,1),TTT,DD,ZZ,VVall,zend,pend); + + end %End of if zerobound conditional. + + zend_uncond = zend; + + + %% STEP 3 (Unconditional data): Kalman Smoother + + if zerobound ==1 + [pred_all,vpred_all,YY_all,A0_,P0_] = ... + augmentSmoother(nstate,r_tlx,r_tl1,nant,antlags,pred0,pred,... + pred_ant,vpred0,vpred,vpred_ant,YY0,YY,YY_ant,A0,P0); + else + pred_all = [pred0,pred]; + + vpred_all = zeros(nstate,nstate,size(YY0,1)+size(YY,1)); + if ~isempty(YY0) + vpred_all(:,:,1:size(YY0,1)) = vpred0; + end + vpred_all(:,:,size(YY0,1)+1:end) = vpred; + + YY_all = [YY0;YY]; + + A0_ = A0; + P0_ = P0; + + ZZ_e = ZZ; + DD_e = DD; + end + + % This section does the smoothing. For the zero bound, + % this can be done in one step, since there is code in + % both the Kalman Smoother and Simulation Smoother that + % set the QQ matrix to zero in all periods before the + % model switch, which ensures that the smoothed shocks + % include no anticipated shocks prior to that time. + [sm_states_all,sm_shocks_all] = ... + kalsmth_k93(A0_,P0_,YY_all',pred_all,vpred_all,TTT,RRR,... + QQ,ZZ_e,DD_e,nant,antlags,0,psize); + + % Since we smoothed back farther than we needed to + % (even before the presample), we only need parts of + % sm_states_all and sm_shocks_all. + + z0T = zeros(nstate,peachflag+1); + if size(YY0,1) ~= 0 + z0T(:,1) = sm_states_all(:,size(YY0,1)); + else + z0T(:,1) = A0_; + end + + % z0T is the smoothed time 0 state vector. If peachflag + % is on it will have two columns to hold one vector + % smoothed without peachdata, and one smoothed with + % peachdata. + + sm_states = sm_states_all(:,size(YY0,1)+1:end); + sm_shocks = sm_shocks_all(:,size(YY0,1)+1:end); + + % Calculate shock histories + QQinv = zeros(nshocks); + QQinv(QQ > 0) = QQ(QQ > 0).^(-1/2); + sm_sdz_shocks = QQinv*sm_shocks; + + shocks.data_ns(a,:) = sm_shocks(:)'; + shocks.data(a,:) = sm_sdz_shocks(:)'; + + %% STEP 2 (Conditional Data): Kalman filter + % Since the new smoothers and filter can automatically deal + % with NaNs in the data matrix, the code can be much + % simplified. + + VVall = zeros(nstate+length(peachdata)); + VVall(1:nstate,1:nstate) = RRR*QQ*RRR'; + + [L,zend_peach,pend_peach,pred_peach,vpred_peach] = ... + kalcvf2NaN(peachdata',lead,zeros(nstate,1),TTT,DD_e,ZZ_e,VVall,... + zend,pend); + + %% STEP 3 (Conditional Data): Kalman smoother + + YY_all_peach = [YY_all;peachdata]; + + pred_all_peach = [pred_all,pred_peach]; + + vpred_all_peach = zeros(length(TTT),length(TTT),... + size(YY_all_peach,1)); + vpred_all_peach(:,:,1:size(YY_all,1)) = vpred_all; + vpred_all_peach(:,:,size(YY_all,1)+1:end) = vpred_peach; + + + [sm_states_all_peach,sm_shocks_all_peach] = ... + kalsmth_k93(A0_,P0_,YY_all_peach',pred_all_peach,... + vpred_all_peach,TTT,RRR,QQ,ZZ_e,DD_e,nant,... + antlags,1,psize); + + if size(YY0,1) ~= 0 + z0T(:,2) = sm_states_all_peach(:,size(YY0,1)); + else + z0T(:,2) = A0_; + end + + sm_states_peach = sm_states_all_peach(:,size(YY0,1)+1:end); + sm_shocks_peach = sm_shocks_all_peach(:,size(YY0,1)+1:end); + + peachdataimplied = ... + getpeachdataimplied(size(peachdata,1),ZZ,DD,... + sm_states_peach(:,end-size(peachdata,1)+1:end)); + + % Calculate conditional shocks histories + sm_sdz_shocks_peach = QQinv*sm_shocks_peach; + + shocks.datawpeach_ns(a,:) = ... + reshape(sm_shocks_peach(:,1:size(YY,1)),1,nshocks*size(YY,1)); + shocks.peach_ns(a,:) = ... + reshape(sm_shocks_peach(:,size(YY,1)+1:end),1,nshocks*psize); + + shocks.datawpeach(a,:) = ... + reshape(sm_sdz_shocks_peach(:,1:size(YY,1)),1,nshocks*size(YY,1)); + shocks.peach(a,:) = ... + reshape(sm_sdz_shocks_peach(:,size(YY,1)+1:end),1,nshocks*psize); + + %% STEP 4: Compute forecasts + + ind_r = find(strcmp(varnames,'Interest Rate')); + ind_r_sh = find(strcmp(names_shocks,'r_m')); + + % Conditional forecast + if peachflag + + if zerobound + + % Calculate forecast with bounded interest rate off + [yypred,yypred_s] = getForecast_s(qahead_extra,nvar,nshocks,zeros(size(TTT,1),1),TTT,RRR,DD,ZZ,QQ,zend_peach,... + ind_r,ind_r_sh,zerobound,0,nant,sflag,A,C_ss,nplotstates,mspec); + + yypred_nocoint = [peachdataimplied; ... + yypred(:,1:nvar)]; + fcast.cond(a,:) = yypred_nocoint(:)'; + + % Calculate forecast with bounded interest rate on + [yypred,yypred_s] = getForecast_s(qahead_extra,nvar,nshocks,zeros(size(TTT,1),1),TTT,RRR,DD,ZZ,QQ,zend_peach,... + ind_r,ind_r_sh,zerobound,1,nant,sflag,A,C_ss,nplotstates,mspec); + yypred_nocoint = [peachdataimplied; ... + yypred(:,1:nvar)]; + fcast.cond_bdd(a,:) = yypred_nocoint(:)'; + + else + + [yypred] = ... + getForecast_s(qahead_extra,nvar,nshocks,zeros(size(TTT,1),1),... + TTT,RRR,DD,ZZ,QQ,zend_peach,ind_r,ind_r_sh,... + zerobound,bdd_int_rate,nant,sflag,A,... + nplotstates,mspec); + + yypred_nocoint = [peachdataimplied; ... + yypred(:,1:nvar)]; + fcast.cond(a,:) = yypred_nocoint(:)'; + + + end %End of if zerobound conditional. + + end %End of if peachflag conditional. + + % Unconditional forecast + if zerobound + + [yypred,yypred_s] = getForecast_s(qahead,nvar,nshocks,zeros(size(TTT,1),1),TTT,RRR,DD,ZZ,QQ,zend_uncond,... + ind_r,ind_r_sh,zerobound,0,nant,sflag,A,C_ss,nplotstates,mspec); + fcast.uncond(a,:) = yypred(:)'; + + % Calculate bounded interest rate forecast + [yypred,yypred_s] = getForecast_s(qahead,nvar,nshocks,zeros(size(TTT,1),1),TTT,RRR,DD,ZZ,QQ,zend_uncond,... + ind_r,ind_r_sh,zerobound,1,nant,sflag,A,C_ss,nplotstates,mspec); + fcast.uncond_bdd(a,:) = yypred(:)'; + + else + [yypred] = ... + getForecast_s(qahead,nvar,nshocks,zeros(size(TTT,1),1),TTT,RRR,... + DD,ZZ,QQ,zend_uncond,ind_r,ind_r_sh,zerobound,... + bdd_int_rate,nant,sflag,A,nplotstates,mspec); + + fcast.uncond(a,:) = yypred(:)'; + + + end %End of if zerobound conditional. + + % Compute Counterfactuals, shock decompositions, deterministic trends, and steady states + + ytrend(a,:) = DD'; + + %deterministic trends + [dettrend(a,:,:)] =... + getdettrend_s(Enddate_forecastfile,nvar,ZZ,TTT,DD,z0T,Startdate,peachflag,A,nplotstates); + %counterfactuals + [counter_all(a,:,:,:)] = ... + getcounter_s(ShockremoveList,peachflag,psize,... + Enddate_forecastfile,sm_states,sm_shocks,... + sm_states_peach,sm_shocks_peach,... + Startdate,nobs,nshocks,qahead,... + nvar,TTT,RRR,DD,ZZ,ind_r,ind_r_sh,bdd_int_rate,A,... + nplotstates,mspec); + %shock decompositions + [shockdec_all(a,:,:,:)] = ... + getshockdec_s(ShockremoveList,peachflag,psize,... + Enddate_forecastfile,sm_shocks,sm_shocks_peach,... + Startdate,nobs,qahead,nvar,TTT,... + RRR,DD,ZZ,ind_r,ind_r_sh,bdd_int_rate,A,nplotstates); + +end + +varargout{1} = shocks; +varargout{2} = ytrend; +varargout{3} = dettrend; +varargout{4} = counter_all; +varargout{5} = shockdec_all; diff --git a/forecast/forecast_parallel_est_ant.m b/forecast/forecast_parallel_est_ant.m new file mode 100644 index 0000000..26766e3 --- /dev/null +++ b/forecast/forecast_parallel_est_ant.m @@ -0,0 +1,314 @@ +% OVERVIEW +% forecast_parallel.m: Computes various forecasts using vcSubmitQueuedJobs.m to +% distribute draws among workers. Each worker +% constructs forecasts using forecastFcn.m. +% +% This program uses draws from gibb.m to create forecasts, +% counterfactuals,shock decompositions, and smoothed +% shock +% estimates, both unconditional and conditional on +% peach Peach's forecast. +% +% IMPORTANT SUBFUNCTIONS +% setInfiles.m, setOutfiles.m: specify infiles and outfiles +% forecastFcn.m: subfunction distributed to each worker, to compute +% forecasts. + +%% Inititalization +tic; +close all; +initializePrograms; + +%% Set warning off for newer versions of MATLAB +try + warning('off', 'MATLAB:warn_r14_stucture_assignment') +end + +%% Specifications + +% Set dimensions of pre-allocated matrices +nstate_0 = nstate; +nshocks_0 = nshocks; + +% Augment the list of shocks to add the anticipated policy shocks +if zerobound == 1 + nshocks_all = nshocks+nant; + ShockremoveList = [ShockremoveList,(nshocks+1:nshocks+nant)]; +else + nshocks_all = nshocks; +end + +%% Read infiles (outputted from gibb_est_ant.m). + +st_adj = adj2part(mspec); + +% List data to be read in +indataType = {'params','TTT','RRR','zend'}; + +% Create structures infile (filenames), numb (# bytes to burn) , and num (# bytes per file) +[infile,numb,num] = setInfiles(indataType,... + spath,nburn,nstate+nant_implied+st_adj,nshocks+nant_implied,npara,nblocks,nsim); +listInfiles = fieldnames(infile); + +for iInfile = 1:length(listInfiles) + infileName = listInfiles{iInfile}; + fid.(infileName) = fopen(infile.(infileName),'r'); + status.(infileName) = fseek(fid.(infileName),numb.(infileName),'bof'); + +end +lambdas=NaN; + +st_adj = adj2part(mspec); + +%% Open outfiles + +% Use spath_overwrite if you want to save output files to a different +% folder than spath. +if exist('spath_overwrite','var'), spath = spath_overwrite; end + +% List data to be written +outdataType = {'hist','forecast','forecast_s'}; +if peachflag, + outdataType = union(outdataType,{'condhist','condforecast','condforecast_s'}); +end +outdataType = union(outdataType,{'states','condforecast','peachshocks','condshocks','datashocks',... + 'condforecast_ns','peachshocks_ns','condshocks_ns','datashocks_ns',... + 'counter','shockdec','ytrend','dettrend','dettrend_peach'}); + +% Create outfile structure (output filenames) +[outfile] = setOutfiles(outdataType,zerobound, spath,peachflag,ShockremoveList); + +% Open outfiles to write +if overwrite + listOutfiles = fieldnames(outfile); + for iOutfile = 1:length(listOutfiles) + outfileName = listOutfiles{iOutfile}; + fid.(outfileName) = fopen(outfile.(outfileName),'w'); + end +end + +%% Load in peachdata and specify qahead_extra +% peachdata (nant x (nvar+nant)): a matrix of conditional data (usually peach Peach's +% nowcast). If we are doing a conditional forecast, +% we append peachdata to the end of our observed data. +% qahead_extra: If we are doing a conditional forecast, we forecast +% qahead_extra (59Q) quarters ahead (psize (1Q) quarters less +% than the unconditional forecast) instead of qahead (60Q). + +% load conditional data +if peachflag > 0, + load(peachfile); + peachdata = data; + + % Population adjust and get into logs + peachdata(1) = peachdata(1)-400*dlMA_pop(1); + + %for models which read in quarterly data, adjust peachdata (Except + %hours) + peachdata([1 3:end]) = peachdata([1 3:end])/4; + + if size(peachdata,2) < nvar + peachdata = [peachdata,NaN(size(peachdata,1),nvar-size(peachdata,2))]; + end + + if zerobound + + [ExpFFR,peachdata_FFR] = ExpFFR_OIS(nant,antlags,psize,zerobound,peachflag); + + ExpFFR = ExpFFR/4; + peachdata_FFR = peachdata_FFR/4; + + if ~is2part(mspec) + peachdata = [peachdata,NaN(size(peachdata,1),nant)]; + end + + for t = 1:size(peachdata,1) + peachdata(t,end-nant+1:end-t) = peachdata_FFR(t,1:nant-t); + end + else + ExpFFR = []; + end + + qahead_extra = qahead - size(peachdata,1); +else + if zerobound + [ExpFFR,peachdata_FFR] = ExpFFR_OIS(nant,antlags,psize,zerobound,peachflag); + if class_mspec(mspec) == 904 %for models which read in quarterly data, adjust FFRs + ExpFFR = ExpFFR/4; + peachdata_FFR = peachdata_FFR/4; + end + else + ExpFFR = []; + end + peachdata = []; + qahead_extra = qahead; +end + +semi_peachdata = []; + + +%% Load in parameter draws, state transition equation matrices, and zend (output from gibb.m) +% priotheta (npara x nsim): parameter draws +% TTTsim (nstate^2 x nsim), RRRsim (nstate*nshocks x nsim), CCCsim (nstate x nsim): matrices of the state transition equation S_t = TTT*S_(t-1) + RRR*eps_t + CCC +% zendsim (nstate x nsim): end-of-sample smoothed state: S_(T/T) + +% priotheta, TTTsim, RRRsim, CCCsim, and zendsim are compressed matrices. +% They are read in by block (with nsim simulations per block) and reshaped. + +priotheta = []; +iblock = 0; +% Read blocks of size nsim +while ( ftell(fid.params) < num.params ) % only if PRIO==0 + + nstate = nstate_0; + nshocks = nshocks_0; + + iblock = iblock+1; + fprintf(1,' block: %2.0f; \n',iblock); + + % only if PRIO==0 + priotheta = fread(fid.params,[npara,nsim],'single')'; + TTTsim = fread(fid.TTT,[(nstate+nant_implied+st_adj)^2,nsim],'single')'; + RRRsim = fread(fid.RRR,[(nstate+nant_implied+st_adj)*(nshocks+nant_implied),nsim],'single')'; + zendsim = fread(fid.zend,[(nstate+nant_implied+st_adj),nsim],'single')'; + + if ~zerobound + priotheta1 = priotheta(1:end-20,:); + + nstate_sim = nstate+nant_implied+1; + nshocks_sim = nshocks+nant_implied; + iSplit = getState(mspec,0,'n_end+n_exo'); + + selectorTTT = ones(nstate_sim, nstate_sim); + selectorTTT(:,iSplit+1:iSplit+(nant_implied+1)) = 0; + selectorTTT(iSplit+1:iSplit+(nant_implied+1),:) = 0; + selectorTTT = selectorTTT(:); + TTTsim = TTTsim(:,logical(selectorTTT)); + + selectorRRR = ones(nstate_sim, nshocks_sim); + selectorRRR(iSplit+1:iSplit+(nant_implied+1),:) = 0; + selectorRRR(:,end-nant_implied+1:end) = 0; + selectorRRR = selectorRRR(:); + RRRsim = RRRsim(:,logical(selectorRRR)); + + selectorzend = ones(nstate_sim,1); + selectorzend(iSplit+1:iSplit+(nant_implied+1)) = 0; + zendsim = zendsim(:,logical(selectorzend)); + end + + priotheta = priotheta(jstep:jstep:nsim,:); + + TTTsim = TTTsim(jstep:jstep:nsim,:); + RRRsim = RRRsim(jstep:jstep:nsim,:); + zendsim = zendsim(jstep:jstep:nsim,:); + + %% Distribute draws to nMaxWorkers, as input for forecastFcn.m + % idx: how many draws to distribute to each worker + % JobOptions: holds input (to function irfsimFcn.m) for each of the nMaxWorkers + % nout: number of output arguments + % pathdep.m: a program that establishes variable PathDependencies + % JobOut: holds output from forecastFcn.m + valid_para=1; + + if distr + nout = 6; + + JobOptions = cell(1,nMaxWorkers); + for k = 1:nMaxWorkers + idx = ceil(nsim/(jstep*nMaxWorkers))*(k-1)+(1:ceil(nsim/(jstep*nMaxWorkers))); + idx = idx(idx<=nsim/jstep); + JobOptions{k} = {k,priotheta(idx,:),TTTsim(idx,:),RRRsim(idx,:),zendsim(idx,:),... + mspec,zerobound,bdd_int_rate,peachflag,0,0,... + nvar,qahead,qahead_extra,nshocks_all,YY,nobs,peachdata,psize,... + Enddate_forecastfile,Startdate,stime,ShockremoveList,... + nant,antlags,varnames,names_shocks,... + nstate_0,nshocks_0,sflag,YY0,... + valid_para,nlags,npara,coint,cointadd,ExpFFR,nplotstates}; + + pathdep; + end + + + JobOut = vcSubmitQueuedJobs(nMaxWorkers,@forecastFcn_est_ant,... + nout,JobOptions,PathDependencies,nMaxWorkers); + + % Concatenate output across workers + temp_fcast = [JobOut{:,1}]; + fcast.uncond = cat(1,temp_fcast(:).uncond); + if zerobound, fcast.uncond_bdd = cat(1,temp_fcast(:).uncond_bdd); end + if peachflag + fcast.cond = cat(1,temp_fcast(:).cond); + if zerobound, fcast.cond_bdd = cat(1,temp_fcast(:).cond_bdd); end + end + + temp_shocks = [JobOut{:,2}]; + shocks.data = cat(1,temp_shocks(:).data); + shocks.data_ns = cat(1,temp_shocks(:).data_ns); + if peachflag + shocks.peach = cat(1,temp_shocks(:).peach); + shocks.datawpeach = cat(1,temp_shocks(:).datawpeach); + shocks.peach_ns = cat(1,temp_shocks(:).peach_ns); + shocks.datawpeach_ns = cat(1,temp_shocks(:).datawpeach_ns); + end + ytrend = cat(1,JobOut{:,3}); + dettrend = cat(1,JobOut{:,4}); + counter_all = cat(1,JobOut{:,5}); + shockdec_all = cat(1,JobOut{:,6}); + + clear JobOut JobOptions; + + else + + % Compute forecasts for each draw sequentially (if debugging, for example) + k=1; + [fcast,shocks,ytrend,dettrend,counter_all,shockdec_all] = ... + forecastFcn_est_ant(k,priotheta,TTTsim,RRRsim,zendsim,... + mspec,zerobound,bdd_int_rate,peachflag,0,0,... + nvar,qahead,qahead_extra,nshocks_all,YY,nobs,peachdata,psize,... + Enddate_forecastfile,Startdate,stime,ShockremoveList,... + nant,antlags,varnames,names_shocks,... + nstate_0,nshocks_0,sflag,YY0,... + valid_para,nlags,npara,coint,cointadd,ExpFFR,nplotstates); + + end + + %% Save forecasts, and other relevant output + if overwrite + fwrite(fid.forecast,fcast.uncond','single'); + if zerobound, fwrite(fid.forecastbdd,fcast.uncond_bdd','single'); end + fwrite(fid.datashocks,shocks.data','single'); + fwrite(fid.datashocks_ns,shocks.data_ns','single'); + for peachcounter = 0:peachflag + shockcount = 0; + for Shockremove = ShockremoveList + shockcount = shockcount + 1; + fwrite(fid.(['counter',num2str(peachcounter),num2str(Shockremove)]),counter_all(:,:,peachcounter+1,shockcount)','single'); + end + end + for peachcounter = 0:peachflag + shockcount = 0; + for Shockremove = ShockremoveList + if Shockremove > 0 + shockcount = shockcount + 1; + fwrite(fid.(['shockdec',num2str(peachcounter),num2str(Shockremove)]),shockdec_all(:,:,peachcounter+1,shockcount)','single'); + end + end + end + + if peachflag + fwrite(fid.peachshocks,shocks.peach','single'); + fwrite(fid.condshocks,shocks.datawpeach','single'); + fwrite(fid.peachshocks_ns,shocks.peach_ns','single'); + fwrite(fid.condshocks_ns,shocks.datawpeach_ns','single'); + fwrite(fid.dettrend_peach,dettrend(:,:,2)','single'); + fwrite(fid.condforecast,fcast.cond','single'); + if zerobound, fwrite(fid.condforecastbdd,fcast.cond_bdd','single'); end + end + fwrite(fid.ytrend,ytrend','single'); + fwrite(fid.dettrend,dettrend(:,:,1)','single'); + end +end + +fclose('all'); + +fprintf('\n Elapsed time is %4.2f minutes',toc/60); diff --git a/forecast/getForecast_s.m b/forecast/getForecast_s.m new file mode 100644 index 0000000..164b076 --- /dev/null +++ b/forecast/getForecast_s.m @@ -0,0 +1,75 @@ +function [yypred,yypred_s] = getForecast_s(qahead,nvar,nshocks,CCC,TTT,RRR,DD,ZZ,QQ,z,... + ind_r,ind_r_sh,zerobound,bdd_int_rate,nant,sflag,A,C_ss,nplotstates,varargin) + +%% Check inputs +switch nargin + case 19 + tflag = 0; + df = []; + case 20 + tflag = 0; + df = []; + mspec = varargin{1}; + case 21 + tflag = varargin{1}; + df = varargin{2}; + case 22 + tflag = varargin{1}; + df = varargin{2}; + mspec = varargin{3}; + otherwise + fprintf('Incorrect number of inputs for getForecast.m'); +end + +if bdd_int_rate && ( isempty(ind_r) || isempty(ind_r_sh) ) + error('accounting for 0.25 interest rate bound: interest rate not in observables or monetary policy shock not in shocks') +end + + +%% Initialize output + +yypred = zeros(qahead,nvar); +yypred_s = zeros(qahead,nplotstates); + +%% Draw shocks for forecasting + +Shocks = repmat(sqrt(diag(QQ)'),qahead,1).*randn(qahead,nshocks); +Shocks(:,ind_r_sh+1:ind_r_sh+nant) = zeros(qahead,nant); + +%% Calculate forecast +% Applying state transition equation and measurement equation +% S_t = TTT*S_(t-1) + RRR*eps_t +% y_t = ZZ*S_t + DD + + +for t = 1:qahead; + z_test = CCC+TTT*z+RRR*Shocks(t,:)'; + yypred(t,:) = (DD+ZZ*z_test)'; + yypred_s(t,:) = (A*z_test+C_ss)'; + + % This changes the monetary policy shock to account for the 0.25 interest rate bound + % For zero bound forecast we need forecasts with bounded interest rate on and off + + if any(mspec==990) + ZeroBound=0.13/4; + ZeroBoundTest=ZeroBound-0.01; + else + error('Must define ZeroBound and ZeroBoundTest values for given mspec.'); + end + + if yypred(t,ind_r) 0 + + else + + end + + shockcount = 0; + + for Shockremove = ShockremoveList + + if Shockremove > 0 + + shockcount = shockcount + 1; + + z = zeros(length(TTT),1); + + shocks = zeros(size(shocks_all)); + shocks(:,Shockremove) = shocks_all(:,Shockremove); + + switch peachcount + case 0 + shocks(Enddate1 - (qahead) + 1:Enddate1,:) = 0; % JC 7/9/2012 + case {1 2} + shocks(Enddate1 - (qahead - psize) + 1:Enddate1,:) = 0; % JC 7/9/2012 + end + + % Use RRR and not RRR1 as the shocks are non standardized + yyshockdec = zeros(Enddate1,nvar); + shockdec_s = zeros(Enddate1,nplotstates); + for t = 1:Enddate1 + + z = TTT*z + RRR*shocks(t,:)'; + yyshockdec(t,:) = (DD + ZZ*z)'; + shockdec_s(t,:) = (A*z)'; + end + + yyshockdec_short = yyshockdec(Startdate:Enddate1,:); + shockdec_s_short = shockdec_s(Startdate:Enddate1,:); + + shockdec_new(:,peachcount+1,shockcount) = yyshockdec_short(:)'; + shockdec_states(:,peachcount+1,shockcount) = shockdec_s_short(:)'; + end + + end + +end \ No newline at end of file diff --git a/forecast/mapStates.m b/forecast/mapStates.m new file mode 100644 index 0000000..339f1e8 --- /dev/null +++ b/forecast/mapStates.m @@ -0,0 +1,553 @@ +function [A, C_ss, cum_for, states_names] = mapStates(mspec,nstate,nplotstate,para) + +% Modified by MDC on 2/18/2014 to have extra output +% "states_names" to facilitate plotting +% Modified by SS on 2/9/2015 to return a constant adjustments for states + +getPara_script; + +A = zeros(nplotstate,nstate); +C_ss=zeros(nplotstate,1); +eval(['states',num2str(mspec)]); +cum_for = 7*ones(1,nplotstate); % Default, no adjustment + +switch mspec + case {401, 402, 403} + A(pi_t ,1) = 1; + A(y_t ,2) = 1; + A(q_t ,3) = 1; + A(i_t ,4) = 1; + A(r_t ,5) = 1; + A(yn_t ,6) = 1; + A(x_t ,7) = 1; + A(p_t ,8) = 1; + A(qnom_t ,9) = 1; + A(a_t ,10) = 1; + A(g_t ,11) = 1; + A(nu_t ,12) = 1; + A(e_t ,13) = 1; + A(rm_t ,14) = 1; + + case {45,803,4501, 805, 825, 826, 827, 829, 830, 835, 8351, 8352, 836, 8361, 8362} + %% Investment + A(1,i_t) = 1; + + %% Consumption + A(2,c_t) = 1; + + %% Output + A(3,y_t) = 1; + + %% Net worth + A(4,:) = NaN; + + %% Leverage + A(5,:) = NaN; + + %% Utilization + A(6,u_t) = 1; + + %% qk_t + A(7,:) = NaN; + + %% Capital + A(8,k_t) = 1; + + case 50 + %% Investment + A(1,i_t) = 1; + + %% Consumption + A(2,c_t) = 1; + + %% Output + A(3,y_t) = 1; + + %% Net worth + A(4,n_t) = 1; + + %% Leverage + A(5,k_t) = 1; + A(5,n_t) = -1; + + %% Utilization + A(6,u_t) = 1; + + %% q_t + A(7,qk_t) = 1; + + %% Capital + A(8,k_t) = 1; + + case {51,510, 555, 556, 557, 5571, 558, 804, 514, 5143 5144, 906, 5131, 5155} + states_names = cell(nplotstate, 1); + + %% Investment + states_names{1} = 'i_t'; + A(1,i_t) = 1; + + %% Consumption + states_names{2} = 'c_t'; + A(2,c_t) = 1; + + %% Output + states_names{3} = 'y_t'; + A(3,y_t) = 1; + + %% Net worth + states_names{4} = 'Net worth'; + A(4,n_t) = 1; + + %% Leverage + states_names{5} = 'Leverage'; + A(5,k_t) = 1; + A(5,n_t) = -1; + + %% Utilization + states_names{6} = 'Utilization'; + A(6,u_t) = 1; + + %% qk_t + states_names{7} = 'qk_t'; + A(7,qk_t) = 1; + + %% Productivity + states_names{8} = 'Productivity'; + %A(8,k_t) = 1; + A(8,z_t) = 1; + + %% installed capital stock or level process + if nplotstate == 9 + if any(mspec == [557 5571 558]) + states_names{9} = 'Z-Lev'; + A(9, zlev_t) = 1; + else + A(9,kbar_t) = 1; + end + end + %% plus rk(t) + if nplotstate == 10 + A(9,kbar_t) = 1; + A(10,E_Rktil+10) = 1; + end + + if nplotstate == 12 + states_names{9} = 'R_t'; + A(9,R_t) = 1; + + states_names{10} = 'pi_t'; + A(10,pi_t) = 1; + + states_names{11} = 'zlev_t'; + A(11, zlev_t) = 1; + + states_names{12} = 'kbar_t'; + A(12,kbar_t) = 1; + end + + if mspec == 5571 + A(10, y_t_n) = 1; + A(11, r_t_n) = 1; + A(12, zlev_t) = 1; + end + + case {828, 8286, 8287} + %% Output Gap + A(1,y_f_t)=-1; + A(1,y_t)=1; + case {8281, 8282, 8283, 8284, 8285} + %% Don't do anything + + case {904, 955, 924, 956, 909, 9043, 9044, 9045, 9046, 90451, 90452, 907, 910} + + %% Investment + states_names{1} = 'Investment'; + A(1,i_t) = 1; + %A(1,gamm_t) = 1; + + %% Consumption + states_names{2} = 'Consumption'; + A(2,c_t) = 1; + + %% Output + states_names{3} = 'yhat'; + A(3,y_t) = 1; + + %% Net worth + states_names{4} = 'Net Worth'; + A(4,n_t) = 1; + + %% Leverage + states_names{5} = 'Leverage'; + A(5,k_t) = 1; + A(5,n_t) = -1; + + states_names{6} = 'Output Gap'; + A(6,y_t) = 1; + A(6,y_f_t) = -1; + + %% mc_t + states_names{7} = 'Marginal Cost'; + A(7,mc_t) = 1; + + %% Productivity + states_names{8} = 'Productivity'; + %A(8,k_t) = 1; + A(8,z_t) = 1; + + %% Natural r_f_t + states_names{9} = 'Natural Rate'; + A(9,r_f_t) = 1; + + %% Flexible output + states_names{10} = 'Flexible Output'; + A(10,y_f_t) = 1; + + %% installed capital stock or level process + if nplotstate == 9 + states_names{9} = 'Capital Stock'; + A(9,mc_t) = 1; + end + + + % taylor rule variables + if nplotstate == 11 + states_names{10} = 'y_f_t'; + A(11,y_f_t) = 1; + A(13, pitil_t) = 1; + A(14, Y_t) = 1; + A(15, Ybar_t) = 1; + A(16, pitil_t) = 1; + end + + % %% natural rates: output and ffr + % if nplotstate == 13 + % states_names{10} = 'Natural Output'; + % states_names{11} = 'Natural Rate'; + % states_names{12} = 'Nstate'; + % states_names{13} = 'Natural FFR'; + % A(10,y_f_t) = 1; + % A(11,r_f_t) = 1; + % A(12,nstate) = 1; + % A(13,i_f_t) = 1; + % end + + case {908, 918} + + states_names{1} = 'Wages'; + A(1,w_t) = 1; + %A(1,WPH_t) = 1; + + %% Consumption + states_names{2} = 'Productivity'; + A(2,z_t) = 1; + + %% Output + states_names{3} = 'Output'; + A(3,y_t) = 1; + + %% Net worth + states_names{4} = 'Net Worth'; + A(4,n_t) = 1; + + %% Leverage + states_names{5} = 'Leverage'; + A(5,k_t) = 1; + A(5,n_t) = -1; + + states_names{6} = 'Output Gap'; + A(6,y_t) = 1; + A(6,y_f_t) = -1; + + %% qk_t + states_names{7} = 'Marginal Cost'; + A(7,mc_t) = 1; + + %% Productivity + states_names{8} = 'Productivity'; + %A(8,k_t) = 1; + A(8,z_t) = 1; + + %% plus rk(t) + states_names{9} = 'y_f_t'; + states_names{10} = 'rk(t)'; + A(9,y_f_t) = 1; + A(10,E_Rktil+10) = 1; + + %% installed capital stock or level process + if nplotstate == 9 + states_names{9} = 'Capital Stock'; + A(9,mc_t) = 1; + end + + + % taylor rule variables + if nplotstate == 11 + states_names{10} = 'y_f_t'; + A(11,y_f_t) = 1; + A(13, pitil_t) = 1; + A(14, Y_t) = 1; + A(15, Ybar_t) = 1; + A(16, pitil_t) = 1; + end + + % %% natural rates: output and ffr + % if nplotstate == 13 + % states_names{10} = 'Natural Output'; + % states_names{11} = 'Natural Rate'; + % states_names{12} = 'Nstate'; + % states_names{13} = 'Natural FFR'; + % A(10,y_f_t) = 1; + % A(11,r_f_t) = 1; + % A(12,nstate) = 1; + % A(13,i_f_t) = 1; + % end + + + case {920, 921, 925, 926} + + states_names{1} = 'Output'; + A(1,y_t) = 1; + + states_names{2} = 'Flex Output'; + A(2,y_f_t) = 1; + + states_names{3} = 'Interest Rate'; + A(3,R_t) = 1; + + states_names{4} = 'Natural Rate'; + A(4,r_f_t) = 1; + + states_names{5} = 'Inflation'; + A(5,pi_t) = 1; + + states_names{6} = 'Annual Inflation'; + A(6,pi_a_t) = 1; + + states_names{7} = 'Output Gap'; + A(7,y_t) = 1; + A(7,y_f_t) = -1; + + states_names{8} = 'Expected Inflation'; + A(8,E_pi) = 1; + + states_names{9} = 'Ex Ante Real Rate '; + A(9,R_t) = 1; + A(9,E_pi) = -1; + + states_names{10} = 'Long Run Inflation'; + A(10,pist_t) = 1; + + states_names{11} = 'Inflation (t-1)'; + A(11,pi_t1) = 1; + + states_names{12} = 'Inflation (t-2)'; + A(12,pi_t2) = 1; + + states_names{13} = 'Interest Rate (t-1)'; + A(13,R_t1) = 1; + + states_names{14} = 'Monetary Policy Shock'; + A(14,rm_t) = 1; + + + case {975, 976, 977, 876, 871, 872, 874, 978, 979} + + states_names{1} = 'y_t'; + A(1,y_t) = 1; + + states_names{2} = 'y_f_t'; + A(2,y_f_t) = 1; + + states_names{3} = 'Interest Rate'; + A(3,R_t) = 1; + + states_names{4} = 'Natural Rate'; + A(4,r_f_t) = 1; + + states_names{5} = 'Inflation'; + A(5,pi_t) = 1; + + states_names{6} = 'Annual Inflation'; + A(6,pi_a_t) = 1; + + states_names{7} = 'Output Gap'; + A(7,y_t) = 1; + A(7,y_f_t) = -1; + + states_names{8} = 'Expected Inflation'; + A(8,E_pi) = 1; + + states_names{9} = 'Ex Ante Real Rate '; + A(9,R_t) = 1; + A(9,E_pi) = -1; + + states_names{10} = 'Long Run Inflation'; + A(10,pist_t) = 1; + + states_names{11} = 'Inflation (t-1)'; + A(11,pi_t1) = 1; + + states_names{12} = 'Inflation (t-2)'; + A(12,pi_t2) = 1; + + states_names{13} = 'Interest Rate (t-1)'; + A(13,R_t1) = 1; + + states_names{14} = 'Monetary Policy Shock'; + A(14,rm_t) = 1; + + states_names{15} = 'ztil_t'; + A(15,ztil_t) = 1; + + states_names{16} = 'z_t'; + A(16,z_t) = 1; + + states_names{17} = 'Consumption'; + A(17,c_t) = 1; + + states_names{18} = 'Investment'; + A(18,i_t) = 1; + + case {989, 985, 986, 988, 990, 991, 992} + + states_names{1} = 'y_t'; + A(1,y_t) = 1; + + states_names{2} = 'y_f_t'; + A(2,y_f_t) = 1; + + states_names{3} = 'Interest Rate'; + A(3,R_t) = 1; + C_ss(3)=Rstarn; + cum_for(3)=5; + + states_names{4} = 'Natural Rate'; + A(4,r_f_t) = 1; + C_ss(4)=100*(rstar-1); + cum_for(4)=5; + + states_names{5} = 'Output Growth with Gamma'; + y_t1 = n_end+n_exo+n_exp+1; + A(5,y_t) = 1; + A(5,y_t1) = -1; + A(5,z_t) = 1; + C_ss(5) = 100*(exp(zstar)-1); + + states_names{6} = 'pi_t'; + A(6,pi_t) = 1; + C_ss(6) = 100*(pistar-1); + cum_for(6) = 5; + + states_names{7} = 'Output Gap'; + A(7,y_t) = 1; + A(7,y_f_t) = -1; + + states_names{8} = 'Expected Inflation'; + A(8,E_pi) = 1; + C_ss(8)=100*(pistar-1); + cum_for(8)=5; + + states_names{9} = 'Ex Ante Real Rate '; + A(9,R_t) = 1; + A(9,E_pi) = -1; + C_ss(9)=Rstarn-100*(pistar-1); + cum_for(9)=5; + + states_names{10} = 'Long Run Inflation'; + A(10,pist_t) = 1; + C_ss(10)=100*(pistar-1); + cum_for(10)=5; + + states_names{11} = 'Marginal Cost'; + A(11,mc_t) = 1; + + states_names{12} = 'Wages'; + A(12,w_t) = 1; + + states_names{13} = 'Flexible Wages'; + A(13,w_f_t) = 1; + + states_names{14} = 'Hours'; + A(14,L_t) = 1; + + states_names{15} = 'Flexible Hours'; + A(15,L_f_t) = 1; + + states_names{16} = 'z_t'; + A(16,z_t) = 1; + + states_names{17} = 'Z_t'; + A(17,z_t) = 1; + C_ss(17) = 100*(exp(zstar)-1); + + states_names{18} = 'ztil_t'; + A(18,ztil_t) = 1; + + case {980, 981, 982, 984, 987} + + states_names{1} = 'y_t'; + A(1,y_t) = 1; + + states_names{2} = 'y_f_t'; + A(2,y_f_t) = 1; + + states_names{3} = 'Interest Rate'; + A(3,R_t) = 1; + + states_names{4} = 'Natural Rate'; + A(4,r_f_t) = 1; + + states_names{5} = 'Inflation'; + A(5,pi_t) = 1; + + states_names{6} = 'Annual Inflation'; + A(6,pi_a_t) = 1; + + states_names{7} = 'Output Gap'; + A(7,y_t) = 1; + A(7,y_f_t) = -1; + + states_names{8} = 'Expected Inflation'; + A(8,E_pi) = 1; + + states_names{9} = 'Ex Ante Real Rate '; + A(9,R_t) = 1; + A(9,E_pi) = -1; + + states_names{10} = 'Long Run Inflation'; + A(10,pist_t) = 1; + + states_names{11} = 'Inflation (t-1)'; + A(11,pi_t1) = 1; + + states_names{12} = 'Inflation (t-2)'; + A(12,pi_t2) = 1; + + states_names{13} = 'Interest Rate (t-1)'; + A(13,R_t1) = 1; + + states_names{14} = 'Monetary Policy Shock'; + A(14,rm_t) = 1; + + states_names{15} = 'ztil_t'; + A(15,ztil_t) = 1; + + states_names{16} = 'z_t'; + A(16,z_t) = 1; + + states_names{17} = 'zlev_t'; + A(17,zlev_t) = 1; + + states_names{18} = 'zp_t'; + A(18,zp_t) = 1; + + + otherwise, + error('"A" matrix not specified for this mspec') +end + + +if ~exist('states_names') + states_names = cell(arrayfun(@(x) ['state' num2str(x)], [1:nplotstate], 'UniformOutput',0)'); +end diff --git a/forecast/pathdep.m b/forecast/pathdep.m new file mode 100644 index 0000000..24476ce --- /dev/null +++ b/forecast/pathdep.m @@ -0,0 +1,13 @@ +TIN=pwd; + +PathDependencies = { + strcat(TIN,'/initialization'); + strcat(TIN,'/forecast'); + strcat(TIN,'/estimation'); + strcat(TIN,'/dsgesolv'); + strcat(TIN,'/data'); + strcat(TIN,'/toolbox'); + strcat(TIN,'/kalman'); + }; + + diff --git a/forecast/setInfiles.m b/forecast/setInfiles.m new file mode 100644 index 0000000..a94115e --- /dev/null +++ b/forecast/setInfiles.m @@ -0,0 +1,22 @@ +function [infile,numb,num] = setInfiles(indataType,... + spath,nburn,nstate,nshocks,npara,nblocks,nsim) +for iDT = 1:length(indataType) + switch indataType{iDT} + case 'params' + infile.params = [spath,'/params']; + numb.params = nburn*npara*4; + num.params = nblocks*nsim*npara*4; + case 'TTT' + infile.TTT = [spath,'/TTT']; + numb.TTT = nburn*nstate^2*4; + num.TTT = nblocks*nsim*nstate^2*4; + case 'RRR' + infile.RRR = [spath,'/RRR']; + numb.RRR = nburn*nstate*nshocks*4; + num.RRR = nblocks*nsim*nstate*nshocks*4; + case 'zend' + infile.zend = [spath,'/zend']; + numb.zend = nburn*nstate*4; + num.zend = nblocks*nsim*nstate*4; + end +end diff --git a/forecast/setOutfiles.m b/forecast/setOutfiles.m new file mode 100644 index 0000000..b033b83 --- /dev/null +++ b/forecast/setOutfiles.m @@ -0,0 +1,127 @@ +% OVERVIEW +% setOutfiles.m creates variable outfile, where each field name is a type of +% data that we want to write (ie forecast or shockdec). +% Each field of outfile is the name of the output file. +% +% IMPORTANT VARIABLES +% outfile: a structure where each field name is a type of +% data that we want to write. Each field of outfile is the +% name of the output file. Example: outfile.forecast = +% '/data/data_dsge_dir/.../forecastm...." +% outdataType: a cell array listing the type of data you want to create +% outfiles for. Example: {forecast,datashocks}. + +function [outfile] = setOutfiles(outdataType,zerobound, spath,peachflag,ShockremoveList) + +for iDT = 1:length(outdataType) + switch outdataType{iDT} + case 'forecast' + if zerobound + outfile.forecast = [spath,'/forecast']; + outfile.forecastbdd = [spath,'/forecastbdd']; + else + outfile.forecast = [spath,'/forecast_nozb']; + end + case 'condforecast' + if zerobound + outfile.condforecast = [spath,'/condforecast']; + outfile.condforecastbdd = [spath,'/condforecastbdd']; + else + outfile.condforecast = [spath,'/condforecast_nozb']; + end + case 'states' + outfile.states = [spath,'/states']; + case 'peachshocks' + outfile.peachshocks = [spath,'/peachshocks']; + case 'semipeachshocks' + outfile.semipeachshocks = [spath,'/semipeachshocks']; + case 'condshocks' + outfile.condshocks = [spath,'/condshocks']; + case 'semicondshocks' + outfile.semicondshocks = [spath,'/semicondshocks']; + case 'datashocks' + outfile.datashocks = [spath,'/datashocks']; + case 'peachshocks_ns' + outfile.peachshocks_ns = [spath,'/peachshocks_ns']; + case 'semipeachshocks_ns' + outfile.semipeachshocks_ns = [spath,'/semipeachshocks_ns']; + case 'condshocks_ns' + outfile.condshocks_ns = [spath,'/condshocks_ns']; + case 'semicondshocks_ns' + outfile.semicondshocks_ns = [spath,'/semicondshocks_ns']; + case 'datashocks_ns' + outfile.datashocks_ns = [spath,'/datashocks_ns']; + case 'counter' + for peachcounter = 0:peachflag + for Shockremove = ShockremoveList + switch peachcounter + case 1, outfile.(['counter',num2str(peachcounter),num2str(Shockremove)]) = [spath,'/counter_peach', num2str(Shockremove)]; + case 0, outfile.(['counter',num2str(peachcounter),num2str(Shockremove)]) = [spath,'/counter', num2str(Shockremove)]; + end + end + end + case 'shockdec' + for peachcounter = 0:peachflag + for Shockremove = ShockremoveList + switch peachcounter + case 1, if Shockremove > 0, outfile.(['shockdec',num2str(peachcounter),num2str(Shockremove)]) = [spath,'/shockdec_peach', num2str(Shockremove)]; end + case 0, if Shockremove > 0, outfile.(['shockdec',num2str(peachcounter),num2str(Shockremove)]) = [spath,'/shockdec', num2str(Shockremove)]; end + end + end + end + case 'ytrend' + outfile.ytrend = [spath,'/ytrend']; + case 'dettrend' + outfile.dettrend = [spath,'/dettrend']; + case 'dettrend_peach' + outfile.dettrend_peach = [spath,'/dettrend_peach']; + case 'hist' + outfile.hist = [spath,'/hist']; + case 'condhist' + outfile.condhist = [spath,'/condhist']; + case 'forecastPRIO' + outfile.forecast = [spath,'/forecastPRIO']; + + case 'forecast_s' + if zerobound + outfile.forecast_s = [spath,'/forecast_s']; + outfile.forecastbdd_s = [spath,'/forecastbdd_s']; + else + outfile.forecast_s = [spath,'/forecast_s']; + end + case 'condforecast_s' + if zerobound + outfile.condforecast_s = [spath,'/condforecast_s']; + outfile.condforecastbdd_s = [spath,'/condforecastbdd_s']; + else + outfile.condforecast_s = [spath,'/condforecast_s']; + end + + case 'dettrend_s' + outfile.dettrend_s = [spath,'/dettrend_s']; + case 'dettrend_peach_s' + outfile.dettrend_peach_s = [spath,'/dettrend_peach_s']; + case 'shockdec_s' + for peachcounter = 0:peachflag + for Shockremove = ShockremoveList + switch peachcounter + case 1, if Shockremove > 0, outfile.(['shockdec_s',num2str(peachcounter),num2str(Shockremove)]) = [spath,'/shockdec_peach_s', num2str(Shockremove)]; end + case 0, if Shockremove > 0, outfile.(['shockdec_s',num2str(peachcounter),num2str(Shockremove)]) = [spath,'/shockdec_s', num2str(Shockremove)]; end + end + end + end + case 'counter_s' + for peachcounter = 0:peachflag + for Shockremove = ShockremoveList + switch peachcounter + case 1, outfile.(['counter_s',num2str(peachcounter),num2str(Shockremove)]) = [spath,'/counter_peach_s', num2str(Shockremove)]; + case 0, outfile.(['counter_s',num2str(peachcounter),num2str(Shockremove)]) = [spath,'/counter_s', num2str(Shockremove)]; + end + end + end + case 'hist_s' + outfile.hist_s = [spath,'/hist_s']; + case 'hist_peach_s' + outfile.hist_peach_s = [spath,'/hist_peach_s']; + end +end diff --git a/forecast/vcSubmitQueuedJobs.m b/forecast/vcSubmitQueuedJobs.m new file mode 100644 index 0000000..d94e673 --- /dev/null +++ b/forecast/vcSubmitQueuedJobs.m @@ -0,0 +1,243 @@ +function JobOut = vcSubmitQueuedJobs(nJobs,JobFcnHandle,nJobArgOut,JobOptions,... + ListPathDependencies,nMaxWorkers,varargin) + +% vcSubmitQueuedJobs +% +% Submit parallel jobs that might exceed the maximum number of workers +% available. +% +% Usage: +% vcSubmitQueuedJobs(nJobs,JobFcnHandle,nJobArgOut,JobOptions,ListPathDependencies) +% vcSubmitQueuedJobs(...,OptionName,OptionValue,...) +% +% Mandatory Inputs: +% +% nJobs +% Number of Jobs to run +% +% JobFcnHandle +% Handle to the function called by each worker. +% +% nJobArgOut +% Number of output arguments in each job. +% +% JobOptions +% Cell array with options required by the function called by the worker. +% It needs to contain one element per job, unless no inputs are +% necessary, in which case, {} needs to be used. +% +% ListPathDependencies +% Cell array with the list of path dependencies needed in function called +% by workers. +% +% nMaxWorkers +% Maximum number of simultaneous workers. +% +% Optional inputs: +% +% nMaxTasks +% Maximum number of tasks per job. Default: 1. +% +% ShowOutput +% If set to 1 all output of each worker is shown. +% Default: 1 if LogFileName is empty, 0 otherwise. +% Note: even though the default is set depending on LogFileName, this +% option can be set independendently of LogFileName. +% +% LogFileName +% If specified, then all output is saved in a ascii file. +% +% OutputPreamble +% If specified this should be a string to introduce in a fprintf command +% before showing the output of each worker. It must receive as input the +% worker number. +% +% SaveTmpFileName +% If specified, it will save the environment in a mat file with the name +% provided. This file is deleted upon completion and data gathering from +% all jobs. +% +% SaveTmpVarAll +% If set to 1 it will save the whole environment, otherwise it will save +% only selected information. +% Default: 0; +% NOTE: Only relevant if SaveTmpFileName is specified as well. +% +% SaveTmpDelete +% If set to one the temporary file is deleted on conclusion. If set to +% zero the temporary file is left in the folder. +% Default: 1 +% +% ......................................................................... +% +% Created: February 11, 2009 +% Updated: August 24, 2010 +% by Vasco Curdia + +%% ------------------------------------------------------------------------ + +%% default options +nMaxTasks = 1; +SaveTmpDelete = 1; +SaveTmpVarAll = 0; +LogFileName = ''; +PauseTime = 10; + +%% Update options +if ~isempty(varargin) + nOptions = length(varargin); + if mod(nOptions,2), error('Incorrect number of optional arguments.'), end + for jO=1:nOptions/2 + eval(sprintf('%s = varargin{%.0f};',varargin{(jO-1)*2+1},jO*2)) + end +end + +%% Checks +if isempty(JobOptions),for j=1:nJobs,JobOptions{j} = {};end,end +if ~exist('ShowOutput','var'),ShowOutput = isempty(LogFileName);end +if ~exist('SaveTmpVarList','var') + SaveTmpVarList = {'nJobs','JobFcnHandle','nJobArgOut','JobOptions',... + 'ListPathDependencies','nMaxWorkers','varargin','nCompleted',... + 'nSubmitted','j','jJob','jobsRunning','JobOut','JobTasks','JobIdx'}; +end + +%% Submit jobs +nCompleted = 0; +nSubmitted = 0; +j = 0; +jJob = 0; +jobsRunning = false(nJobs,1); +JobOut = cell(nJobs,nJobArgOut); +JobTasks=[]; +JobIdx=[]; +%JobToc = toc; +if exist('SaveTmpFileName','var') + if SaveTmpVarAll + save(SaveTmpFileName) + else + save(SaveTmpFileName,SaveTmpVarList{:}) + end +end +while nCompleted 0 + + % This section adds the anticipated shocks. There is one state for all the + % anticipated shocks that will hit in a given period (i.e. rm_tl2 holds + % those that will hit in two periods), and the equations are set up so that + % rm_tl2 last period will feed into rm_tl1 this period (and so on for other + % numbers), and last period's rm_tl1 will feed into the rm_t process (and + % affect the Taylor Rule this period). + + %note: belongs to eq_rm equation above^^ + G1(eq_rm,rm_tl1) = 1; + %___________________________________ + + G0(eq_rml1,rm_tl1) = 1; + PSI(eq_rml1,rm_shl1) = 1; + + if nant > 1 + for i = 2:nant + eval(strcat('G1(eq_rml',num2str(i-1),',rm_tl',num2str(i),') = 1;')); + %___________________________________ + + eval(strcat('G0(eq_rml',num2str(i),',rm_tl',num2str(i),') = 1;')); + eval(strcat('PSI(eq_rml',num2str(i),',rm_shl',num2str(i),') = 1;')); + end + end + end +end + +%****************************************** +%** Rational Expectations Errors +%*******************************************/ +%* E[c) **/ +%* sticky prices and wages **/ +G0(eq_Ec,c_t ) = 1; +G1(eq_Ec,E_c) = 1; + PIE(eq_Ec,Ec_sh ) = 1; + +%* flexible prices and wages **/ +G0(eq_Ec_f,c_f_t ) = 1; +G1(eq_Ec_f,E_c_f) = 1; + PIE(eq_Ec_f,Ec_f_sh ) = 1; + +%* E(q) **/ +%* sticky prices and wages **/ +G0(eq_Eqk,qk_t) = 1; +G1(eq_Eqk,E_qk) = 1; + PIE(eq_Eqk,Eqk_sh ) = 1; + +%* flexible prices and wages **/ +G0(eq_Eqk_f,qk_f_t ) = 1; +G1(eq_Eqk_f,E_qk_f) = 1; + PIE(eq_Eqk_f,Eqk_f_sh) = 1; + +%* E(i) **/ +%* sticky prices and wages **/ +G0(eq_Ei,i_t ) = 1; +G1(eq_Ei,E_i) = 1; + PIE(eq_Ei,Ei_sh ) = 1; + +%* flexible prices and wages **/ +G0(eq_Ei_f,i_f_t ) = 1; +G1(eq_Ei_f,E_i_f) = 1; + PIE(eq_Ei_f,Ei_f_sh ) = 1; + +%* E(pi) **/ +%* sticky prices and wages **/ +G0(eq_Epi,pi_t ) = 1; +G1(eq_Epi,E_pi) = 1; + PIE(eq_Epi,Epi_sh ) = 1; + +%* E(l) **/ +%* sticky prices and wages **/ +G0(eq_EL,L_t ) = 1; +G1(eq_EL,E_L) = 1; + PIE(eq_EL,EL_sh ) = 1; + +%* flexible prices and wages **/ +G0(eq_EL_f,L_f_t ) = 1; +G1(eq_EL_f,E_L_f) = 1; + PIE(eq_EL_f,EL_f_sh ) = 1; + +%* E(rk) **/ +%* sticky prices and wages **/ +G0(eq_Erk,rk_t ) = 1; +G1(eq_Erk,E_rk) = 1; + PIE(eq_Erk,Erk_sh ) = 1; + +%* flexible prices and wages **/ +G0(eq_Erk_f,rk_f_t ) = 1; +G1(eq_Erk_f,E_rk_f) = 1; + PIE(eq_Erk_f,Erk_f_sh ) = 1; + +%* E(w) **/ +%* sticky prices and wages **/ +G0(eq_Ew,w_t ) = 1; +G1(eq_Ew,E_w) = 1; +PIE(eq_Ew,Ew_sh ) = 1; + +%% E_Rktil +%* sticky prices and wages **/ +G0(eq_ERktil,Rktil_t) = 1; +G1(eq_ERktil,E_Rktil) = 1; +PIE(eq_ERktil,ERktil_sh) = 1; + + +%****************************************** +%% EXTRA STATES +% These aren't strictly necessary, but they +% track lags or simplify the equations +%*******************************************/ + + +%% pi_t1 +G0(pi1,pi_t1) = 1; +G1(pi1,pi_t) = 1; + +%% pi_t2 +G0(pi2,pi_t2) = 1; +G1(pi2,pi_t1) = 1; + +%% pi_a +G0(pi_a, pi_a_t)= 1; +G0(pi_a, pi_t) = -1; +G0(pi_a, pi_t1) = -1; +G0(pi_a, pi_t2) = -1; +G1(pi_a, pi_t2) = 1; + +%% Rt1 +G0(Rt1, R_t1)= 1; +G1(Rt1, R_t) = 1; + +%% E_z +G0(eq_Ez, E_z) = 1; +G0(eq_Ez, ztil_t) = -(1/(1-alp))*(rho_z-1); +G0(eq_Ez, zp_t) = -rho_zp; diff --git a/initialization/eqs990.m b/initialization/eqs990.m new file mode 100644 index 0000000..3809913 --- /dev/null +++ b/initialization/eqs990.m @@ -0,0 +1,81 @@ + %% Equilibrium conditions +euler = 1; +inv = 2; +capval = 3; +spread = 4; +nevol = 5; +output = 6; +caputl = 7; +capsrv = 8; +capev = 9; +mkupp = 10; +phlps = 11; +caprnt = 12; +msub = 13; +wage = 14; +mp = 15; +res = 16; +eq_g = 17; +eq_b = 18; +eq_mu = 19; +eq_z = 20; +eq_laf = 21; +eq_law = 22; +eq_rm = 23; +eq_sigw = 24; +eq_mue = 25; +eq_gamm = 26; +eq_laf1 = 27; +eq_law1 = 28; +eq_Ec = 29; +eq_Eqk = 30; +eq_Ei = 31; +eq_Epi = 32; +eq_EL = 33; +eq_Erk = 34; +eq_Ew = 35; +eq_ERktil = 36; +euler_f = 37; +inv_f = 38; +capval_f = 39; +output_f = 40; +caputl_f = 41; +capsrv_f = 42; +capev_f = 43; +mkupp_f = 44; +caprnt_f = 45; +msub_f = 46; +res_f = 47; +eq_Ec_f = 48; +eq_Eqk_f = 49; +eq_Ei_f = 50; +eq_EL_f = 51; +eq_Erk_f = 52; +eq_ztil = 53; +eq_pist = 54; +pi1 = 55; +pi2 = 56; +pi_a = 57; +Rt1 = 58; +eq_zp = 59; +eq_Ez = 60; + +n_eqc = 60; + +if exist('nant','var') + if nant > 0 + + % These are the anticipated shocks. For each there is both an innovation + % (for new anticipated shocks, calculated in period T only), + % and a process, so that the shocks can be passed from period to + % period. + + for i = 1:nant + eval(strcat('eq_rml',num2str(i),' = ',num2str(n_eqc+i),';')); + end + + n_eqc=n_eqc+nant; + + end + +end diff --git a/initialization/getPara_script.m b/initialization/getPara_script.m new file mode 100644 index 0000000..bd43626 --- /dev/null +++ b/initialization/getPara_script.m @@ -0,0 +1,50 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Created 3/17/2014 by Matt Cocci + +%% Summary/Motivation +% This script, depending on the mspec will assign values to the parameters +% used in the mode +% This is done to allow for easy access to parameter values given a +% parameter vector, rather than copyying the long list of output, as we +% have below + +%% Important Variables +% Important variables that must be set to run this: +% 1. para -- vector which will be assigned out to parameter names +% 2. mspec -- the mspec to use, which is crucial because different models +% have different parameter names and numbers of parameters + +%% Getting Parameter Values +% To access the modal values of the parameters +% 1. run your spec file +% 2. run forecast_mode_est_ant +% 3. set para = params +% 4. run this script + +% Where this script is run: +% 1. dsgesolv.m +% 2. measure/meausurMSPEC.m + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +if mspec==557 + [alp,zeta_p,iota_p,del,ups,Bigphi,s2,h,a2,nu_l,nu_m,zeta_w,iota_w,law,rstar,psi1,psi2,rho_r,pistar,... + Fom,sprd,zeta_spb,gammstar,NEW_5,... + gam,Lstar,chi,laf,gstar,Ladj,... + rho_z,rho_phi,rho_chi,rho_laf,rho_mu,rho_b,rho_g,rho_sigw,rho_mue,rho_gamm,... + sig_z,sig_phi,sig_chi,sig_laf,sig_mu,sig_b,sig_g,sig_r,sig_sigw,sig_mue,sig_gamm,... + bet,zstar,phi,istokbarst,rkstar,cstar,ystar,istar,kstar,kbarstar,Rstarn,wstar,wadj,mstar,... + zeta_nRk, zeta_nR, zeta_nqk, zeta_nn, zeta_nmue, zeta_spmue, zeta_nsigw, zeta_spsigw, ... + vstar, nstar, Rkstar, sig_r_ant] = getpara00_557(para); +elseif mspec==990 + [alp,zeta_p,iota_p,del,ups,Bigphi,s2,h,ppsi,nu_l,zeta_w,iota_w,law,laf,bet,Rstarn,psi1,psi2,psi3,pistar,sigmac,rho,epsp,epsw... + gam,Lmean,Lstar,gstar,rho_g,rho_b,rho_mu,rho_z,rho_laf,rho_law,rho_rm,rho_sigw,rho_mue,rho_gamm,rho_pist,rho_lr,rho_zp,rho_tfp,rho_gdpdef,rho_pce,... + sig_g,sig_b,sig_mu,sig_z,sig_laf,sig_law,sig_rm,sig_sigw,sig_mue,sig_gamm,sig_pist,sig_rm_ant,sig_lr,sig_zp,sig_tfp,sig_gdpdef,sig_pce,... + eta_gz,eta_laf,eta_law,modelalp_ind,gamm_gdpdef,del_gdpdef,... + zstar,rstar,rkstar,wstar,wl_c,cstar,kstar,kbarstar,istar,ystar,sprd,zeta_spb,gammstar,vstar,nstar,... + zeta_nRk,zeta_nR,zeta_nsigw,zeta_spsigw,zeta_nmue,zeta_spmue,zeta_nqk,zeta_nn] = getpara00_990(para); +end + + diff --git a/initialization/getState.m b/initialization/getState.m new file mode 100644 index 0000000..36b0ef9 --- /dev/null +++ b/initialization/getState.m @@ -0,0 +1,17 @@ +% OVERVIEW +% getState.m gets the numerical index for a state. This function replaces +% getE_pi.m, getpigap_t.m, getr_sh.m, getrt.m, getR_t.m +% +% INPUTS +% name: the state name as a string +% +% OUTPUTS +% stateNum: state's numerical index +% +% EXAMPLE: +% r_sh = getState(mspec,nant,'r_sh') +% returns r_sh = 10 + +function stateNum = getState(mspec,nant,namer) +eval(['states' num2str(mspec)]); +eval(['stateNum = ',namer,';']); \ No newline at end of file diff --git a/initialization/getmeasur.m b/initialization/getmeasur.m new file mode 100644 index 0000000..62d9d21 --- /dev/null +++ b/initialization/getmeasur.m @@ -0,0 +1,7 @@ +function [ZZ,DD,DDcointadd,QQ,EE,MM,retcode] = getmeasur(mspec,TTT,RRR,valid,params,nvar,nlags,npara,coint,cointadd, nant) + +if exist('nant','var') + eval(strcat('[ZZ,DD,DDcointadd,QQ,EE,MM,retcode] = measur',num2str(mspec),'(TTT,RRR,valid,params,nvar,nlags,',num2str(mspec),',npara,coint,cointadd,nant);')); +else + eval(strcat('[ZZ,DD,DDcointadd,QQ,EE,MM,retcode] = measur',num2str(mspec),'(TTT,RRR,valid,params,nvar,nlags,',num2str(mspec),',npara,coint,cointadd);')); +end diff --git a/initialization/getmodel.m b/initialization/getmodel.m new file mode 100644 index 0000000..325611d --- /dev/null +++ b/initialization/getmodel.m @@ -0,0 +1,5 @@ +function [TTT,RRR,zend] = getmodel(TTTsim,RRRsim,zendsim,j2,nstate,nshocks) + +TTT = reshape(TTTsim(j2,:),nstate,nstate); +RRR = reshape(RRRsim(j2,:),nstate,nshocks); +zend = reshape(zendsim(j2,:),nstate,1); \ No newline at end of file diff --git a/initialization/getpara00_990.m b/initialization/getpara00_990.m new file mode 100644 index 0000000..ae8bff2 --- /dev/null +++ b/initialization/getpara00_990.m @@ -0,0 +1,306 @@ +function [alp,zeta_p,iota_p,del,ups,Bigphi,s2,h,ppsi,nu_l,zeta_w,iota_w,law,laf,bet,Rstarn,psi1,psi2,psi3,pistar,sigmac,rho,epsp,epsw... + gam,Lmean,Lstar,gstar,rho_g,rho_b,rho_mu,rho_z,rho_laf,rho_law,rho_rm,rho_sigw,rho_mue,rho_gamm,rho_pist,rho_lr,rho_zp,rho_tfp,rho_gdpdef,rho_pce,... + sig_g,sig_b,sig_mu,sig_z,sig_laf,sig_law,sig_rm,sig_sigw,sig_mue,sig_gamm,sig_pist,sig_rm_ant,sig_lr,sig_zp,sig_tfp,sig_gdpdef,sig_pce,... + eta_gz,eta_laf,eta_law,modelalp_ind,gamm_gdpdef,del_gdpdef,... + zstar,rstar,rkstar,wstar,wl_c,cstar,kstar,kbarstar,istar,ystar,sprd,zeta_spb,gammstar,vstar,nstar,... + zeta_nRk,zeta_nR,zeta_nsigw,zeta_spsigw,zeta_nmue,zeta_spmue,zeta_nqk,zeta_nn] = getpara00_990(para) + + +nantpad = 20; + +alp = para(1); +zeta_p = para(2); +iota_p = para(3); +del = .025; +ups = 1; %exp(para(4)/100);%maybe take out para(5)fix 0 +Bigphi = para(5); +s2 = para(6); +h = para(7); +ppsi = para(8); +nu_l = para(9); +zeta_w = para(10); +iota_w = para(11); +law = 1.5; +laf = []; +bet = 1/(1+para(12)/100); +psi1 = para(13); +psi2 = para(14); +psi3 = para(15); +pistar = (para(16)/100)+1; +sigmac = para(17); +rho = para(18); +epsp = 10; +epsw = 10; + +%Financial Frictions Parameters +Fom = 1-(1-para(19))^(1/4); %% F(omega) from annualized to quarterly default prob +sprd = (1+para(20)/100)^(1/4); %exp(para(21)/400); %% st st spread from annual perc to quarterly number +zeta_spb = para(21); +gammstar = para(22); + +npara = 22; + + +%% exogenous processes - level + +gam = para(npara+1)/100; +Lmean = para(npara+2); +gstar = .18; + +npara = npara+2; + +%% exogenous processes - autocorrelation + +rho_g = para(npara+1); +rho_b = para(npara+2); +rho_mu = para(npara+3); +rho_z = para(npara+4); +rho_laf = para(npara+5); +rho_law = para(npara+6); +rho_rm = para(npara+7); + +rho_sigw = para(npara+8); +rho_mue = para(npara+9); +rho_gamm = para(npara+10); + +rho_pist = para(npara+11); +rho_lr = para(npara+12); + +rho_zp = para(npara+13); +rho_tfp =para(npara+14); + +rho_gdpdef = para(npara+15); +rho_pce = para(npara+16); +npara = npara+16; + + +%% exogenous processes - standard deviation + +sig_g = para(npara+1); +sig_b = para(npara+2); +sig_mu = para(npara+3); +sig_z = para(npara+4); +sig_laf = para(npara+5); +sig_law = para(npara+6); +sig_rm = para(npara+7); + +sig_sigw = para(npara+8); +sig_mue = para(npara+9); +sig_gamm = para(npara+10); + +sig_pist = para(npara+11); +sig_lr = para(npara+12); + +sig_zp = para(npara+13); +sig_tfp= para(npara+14); + +sig_gdpdef= para(npara+15); +sig_pce= para(npara+16); +npara = npara+16; + +%% Standard deviations of the anticipated policy shocks +for i = 1:nantpad + eval(strcat('sig_rm',num2str(i), '= para(npara +',num2str(i),');')); + eval(strcat('sig_rm_ant(', num2str(i),') = sig_rm',num2str(i),';')); +end +npara = npara+nantpad; + +eta_gz = para(npara+1); +eta_laf = para(npara+2); +eta_law = para(npara+3); + +npara = npara+3; + +modelalp_ind = para(npara+1); +gamm_gdpdef = para(npara+2); +del_gdpdef = para(npara+3); + +npara = npara+3; + + +%% Parameters (implicit) -- from steady state + +zstar = log(gam+1)+(alp/(1-alp))*log(ups); + +rstar = (1/bet)*exp(sigmac*zstar); + +Rstarn = 100*(rstar*pistar-1); + +rkstar = sprd*rstar*ups - (1-del);%NOTE: includes "sprd*" + +wstar = (alp^(alp)*(1-alp)^(1-alp)*rkstar^(-alp)/Bigphi)^(1/(1-alp)); + +Lstar = 1; + +kstar = (alp/(1-alp))*wstar*Lstar/rkstar; + +kbarstar = kstar*(gam+1)*ups^(1/(1-alp)); + +istar = kbarstar*( 1-((1-del)/((gam+1)*ups^(1/(1-alp)))) ); + +ystar = (kstar^alp)*(Lstar^(1-alp))/Bigphi; +if ystar <= 0 + + disp([alp, bet, kstar,Lstar]) + dm([ystar,Lstar,kstar,Bigphi]) + +end +cstar = (1-gstar)*ystar - istar; + +wl_c = (wstar*Lstar/cstar)/law; + + +%FINANCIAL FRICTIONS ADDITIONS +% solve for sigmaomegastar and zomegastar +zwstar = norminv(Fom); +sigwstar = fzero(@(sigma)zetaspbfcn(zwstar,sigma,sprd)-zeta_spb,0.5); +% zetaspbfcn(zwstar,sigwstar,sprd)-zeta_spb % check solution + +% evaluate omegabarstar +omegabarstar = omegafcn(zwstar,sigwstar); + +% evaluate all BGG function elasticities +Gstar = Gfcn(zwstar,sigwstar); +Gammastar = Gammafcn(zwstar,sigwstar); +dGdomegastar = dGdomegafcn(zwstar,sigwstar); +d2Gdomega2star = d2Gdomega2fcn(zwstar,sigwstar); +dGammadomegastar = dGammadomegafcn(zwstar); +d2Gammadomega2star = d2Gammadomega2fcn(zwstar,sigwstar); +dGdsigmastar = dGdsigmafcn(zwstar,sigwstar); +d2Gdomegadsigmastar = d2Gdomegadsigmafcn(zwstar,sigwstar); +dGammadsigmastar = dGammadsigmafcn(zwstar,sigwstar); +d2Gammadomegadsigmastar = d2Gammadomegadsigmafcn(zwstar,sigwstar); + +% evaluate mu, nk, and Rhostar +muestar = mufcn(zwstar,sigwstar,sprd); +nkstar = nkfcn(zwstar,sigwstar,sprd); +Rhostar = 1/nkstar-1; + +% evaluate wekstar and vkstar +wekstar = (1-gammstar/bet)*nkstar... + -gammstar/bet*(sprd*(1-muestar*Gstar)-1); +vkstar = (nkstar-wekstar)/gammstar; + +% evaluate nstar and vstar +nstar = nkstar*kstar; +vstar = vkstar*kstar; + +% a couple of combinations +GammamuG = Gammastar-muestar*Gstar; +GammamuGprime = dGammadomegastar-muestar*dGdomegastar; + +% elasticities wrt omegabar +zeta_bw = zetabomegafcn(zwstar,sigwstar,sprd); +zeta_zw = zetazomegafcn(zwstar,sigwstar,sprd); +zeta_bw_zw = zeta_bw/zeta_zw; + +% elasticities wrt sigw +zeta_bsigw = sigwstar*(((1-muestar*dGdsigmastar/dGammadsigmastar)/... + (1-muestar*dGdomegastar/dGammadomegastar)-1)*dGammadsigmastar*sprd+... + muestar*nkstar*(dGdomegastar*d2Gammadomegadsigmastar-dGammadomegastar*d2Gdomegadsigmastar)/... + GammamuGprime^2)/... + ((1-Gammastar)*sprd+dGammadomegastar/GammamuGprime*(1-nkstar)); +zeta_zsigw = sigwstar*(dGammadsigmastar-muestar*dGdsigmastar)/GammamuG; +zeta_spsigw = (zeta_bw_zw*zeta_zsigw-zeta_bsigw)/(1-zeta_bw_zw); + +% elasticities wrt mue +zeta_bmue = muestar*(nkstar*dGammadomegastar*dGdomegastar/GammamuGprime+dGammadomegastar*Gstar*sprd)/... + ((1-Gammastar)*GammamuGprime*sprd+dGammadomegastar*(1-nkstar)); +zeta_zmue = -muestar*Gstar/GammamuG; +zeta_spmue = (zeta_bw_zw*zeta_zmue-zeta_bmue)/(1-zeta_bw_zw); + +% some ratios/elasticities +Rkstar = sprd*pistar*rstar; % (rkstar+1-delta)/ups*pistar; +zeta_Gw = dGdomegastar/Gstar*omegabarstar; +zeta_Gsigw = dGdsigmastar/Gstar*sigwstar; + +% elasticities for the net worth evolution +zeta_nRk = gammstar*Rkstar/pistar/exp(zstar)*(1+Rhostar)*(1-muestar*Gstar*(1-zeta_Gw/zeta_zw)); +zeta_nR = gammstar/bet*(1+Rhostar)*(1-nkstar+muestar*Gstar*sprd*zeta_Gw/zeta_zw); +zeta_nqk = gammstar*Rkstar/pistar/exp(zstar)*(1+Rhostar)*(1-muestar*Gstar*(1+zeta_Gw/zeta_zw/Rhostar))... + -gammstar/bet*(1+Rhostar); +zeta_nn = gammstar/bet+gammstar*Rkstar/pistar/exp(zstar)*(1+Rhostar)*muestar*Gstar*zeta_Gw/zeta_zw/Rhostar; +zeta_nmue = gammstar*Rkstar/pistar/exp(zstar)*(1+Rhostar)*muestar*Gstar*(1-zeta_Gw*zeta_zmue/zeta_zw); +zeta_nsigw = gammstar*Rkstar/pistar/exp(zstar)*(1+Rhostar)*muestar*Gstar*(zeta_Gsigw-zeta_Gw/zeta_zw*zeta_zsigw); + + +end + +function f=zetaspbfcn(z,sigma,sprd) +zetaratio = zetabomegafcn(z,sigma,sprd)/zetazomegafcn(z,sigma,sprd); +nk = nkfcn(z,sigma,sprd); +f = -zetaratio/(1-zetaratio)*nk/(1-nk); +end + +function f=zetabomegafcn(z,sigma,sprd) +nk = nkfcn(z,sigma,sprd); +mustar = mufcn(z,sigma,sprd); +omegastar = omegafcn(z,sigma); +Gammastar = Gammafcn(z,sigma); +Gstar = Gfcn(z,sigma); +dGammadomegastar = dGammadomegafcn(z); +dGdomegastar = dGdomegafcn(z,sigma); +d2Gammadomega2star = d2Gammadomega2fcn(z,sigma); +d2Gdomega2star = d2Gdomega2fcn(z,sigma); +f = omegastar*mustar*nk*(d2Gammadomega2star*dGdomegastar-d2Gdomega2star*dGammadomegastar)/... + (dGammadomegastar-mustar*dGdomegastar)^2/sprd/... + (1-Gammastar+dGammadomegastar*(Gammastar-mustar*Gstar)/(dGammadomegastar-mustar*dGdomegastar)); +end + +function f=zetazomegafcn(z,sigma,sprd) +mustar = mufcn(z,sigma,sprd); +f = omegafcn(z,sigma)*(dGammadomegafcn(z)-mustar*dGdomegafcn(z,sigma))/... + (Gammafcn(z,sigma)-mustar*Gfcn(z,sigma)); +end + +function f=nkfcn(z,sigma,sprd) +f = 1-(Gammafcn(z,sigma)-mufcn(z,sigma,sprd)*Gfcn(z,sigma))*sprd; +end + +function f=mufcn(z,sigma,sprd) +f = (1-1/sprd)/(dGdomegafcn(z,sigma)/dGammadomegafcn(z)*(1-Gammafcn(z,sigma))+Gfcn(z,sigma)); +end + +function f=omegafcn(z,sigma) +f = exp(sigma*z-1/2*sigma^2); +end + +function f=Gfcn(z,sigma) +f = normcdf(z-sigma); +end + +function f=Gammafcn(z,sigma) +f = omegafcn(z,sigma)*(1-normcdf(z))+normcdf(z-sigma); +end + +function f=dGdomegafcn(z,sigma) +f=normpdf(z)/sigma; +end + +function f=d2Gdomega2fcn(z,sigma) +f = -z*normpdf(z)/omegafcn(z,sigma)/sigma^2; +end + +function f=dGammadomegafcn(z) +f = 1-normcdf(z); +end + +function f=d2Gammadomega2fcn(z,sigma) +f = -normpdf(z)/omegafcn(z,sigma)/sigma; +end + +function f=dGdsigmafcn(z,sigma) +f = -z*normpdf(z-sigma)/sigma; +end + +function f=d2Gdomegadsigmafcn(z,sigma) +f = -normpdf(z)*(1-z*(z-sigma))/sigma^2; +end + +function f=dGammadsigmafcn(z,sigma) +f = -normpdf(z-sigma); +end + +function f=d2Gammadomegadsigmafcn(z,sigma) +f = (z/sigma-1)*normpdf(z); +end diff --git a/initialization/initializePrograms.m b/initialization/initializePrograms.m new file mode 100644 index 0000000..f85b6c1 --- /dev/null +++ b/initialization/initializePrograms.m @@ -0,0 +1,69 @@ + +%% Set Random Number Generators +rand('state',12345) +randn('state',12345) + +%% Initialize Model Specifications +spec + +%% Load data +[YYall,XXall,ti,nobsall,dlpopall,dlMA_pop,MA_pop,population] = loaddata(nvar,nlags,nant,antlags,psize,zerobound,peachflag,mspec); + +% Augment number of observerved variables by number of anticipated policy shocks. +nvar = nvar+nant; + +% Define in-sample data +I = find(ti == dates); +YY = YYall(I-stime+1:I,:); +XX = XXall(I-stime+1:I,:); +tiI = ti(I-stime+1:I); +dlpop = dlpopall(I-stime+1:I); +pop_smth = population(I-stime+2+nlags:I+1+nlags); +nobs = size(YY,1); + +% Define pre-sample data +YY_p = YYall(1:I-stime,:); +XX_p = XXall(1:I-stime,:); +dlpop_p = dlpopall(1:I-stime); +nobs_p = size(YY_p,1); + +% Initialize date-relevant variables +Idate = find(tiI == dates); +tiall = [tiI(1:end-1);(tiI(end):0.25:(tiI(end)+.25*(qahead+stime-Startdate)))']; +datesall = strcat(num2str(floor(tiall)),'-',num2str(round(1+4*(tiall-floor(tiall))))); + +% Transformations associated with level variables +if mspec==557 + YY(1,[1:6 8:end]) = NaN; + YY(2:end,7) = NaN; +end + +%% Load information for prior distribution +prior = priors990(); + +pmean = prior(1:npara,1); +pstdd = prior(1:npara,2); +pshape = prior(1:npara,3); + +pshape = pshape.*(1-para_mask); +pmean = pmean.*(1-para_mask)+para_fix.*para_mask; +pstdd = pstdd.*(1-para_mask); + +nonpolipar = [1:1:npara]; +nonpolipar(polipar) = []; + +%% Load transformation scheme for parameters +trspec = transp990(); +trspec(:,1) = trspec(:,1).*(1-para_mask); + +%% Set number of states and shocks +[TTT,RRR,CCC,valid] = dsgesolv(mspec, para); +[nstate,nshocks] = size(RRR); + +%% Calculate lagged growth rates +YY0 = zeros(nlags,size(YY,2)); +nobs0 = size(YY0,1); +for lagind = 1:nlags + YY0(nlags-lagind+1,:) = XX(1,1+cointall+(lagind-1)*nvar+1:1+cointall+lagind*nvar); +end +YYcoint0=[]; diff --git a/initialization/keep.m b/initialization/keep.m new file mode 100644 index 0000000..ab5dcc0 --- /dev/null +++ b/initialization/keep.m @@ -0,0 +1,74 @@ +function keep(varargin) +% function keep(var1,var2, ...) +% "keep" keeps the caller workspace variables of your choice and clear the rest. +% It compliments "clear" and its usage is similar but only for variables. +% String matches will work similarly to "clear", e.g. keep var* +% Examples: +% "keep" by itself does nothing and keeps all variables. +% compare with: "clear" by itself deletes all variables and removes links +% for global variables to the caller's workspace. +% "keep global" will keep all global variables deleting workspace variables +% "keep global var1" will keep global var1, deleting the remaining global variables +% while keeping the remaining workspace variables. +% "keep global -regexp expr1" will keep global variables matching the regular +% expression expr1. +% "keep -regexp expr1" will keep workspace variables matching the regular +% expression expr1. +% +% based upon KEEP by Xiaoning (David) Yang 1998, 1999 +% written by Mirko Hrovat 03/10/2005 mhrovat@email.com +% modified by Mirko Hrovat 06/27/2006 +% - to account for empty sets for variables to be deleted. +% Differences of this version from the other version of KEEP. +% - eliminated error message if workspace is empty +% - insured that global variable links were not removed from the workspace +% - added support for "global" key word +% - allowed wildcard and regexp matching +% - uses setxor, intersect, & union to determine the variable set to be deleted. +sep={''','''}; +if nargin==0 || isempty(varargin{1}), + return, % do nothing if no arguments +end +arglist=varargin; % list has the list of variables to keep +vars = evalin('caller','who'); % vars has workspace varaibles as well as linked globals +glbls = who('global'); % glbls has all global variables + +if strcmpi(arglist{1},'global') + % no more variables listed, delete workspace but keep globals + if nargin==1 || isempty(arglist{2}), + lsrs = setxor(vars,intersect(vars,glbls)); + % intersection of vars & glbls gives linked globals + % xor of vars & linked glbls gives the rest of the workspace + + else % keep regular variables and keep only the listed globals + % kprs are the list of global variables to keep + kprs = who(arglist{:}); + lsrs = setxor(glbls,kprs); + if ~isempty(lsrs), % if any global lsrs found then add keyword global + lsrs = {'global',lsrs{:}}; + end + end +else % keep listed regular variables and keep all globals + nargs=length(arglist); + list=cell(2,nargs); + list(1,:)=arglist; + list(2,:)=repmat(sep,[1,nargs]); % need to add separators to list + list(2,nargs)={''')'}; + kprs = evalin('caller',['who(''',list{:}]); % kprs are the list of variables to keep + % Need to make a union of vars & glbls in case some global variables are + % not linked to the workspace in order to get all variables. + % union of kprs & glbls gets all variables except those to be deleted + % union of vars & glbls gets all possible variables + lsrs = setxor(union(vars,glbls),union(kprs,glbls)); +end + +% now create the list of loser variables +nargs=length(lsrs); +if nargs>0, % only execute if there are variables to lose. + list=cell(2,nargs); + list(1,:)=lsrs; + list(2,:)=repmat(sep,[1,nargs]); % need to add separators to list + list(2,nargs)={''')'}; + evalin('caller',['clear(''',list{:}]); +end +%-------------------- the end ---------------------- \ No newline at end of file diff --git a/initialization/keepVars.m b/initialization/keepVars.m new file mode 100644 index 0000000..b6da36e --- /dev/null +++ b/initialization/keepVars.m @@ -0,0 +1,107 @@ +% OVERVIEW +% keepVars.m: Keep important variables in the workspace. This allows us to +% loop over programs. +% +% IMPORTANT VARIABLES +% keepList: a list of variables to keep + +%% Important +keepList = {'overwrite', 'reoptimize'}; + +%% Model +keepList = union(keepList,{'mspec','subspec','pf_mod','mprior','peachsm','dataset','dates','stime', ... + 'altdata'}); + +%% Zerobound +keepList = union(keepList,{'zerobound','nant','nant_implied','antlags'}); + +%% Parallel +keepList = union(keepList,{'parallelflag','parflag','distr','nMaxWorkers'}); + +%% Conditional +keepList = union(keepList,{'peachfile','peachfileold'}); + +%% Forecasting +keepList = union(keepList,{'simple_forecast','bdd_int_rate','peachflag','dsflag','jstep','save_states','qahead','nplotstates'}); + +%% Forplot +keepList = union(keepList,{'plot*','fancharts','fourq_flag','Q4Q4table','q_adj', 'vars_to_plot'}); + +%% Plotting +keepList = union(keepList,{'newsletter','system','pres','useSavedMB','plotList','medianFlag','issue_num'}); + +%% IRFs +keepList = union(keepList,{'irfStates','redo_irfsims','nirf'}); + +%% Vardecs +keepList = union(keepList,{'vdec_states'}); + +%% PLT +keepList = union(keepList,{'MODEstr','experiment_flag','useMode'}); + +%% Debugging +keepList = union(keepList,{'nsim','nblocks','nburn'}); + +%% Paths +keepList = union(keepList,{'spath','fpath','spath_overwrite','fpath_overwrite','gpath_overwrite'}); + +%% Output-producing scripts +keepList = union(keepList,{'baseDir', 'matlabDir', 'spec_file','systemDir', 'my_keepList', 'forecast_again'}); + +%% For script-wrapping +keepList = union(keepList,{'varargin', 'script'}); + +%% Productivity +keepList = union(keepList,{'prodflag'}); + +%% Aux variables +keepList = union(keepList,{'auxFlag','bolUseFinals','mnobss','shockdec_history','useRtParallelResults','saveSemiCondStShFlag',... + 'paramFile','paramSpecFile', 'replaceBlock','edate','sdate','h1','h2','h3','hairType','haircompare','swapKapSSS','rwMC','varName',... + 'sh_ind','st_ind','sh_cmp','st_cmp'}); + +%% Misc +% iter save_states iInput stime dates mnobss shockdec_history +% experiment_flag useMode MODEstr input +% irfStates vdec_states sd_states +% modeonly ssonly ShockremoveList + +%% T-distributed shocks +keepList = union(keepList,{'tflag','df_bar_num','dfflag','pargibbflag','onepctflag','tstr'}); + +%% Realtime +keepList = union(keepList,{'judge','qvint','ovint','sflag','r_exp','nantmax','antpolflag','mant','first','compound','paramDate'}); + +%% PLT specs +if exist('PLT','var') && PLT==1 + keepList = union(keepList,{'experiment_flag','useMode','nsim','nburn','nblocks',... + 'jstep','init*','pigap_0','MODEstr','EXPE','exp','expers',... + 'plottype','fancharts','Means_*','alt_baseline'}); +end + +%% Forecast Loop through multiple models (see forecastAndPlotLoop.m) +keepList = union(keepList,{'cellSpecList'}); + +%% Alternate Gensys +keepList = union(keepList,{'gensys2', 'model2_num', 'add', 'mspec1', 'mspec2', 'infile0', 'param_555', 'param_556'}); + +%% IRF one draw and output gap +keepList = union(keepList,{'irfvars','irfstates','ygapflag','params'}); + +%% Forward guidance dates, colors, plot data +keepList = union(keepList,{'exercise_flag','policy_flag','t1','t2','t2path','t2i','FGplot','FGbaseline'}); +keepList = union(keepList,{'iPlot','types','type','colors','ind','inds'}); + +% alternative policy rules +keepList = union(keepList,{'alt_policy', 'alt_policy_flag', 'alt_policy_list', 'alt_policy_series', 'rule', 'ii', 'altrules'}); +keepList = union(keepList, {'alt_policy_spath_override'}); +keepList = union(keepList, {'to_save', 'start_loc', 'quarters_fwd', 'folder_loc'}); + +% specific plot-path +keepList = union(keepList, {'gpath_override'}); +keepList = union(keepList, {'gpath', 'path_to_plotdirs'}); +keepList = union(keepList, {'scenario_fcast'}); + +% I want to use variables that don't disappear!! - MJS 08-01-14 +keepList = union(keepList, {'myCustomVar1', 'myCustomVar2', 'myCustomVar3'}); + +eval(['keep ', sprintf(repmat('%s ',1,length(keepList)),keepList{:})]) diff --git a/initialization/loaddata.m b/initialization/loaddata.m new file mode 100644 index 0000000..8f141d2 --- /dev/null +++ b/initialization/loaddata.m @@ -0,0 +1,143 @@ +%% loaddata +% +% Description: reads time series data from ASCII +% Output: +% 1) YYall ---> matrix of observables +% 2) XXall ---> +% 3) ti --> +% 4) nobs --> number of periods in data imported +% 4) dlpopall --> log differences of the population obtained from Haver Analaytics +% 5) dlMA_pop --> log differences of the population forecasted by Macro Advisers + +function [YYall,XXall,ti,nobs,dlpopall,dlMA_pop,MA_pop,population] = loaddata(nvar,nlags,nant,antlags,psize,zerobound,peachflag,mspec) + +if mspec==990 + start_date = 1959.00; + load('rawData_990'); + + popreal=data(1:end,11); + m = length(MA_pop); + [xxx,popfor]=Hpfilter([popreal;MA_pop(2:end)],1600); + population = popfor(1:end-m+1); + MA_pop = popfor(end-m+1:end); + + dlpopreal = log(popreal(2:end)) - log(popreal(1:end-1)); + dlpopall = log(population(2:end)) - log(population(1:end-1)); + dlMA_pop = log(MA_pop(2:end)) - log(MA_pop(1:end-1)); + + nobs=size(data,1); + + ti = (start_date:.25:(start_date+.25*(nobs-1)))'; + + %% Series + series = nan(nobs-1,nvar); + + %Trim series for growth rate transformations + nobs = nobs - 1; + ti = ti(2:end); + + %% Output growth (log approximation quarterly) + %% Load levels + Output = 100*(log(data(2:end,1))-log(data(1:end-1,1))); + series(:,1) = Output + 100*(dlpopreal - dlpopall); % Add back in the adjustment from HP Filtering + + %% Employment/Hours per capita + % log hours per capita + series(:,2) = (log(3*(data(2:end,14).*data(2:end,13)/100))-log(population(2:end)))*100; + %% Real Wage Growth + % per hour + series(:,3) = 100*((log(data(2:end,15))-log(data(1:end-1,15)))-(log(data(2:end,2))-log(data(1:end-1,2)))); + nn=3; + + %% Inflation + + % Core PCE + series(:,nn+1) = 100*(log(data(2:end,12))-log(data(1:end-1,12))); + % GDP Deflator + series(:,nn+1) = 100*(log(data(2:end,2))-log(data(1:end-1,2))); + + % Add Core PCE for models with factor structure on inflation. + if any(mspec == [988 990 991 992]) + nn=nn+1; + series(:,nn+1) = 100*(log(data(2:end,12))-log(data(1:end-1,12))); + end + + %% nominal short-term interest rate (3 months) - % annualized + %series(:,6) = robs(68:end); + series(:,nn+2) = data(2:end,8); + + %% Consumption growth (log approximation quarterly annualized) + %series(:,7) = dc(68:end); + Consumption = 100*(log(data(2:end,3))-log(data(1:end-1,3))); + series(:,nn+3) = Consumption + 100*(dlpopreal - dlpopall); + + + %% Investment growth (log approximation quarterly annualized) + %series(:,8) = dinve(68:end); + Investment = 100*(log(data(2:end,4))-log(data(1:end-1,4))); + series(:,nn+4) = Investment + 100*(dlpopreal - dlpopall); + + %% Unemployment + nn = nn+4; + + + %% spread: BAA-10yr TBill + series(:,nn+1) = data(2:end,10); %%add for model with Financial Frictions + + %% Long Term Inflation Expectations + series(:,nn+2) = longinf(2:end)/4; + + % Add long rate data + data_add = [nan(length(series)-length(lrate),1); lrate]/4; + series(:,nn+3) = data_add; % Last column is nans, just waiting for long rate data, so throw it out + + % Add output level + if any(mspec == [977 980 981 982]) + % output log levels + series(:,nn+4) = 100*log(data(2:end,1)) + 100*(log(popreal(2:end))-log(population(2:end))); + end + + % Add Fernald TFP series + Alpha=fernaldTFP(1:nobs,1); + tfp_unadj=fernaldTFP(1:nobs,2); + tfp_adj=fernaldTFP(1:nobs,3); + tfp = tfp_unadj; + tfp=(tfp-nanmean(tfp)) ./ (4*(1-Alpha)); + series(:,nn+4) = tfp; + + + %% Adding OIS expectations + %getting expectations + [ExpFFR,peachdata_FFR] = ExpFFR_OIS(nant,antlags,psize,zerobound,peachflag); + + % Account for fact that our dataset might stop earlier than OIS, which + % means we should truncate OIS + ExpFFR = ExpFFR(1:antlags+1,:); + + E_num = size(ExpFFR,1); + fill = nan(length(series)-E_num,nant); + data_add = [fill;ExpFFR]/4; + series = [series,data_add]; + nvar = nvar + nant; + + YYall = series(1+nlags:nobs,:);%%nlags switched from T0, DF + XXall = ones(nobs-nlags, 1+nvar*nlags); + ti = ti(1+nlags:nobs,:); + dlpopall = dlpopall(1+nlags:nobs); % NEW + + for i = 1:1:nlags; + XXall(:,1+(i-1)*nvar+1:1+i*nvar) = series(nlags-i+1:nobs-i,:); + end + + if nlags > 0 + XXall = [XXall;[1,YYall(end,:),XXall(end,1+1:1+nvar*nlags-nvar)]]; + end + nobs = size(YYall,1); + + + +else + error('Appropriate data transformations not specified for given model specification. Please see loaddata.m'); + +end + diff --git a/initialization/measur990.m b/initialization/measur990.m new file mode 100644 index 0000000..9a8bb65 --- /dev/null +++ b/initialization/measur990.m @@ -0,0 +1,208 @@ +function [ZZ,DD,DDcointadd,QQ,EE,MM,retcode] = measur990(TTT,RRR,valid,para,nvar,nlags,mspec,npara,coint,cointadd,nant,varargin); +%% description: +%% solution to DSGE model - delivers transition equation for the state variables S_t +%% transition equation: S_t = TC+TTT S_{t-1} +RRR eps_t, where var(eps_t) = QQ +%% define the measurement equation: X_t = ZZ S_t +D+u_t +%% where u_t = eta_t+MM* eps_t with var(eta_t) = EE +%% where var(u_t) = HH = EE+MM QQ MM', cov(eps_t,u_t) = VV = QQ*MM' + +if length(varargin) > 0 + subspec = varargin{1}; +end + +retcode = 1; + +if valid < 1; + retcode = 0; + + ZZ = []; + DD = []; + QQ = []; + EE = []; + MM = []; + DDcointadd = []; + + return +end + +nstate = size(TTT,1); +DDcointadd = 0; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% step 1: assign names to the parameters +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Parameters +getPara_script + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% step 2: assign names to the columns of GAM0, GAM1 -- state variables +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +eval(strcat('states',num2str(mspec))); + +%% additional states +y_t1 = n_end+n_exo+n_exp+1; +c_t1 = n_end+n_exo+n_exp+2; +i_t1 = n_end+n_exo+n_exp+3; +w_t1 = n_end+n_exo+n_exp+4; +pi_t1 = n_end+n_exo+n_exp+5; % Add lagged mc_t state +L_t1 = n_end+n_exo+n_exp+6; % Add lagged L_t state +Et_pi_t = n_end+n_exo+n_exp+7; % Add forward looking expected infl. +lr_t = n_end+n_exo+n_exp+8; % Add in measurement error for long run series +tfp_t = n_end+n_exo+n_exp+9; % Add measurement error for Fernald TFP series +e_gdpdef = n_end+n_exo+n_exp+10; % Add measurement error for GDP Deflator +e_pce = n_end+n_exo+n_exp+11; % Add measurement error for Core PCE +u_t1 = n_end+n_exo+n_exp+12; % Add measurement error for Fernald TFP series + +if nstate ~= (n_end+n_exo+n_exp+12) + + retcode = 0; + + yyyyd = zeros(nvar,nvar); + xxyyd = zeros(1+nlags*nvar,nvar); + xxxxd = zeros(1+nlags*nvar,1+nlags*nvar); + + disp('\n\n number of states does not match in vaprio\n'); + return +end + +if ~exist('nant','var') + nvar = 12; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% step 3: assign measurement equation : X_t = ZZ*S_t + DD + u_t +%% where u_t = eta_t+MM* eps_t with var(eta_t) = EE +%% where var(u_t) = HH = EE+MM QQ MM', cov(eps_t,u_t) = VV = QQ*MM' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% create system matrices for state space model +ZZ = zeros(nvar+coint,nstate); +%% constant +DD = zeros(nvar+coint,1); +%% cov(eps_t,u_t) = VV +MM = zeros(nvar+coint,nex); +%% var(eta_t) = EE +EE = zeros(nvar+coint,nvar+coint); +%% var(eps_t) = QQ +QQ = zeros(nex,nex); + + + +%% Output growth - Quarterly! +ZZ(1,y_t) = 1; +ZZ(1,y_t1) = -1; +ZZ(1,z_t) = 1; +DD(1) = 100*(exp(zstar)-1); + +%% Hoursg +ZZ(2,L_t) = 1; +DD(2) = Lmean; + +%% Labor Share/real wage growth +% ZZ(3,L_t) = 1; +% ZZ(3,w_t) = 1; +% ZZ(3,y_t) = -1; +% DD(3) = 100*log((1-alp)/(1+laf)); + +ZZ(3,w_t) = 1; +ZZ(3,w_t1) = -1; +ZZ(3,z_t) = 1; + +DD(3) = 100*(exp(zstar)-1); + +%% Inflation (GDP Deflator) +ZZ(4,pi_t) = gamm_gdpdef; +ZZ(4,e_gdpdef) = 1; +DD(4) = 100*(pistar-1) + del_gdpdef; + +%% Inflation (Core PCE) +ZZ(5,pi_t) = 1; +ZZ(5,e_pce) = 1; +DD(5) = 100*(pistar-1); + +%% Nominal interest rate +ZZ(6,R_t) = 1; +DD(6) = Rstarn; + +%% Consumption Growth +ZZ(7,c_t) = 1; +ZZ(7,c_t1) = -1; +ZZ(7,z_t) = 1; +DD(7) = 100*(exp(zstar)-1); + +%% Investment Growth +ZZ(8,i_t) = 1; +ZZ(8,i_t1) = -1; +ZZ(8,z_t) = 1; +DD(8) = 100*(exp(zstar)-1); + +%% Spreads +ZZ(9,E_Rktil) = 1; +ZZ(9,R_t) = -1; +DD(9) = 100*log(sprd); + +%% 10 yrs infl exp + + % Create a TTT matrix that has the level rows/cols (i.e. the part with the + % unit root) stripped out + % strip_out = [zlev_t]; + % TTT_tmp = TTT; TTT_tmp(strip_out,:) = []; TTT_tmp(:,strip_out) = []; + % replace_inds = reshape(1:nstate^2, nstate, nstate); + % replace_inds(strip_out,:) = []; + % replace_inds(:,strip_out) = []; + % replace_inds = replace_inds(:); + + % Invert that matrix + % TTT10_tmp = (1/40)*((eye(size(TTT_tmp,1)) - TTT_tmp)\(TTT_tmp - TTT_tmp^41)); + + % Construct TTT10 matrix + TTT10 = (1/40)*((eye(size(TTT,1)) - TTT)\(TTT - TTT^41)); + +ZZ(10,:) = TTT10(pi_t,:); +DD(10) = 100*(pistar-1); + +%% Long Rate +ZZ(11,:) = ZZ(6,:)*TTT10; +ZZ(11,lr_t) = 1; +DD(11) = Rstarn; + +%% TFP +ZZ(12,z_t) = (1-alp)*modelalp_ind + 1*(1-modelalp_ind); +ZZ(12,tfp_t) = 1; +ZZ(12,u_t) = alp/( (1-alp)*(1-modelalp_ind) + 1*modelalp_ind ); +ZZ(12,u_t1) = -(alp/( (1-alp)*(1-modelalp_ind) + 1*modelalp_ind) ); + +QQ(g_sh,g_sh) = sig_g^2; +QQ(b_sh,b_sh) = sig_b^2; +QQ(mu_sh,mu_sh) = sig_mu^2; +QQ(z_sh,z_sh) = sig_z^2; +QQ(laf_sh,laf_sh) = sig_laf^2; +QQ(law_sh,law_sh) = sig_law^2; +QQ(rm_sh,rm_sh) = sig_rm^2; +QQ(sigw_sh,sigw_sh) = sig_sigw^2; +QQ(mue_sh,mue_sh) = sig_mue^2; +QQ(gamm_sh,gamm_sh) = sig_gamm^2; +QQ(pist_sh,pist_sh) = sig_pist^2; +QQ(lr_sh,lr_sh) = sig_lr^2; +QQ(zp_sh,zp_sh) = sig_zp^2; +QQ(tfp_sh,tfp_sh)=sig_tfp^2; +QQ(gdpdef_sh,gdpdef_sh)=sig_gdpdef^2; +QQ(pce_sh,pce_sh)=sig_pce^2; + +if exist('nant','var') + if nant > 0 + % These lines set the standard deviations for the anticipated shocks. They + % are here no longer calibrated to the std dev of contemporaneous shocks, + % as we had in 904 + for i = 1:nant + eval(strcat('QQ(rm_shl',num2str(i),',rm_shl',num2str(i),') = sig_rm_ant(', num2str(i), ')^2;')); + end + + for i_ = 1:nant + ZZ(12 + i_,:) = ZZ(6,:)*(TTT^i_); + DD(12 + i_) = Rstarn; + end + end +end +%keyboard; diff --git a/initialization/mspec_add.m b/initialization/mspec_add.m new file mode 100644 index 0000000..c5dd473 --- /dev/null +++ b/initialization/mspec_add.m @@ -0,0 +1,112 @@ + +function [nvar,varnames,graph_title,cum_for,popadj,varnames_YL,varnames_irfs,varnames_YL_4Q,varnames_YL_irfs,... + names_shocks,names_shocks_title,nl_shocks_title,shocksnames,cum_irf,vardec_varnames,shockcats,list,shockdec_color] = mspec_add(mspec,dataset,zerobound,nant,fourq_flag) + +eval(['states',num2str(mspec)]); + +if any(mspec==990) + nvar = 12; + + % add TFP series + if any(mspec==990) + tfp = 'Unadjusted'; + else + error('Must specify which TFP data series to use'); + end + + varnames= {'Output Growth'; 'Aggregate Hours Growth'; 'Real Wage Growth'; 'GDP Deflator';'Core PCE Inflation';... + 'Interest Rate'; 'Consumption Growth'; 'Investment Growth'; 'Spread'; 'Long Inf';... + 'Long Rate'; ['Total Factor Productivity, Util.' tfp]}; + + varnames_irfs = { 'Output Growth'; 'Aggregate Hours Growth'; 'Real Wage Growth';... + 'GDP Deflator'; 'Core PCE Inflation'; 'Interest Rate'; 'Consumption Growth';... + 'Investment Growth'; 'Spread'; 'Long Inf'; 'Long Rate'; 'TFP'}; + + % Save titles for graphs + graph_title = { 'Output'; 'Labor_Supply'; 'Real_Wage'; 'GDP_Deflator'; 'Core_PCE';... + 'Interest_Rate'; 'Consumption'; 'Investment'; 'Spread'; 'Long_Inf';... + 'Long_Rate'; ['Total_Factor_Productivity_Util' tfp]}; + + % Adjustments to be made before plotting, like going to quarterly annualized + cum_for = [1 2 1 1 1 0 1 1 1 1 0 0]; + + % Whether to population adjust the variables + popadj = [1 1 0 0 0 0 1 1 0 0 0 0]; + + % Y-Axis Labels + varnames_YL = {'Percent Q-to-Q Annualized'; 'Percent Q-to-Q Annualized';... + 'Percent Q-to-Q Annualized'; 'Percent Q-to-Q Annualized'; ... + 'Percent Q-to-Q Annualized';... + 'Percent Annualized'; 'Percent Q-to-Q Annualized'; 'Percent Q-to-Q Annualized';... + 'Level'; 'Level'; 'Percent Annualized'; 'Percent Annualized'}; + varnames_YL_4Q = {'Percent 4Q Growth';'Percent 4Q Growth'; 'Percent 4Q Growth';... + 'Percent 4Q Growth';'Percent 4Q Growth'; 'Percent Annualized'; 'Percent Annualized'}; + varnames_YL_irfs = {'Percent Annualized'; 'Percent Annualized'; 'Percent Annualized'; ... + 'Percent Annualized'; 'Percent Annualized'; 'Percent Annualized'; 'Percent Annualized'; ... + 'Percent Annualized'; 'Percent Annualized';... + 'Percent Annualized'; 'Percent Annualized'; 'Percent Annualized'}; + + % Plot titles for plots of shock histories + names_shocks = {'g'; 'b'; '\mu'; 'z'; '\lambda_f'; '\lambda_w'; 'r_m'; '\sigma_w'; '\mu_e';... + '\gamma'; '\pi_*'; 'e_{LR}'; 'z^p'; 'e_{TFP}'; 'e_{gdpdef}'; 'e_{pce}'};... + names_shocks_title = {'govt'; 'asset'; 'inv_tech'; 'neutral_tech'; 'price_mkp'; 'wage_mkp';... + 'Money'; 'spread'; 'mue'; 'gamma'; 'pistar'; 'me_LR'; 'zp'; 'me_tfp'; ... + 'me_gdpdef'; 'me_pce'}; + shocksnames = names_shocks'; + + % Save names for plots of shock histories + nl_shocks_title = {'Technology'; 'phi'; 'Financial'; 'b'; 'g'; 'Mark-Up'; 'Monetary Policy'}; + + + % Not relevant + cum_irf = []; + vardec_varnames = {'Output Growth'; 'Aggregate Hours Growth'; 'Real Wage';... + 'GDP Deflator'; 'Core PCE Inflation'; 'Interest Rate'; 'Consumption Growth';... + 'Investment Growth';}; + + rm_total_sh=rm_sh; + if nant>0 + for i = 1:nant + eval(strcat('rm_total_sh = [rm_total_sh rm_shl',num2str(i),'];')); + end + end + + % Which shocks to plot in the shock decompositions: + % - Give the indices of the shocks, where the labels (used below) aliasing + % the index numbers come from running statesMSPEC above + % - Can group shocks by making an entry be an array like [mu_sh z_sh] + shockcats = {g_sh;b_sh;[ gamm_sh mue_sh sigw_sh]; z_sh; laf_sh; law_sh; rm_total_sh; ... + pist_sh; mu_sh; [lr_sh tfp_sh gdpdef_sh pce_sh]; zp_sh; 0;}; + + % How to label each element of shockcats in the legend + list = {'g'; 'b'; 'FF'; 'z'; 'p-mkp'; 'w-mkp'; 'pol.'; 'pi-LR'; 'mu'; 'me'; 'zp'; 'dt';}; + + % Colors of the bars in the shockdecs + shockdec_color = {'firebrick'; [0.3 0.3 1.0]; 'indigo'; 'darkorange'; 'yellowgreen'; 'teal';... + 'gold'; 'pink'; 'cyan'; [0 0.8 0]; [0 0.3 0]; 'gray';}'; + + + %% Adding information for expectations + + if zerobound + gen_temp = @(pattern) arrayfun(@(i_) sprintf(pattern, i_), 1:nant, 'UniformOutput', false); + temp1 = gen_temp('exp_%i'); + temp2 = gen_temp(''); + temp3 = gen_temp('Ant %i'); + temp4 = gen_temp('%iqA ant.sh.'); + temp5 = gen_temp('Ant%i'); + + varnames(end+1:end+nant) = temp1(1:nant); + varnames_YL(end+1:end+nant) = temp2(1:nant); + varnames_YL_4Q(end+1:end+nant) = temp2(1:nant); + varnames_irfs(end+1:end+nant) = temp2(1:nant); + varnames_YL_irfs(end+1:end+nant) = temp2(1:nant); + cum_for(end+1:end+nant) = zeros(1,nant); + popadj(end+1:end+nant) = zeros(1,nant); + names_shocks(end+1:end+nant) = temp3(1:nant); + nl_shocks_title(end+1:end+nant) = temp4(1:nant); + names_shocks_title(end+1:end+nant) = temp5(1:nant); + + shocksnames = names_shocks'; + end +end diff --git a/initialization/mspec_parameters_990.m b/initialization/mspec_parameters_990.m new file mode 100644 index 0000000..e988628 --- /dev/null +++ b/initialization/mspec_parameters_990.m @@ -0,0 +1,285 @@ +function [para,para_names,para_mask,para_fix,npara,polipar,polivalue,bounds] = mspec_parameters_990(subspec,dataset) + +%% names of parameters +% the parameters in para_names must be lsited in the order they appear +% below and in the model's priorfile + +nantpad = 20; + +para_names = [... + { '\alpha';'\zeta_p';'\iota_p';'\Upsilon';'\Phi';'S''''';'h';'psi';'\nu_l';'\zeta_w';... + '\iota_w';'\beta';... + '\psi_1';'\psi_2';'\psi_3';'\pi^*';'\sigma_{c}';'\rho';'F(\omega)';'spr_*';'\zeta_{sp}';'\gamma_*';... + '\gamma';'Lmean';... + ... + '\rho_{g}';'\rho_{b}';'\rho_{\mu}';'\rho_{z}';'\rho_{\lambda_f}';'\rho_{\lambda_w}';... + '\rho_{rm}';'\rho_{sigw}';'\rho_{mue}';'\rho_{gamm}';'\rho_{pi}^*';'\rho_{lr}';'\rho_{z^p}';'\rho_{tfp}';'\rho_{gdpdef}';'\rho_{pce}';... + ... + '\sigma_{g}';'\sigma_{b}';'\sigma_{\mu}';'\sigma_{z}';'\sigma_{\lambda_f}';'\sigma_{\lambda_w}';... + '\sigma_{rm}';'\sigma_{sigw}';'\sigma_{mue}';'\sigma_{gamm}';'\sigma_{pi}^*';'\sigma_{lr}';'\sigma_{z^p}';'\sigma_{tfp}';'\sigma_{gdpdef}';'\sigma_{pce}';... + }; ... + ... + arrayfun(@(i_) sprintf('\\sigma_{ant%d}', i_), [1:nantpad]', 'un', 0); + ... + {'\eta_{gz}';'\eta_{\lambda_f}';'\eta_{\lambda_w}'; 'i_{\alpha}^{model}'; '\Gamma_{gdpdef}'; '\delta_{gdpdef}'} ... + ]; + +%% values for parameters + +% fixing the parameters + +para = zeros(100,1); +para_mask = zeros(100,1); %npara x 1, set corresponding element to 1 to fix the parameters +para_fix = zeros(100,1); %npara x 1, contains values for fixed parameters + +if subspec == 93 + para(1) = 0.3000; %para_mask(1) = 1; para_fix(1) = para(1); %% alp; 1 +else + para(1) = 0.1596; %para_mask(1) = 1; para_fix(1) = para(1); %% alp; 1 +end +para(2) = 0.8940; %para_mask(2) = 1; para_fix(2) = para(2); %% zeta_p; 2 +para(3) = 0.1865; %para_mask(3) = 1; para_fix(3) = para(3); %% iota_p; 3 +para(4) = 1.0000; para_mask(4) = 1; para_fix(4) = para(4); %% ups; .1 5 +para(5) = 1.1066; %para_mask(5) = 1; para_fix(5) = para(5); %% Bigphi; 6 +para(6) = 2.7314; %para_mask(6) = 1; para_fix(6) = para(6); %% s2; 7 +para(7) = 0.5347; %para_mask(7) = 1; para_fix(7) = para(7); %% h; 8 +para(8) = 0.6862; %para_mask(8) = 1; para_fix(8) = para(8); %% ppsi; 9 +para(9) = 2.5975; %para_mask(9) = 1; para_fix(9) = para(9); %% nu_l 10 +para(10) = 0.9291; %para_mask(10) = 1; para_fix(10) = para(10); %% zeta_w; 11 +para(11) = 0.2992; %para_mask(11) = 1; para_fix(11) = para(11); %% iota_w; 12 +para(12) = 0.1402; %para_mask(12) = 1; para_fix(12) = para(12); %% bet; 14 +para(13) = 1.3679; %para_mask(13) = 1; para_fix(13) = para(13); %% psi1; 15 +para(14) = 0.0388; %para_mask(14) = 1; para_fix(14) = para(14); %% psi2; 16 +para(15) = 0.2464; %para_mask(15) = 1; para_fix(15) = para(15); %% psi3; 17 +if subspec == 2 + para(16) = 0.5000; para_mask(16) = 1; para_fix(16) = para(16); %% pistar; 18 +else + para(16) = 1.1121; %para_mask(16) = 1; para_fix(16) = para(16); %% pistar; 18 +end +para(17) = 0.8719; %para_mask(17) = 1; para_fix(17) = para(17); %% sigmac; 19 +para(18) = 0.7126; %para_mask(18) = 1; para_fix(18) = para(18); %% rho; 19 + +%Financial Frictions Parameters +para(19) = 0.0300; para_mask(19) = 1; para_fix(19) = para(19); %% Fom +para(20) = 1.7444; %para_mask(20) = 1; para_fix(20) = para(20); %% st st spread +para(21) = 0.0559; %para_mask(21) = 1; para_fix(21) = para(21); %% zeta_spb0.050; +para(22) = 0.9900; para_mask(22) = 1; para_fix(22) = para(22); %% gammstar + +npara = 22; %number of parameters + +%% exogenous processes - level + +para(npara+1) = 0.3673; %para_mask(npara+1) = 1; para_fix(npara+1) = para(npara+1); %% gam; +para(npara+2) = -45.9364; %para_mask(npara+2) = 1; para_fix(npara+2) = para(npara+2); %% Lmean; + +npara = npara+2; + +% exogenous processes - autocorrelation + +para(npara+1) = 0.9863; %para_mask(npara+1) = 1; para_fix(npara+1) = para(npara+1); %% rho_g +para(npara+2) = 0.9410; %para_mask(npara+2) = 1; para_fix(npara+2) = para(npara+2); %% rho_b; +para(npara+3) = 0.8735; %para_mask(npara+3) = 1; para_fix(npara+3) = para(npara+3); %% rho_mu +para(npara+4) = 0.9446; %para_mask(npara+4) = 1; para_fix(npara+4) = para(npara+4); %% rho_z; +para(npara+5) = 0.8827; %para_mask(npara+5) = 1; para_fix(npara+5) = para(npara+5); %% rho_laf; +para(npara+6) = 0.3884; %para_mask(npara+6) = 1; para_fix(npara+6) = para(npara+6); %% rho_law; +para(npara+7) = 0.2135; %para_mask(npara+7) = 1; para_fix(npara+7) = para(npara+7); %% rho_rm; +para(npara+8) = 0.9898; %para_mask(npara+8) = 1; para_fix(npara+8) = para(npara+8); %% rho_sigw +para(npara+9) = 0.7500; para_mask(npara+9) = 1; para_fix(npara+9) = para(npara+9); %% rho_mue +para(npara+10) = 0.7500; para_mask(npara+10) = 1; para_fix(npara+10) = para(npara+10); %% rho_gamm +para(npara+11) = 0.9900; para_mask(npara+11) = 1; para_fix(npara+11) = para(npara+11); %% rho_pist; +para(npara+12) = 0.6936; %para_mask(npara+12) = 1; para_fix(npara+12) = para(npara+12); %% rho_lr; +para(npara+13) = 0.8910; %para_mask(npara+13) = 1; para_fix(npara+13) = para(npara+13); %% rho_zp; +para(npara+14) = 0.1953; %para_mask(npara+14) = 1; para_fix(npara+14) = para(npara+14); %% rho_tfp; +if subspec == 94 + para(npara+15) = 0.0000; para_mask(npara+15) = 1; para_fix(npara+15) = para(npara+15); %% rho_gdpdef; + para(npara+16) = 0.0000; para_mask(npara+16) = 1; para_fix(npara+16) = para(npara+16); %% rho_pce; +else + para(npara+15) = 0.5379; %para_mask(npara+15) = 1; para_fix(npara+15) = para(npara+15); %% rho_gdpdef; + para(npara+16) = 0.2320; %para_mask(npara+16) = 1; para_fix(npara+16) = para(npara+16); %% rho_pce; +end + +npara = npara+16; + +%% exogenous processes - standard deviation +para(npara+1) = 2.5230; %para_mask(npara+1) = 1; para_fix(npara+1) = para(npara+1); %% sig_g; +para(npara+2) = 0.0292; %para_mask(npara+2) = 1; para_fix(npara+2) = para(npara+2); %% sig_b; +para(npara+3) = 0.4559; %para_mask(npara+3) = 1; para_fix(npara+3) = para(npara+3); %% sig_mu; +para(npara+4) = 0.6742; %para_mask(npara+4) = 1; para_fix(npara+4) = para(npara+4); %% sig_z; +para(npara+5) = 0.1314; %para_mask(npara+5) = 1; para_fix(npara+5) = para(npara+5); %% sig_laf; +para(npara+6) = 0.3864; %para_mask(npara+6) = 1; para_fix(npara+6) = para(npara+6); %% sig_law; +para(npara+7) = 0.2380; %para_mask(npara+7) = 1; para_fix(npara+7) = para(npara+7); %% sig_rm; +para(npara+8) = 0.0428; %para_mask(npara+8) = 1; para_fix(npara+8) = para(npara+8); %% sig_sigw +para(npara+9) = 0 ; para_mask(npara+9) = 1; para_fix(npara+9) = para(npara+9); %% sig_mue +para(npara+10) = 0 ; para_mask(npara+10) = 1; para_fix(npara+10) = para(npara+10); %% sig_gamm +para(npara+11) = 0.0269; %para_mask(npara+11) = 1; para_fix(npara+11) = para(npara+11); %% sig_pist; +para(npara+12) = 0.1766; %para_mask(npara+12) = 1; para_fix(npara+12) = para(npara+12); %% sig_lr; +para(npara+13) = 0.1662; %para_mask(npara+13) = 1; para_fix(npara+13) = para(npara+13); %% sig_zp; +if subspec == 9 + para(npara+14) = 0.8000; para_mask(npara+14) = 1; para_fix(npara+14) = para(npara+14); %% sig_tfp; +elseif any(subspec == [2 90 93 94]) + para(npara+14) = 0.9391; %para_mask(npara+14) = 1; para_fix(npara+14) = para(npara+14); %% sig_tfp; +else + error('Not implemented.'); +end +para(npara+15) = 0.1575; %para_mask(npara+15) = 1; para_fix(npara+15) = para(npara+15); %% sig_gdpdef; +para(npara+16) = 0.0999; %para_mask(npara+16) = 1; para_fix(npara+16) = para(npara+16); %% sig_pce; + +npara = npara+16; + + +% Standard Deviations of the anticipated policy shocks +for i = 1:nantpad + eval(strcat('para(npara +',num2str(i),') = 0.20;')); + if i >=13 + eval(strcat('para_mask(npara +',num2str(i),') = 1;')); + eval(strcat('para_fix(npara +',num2str(i),') = 0;')); + end +end +npara = npara+nantpad; + +para(npara+1) = 0.8400; %para_mask(npara+12) = 1; para_fix(npara+12) = para(npara+12); %% eta_gz; +para(npara+2) = 0.7892; %para_mask(npara+13) = 1; para_fix(npara+13) = para(npara+13); %% eta_laf; +para(npara+3) = 0.4226; %para_mask(npara+14) = 1; para_fix(npara+14) = para(npara+14); %% eta_law; +npara = npara+3; + +if subspec == 9 + para(npara+1) = 1.0000; para_mask(npara+1) = 1; para_fix(npara+1) = para(npara+1); %% modelalp_ind, datasets 712; +elseif any(subspec == [2 90 93 94]) + para(npara+1) = 0.0000; para_mask(npara+1) = 1; para_fix(npara+1) = para(npara+1); %% modelalp_ind datasets 714; +else + error('Not implemented.'); +end +para(npara+2) = 1.0354; %para_mask(npara+3) = 3; para_fix(npara+3) = para(npara+3); %% gamm_gdpdef +para(npara+3) = 0.0181; %para_mask(npara+4) = 4; para_fix(npara+4) = para(npara+4); %% del_gdpdef +npara = npara+3; + +para = para(1:npara); +para_mask = para_mask(1:npara); +para_fix = para_fix(1:npara); + +%% initialize parameters at fixed value or 0 + +para = para.*(1-para_mask)+para_fix.*para_mask; + +%% identify policy and non policy parameters - I don't think we use these + +polipar = 16; +polivalue = 2; + +%% bounds for MH + +bounds = zeros(100,2); + +bounds(1,:) = [1E-5 .999]; %% alp; 1 +bounds(2,:) = [1E-5 .999]; %% zeta_p; 2 +bounds(3,:) = [1E-5 .999]; %% iota_p; 3 +bounds(4,:) = [0 10]; %% ups; 5 +bounds(5,:) = [1 10]; %% Bigphi; 6 +bounds(6,:) = [-15 15]; %% s2; 7 +bounds(7,:) = [1E-5 .999]; %% h; 8 +bounds(8,:) = [1E-5 .999]; %% ppsi; 9 +bounds(9,:) = [1E-5 10]; %% nu_l 10 +bounds(10,:) = [1E-5 .999]; %% zeta_w; 11 +bounds(11,:) = [1E-5 .999]; %% iota_w; 12 +bounds(12,:) = [1E-5 10]; %% bet; 14 +bounds(13,:) = [1E-5 10]; %% psi1; 15 +bounds(14,:) = [-.5 .5]; %% psi2; 16 +bounds(15,:) = [-.5 .5]; %% psi3; 17 +bounds(16,:) = [1E-5 10]; %% pistar; 18 +bounds(17,:) = [1E-5 10]; %% sigmac; 19 +bounds(18,:) = [1E-5 .999]; %% rho; 19 + +bounds(19,:) = [1E-5 .99999]; %% Fom +bounds(20,:) = [0 100]; %% st st spread +bounds(21,:) = [1E-5 .99999]; %% zeta_sp +bounds(22,:) = [1E-5 .99999]; %% gammstar + +npara = 22; + +%% exogenous processes - level + +bounds(npara+1,:) = [-5 5]; %% gam; 22 +bounds(npara+2,:) = [-1000 1000]; %% Lstar; 23 + +npara = npara+2; + +%% exogenous processes - autocorrelation + +bounds(npara+1,:) = [1E-5 .999]; %% rho_g; +bounds(npara+2,:) = [1E-5 .999]; %% rho_b; +bounds(npara+3,:) = [1E-5 .999]; %% rho_mu; +bounds(npara+4,:) = [1E-5 .999]; %% rho_z; +bounds(npara+5,:) = [1E-5 .999]; %% rho_laf; +bounds(npara+6,:) = [1E-5 .999]; %% rho_law; +bounds(npara+7,:) = [1E-5 .999]; %% rho_rm; + +bounds(npara+8,:) = [1E-5 .99999]; %% rho_sigw +bounds(npara+9,:) = [1E-5 .99999]; %% rho_mue +bounds(npara+10,:)= [1E-5 .99999]; %% rho_gamm + +bounds(npara+11,:) = [1E-5 .999]; %% rho_pist; +bounds(npara+12,:) = [1E-5 .999]; %% rho_lr; + +bounds(npara+13,:) = [1E-5 .999]; %% rho_zp; +bounds(npara+14,:) = [1E-5 .999]; %% rho_tfp; +bounds(npara+15,:) = [1E-5 .999]; %% rho_gdpdef; +bounds(npara+16,:) = [1E-5 .999]; %% rho_pce; +npara = npara+16; + +%% exogenous processes - standard deviation + +bounds(npara+1,:) = [1E-8 5]; %% sig_g (sig_zP if mspec == 8); +bounds(npara+2,:) = [1E-8 5]; %% sig_b; +bounds(npara+3,:) = [1E-8 5]; %% sig_mu; +bounds(npara+4,:) = [1E-8 5]; %% sig_z; +bounds(npara+5,:) = [1E-8 5]; %% sig_laf; +bounds(npara+6,:) = [1E-8 5]; %% sig_law; +bounds(npara+7,:) = [1E-8 5]; %% sig_rm; + +bounds(npara+8,:) = [1E-7 100]; %% sig_sigw +bounds(npara+9,:) = [1E-7 100]; %% sig_mue +bounds(npara+10,:) = [1E-7 100]; %% sig_gamm + +bounds(npara+11,:) = [1E-8 5]; %% sig_pist; +bounds(npara+12,:) = [1E-8 10]; %% sig_lr; + +bounds(npara+13,:) = [1E-8 5]; %% sig_z; +bounds(npara+14,:) = [1E-8 5]; %% sig_tfp; +bounds(npara+15,:) = [1E-8 5]; %% sig_gdpdef; +bounds(npara+16,:) = [1E-8 5]; %% sig_pce; +npara = npara+16; + + +%% Standard Deviations of the Anticipated Shocks +for i = 1:nantpad + eval(strcat('bounds(npara +',num2str(i),',:) = [1E-7 100];')); +end +npara = npara+nantpad; + +bounds(npara+1,:) = [1E-5 .999]; %% eta_gz; +bounds(npara+2,:) = [1E-5 .999]; %% eta_laf; +bounds(npara+3,:) = [1E-5 .999]; %% eta_law; +npara = npara+3; + +bounds(npara+1,:) = [0.000 1.00]; %% modelalp_ind; +bounds(npara+2,:) = [-10 10]; %% gamm_gdpdef +bounds(npara+3,:) = [-9.1 9.1]; %% del_gdpdef + +npara = npara+3; + + +bounds = bounds(1:npara,:); + + + + + + + + + + + + + + diff --git a/initialization/priors990.m b/initialization/priors990.m new file mode 100644 index 0000000..a3a133c --- /dev/null +++ b/initialization/priors990.m @@ -0,0 +1,107 @@ +% Define Prior parameters +% pshape is 1: BETA(mean,stdd) +% 2: GAMMA(mean,stdd) +% 3: NORMAL(mean,stdd) +% 4: INVGAMMA(s^2,nu) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% loose lambda_f prior %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function prior = pri990 + +prior = zeros(100,3); +nantpad = 20; + +prior(1,:) = [.30 .05 3]; %% alp - beta -changed +prior(2,:) = [.5 .1 1]; %% zeta_p - beta -changed +prior(3,:) = [.5 .15 1]; %% iota_p - betaa +prior(4,:) = [1 .5 2]; %% ups - gamma +prior(5,:) = [1.25 .12 3]; %% Bigphi - gamma +prior(6,:) = [4 1.5 3]; %% s2 - gamma +prior(7,:) = [.7 .1 1]; %% h - beta -changed +prior(8,:) = [.5 .15 1]; %% ppsi - gamma +prior(9,:) = [2 .75 3]; %% nu_l - gamma - new mean +prior(10,:) = [.5 .1 1]; %% zeta_w - beta -changed +prior(11,:) = [.5 .15 1]; %% iota_w - beta +prior(12,:) = [.25 .1 2]; %% bet - beta +prior(13,:) = [1.5 .25 3]; %% psi1 - gamma -changed +prior(14,:) = [.12 .05 3]; %% psi2 - gamma +prior(15,:) = [.12 .05 3]; %% psi3 - gamma +prior(16,:) = [.75 .4 2]; %% pistar - gamma +prior(17,:) = [1.5 0.37 3]; %% sigmac - normal +prior(18,:) = [.75 0.10 1]; %% rho + +prior(19,:) = [.03 .01 1]; %% Fom - beta +prior(20,:) = [2 .1 2]; %% st st spread - gamma +prior(21,:) = [.05 .005 1]; %% zeta_sp - beta +prior(22,:) = [.99 .002 1]; %% gammstar - beta + + +npara = 22; + +%% exogenous processes - level +prior(npara+1,:) = [.4 .1 3]; %% gam - normal +prior(npara+2,:) = [-45 5 3]; %% Lmean - normal +%prior(npara+3,:) = [0.71 1 3]; %% zconst - normal + +npara = npara+2; + +%% exogenous processes - autocorrelation -CHANGE TO STANDARD! +prior(npara+1,:) = [.5 .2 1]; %% rho_g - beta +prior(npara+2,:) = [.5 .2 1]; %% rho_b - beta +prior(npara+3,:) = [.5 .2 1]; %% rho_mu - beta +prior(npara+4,:) = [.5 .2 1]; %% rho_z - beta +prior(npara+5,:) = [.5 .2 1]; %% rho_laf - beta +prior(npara+6,:) = [.5 .2 1]; %% rho_law - beta +prior(npara+7,:) = [.5 .2 1]; %% rho_rm - beta + +prior(npara+8,:) = [.75 .15 1]; %% rho_sigw - beta +prior(npara+9,:) = [.75 .15 1]; %% rho_mue - beta +prior(npara+10,:) = [.75 .15 1]; %% rho_gamm - beta +prior(npara+11,:) = [.5 .2 1]; %% rho_pist - beta +prior(npara+12,:) = [.5 .2 1]; %% rho_lr - beta +prior(npara+13,:) = [.5 .2 1]; %% rho_zp - beta +prior(npara+14,:) = [.5 .2 1]; %% rho_tfp - beta +prior(npara+15,:) = [.5 .2 1]; %% rho_gdpdef - beta +prior(npara+16,:) = [.5 .2 1]; %% rho_pce - beta + +npara = npara+16; + +%% exogenous processes - standard deviation +prior(npara+1,:) = [0.10, 2.00, 4]; %% sig_g; +prior(npara+2,:) = [0.10, 2.00, 4]; %% sig_b; +prior(npara+3,:) = [0.10, 2.00, 4]; %% sig_mu; +prior(npara+4,:) = [0.10, 2.00, 4]; %% sig_z; +prior(npara+5,:) = [0.10, 2.00, 4]; %% sig_laf; +prior(npara+6,:) = [0.10, 2.00, 4]; %% sig_law; +prior(npara+7,:) = [0.10, 2.00, 4]; %% sig_rm; + +prior(npara+8,:) = [.20/4 4.00 4]; %% sig_sigw; +prior(npara+9,:) = [.20/4 4.00 4]; %% sig_mue; +prior(npara+10,:) = [.01 4.00 4]; %% sig_gamm; + +prior(npara+11,:) = [0.03, 6, 4]; %% sig_pist; +prior(npara+12,:) = [0.75, 2, 4]; %% sig_lr; + +prior(npara+13,:) = [0.10, 2.00, 4]; %% sig_zp; +prior(npara+14,:) = [0.10, 2.00, 4]; %% sig_tfp; +prior(npara+15,:) = [0.10, 2.00, 4]; %% sig_gdpdef; +prior(npara+16,:) = [0.10, 2.00, 4]; %% sig_pce; + +npara = npara+16; + +for i = 1:nantpad + eval(strcat('prior(npara +',num2str(i),',:) = [.2 4.00 4];')); +end +npara = npara+nantpad; + +prior(npara+1,:) = [0.50, 0.20, 1]; %% eta_gz; +prior(npara+2,:) = [0.50, 0.20, 1]; %% eta_laf; +prior(npara+3,:) = [0.50, 0.20, 1]; %% eta_law; + +npara = npara+3; + +prior(npara+1,:) = [0.50, 0.20, 1]; %% modelalp_ind; +prior(npara+2,:) = [1.00, 2, 3]; %% gamm_gdpdef; +prior(npara+3,:) = [0.00, 2, 3]; %% del_gdpdef; +npara = npara+3; + +prior = prior(1:npara,:); diff --git a/initialization/spec.m b/initialization/spec.m new file mode 100644 index 0000000..65ba9fe --- /dev/null +++ b/initialization/spec.m @@ -0,0 +1,314 @@ +% filename: spec.m -- updated with 2010:Q2 data specifications +% description: + +%% Main model specifications and important flags +iter = 1; + +if ~exist('CH','var'), CH = 1; end +if ~exist('reoptimize','var'), reoptimize = 1; end + +%% Number of observations used in VAR +precrisis = 0; + + +%% Set Number of Anticipated Shocks + +% zerobound is a flag for using anticipated shocks to fix interest rate +% expectations near zero. nant is the number of periods that the interest rate +% should be fixed near zero. + +if mspec==557 + nant_implied=4; +elseif mspec==990 + nant_implied = 6; +end + +if zerobound + % antlags contains a value for the number of periods back we should start + % incorporating zero bound expectations. ZLB expectations should begin + % 2008Q4 + if ~exist('antlags','var'), antlags = 24; end + + % nant contains the number of periods forward that expectations are fixed + % to zero. + if ~exist('nant','var'), nant = nant_implied; end +else + nant = 0; + antlags = 0; +end + +%% Set an interest rate lower bound of 0.25 +%The monetary policy shock adjusts to preserve the bound. +bdd_int_rate = 0; + +%% Forecast: general options + +if ~exist('qahead','var'),qahead = 60; end + +%% Forecast: implied observables + +history = 0; % plot history (1:stime+qhead) + +% alternative specifications: these specs pertain to the model that you +% load actual data for comparison + +%% Forecast: conditional data +peachdesclist{1} = 'Unconditional'; +peachdesclist{2} = 'Central Scenario'; +peachdesclist{3} = 'Cond. FFR & Spread'; +peachdesc = char(peachdesclist(peachflag+1)); + +peachstr = {'';'_peach';'_semicond'}; +peachfile=('conddata'); + +if peachflag + load(peachfile); + psize = size(data,1); + clear data; +else + psize = 0; +end + +%% Parallel Processing + +% For alternative parallel programs using vcSubmitQueuedJobs +if ~exist('nMaxWorkers','var'),nMaxWorkers = 20; end +if ~exist('distr','var'); distr = 0; end; +if ~exist('parflag','var'), parflag = 1; end + +%% Disturbance Smoothing + +%% Turn Shocks off: Forecast distribution then reflects only param uncertainty +if ~exist('sflag','var'), sflag = 0; end % sflag = 1: Turn all shocks off in the forecast + +%% Plotting: general specifications (forplot.m and plot_all.m) +if ~exist('useSavedMB','var'), useSavedMB = 0; end +% if useSavedMB = 0, forplot recalculates and resaves means and bands +% if useSavedMB = 1, forplot loads in means and bands saved from a previous run +% means and bands are saved to a file called fcastMeans*.mat. + +% when creating this .mat file for the first time, make sure plotList is +% complete so that means and bands are calculated for all figures + +if ~exist('fancharts','var'), fancharts = 1; end + +% try to get rid of this section +if ~exist('plotSeparate','var'), plotSeparate = 0; end % 1 = each observable is graphed in a separate PDF rather than as part of a 2x2 subplot + +plotSeparate_fcast = 1; % 1 = each observable is graphed in a separate PDF rather than as part of a 2x2 subplot +plotSeparate_counter = 0; % 1 = each observable is graphed in a separate PDF rather than as part of a 2x2 subplot +plotSeparate_shockdec = 0; +plotSeparate_irf = 0; % 1 = each observable is graphed in a separate PDF rather than as part of a 2x2 subplot +plotSeparate_shocks = 1; % 1 = each observable is graphed in a separate PDF rather than as part of a 2x2 subplot +plotSeparate_vdec = 1; + +%% Plotting: shockdec settings (forplot.m and plot_all.m) +shockdec_history = 0; + +%% Plotting: counterfactual settings (forplot.m and plot_all.m) +if ~exist('Counterforecast','var'), Counterforecast = 2; end +if ~exist('Shockremove','var'), Shockremove = 1; end + + +if ~exist('ShockremoveList','var'), + switch mspec + case {557}, ShockremoveList = [0:10]; + case {990}, ShockremoveList = [0:16]; + otherwise, error('Set ShockremoveList variable'); + end +end + +if ~exist('stime','var') + if precrisis==0, + if mspec== 557 + stime = 122; + elseif mspec==990 + stime = 220; + end + end +end + +Enddate_forecastfile = stime+qahead; + +%% Plotting: presentation options (forplot.m) +% Note: specifications for make_presentation.m are now in pres_spec.m +if ~exist('plotList','var') + plotList = {'Forecast'; + 'Shock Decomposition'; + 'Counterfactual by Variable'; + 'Counterfactual by Shock'; + 'Shock'; + 'ShockAnt'}; + %'Q4Q4 Table'; +end + +%% Plotting: +percent = 0.68; % Percent for the bands + +if ~exist('fourq_flag','var'), fourq_flag = 0; end + + +%% mspec_add +% try to incorporate graphing variables into forplot, group with other graphing variables +[nvar,varnames,graph_title,cum_for,popadj,varnames_YL,varnames_irfs,varnames_YL_4Q,varnames_YL_irfs,... + names_shocks,names_shocks_title,nl_shocks_title,shocksnames,cum_irf,vardec_varnames,shockcats,list,shockdec_color] = mspec_add(mspec,dataset,zerobound,nant,fourq_flag); + + +cum_for_4q = cum_for; +cum_for_4q(4) = 4; + + +q_adj=100; + + +% To plot 99 percent bands +if ~exist('onepctflag','var'), onepctflag = 0; end +if onepctflag + onepctstr = '1pct'; +else + onepctstr = ''; +end + +%% Set end date for data (loaddata.m, forplot.m, plot_all.m) +if ~exist('dates','var') + if precrisis==0, dates = 2014.75; end % for the post-crisis estimate + if precrisis==1, dates = 2007.25; end % for the pre-crisis estimate +end + +if ~exist('mnobss','var'), mnobss = (dates - 2007)*4; end % use for graphs starting in 2007Q1 +pnobss=psize; +plot_forward = 13; + +future = plot_forward+4-round(1+4*(dates-floor(dates))); + +if exist('shockdec_history','var') && shockdec_history==1 + Startdate = 1; +else + Startdate= stime - mnobss; +end + +if Counterforecast==0 + Enddate = stime + pnobss; +elseif Counterforecast==1 + Enddate = stime + qahead; +elseif Counterforecast==2 % Enddate gets set in forplot_dick % Moving it back to spec to avoid duplication of vars in make_pres + Enddate =stime + future; +end + +counter_ahead = (Enddate_forecastfile - Startdate); + +%% Set start and end dates for X-axis +% sirf different for each type of figure +% sirf needs to be created here so that means and bands have correct pre-allocated size +% remove sirf from figspecs +sirf = (Startdate:stime+future); % Startdate and future are set in spec +sirf_shockdec = (Startdate:Enddate); +sirf_counter = (Startdate:Enddate); +sirf_shock_1 = (Startdate:stime); % further modified in plotNL + +%% IRF Settings (irfsim.m, irfplot.m) +% redo_irfsims similar to useSavedMB for parforecast. +% 1 = re-calculate IRFs using draws from gibb +% 0 = re-caculate means and bands using existing IRFs +if ~exist('redo_irfsims','var'), redo_irfsims = 1; end +if ~exist('nirf','var'), nirf = 40; end +nplotstates = 18; +if ~exist('irfStates','var'), irfStates = 0; end +fix = -0.5; % Calculate a bp policy shock. If fix is negative, then this calculates an expansionary policy shock. + +%% Moments options (mom.m) +paragroupseq = ['']; +if ~exist('PLOTDRAWS','var'), PLOTDRAWS = 0; end +%paragroupseq = ['' 'l' 'g']; % to see moments for only those parameters +% for which the inflation forecast 20 quarters out is +% greater than 4 (g) or less than 3 (l) + +%% Configure the Metropolis Algorithm (number of simulations) (gibb.m, parforecast.m, forplot.m) +if ~exist('nblocks','var'), nblocks = 11; end +if ~exist('nsim','var'), nsim = 10000; end +if ~exist('nburn','var'), nburn = nsim; end % initial simulations to 'burn' +if ~exist('jstep','var'), jstep = 5; end % decreasing jstep to make forecasts and bands smoother +ntimes = 5; + +%% mspec_parameters; mspec_parameters_'mspec'(subspec,dataset); +eval(['[para,para_names,para_mask,para_fix,npara,polipar,polivalue,bounds] = mspec_parameters_',num2str(mspec),'(',num2str(subspec),',',num2str(dataset),');']); + +%% Name string variables: Can be used in saving +lmodel = ['m',num2str(mspec),num2str(subspec)]; +lprior = [num2str(mprior),num2str(pf_mod)]; +ds = num2str(10*dataset); +if sflag==0; + ssf=''; +else + ssf=num2str(sflag); +end + +if isempty(stime), + st = ''; +else + st = num2str(stime); +end +if mspec == 1, st = num2str([]); end; + +if zerobound + antstr = ['ZB_' num2str(nant) '_L' num2str(antlags)]; + antstrold = ['ZB_' num2str(nant+1) '_L' num2str(antlags-1)]; +else + antstr = ''; + antstrold = ''; +end + +if parflag, parstr = 'par'; else parstr = ''; end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% INFREQUENTLY CHANGED VARIABLES %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Specific to Euro, we don't understand + +coint = 0; +cointadd = 0; +cointall = coint + cointadd; + +%% choose policy option +Policy_Sel = []; + +%% use prior (= 1) or posterior (= 0) +if ~exist('PRIO','var') + PRIO = 0; +end +%% Flag - exclude monetary policy shocks from loss computation +NoMon = 1; + +%% Flag - allow for mispecification in the estimated policy rule (backward) +MPol = []; +if MPol + MPol_ = 'Mpol'; +else + MPol_ = ''; +end + +%% change deep parameters, otherwise set Ideep = [] +Ideep = [];%[9 .6]; + +%% number of lags +if mspec==557 + nlags = 0; +elseif mspec == 990 + nlags = 2; +else + error('nlags needs to be defined for specified mspec.'); +end + +%% End of Presample +%T0 = nlags; %%0 +T0 = 0; % Set this to nlags unless you want no presample - then do 0. +Tend = 0; % End of Estimation Sample + +%% note: max number of inderminancies across all draws/policy parameter combinations. +%% if actual > maxind for some draws/policy parameter combination , programs won't work +%% if storage space is not concern, just set maxind high (say 5 or so) +IND = 1; +maxind = 3; + + diff --git a/initialization/states990.m b/initialization/states990.m new file mode 100644 index 0000000..f83aecd --- /dev/null +++ b/initialization/states990.m @@ -0,0 +1,129 @@ +%% Endogenous variables +y_t = 1; +c_t = 2; +i_t = 3; +qk_t = 4; +k_t = 5; +kbar_t = 6; +u_t = 7; +rk_t = 8; +Rktil_t = 9; +n_t = 10; +mc_t = 11; +pi_t = 12; +muw_t = 13;%exo +w_t = 14; +L_t = 15; +R_t = 16; +g_t = 17;%exo +b_t = 18;%exo +mu_t = 19;%exo +z_t = 20;%exo %%%z_t +laf_t = 21;%exo +laf_t1 = 22;%exo +law_t = 23;%exo +law_t1 = 24;%exo +rm_t = 25;%exo +sigw_t = 26;%exo - FF +mue_t = 27;%exo - FF +gamm_t = 28;%exo - FF +pist_t = 29;%exo - pistart_t +E_c = 30;%exp +E_qk = 31;%exp +E_i = 32;%exp +E_pi = 33;%exp +E_L = 34;%exp +E_rk = 35;%exp +E_w = 36;%exp +E_Rktil = 37;%exp - FF +y_f_t = 38; +c_f_t = 39; +i_f_t = 40; +qk_f_t = 41; +k_f_t = 42; +kbar_f_t = 43; +u_f_t = 44; +rk_f_t = 45; +w_f_t = 46; +L_f_t = 47; +r_f_t = 48; +E_c_f = 49;%exp +E_qk_f = 50;%exp +E_i_f = 51;%exp +E_L_f = 52;%exp +E_rk_f = 53;%exp4 +ztil_t = 54; +pi_t1 = 55; +pi_t2 = 56; +pi_a_t = 57; +R_t1 = 58; +zp_t = 59; +E_z = 60; + +nstates=60; + + +%/* shock indices */ EXOGENOUS +g_sh = 1; +b_sh = 2; +mu_sh = 3; +z_sh = 4; +laf_sh = 5; +law_sh = 6; +rm_sh = 7; +sigw_sh = 8;% - FF +mue_sh = 9;% - FF +gamm_sh = 10;% - FF +pist_sh = 11;% +lr_sh = 12; % Measurement error on the long rate + +zp_sh = 13; +tfp_sh = 14; +gdpdef_sh = 15; +pce_sh = 16; + +nex=16; + +%/* expectation errors */ +Ec_sh = 1; +Eqk_sh = 2; +Ei_sh = 3; +Epi_sh = 4; +EL_sh = 5; +Erk_sh = 6; +Ew_sh = 7; +ERktil_sh = 8; +Ec_f_sh = 9; +Eqk_f_sh = 10; +Ei_f_sh = 11; +EL_f_sh = 12; +Erk_f_sh = 13; + + +n_exp=13; +n_exo=13;%12 +n_end=nstates-n_exp-n_exo; +nend=n_exp; + +if exist('nant','var') + if nant > 0 + + % These are the anticipated shocks. For each there is both an innovation + % (for new anticipated shocks, calculated in period T only), + % and a process, so that the shocks can be passed from period to + % period. + + for i = 1:nant + eval(strcat('rm_shl',num2str(i),' = ',num2str(nex + i),';')); + eval(strcat('rm_tl',num2str(i),' = ',num2str(nstates+i),';')); + end + + n_exo = n_exo + nant; + nex = nex + nant; + nstates=nstates+nant; + + end + + +end + diff --git a/initialization/transp990.m b/initialization/transp990.m new file mode 100644 index 0000000..45a3d57 --- /dev/null +++ b/initialization/transp990.m @@ -0,0 +1,110 @@ +%% Transformations: +%% format: [type, a, b, c] +%% Type 1: +%% x is [a,b] -> [-1,1] -> [-inf,inf] by (1/c)*c*z/sqrt(1-c*z^2) +%% Type 2: +%% x is [0,inf] -> [-inf,inf] by b + (1/c)*ln(para[i]-a); + +function trspec = transp990(mspec) + + trspec = zeros(100,4); + nantpad = 20; + + + trspec(1,:) = [1 1E-5 .999 1]; %% alp; + trspec(2,:) = [1 1E-5 0.999 1]; %% zeta_p; + trspec(3,:) = [1 1E-5 .999 1]; %% iota_p; + trspec(4,:) = [2 1E-5 0 1]; %% ups; + trspec(5,:) = [2 1.00 10.00 1]; %% Bigphi; + trspec(6,:) = [0 -15.0 15.0 1]; %% s2; + trspec(7,:) = [1 1E-5 .999 1]; %% h; + trspec(8,:) = [1 1E-5 .999 1]; %% ppsi; + trspec(9,:) = [2 1E-5 10 1]; %% nu_l; + trspec(10,:) = [1 1E-5 0.999 1]; %% zeta_w; + trspec(11,:) = [1 1E-5 .999 1]; %% iota_w; + trspec(12,:) = [2 1E-5 10 1]; %% bet; + trspec(13,:) = [2 1E-5 10.00 1]; %% psi1; + trspec(14,:) = [0 -0.5 0.5 1]; %% psi2; + trspec(15,:) = [0 -0.5 0.5 1]; %% psi3; + trspec(16,:) = [2 1E-5 10 1]; %% pistar; + trspec(17,:) = [2 1E-5 10 1]; %% sigmac; + trspec(18,:) = [1 1E-5 .999 1]; %% rho; + + trspec(19,:) = [1 1E-5 .99 1]; %% F(omega) + trspec(20,:) = [2 1E-5 0 1]; %% st st spread + trspec(21,:) = [1 1E-5 .99 1]; %% zeta_sp + trspec(22,:) = [1 1E-5 .99 1]; %% gammst + + + npara = 22; + + %% exogenous processes - level + trspec(npara+1,:) = [0 -5.0 5.0 1]; %% gam; + trspec(npara+2,:) = [0 -1000 1000 1]; %% Lmean; + + npara = npara+2; + + %% exogenous processes - autocorrelation + trspec(npara+1,:) = [1 1E-5 .999 1]; %% rho_g; + trspec(npara+2,:) = [1 1E-5 .999 1]; %% rho_b; + trspec(npara+3,:) = [1 1E-5 .999 1]; %% rho_mu; + trspec(npara+4,:) = [1 1E-5 .999 1]; %% rho_z; + trspec(npara+5,:) = [1 1E-5 .999 1]; %% rho_laf; + trspec(npara+6,:) = [1 1E-5 .999 1]; %% rho_law; + trspec(npara+7,:) = [1 1E-5 .999 1]; %% rho_rm; + trspec(npara+8,:) = [1 1E-5 .99 1]; %% rho_sigw; + trspec(npara+9,:) = [1 1E-5 .99 1]; %% rho_mue; + trspec(npara+10,:) = [1 1E-5 .99 1]; %% rho_gamm; + trspec(npara+11,:) = [1 1E-5 .999 1]; %% rho_pist; + trspec(npara+12,:) = [1 1E-5 .999 1]; %% rho_lr; + + trspec(npara+13,:) = [1 1E-5 .999 1]; %% rho_zp; + trspec(npara+14,:) = [1 1E-5 .999 1]; %% rho_tfp; + trspec(npara+15,:) = [1 1E-5 .999 1]; %% rho_gdpdef; + trspec(npara+16,:) = [1 1E-5 .999 1]; %% rho_pce; + + npara = npara+16; + + %% exogenous processes - standard deviation + trspec(npara+1,:) = [2 1E-8 5 1]; %% sig_g; + trspec(npara+2,:) = [2 1E-8 5 1]; %% sig_b; + trspec(npara+3,:) = [2 1E-8 5 1]; %% sig_mu; + trspec(npara+4,:) = [2 1E-8 5 1]; %% sig_z; + trspec(npara+5,:) = [2 1E-8 5 1]; %% sig_laf; + trspec(npara+6,:) = [2 1E-8 5 1]; %% sig_law; + trspec(npara+7,:) = [2 1E-8 5 1]; %% sig_rm; + trspec(npara+8,:) = [2 1E-5 0 1]; %% sig_sigw; + trspec(npara+9,:) = [2 1E-5 0 1]; %% sig_mue; + trspec(npara+10,:) = [2 1E-5 0 1]; %% sig_gamm; + trspec(npara+11,:) = [2 1E-8 5 1]; %% sig_pist; + trspec(npara+12,:) = [2 1E-8 5 1]; %% sig_lr; + + trspec(npara+13,:) = [2 1E-8 5 1]; %% sig_zp; + trspec(npara+14,:) = [2 1E-8 5 1]; %% sig_tfp; + + trspec(npara+15,:) = [2 1E-8 5 1]; %% sig_gdpdef; + trspec(npara+16,:) = [2 1E-8 5 1]; %% sig_pce; + npara = npara+16; + + %% Standard Deviation of the Anticipated Shocks + for i = 1:nantpad + eval(strcat('trspec(npara +',num2str(i),',:) = [2 1E-5 0 1];')); + end + npara = npara+nantpad; + + trspec(npara+1,:) = [1 1E-5 0.999 1]; %% eta_gz; + trspec(npara+2,:) = [1 1E-5 0.999 1]; %% eta_laf; + trspec(npara+3,:) = [1 1E-5 0.999 1]; %% eta_law; + npara = npara+3; + + trspec(npara+1,:) = [0 0 0 0]; %% modelalp_ind; + trspec(npara+2,:) = [0 -10 -10 1]; %% gamm_gdpdef; + trspec(npara+3,:) = [0 -10 -10 1]; %% del_gdpdef; + + npara = npara+3; + + + trspec = trspec(1:npara,:); + + + diff --git a/kalman/augmentFilter.m b/kalman/augmentFilter.m new file mode 100644 index 0000000..a8aef12 --- /dev/null +++ b/kalman/augmentFilter.m @@ -0,0 +1,118 @@ +% OVERVIEW +% augmentFilter.m augments the output matrices in order to +% accomodate additional states for anticipated shocks: +% +% The state transition equation is: S_t = TTT*S_t-1+RRR*eps_t +% The measurement equation is: Y_t = ZZ*S_t+DD +% +% INPUTS +% r_tl1: For new, augmented state vector, this is the index of the first ant policy state +% r_tlx: For old, passed-in state vector, this is used as an index to indentify ant policy states +% nant: number of anticipated shocks +% antlags: number of past periods in which the zerobound was in effect +% ind_r: variable indexing the FFR among all observable variables +% zend: end-of-sample smoothed state from the model without anticipated +% shocks +% pend: end-of-sample smoothed states covariance matrix from +% the model without anticipated shocks +% YY: matrix of observable data +% +% OUTPUTS +% zprev: vector of filtered states +% pprev: matrix of filtered state covariances +% MM_ant +% EE_ant: variance of expectational error +% ZZ_e: nant period ahead measurement equation matrix (maps +% states into observables. +% DD_e: nant period ahead steady state vector. +% YY_ant: data matrix that includes nant periods of zerobound +% (0.25) FFR +% + +function [zprev,pprev,MM_ant,EE_ant,ZZ_e,DD_e,YY_ant] = augmentFilter(r_tl1,r_tlx,nant,antlags,ind_r,zend,pend,MM,EE,ZZ,DD,YY,TTT,ExpFFR) + +nstate = size(TTT,1); % Number of new states in new, augmented state space + +up_to_ant_all = 1:(r_tlx-2); % Indices for all states up to (but not including) ant and (maybe, if 557) new monetary shock states +aftr_ant_prev = (r_tl1+nant):nstate; % State indices for everything after ant in the new zprev vector +aftr_ant_ends = (r_tlx-1):length(zend); % State indices for everything after ant in the old zend vector + + +% We have added states so the results from filtering using +% the old model now have the wrong dimension, so create new +% predicted states (zprev) and state covariance matrices (pprev) +% that have zeros in the rows and columns corresponding to +% the new anticipated shock states. +zprev = zeros(nstate,1); +zprev(up_to_ant_all) = zend(up_to_ant_all,end); % All states up to (but not including) ant and (maybe) new ant shock states +zprev(aftr_ant_prev) = zend(aftr_ant_ends,end); + +pprev = zeros(size(TTT)); +pprev(up_to_ant_all, up_to_ant_all) = pend(up_to_ant_all, up_to_ant_all,end); +pprev(aftr_ant_prev, up_to_ant_all) = pend(aftr_ant_ends, up_to_ant_all,end); +pprev(up_to_ant_all, aftr_ant_prev) = pend(up_to_ant_all, aftr_ant_ends,end); +pprev(aftr_ant_prev, aftr_ant_prev) = pend(aftr_ant_ends, aftr_ant_ends,end); + +MM_ant = zeros(size(MM,1)+nant,size(MM,2)); +EE_ant = zeros(size(EE,1)+nant,size(EE,2)+nant); + +% Now create the augmented measurement equation. We need to create +% a transformation to go from model states to our new "observable" +% of the expected interest rate i periods ahead, where i ranges +% from 1 to nant, the number of periods we are fixing. + +% To find the expected interest rate i periods ahead given the +% model states, note that the expected states in i periods is just +% the current states vector with the TTT matrix applied i times). +% So to get the expected interest rate we just apply the "interest +% rate" row of the current ZZ matrix to the expected states vector, +% or equivalently to TTT^i applied to the current states vector. + +ZZ_e = zeros(size(ZZ,1) + nant,size(ZZ,2)); +ZZ_e(1:size(ZZ,1),:) = ZZ; + +for i = 1:nant +ZZ_e(size(ZZ,1) + i,:) = ZZ(ind_r,:)*(TTT^i); +end + +DD_e = [DD;repmat(DD(ind_r),nant,1)]; + +% Augmenting the data, assuming a path fixed at 0.25. +% Change to change the path to which interest rate +% expectations are fixed. + +% Add a catch so we can forecast +% It might be that ExpFFR is "too big" relative to antlags for a +% particular model. +% +% This could be because the ExpFFR_OIS.m file has been updated with a new +% quarter of data, but the rest of the quarterly data (GDP, PCE, etc.) +% has not. In this case, we'd want to chop off the bottom of the ExpFFR +% matrix. +% +% Or, it could be the case that we shorten antlags so that the ZB period +% starts one or more quarters later. In this case, we'd want to chop off +% the top of the ExpFFR matrix. +% +% Since chopping off the top or bottom of ExpFFR cannot be determined +% solely from antlags (or the discrepancy between the size of ExpFFR and +% the subset of YY we take based on antlags, we need to be more explicit +% about what we want to do. +% +% For that reason, we have "delay," which is the number of quarters AFTER +% 2008Q4 (the usual ZB start) in which we should start the ZB period. We NaN +% out the other periods before delay. You should also decrement antlags by 1. +% +% MDC 7/21/2014 + +% How many quarters to delay the ZB period; use this in concjunction with changing antlags +delay = 0; + +try + % YY_ant = [YY(end-antlags:end,:),repmat(0.25,antlags+1,nant)]; + YY_ant = [YY(end-antlags:end,:),[nan(delay,size(ExpFFR,2)); ExpFFR(1+delay:end,:)] ]; +catch + YY_ant = [YY(end-antlags:end,:),[nan(delay,size(ExpFFR,2)); ExpFFR(1+delay:antlags+1,:)] ]; +end + + diff --git a/kalman/augmentSmoother.m b/kalman/augmentSmoother.m new file mode 100644 index 0000000..6c1ebfe --- /dev/null +++ b/kalman/augmentSmoother.m @@ -0,0 +1,81 @@ +% OVERVIEW +% augmentSmoother.m augments output matrices to accomodate +% additional states for anticipated shocks. +% +% The state transition equation is: S_t = TTT*S_t-1+RRR*eps_t +% The measurement equation is: Y_t = ZZ*S_t+DD +% +% INPUTS +% r_tlx, r_tl1: +% nant: number of anticipated shocks +% antlags: number of past periods in which the zerobound was in effect +% A0,P0: initial state vector and state covariance matrix +% pred0,pred,pred_ant: filtered state vector over (1) presample, (2) main sample up to +% T-antlags-1, and (3) main sample from T-antlags:T +% vpred0,vpred,vpred_ant: filtered state covariance matrix over (1) presample, +% (2) main sample up to T-antlags-1, and (3) main sample from T-antlags:T +% YY0,YY,YY_ant: (1) pre-sample data (2) main sample data up to +% T-antlags-1, and (3) main sample data from T-antlags:T + +% OUTPUTS +% NOTE: *_all variables concatenate pre-sample and main sample including +% anticipated shocks period +% pred_all: time series of the state vector +% vpred_all: time series of the state covariance matrix +% YY_all: time series of observable data +% A0_,P0_: augmented initial state vector and state covariance matrix + +function [pred_all,vpred_all,YY_all,A0_,P0_] = augmentSmoother(nstate,r_tlx,r_tl1,nant,antlags,... + pred0,pred,pred_ant,... + vpred0,vpred,vpred_ant,... + YY0,YY,YY_ant,... + A0,P0) + + +pred_all = zeros(nstate,size(YY,1)+size(YY0,1)); + +if size(YY0,1) ~= 0 + pred_all(1:r_tlx-2,1:size(YY0,1)) = pred0(1:r_tlx-2,:); + pred_all(r_tl1+nant:end,1:size(YY0,1)) = pred0(r_tlx-1:end,:); +end +pred_all(1:r_tlx-2,size(YY0,1)+1:size(YY0,1)+size(YY,1)-antlags-1) = pred(1:r_tlx-2,:); +pred_all(r_tl1+nant:end,size(YY0,1)+1:size(YY0,1)+size(YY,1)-antlags-1) = pred(r_tlx-1:end,:); + +pred_all(:,size(YY0,1)+size(YY,1)-antlags:end) = pred_ant; + +vpred_all = zeros(nstate,nstate,size(YY,1)+size(YY0,1)); +if size(YY0,1) ~= 0 % this is because 557 doesn't work with presample + vpred_all(1:r_tlx-2,1:r_tlx-2,1:size(YY0,1)) = vpred0(1:r_tlx-2,1:r_tlx-2,:); + vpred_all(r_tl1+nant:end,1:r_tlx-2,1:size(YY0,1)) = vpred0(r_tlx-1:end,1:r_tlx-2,:); + vpred_all(1:r_tlx-2,r_tl1+nant:end,1:size(YY0,1)) = vpred0(1:r_tlx-2,r_tlx-1:end,:); + vpred_all(r_tl1+nant:end,r_tl1+nant:end,1:size(YY0,1)) = vpred0(r_tlx-1:end,r_tlx-1:end,:); +end +vpred_all(1:r_tlx-2,1:r_tlx-2,size(YY0,1)+1:size(YY0,1)+size(YY,1)-antlags-1) = vpred(1:r_tlx-2,1:r_tlx-2,:); +vpred_all(r_tl1+nant:end,1:r_tlx-2,size(YY0,1)+1:size(YY0,1)+size(YY,1)-antlags-1) = vpred(r_tlx-1:end,1:r_tlx-2,:); +vpred_all(1:r_tlx-2,r_tl1+nant:end,size(YY0,1)+1:size(YY0,1)+size(YY,1)-antlags-1) = vpred(1:r_tlx-2,r_tlx-1:end,:); +vpred_all(r_tl1+nant:end,r_tl1+nant:end,size(YY0,1)+1:size(YY0,1)+size(YY,1)-antlags-1) = vpred(r_tlx-1:end,r_tlx-1:end,:); + +vpred_all(:,:,size(YY,1)+size(YY0,1)-antlags:end) = vpred_ant; + +% The data also needs to be concatated, with NaNs in +% the expectation terms for all periods prior to the +% model switch. + +YY_all = NaN(size(YY,1)+size(YY0,1),size(YY_ant,2)); + +YY_all(1:size(YY0,1),1:size(YY0,2)) = YY0; +YY_all(size(YY0,1)+1:size(YY0,1)+size(YY,1)-antlags-1,1:size(YY,2)) = YY(1:end-antlags-1,:); +YY_all(end-antlags:end,:) = YY_ant; + +% The starting expectation and covariance also need to +% be augmented (with zeros). + +A0_ = zeros(nstate,1); +A0_(1:r_tlx-2) = A0(1:r_tlx-2); +A0_(r_tl1+nant:end) = A0(r_tlx-1:end); + +P0_ = zeros(nstate); +P0_(1:r_tlx-2,1:r_tlx-2) = P0(1:r_tlx-2,1:r_tlx-2); +P0_(1:r_tlx-2,r_tl1+nant:end) = P0(1:r_tlx-2,r_tlx-1:end); +P0_(r_tl1+nant:end,1:r_tlx-2) = P0(r_tlx-1:end,1:r_tlx-2); +P0_(r_tl1+nant:end,r_tl1+nant:end) = P0(r_tlx-1:end,r_tlx-1:end); \ No newline at end of file diff --git a/kalman/distsmth_k93.m b/kalman/distsmth_k93.m new file mode 100644 index 0000000..a399c62 --- /dev/null +++ b/kalman/distsmth_k93.m @@ -0,0 +1,121 @@ +function [r,varargout] = distsmth_k93(y,pred,vpred,T,R,Q,Z,b,peachcount,psize,nant,antlags) + +% DISTSMTH_K93.M + +% This is a Kalman Smoothing program based on S.J. Koopman's "Disturbance +% Smoother for State Space Models" (Biometrika, 1993), as specified in +% Durbin and Koopman's "A Simple and Efficient Simulation Smoother for +% State Space Time Series Analysis" (Biometrika, 2002). The algorithm has been +% simplified for the case in which there is no measurement error, and the +% model matrices do not vary with time. + +% This disturbance smoother is intended for use with the state smoother +% kalsmth_93.m from the same papers (Koopman 1993, Durbin and Koopman +% 2002). It produces a matrix of vectors, r, that is used for state +% smoothing, and an optional matrix, eta_hat, containing the smoothed +% shocks. It has been adjusted to account for the possibility of missing +% values in the data, and to accommodate the zero bound model, which +% requires that no anticipated shocks occur before the zero bound window, +% which is achieved by setting the entries in the Q matrix corresponding to +% the anticipated shocks to zero in those periods. + +% Nz will stand for the number of states, Ny for the number of observables, +% Ne for the number of shocks, and Nt for the number of periods of data. + +% The state space is assumed to take the form: +% y(t) = Z*alpha(t) + b +% alpha(t+1) = T*alpha(t) + R*eta(t+1) + +% INPUTS: + +% y, the (Ny x Nt) matrix of observable data. +% pred, the (Nz x Nt) matrix of one-step-ahead predicted states (from the Kalman Filter). +% vpred, the (Nz x Nz x Nt) matrix of one-step-ahead predicted covariance matrices. +% T, the (Nz x Nz) transition matrix. +% R, the (Nz x Ne) matrix translating shocks to states. +% Q, the (Ne x Ne) covariance matrix for the shocks. +% Z, the (Ny x Nz) measurement matrix. +% b, the (Ny x 1) constant vector in the measurement equation. + +% nant, an optional scalar for the zero bound specification indicating the +% number of periods ahead the interest rate is fixed. +% antlags, an optional scalar for the zero bound specification indicating +% the number of periods for which interest rate expectations have +% been fixed +% Ny0, an optional scalar indicating the number of periods of presample +% (i.e. the number of periods for which smoothed states are not +% required). + +% OUTPUTS: + +% r, the (Nz x Nt) matrix used for state smoothing. +% eta_hat, the optional (Ne x Nt) matrix of smoothed shocks. + +% Dan Greenwald, 7/7/2010. + +if nargin < 10, error('At least ten inputs required'); end +if nargin == 11, error('Zero or two optional inputs required'); end +if nargin > 12, error('At most twelve inputs allowed'); end + +Nt = size(y,2); +Nz = length(T); + +r = zeros(Nz,Nt); % holds r_T-1,...r_0 +r_t = zeros(Nz,1); + +if nargout > 1 + Ne = size(R,2); + eta_hat = zeros(Ne,Nt); +end + +for t = Nt:-1:1 + + y_t = y(:,t); + + % This section deals with the possibility of missing values in the y_t + % vector (especially relevant for smoothing over peachdata). + notnan = ~isnan(y_t); + y_t = y_t(notnan); + Z_t = Z(notnan,:); + b_t = b(notnan); + + a = pred(:,t); + P = vpred(:,:,t); + + F = Z_t*P*Z_t'; + v = y_t - Z_t*a - b_t; + K = T*P*Z_t'/F; + L = T - K*Z_t; + + r_t = Z_t'/F*v + L'*r_t; + r(:,t) = r_t; + + if nargout > 1 + + % This section relates to the zero bound framework, in which no + % anticipated shocks are supposed to occur before the model switch. + % In these periods, this is accomplished by setting the relevant + % rows and columns of the Q matrix to zero. In other periods, or in + % specifications with zero bound off (and hence with nant = 0), the + % normal Q matrix can be used. + +% if exist('nant','var') && exist('antlags','var') + if ~isempty(nant) && ~isempty(antlags) + % The first part of the conditional below pertains to the periods in which zerobound is off. + % To specify this period, we must account for (peachcount*psize) since peachdata is augmented to y. + % JC 11/30/10 + if nant > 0 && t < Nt-antlags-(peachcount*psize) + Q_t = zeros(Ne,Ne); + Q_t(1:Ne-nant,1:Ne-nant) = Q(1:Ne-nant,1:Ne-nant); + eta_hat(:,t) = Q_t*R'*r_t; + else + eta_hat(:,t) = Q*R'*r_t; + end + else + eta_hat(:,t) = Q*R'*r_t; + end + end + +end + +if nargout > 1, varargout(1) = {eta_hat}; end \ No newline at end of file diff --git a/kalman/kalcvf2NaN.m b/kalman/kalcvf2NaN.m new file mode 100644 index 0000000..2755b2f --- /dev/null +++ b/kalman/kalcvf2NaN.m @@ -0,0 +1,234 @@ +function [L,zend,Pend,varargout] = kalcvf2NaN(data, lead, a, F, b, H, var, varargin) +% This version of kalcvf2.m is supposed to deal w missing data, which MUST correspond to NaN in the 'data' matrix +% if an element of the vector y(t) is missing (NaN) for the observation t, the corresponding row is ditched from the +% measurement equation. +% +%KALCVF The Kalman filter +% +% State space model is defined as follows: +% z(t+1) = a+F*z(t)+eta(t) (state or transition equation) +% y(t) = b+H*z(t)+eps(t) (observation or measurement equation) +% +% [logl, >] = kalcvf(data, lead, a, F, b, H, var, ) +% computes the one-step prediction and the filtered estimate, as well as their covariance matrices. +% The function uses forward recursions, and you can also use it to obtain k-step estimates. +% +% The inputs to the KALCVF function are as follows: +% data is a [Ny x T] matrix containing data (y(1), ... , y(T)). +% lead is the number of steps to forecast after the end of the data. +% a is an [Nz x 1] vector for a time-invariant input vector in the transition equation. +% F is an [Nz x Nz] matrix for a time-invariant transition matrix in the transition equation. +% b is an [Ny x 1] vector for a time-invariant input vector in the measurement equation. +% H is an [Ny x Nz] matrix for a time-invariant measurement matrix in the measurement equation. +% var is an [Ny + Nz] x [Ny + Nz] matrix for a time-invariant variance matrix for +% the error in the transition equation and the error in the measurement equation, +% that is, [eta(t)', eps(t)']'. +% z0 is an optional [Nz x 1] initial state vector. +% vz0 is an optional [Nz x Nz] covariance matrix of an initial state vector. +% +% The KALCVF function returns the following output: +% logl is a value of the average log likelihood function of the SSM +% under assumption that observation noise eps(t) is normally distributed +% pred is an optional [Nz x (T+lead)] matrix containing one-step predicted state vectors. +% vpred is an optional [Nz x Nz x(T+lead)] matrix containing mean square errors of predicted state vectors. +% filt is an optional [Nz x T] matrix containing filtered state vectors. +% vfilt is an optional [Nz x Nz x T] matrix containing mean square errors of filtered state vectors. +% +% The initial state vector and its covariance matrix of the time invariant Kalman filters +% are computed under the stationarity condition: +% z0 = (I-F)\a +% vz0 = (I-kron(F,F))\(V(:),Nz,Nz) +% where F and V are the time invariant transition matrix and the covariance matrix of transition equation noise, +% and vec(V) is an [Nz^2 x 1] column vector that is constructed by the stacking Nz columns of matrix V. +% Note that all eigenvalues of the matrix F are inside the unit circle when the SSM is stationary. +% When the preceding formula cannot be applied, the initial state vector estimate is set to a +% and its covariance matrix is given by 1E6I. Optionally, you can specify initial values. +% +% This is a M-file for MATLAB. +% Copyright 2002-2003 Federal Reserve Bank of Atlanta +% $Revision: 1.2 $ $Date: 2003/03/19 19:16:17 $ +% Iskander Karibzhanov 5-28-02. +% Master of Science in Computational Finance +% Georgia Institute of Technology +%========================================================================== +% Revision history: +% +% 03/19/2003 - algorithm and interface were adapted from SAS/IML KALCVF subroutine for use in MATLAB M file +% +%========================================================================== + + T = size(data,2); + Nz = size(a,1); + Ny = size(b,1); + + nin = nargin; + if nin~=7 && nin~=9 + error('Seven or nine input arguments required.') + end + if nin==9 + z = varargin{1}; + P = varargin{2}; + end + nout = nargout; + %if nout~=1 && nout ~=3 && nout ~=5 + % error('One, three, or five output arguments required.') + %end + + % Check input matrix dimensions + if size(data,1)~=Ny + error('data and b must have the same number of rows') + end + if size(a,2)~=1 + error('a must be column vector') + end + if any(size(F)~=[Nz Nz]) + error('F must be square') + end + if size(b,2)~=1 + error('b must be column vector') + end + if any(size(H)~=[Ny Nz]) + error('H must be Ny by Nz matrix') + end + if any(size(var)~=[(Ny+Nz) (Ny+Nz)]) + error('var must be (Ny+Nz) by (Ny+Nz) matrix') + end + if nin==9 && any(size(z)~=[Nz 1]) + error('z0 must be column vector of length Nz') + end + if nin==9 && any(size(P)~=[Nz Nz]) + error('vz0 must be Nz by Nz matrix') + end + + % V(t) and R(t) are variances of eta(t) and eps(t), respectively, + % and G(t) is a covariance of eta(t) and eps(t) + % In dsgelh : + % --- V is same as QQ + % --- R is same as EE + % --- G is same as VV = QQ*MM + V = var(1:Nz,1:Nz); + R = var(Nz+1:end,Nz+1:end); + G = var(1:Nz,Nz+1:end); + + if nin==7 + e = eig(F); + if all(all(e*e'-eye(Nz))) + z = (eye(Nz)-F)\a; + P = reshape((eye(Nz^2)-kron(F,F))\V(:),Nz,Nz); + else + z = a; + P = eye(Nz)*1e6; + end + end + + if nout>1 + pred = zeros(Nz,T); + vpred = zeros(Nz,Nz,T); + + if nout>3 + yprederror = NaN*zeros(Ny,T); + ystdprederror = NaN*zeros(Ny,T); + end + if nout > 6 + filt = zeros(Nz,T); + vfilt = zeros(Nz,Nz,T); + end + + end + + + L = 0; + + for t=1:T + + % If an element of the vector y(t) is missing (NaN) for the observation t, the corresponding row is ditched from the + % measurement equation. + + notis_nan = ~isnan(data(:,t)); + + data_t = data(notis_nan,t); %--- data_t is matrix of observable data time-series (i.e. data_t = Y_{T} = [y1,y2,....yT]) + H_t = H(notis_nan,:); %--- H_t is matrix mapping states to observables (i.e. H_t = ZZ) + G_t = G(:,notis_nan); %--- G_t is Cov[eta_t, eps_t] + R_t = R(notis_nan,notis_nan); %--- R_t is Var[eps_t] + Ny_t = length(data_t); %--- Ny_t is length of time (i.e. T) + b_t = b(notis_nan); %--- b_t = DD + + %% forecasting + + z = a+F*z; %--- z_{t|t-1} = a + F(theta)*z{t-1|t-1} + + P = F*P*F'+V; %--- P_{t|t-1} = F(theta)*P_{t-1|t-1}*F(theta)' + F(theta)*Var(eta_t)*F(theta)' + + dy = data_t-H_t*z-b_t; %--- dy is your "prediction error" OR "innovation", + % dy = y_{t} - H(theta)*z_{t|t-1} - DD + + HG = H_t*G_t; %--- HG is ZZ*Cov[eta_t, eps_t] + D = H_t*P*H_t'+HG+HG'+R_t; %--- D = ZZ*P_{t+t-1}*ZZ' + HG + HG' + R_t + + D = .5*(D+D'); + + if nout > 0 + pred(:,t) = z; + vpred(:,:,t) = P; + if nout> 3 + + yprederror(notis_nan,t) = dy; + ystdprederror(notis_nan,t) = dy./sqrt(diag(D)); + end + end + +% if det(D) < 10^(-4) +% keyboard; +% end + + ddy = D\dy; + %--- We evaluate the log likelihood function by adding values of L + %--- at every iteration step (for each t = 1,2,...T) + L = L-.5*log(det(D))-.5*dy'*ddy-.5*Ny_t*log(2*pi); + + + %% updating + PHG = (P*H_t'+G_t); + z = z+PHG*ddy; % z_{t|t} = z_{t|t-1} + P_{t|t-1}*H(theta)' + ...... + P = P-PHG/D*PHG'; % P_{t|t} = P_{t|t-1} - PHG*(1/D)*PHG + + + if nout > 6 + PH = P*H_t'; + filt(:,t) = z; + vfilt(:,:,t) = P; + end + end + zend = z; + Pend = P; + + if lead>1 && nout>1 + for t=T+2:T+lead + z = F*z+a; + P = F*P*F'+V; + pred(:,t) = z; + vpred(:,:,t) = P; + end + + end + + if nout > 0 + varargout(1) = {pred}; + varargout(2) = {vpred}; + if nout>3 + + varargout(3) = {yprederror}; + varargout(4) = {ystdprederror}; + varargout(5) = {sqrt(mean((yprederror.^2)'))}; + varargout(6) = {sqrt(mean((ystdprederror.^2)'))}; + if nout > 6 + varargout(7) = {filt}; + end + if nout > 7 + varargout(8) = {vfilt}; + end + + end + end + + diff --git a/kalman/kalsmth_k93.m b/kalman/kalsmth_k93.m new file mode 100644 index 0000000..d538481 --- /dev/null +++ b/kalman/kalsmth_k93.m @@ -0,0 +1,109 @@ +function [alpha_hat,varargout] = kalsmth_k93(A0,P0,y,pred,vpred,T,R,Q,Z,b,nant,antlags,peachcount,psize,Ny0) + +% KALSMTH_K93.M + +% This is a Kalman Smoothing program based on S.J. Koopman's "Disturbance +% Smoother for State Space Models" (Biometrika, 1993), as specified in +% Durbin and Koopman's "A Simple and Efficient Simulation Smoother for +% State Space Time Series Analysis" (Biometrika, 2002). The algorithm has been +% simplified for the case in which there is no measurement error, and the +% model matrices do not vary with time. + +% Unlike other Kalman Smoothing programs, there is no need to invert +% singular matrices using the Moore-Penrose pseudoinverse (pinv), which +% should lead to efficiency gains and fewer inversion problems. Also, the +% states vector and the corresponding matrices do not need to be augmented +% to include the shock innovations. Instead they are saved automatically +% in the eta_hat matrix. + +% Nz will stand for the number of states, Ny for the number of observables, +% Ne for the number of shocks, and Nt for the number of periods of data. + +% The state space is assumed to take the form: +% y(t) = Z*alpha(t) + b +% alpha(t+1) = T*alpha(t) + R*eta(t+1) + +% INPUTS: + +% A0, the (Nz x 1) initial (time 0) states vector. +% P0, the (Nz x Nz) initial (time 0) state covariance matrix. +% y, the (Ny x Nt) matrix of observable data. +% pred, the (Nz x Nt) matrix of one-step-ahead predicted states (from the Kalman Filter). +% vpred, the (Nz x Nz x Nt) matrix of one-step-ahead predicted covariance matrices. +% T, the (Nz x Nz) transition matrix. +% R, the (Nz x Ne) matrix translating shocks to states. +% Q, the (Ne x Ne) covariance matrix for the shocks. +% Z, the (Ny x Nz) measurement matrix. +% b, the (Ny x 1) constant vector in the measurement equation. + +% nant, an optional scalar for the zero bound specification indicating the +% number of periods ahead the interest rate is fixed. +% antlags, an optional scalar for the zero bound specification indicating +% the number of periods for which interest rate expectations have +% been fixed +% Ny0, an optional scalar indicating the number of periods of presample +% (i.e. the number of periods for which smoothed states are not required). + +% OUTPUTS: + +% alpha_hat, the (Nz x Nt) matrix of smoothed states. +% eta_hat, the optional (Ne x Nt) matrix of smoothed shocks. + +% If Ny0 is nonzero, the alpha_hat and eta_hat matrices will be shorter by +% that number of columns (taken from the beginning). + +% Dan Greenwald, 7/7/2010. + +% if nargin < 12, error('At least twelve inputs required'); end +% if nargin == 13, error('Zero, two, or three optional inputs required'); end +% if nargin > 15, error('At most 15 inputs allowed'); end + +Ne = size(R,2); +Nt = size(y,2); +% Ny = size(y,1); +Nz = length(T); + +alpha_hat = zeros(Nz,Nt); + +if nargout > 1 + [r,eta_hat] = distsmth_k93(y,pred,vpred,T,R,Q,Z,b,peachcount,psize,nant,antlags); +else + r = distsmth_k93(y,pred,vpred,T,R,Q,Z,b,peachcount,psize); +end + +ah_t = A0 + P0*r(:,1); +alpha_hat(:,1) = ah_t; + +for t = 2:Nt + + % This section relates to the zero bound framework, in which no + % anticipated shocks are supposed to occur before the model switch. + % In these periods, this is accomplished by setting the relevant + % rows and columns of the Q matrix to zero. In other periods, or in + % specifications with zero bound off (and hence with nant = 0), the + % normal Q matrix can be used. + + if ~isempty(antlags) && ~isempty(nant); + % The first part of the conditional below pertains to the periods in which zerobound is off. + % To specify this period, we must account for (peachcount*psize) since peachdata is augmented to y. + % JC 11/30/10 + if nant > 0 && t < Nt-antlags-(peachcount*psize) + Q_t = zeros(Ne,Ne); + Q_t(1:Ne-nant,1:Ne-nant) = Q(1:Ne-nant,1:Ne-nant); + ah_t = T*ah_t + R*Q_t*R'*r(:,t); + else + ah_t = T*ah_t + R*Q*R'*r(:,t); + end + else + ah_t = T*ah_t + R*Q*R'*r(:,t); + end + + alpha_hat(:,t) = ah_t; +end + +if exist('Ny0','var') + alpha_hat = alpha_hat(:,Ny0+1:end); + if nargout > 1, eta_hat = eta_hat(:,Ny0+1:end); end +end + +if nargout > 1, varargout(1) = {eta_hat}; end \ No newline at end of file diff --git a/plotting/applyfigspecs.m b/plotting/applyfigspecs.m new file mode 100644 index 0000000..3620b84 --- /dev/null +++ b/plotting/applyfigspecs.m @@ -0,0 +1,66 @@ + +%% Figure Specifications + +% Adjust Yaxis +YL = ylabel(Yaxis.axislabel); +set(YL,'FontSize',Yaxis.axislabelsize); +if exist('Yaxis.lim') && ~isempty(Yaxis.lim) + set(gca,'YLim',Yaxis.lim); + set(gca,'YTick',(Yaxis.lim(1):Yaxis.freq:Yaxis.lim(2)),'FontSize',Yaxis.ticklabelsize); +end +% +% if ~isempty(Yaxis.lim) +% if exist('experiment_flag','var') && experiment_flag==1 && strcmp(plotList{plotnum},'Exp_Forecast') +% switch V_a +% case 1, Yaxis.lim = [-7 16]; +% case 2, Yaxis.lim = [-16 22]; +% case 5, Yaxis.lim = [0 7]; +% end +% end +% set(gca,'YLim',Yaxis.lim); +% set(gca,'YTick',(Yaxis.lim(1):Yaxis.freq:Yaxis.lim(2)),'FontSize',Yaxis.ticklabelsize); +% end + +% Adjust Xaxis +set(gca,'XLim',Xaxis.limits); +set(gca,'XTick',Xaxis.freq); +set(gca,'XTickLabel',Xaxis.ticklabels); + +% Secondary Yaxis - must be done after Xaxis, but before title to avoid +% resizing +h1 = gca; +h2 = axes('Position',get(gca,'Position')); +set(h2,'YAxisLocation','right','Color','none','XTick',[],'XTickLabel',[]); + +% if ~isempty(Yaxis.lim) +% set(h2,'YLim',Yaxis.lim); +% set(gca,'YTick',(Yaxis.lim(1):Yaxis.freq:Yaxis.lim(2)),'FontSize',Yaxis.ticklabelsize); +% end + +% These lines will align the size, ticks, and fontsize of the two axes. +h(1) = h1; +h(2) = h2; +linkprop(h,{'YLim','YTick','FontSize'}); +% for some reason, the YTicks don't synchronize, so this additional line is needed +% if graphs still don't look right, set the rest of the Yaxis properties after the line below +if exist('Yaxis.lim') && ~isempty(Yaxis.lim) + set(h,'YTick',(Yaxis.lim(1):Yaxis.freq:Yaxis.lim(2))); +end; + +% Title +if ~isequal(V_a,Vseq_alt) && ~noTitles + T = title(Title.name); + set(T,'FontSize',Title.size); +end + +% Misc +if any(strcmp(plotList{plotnum},{'Forecast','Forward Guidance','Forecast Semicond'})) + set(gca,'Layer','top'); +elseif any(strcmp(plotList{plotnum},{'Shock Decomposition'})) + set(gca,'YGrid','on') +elseif any(strcmp(plotList{plotnum},{'Counterfactual by Variable','Counterfactual by Shock'})) + grid on; +elseif any(strcmp(plotList,'Shock')) + grid off +end + diff --git a/plotting/figspecs.m b/plotting/figspecs.m new file mode 100644 index 0000000..c648dda --- /dev/null +++ b/plotting/figspecs.m @@ -0,0 +1,216 @@ +% figspecs.m will output specifications for each type of product and figure + +function [Xaxis,Yaxis,Title,line,lgnd,plotSeparate] = ... + figspecs(V_a,V_1,mspec,peachcount,plotType,... + varnames,varnames_YL,varnames_YL_4Q,Vseq,Vseq_alt,nobs,Idate,Startdate,Enddate,... + sirf,sirf_shockdec,sirf_counter,sirf_shock,datesall,dataset,zerobound,... + nvar,list,Counterforecast,shocksnames,names_shocks,pass,varargin) + +if pass % For counterfactuals, pass=1 only when figspecs is called the second time; for counterfactuals, figspecs requires S_a as well as V_a (shock and var loop) + S_a = varargin{1}; +end + +switch plotType + %% Forecast + case {'Forecast','Forecast Semicond', 'Forecast Comparison','4Q Forecast','Exp_Forecast','Forecast Comparison Separate','4Q Forecast Separate','Forward Guidance'} + plotSeparate = 0; + + Xaxis.limits = [min(sirf),max(sirf)]; + + if strcmp('4Q Forecast',plotType) + Yaxis.axislabel = varnames_YL_4Q(V_a); + else + Yaxis.axislabel = varnames_YL(V_a); + end + + if any(V_a==Vseq_alt) + Title.name = []; + Title.size = 13; + Xaxis.freq = sirf(1:8:end)'; + if ~strcmp(datesall(Xaxis.freq(1),end),'1') + disp('NOTE: Xaxis labels do not mark first quarter') + end + Xaxis.ticklabels = datesall(Xaxis.freq,1:4); + Xaxis.ticklabelsize = 14; + Yaxis.axislabelsize = 14; + Yaxis.ticklabelsize = 10; + else + Title.name = varnames(V_a); + Title.size = 11; + Xaxis.freq = sirf(1:8:end)'; + + if ~strcmp(datesall(Xaxis.freq(1),end),'1') + disp('NOTE: Xaxis labels do not mark first quarter') + end + Xaxis.ticklabels = datesall(Xaxis.freq,1:4); + Xaxis.ticklabelsize = 6; + + Title.size = 18; + Yaxis.axislabelsize = 16; + Yaxis.ticklabelsize = 12; + end + + lgnd = []; + + %% Shock Decomposition + case {'Shock Decomposition','Shock Decomposition-noDet'} + plotSeparate = 0; + Xaxis.limits = [min(sirf_shockdec),max(sirf_shockdec)]; + Xaxis.freq = sirf_shockdec(1:4:end); + Xaxis.ticklabels = datesall(Xaxis.freq,1:4); + + if V_a==3 + Yaxis.axislabel = 'Percent'; + else + Yaxis.axislabel = 'Percent Q-to-Q Annualized'; + end + + if any(V_a == Vseq_alt) + Yaxis.axislabelsize = 12; + Yaxis.ticklabelsize = 12; + else + Yaxis.axislabelsize = 11; + Yaxis.ticklabelsize = 11; + end + + if strcmp(plotType,'Shock Decomposition-noDet') + if V_1 == length(Vseq)-length(Vseq_alt) + lgnd.size = 11; + elseif V_1 == length(Vseq) + lgnd.size = 11; + else lgnd = []; + end + elseif strcmp(plotType,'Shock Decomposition') + if V_1 == length(Vseq)-length(Vseq_alt) + lgnd.size = 14; + elseif V_1 == length(Vseq) + lgnd.size = 14; + else + lgnd = []; + end + end + + Title.name = [varnames(V_a), '(deviations from mean)']; + Title.size = 11; + + + %% Counterfactuals + case {'Counterfactual by Shock', 'Counterfactual by Variable'} + plotSeparate = 0; + % Counterforecast=1 plots 60QAhead, Counterforecast=1 or 2 plots up to stime only + if Counterforecast==1,tick_counter=3; else tick_counter=1; end + + sirf_counter = (Startdate:Enddate); + + if strcmp(plotType, 'Counterfactual by Shock') + if pass + S_a = varargin{1}; + Yaxis.axislabel = varnames_YL(S_a); + Title.name = varnames(S_a); + end + else + if pass + S_a = varargin{1}; + Title.name = shocksnames(S_a); + end + Yaxis.axislabel = varnames_YL(V_a); + end + + Title.size = 10; + Xaxis.limits = [min(sirf_counter),max(sirf_counter)]; + Xaxis.freq = sirf_counter(1:4*tick_counter:end); + Yaxis.axislabelsize = 8; + Yaxis.ticklabelsize = 6; + % if plotSeparate_counter + if plotSeparate + Xaxis.ticklabels = datesall(Xaxis.freq,:); + else + Xaxis.ticklabels = datesall(Xaxis.freq,3:end); + end + lgnd=[]; + + %% Shock innovations + case {'Shock'} + plotSeparate = 1; + sirf_shock = (Startdate:Idate + logical(peachcount)); + + Title.name = [shocksnames(V_a)]; + Title.size = 10; + + Xaxis.limits = [min(sirf_shock),max(sirf_shock)]; + + Xaxis.freq = sirf_shock(1:4:end); + Yaxis.axislabel = 'Standard Deviations'; + Yaxis.axislabelsize = 8; + Yaxis.ticklabelsize = 6; + + % if plotSeparate_shocks + if plotSeparate + Xaxis.ticklabels = datesall(Xaxis.freq,1:4); + else + Xaxis.ticklabels = datesall(Xaxis.freq,3:end); + end + + lgnd=[]; + case {'ShockAnt'} + plotSeparate = 1; + sirf_shock = (Startdate:Idate + logical(peachcount)); + + Title.name = [shocksnames(V_a)]; + Title.size = 10; + + Xaxis.limits = [min(sirf_shock),max(sirf_shock)]; + + Xaxis.freq = sirf_shock(1:4:end); + Yaxis.axislabel = 'Percent'; + Yaxis.axislabelsize = 8; + Yaxis.ticklabelsize = 6; + + % if plotSeparate_shocks + if plotSeparate + Xaxis.ticklabels = datesall(Xaxis.freq,1:4); + else + Xaxis.ticklabels = datesall(Xaxis.freq,3:end); + end + + lgnd=[]; + + case {'Shock Squared','Htil','Eta Squared','Sigma'} + plotSeparate = 1; + sirf_shock_sq = 1:nobs; + + Title.name = [shocksnames(V_a)]; + Title.size = 10; + + Xaxis.limits = [min(sirf_shock_sq),max(sirf_shock_sq)]; + + Xaxis.freq = sirf_shock_sq(1:4:end); + Yaxis.axislabel = 'Standard Deviations'; + Yaxis.axislabelsize = 8; + Yaxis.ticklabelsize = 6; + + % if plotSeparate_shocks + if plotSeparate + Xaxis.ticklabels = datesall(Xaxis.freq,:); + else + Xaxis.ticklabels = datesall(Xaxis.freq,3:end); + end + + lgnd=[]; + +end + +line.width = 2.2; +switch plotType + case {'Forecast' 'Forward Guidance'} + plotSeparate = 1; + case 'Counterfactual by Shock' + plotSeparate = 0; + case 'Counterfactual by Variable' + plotSeparate = 0; + case {'Shock','ShockAnt'} + plotSeparate = 1; + case {'Shock Decomposition','Shock Decomposition-noDet'} + plotSeparate = 1; +end + diff --git a/plotting/forplot.m b/plotting/forplot.m new file mode 100644 index 0000000..4470176 --- /dev/null +++ b/plotting/forplot.m @@ -0,0 +1,786 @@ +% OVERVIEW (written Jan 23, 2014 by MDC, day this is put into use) +% forplot.m: Computes the means and bands for the states; prepares +% for plotting. +% IMPORTANT VARIABLES +% Means: a structure variable with fields for each type of plot. Each field +% holds the mean across draws. +% Bands: a structure variable with fields for each type of plot. Each field +% holds fanchart bands across draws. +% useSavedMB: a flag that allows us to use means and bands calculated and +% saved from a +% previous run of forplot. This option allows us to avoid +% re-loading in forecasts computed across draws, which is the most +% time-consuming aspect of forplot. +% plotList: a cell array containing the types of plots you want to +% produce. If not set, this will be set to a default by spec.m + + +clear infile* +close all; +keepVars; +initializePrograms; + + +% Set up 'number of' dimension to either nvar or nplotstates +% Set up the suffix that imports either the states or the observable forecast + + ndim = nvar; + + cum_for_plot = cum_for; + popadj_plot = popadj; + + +notzero = ShockremoveList > 0; +ShockremoveList = ShockremoveList(notzero); + +if zerobound + ShockremoveList = [ShockremoveList,(nshocks+1:nshocks+nant)]; + nshocks = nshocks+nant; +end + + +record = struct([]); + +%% Re-calculate means and bands +if ~useSavedMB + + %% Initialize means and bands + Means.forecast = zeros(ndim,qahead,peachflag+1); + Bands.forecast = zeros(2,ndim,qahead,peachflag+1); + + if onepctflag, Bands_onepct = zeros(2,ndim,qahead,peachflag+1); end + + if any(ismember(plotList,{'Counterfactual by Variable', 'Counterfactual by Shock'})) + Means.counter = zeros(ndim,counter_ahead,peachflag+1,length(ShockremoveList)); + Bands.counter = zeros(2,ndim,counter_ahead,peachflag+1,length(ShockremoveList)); + end + + if any(ismember(plotList,{'Shock Decomposition','Shock Decomposition-noDet'})) + Means.trend = zeros(ndim,counter_ahead); + Bands.trend = zeros(2,ndim,counter_ahead); + + Means.shockdec = zeros(ndim,counter_ahead,peachflag+1,length(ShockremoveList)); + Bands.shockdec = zeros(2,ndim,counter_ahead,peachflag+1,length(ShockremoveList)); + + Means.dettrend = zeros(ndim,counter_ahead,peachflag+1); + end + + if any(ismember(plotList,{'Shock'})) + Means.uncondshocks = zeros(nshocks,nobs); + Bands.uncondshocks = zeros(2,nshocks,nobs); + if peachflag + Means.condshocks = zeros(nshocks,nobs+psize); + Bands.condshocks = zeros(2,nshocks,nobs+psize); + end + end + + if any(ismember(plotList,{'ShockAnt'})) + Means.uncondshocks_ns = zeros(nshocks,nobs); + Bands.uncondshocks_ns = zeros(2,nshocks,nobs); + if peachflag + Means.condshocks_ns = zeros(nshocks,nobs+psize); + Bands.condshocks_ns = zeros(2,nshocks,nobs+psize); + end + end + + if any(ismember(plotList,{'4Q Forecast'})) + Means.forecast4q = zeros(size(Means.forecast)); + Bands.forecast4q = zeros(size(Bands.forecast)); + end + + if any(ismember(plotList,'Q4Q4 Table')) + Means.table4q = zeros(size(Means.forecast)); + Bands.table4q = zeros(size(Bands.forecast)); + + Means.tableq4q4 = zeros(ndim,3,peachflag+1); + Bands.tableq4q4 = zeros(2,ndim,3,peachflag+1); + end + + %% Open forecast files to read from + + if any(ismember(plotList,{'Forecast','4Q Forecast','Counterfactual by Variable','Counterfactual by Shock','Shock Decomposition','Shock Decomposition-noDet','Q4Q4 Table'})) + if zerobound + infile6 = [spath,'/forecast']; + infile16 = [spath,'/forecastbdd']; + if peachflag + infile1 = [spath,'/condforecast']; + infile11 = [spath,'/condforecastbdd']; + end + else + infile6 = [spath,'/forecast']; + if peachflag + infile1 = [spath,'/condforecast']; + end + end + end + + if any(ismember(plotList,{'Shock'})) + infile4 = [spath,'/datashocks']; + if peachflag + infile2 = [spath,'/peachshocks']; + infile3 = [spath,'/condshocks']; + end + end + + if any(ismember(plotList,{'ShockAnt'})) + infile45 = [spath,'/datashocks_ns']; + if peachflag + infile25 = [spath,'/peachshocks_ns']; + infile35 = [spath,'/condshocks_ns']; + end + end + + + if any(ismember(plotList,{'Counterfactual by Variable', 'Counterfactual by Shock'})) + for peachcount = 0:peachflag + for Shockremove = ShockremoveList + if peachcount + eval(['infile1' num2str(peachcount) num2str(Shockremove) ' = [spath,''/counter_peach'',' 'num2str(Shockremove)' '];']) + else + eval(['infile1' num2str(peachcount) num2str(Shockremove) ' = [spath,''/counter'',' 'num2str(Shockremove)' '];']) + end + end + end + end + + + if any(ismember(plotList,{'Shock Decomposition','Shock Decomposition-noDet'})) + infile200 = [spath,'/ytrend']; + for peachcount = 0:peachflag + for Shockremove = ShockremoveList + if peachflag + eval(['infile2' num2str(peachcount) num2str(Shockremove) ' = [spath,''/shockdec_peach'', ' 'num2str(Shockremove)' '];']); + else + eval(['infile2' num2str(peachcount) num2str(Shockremove) ' = [spath,''/shockdec'',' 'num2str(Shockremove)' '];']); + end + end + end + infile300 = [spath,'/dettrend']; + infile301 = [spath,'/dettrend_peach']; + infile301_semi = [spath,'/dettrend_semipeach']; + end + + + %% Specify num_* (number of bytes per file) and numb_*(number of bytes to discard) + + numb_for = nburn*(ndim)*qahead*4; + num_for = (nblocks*nsim*(ndim)*qahead*4-numb_for)/jstep; + + numb_counter = nburn*ndim*counter_ahead*4; + num_counter = (nblocks*nsim*ndim*counter_ahead*4-numb_counter)/jstep; + + numb_shockdec = nburn*ndim*(counter_ahead+1)*4; + num_shockdec = (nblocks*nsim*ndim*(counter_ahead+1)*4-numb_shockdec)/jstep; + + numb_trend = nburn*ndim*4; + num_trend = (nblocks*nsim*ndim*4 - numb_trend)/jstep; + + numb_forshocks = nburn*nshocks*psize*4; + num_forshocks = (nblocks*nsim*nshocks*psize*4-numb_forshocks)/jstep; + + numb_data = nburn*nshocks*nobs*4; + num_data = (nblocks*nsim*nshocks*nobs*4-numb_data)/jstep; + + numb_hist = nburn*(ndim)*stime*4; + num_hist = (nblocks*nsim*(ndim)*stime*4-numb_hist)/jstep; + + %% Open infiles to read + % infile should not be a variable name, if used for a purpose other than this + % fid should correspond exactly to infile, + % ie fid1=fopen(infile1,'r'), not fid01 = fopen(infile1,'r') + listInfiles = who('infile*'); + for nInfiles = 1:size(listInfiles) + fidNum = strrep(listInfiles{nInfiles},'infile',''); + eval(['fid',fidNum,'=fopen(infile',fidNum,',','''r'');']) + end + + %% Population adjustment + % We add Macroeconomic Advisers' population growth forecast to + % transform our forecasts from per-capita to aggregate. For forecast + % horizons beyond the scope of MA's forecasts, we use MA's furthest + % horizon forecast. + if any(popadj == 1) + if any(ismember(plotList,{'Forecast','4Q Forecast','Q4Q4 Table'})) + if qahead > size(dlMA_pop,1) + dlpop_fcst = [repmat(dlMA_pop',((nblocks-nburn/nsim)*nsim/jstep),1), repmat(dlMA_pop(end),((nblocks-nburn/nsim)*nsim)/jstep, qahead - size(dlMA_pop,1))]; + else + dlpop_fcst = repmat(dlMA_pop(1:qahead)',(nblocks*nsim)/jstep,1); + end + else + dlpop_fcst = []; + end + + if any(ismember(plotList,{'4Q Forecast','Q4Q4 Table','Counterfactual by Variable','Counterfactual by Shock','Shock Decomposition','Shock Decomposition-noDet'})) + if counter_ahead - mnobss > size(dlMA_pop,1) + dlpop_ctr = [repmat(dlMA_pop',((nblocks-nburn/nsim)*nsim/jstep),1), repmat(dlMA_pop(end),((nblocks-nburn/nsim)*nsim)/jstep,counter_ahead-mnobss-size(dlMA_pop,1))]; + else + dlpop_ctr = repmat(dlMA_pop(1:counter_ahead-mnobss)',(nblocks*nsim)/jstep,1); + end + dlpop_old = repmat(dlpop(end-mnobss+1:end)',((nblocks-nburn/nsim)*nsim/jstep),1); + else + dlpop_ctr = []; + end + else + dlpop_fcst=[]; + dlpop_old=[]; + dlpop_ctr = []; + end + + % Read in implied state histories if we're plotting states + + + %% Forecast + + % Read in data + if any(ismember(plotList,{'Forecast','4Q Forecast','Counterfactual by Variable','Counterfactual by Shock','Shock Decomposition','Shock Decomposition-noDet','Q4Q4 Table'})) + ypath = []; + while ( ftell(fid6) < num_for ) % Read blocks of size nsim + ypathadd = fread(fid6,[(ndim)*qahead,nsim/jstep],'single')'; + ypath = [ypath;ypathadd]; + ftell(fid6); + end; + clear ypathadd; + fclose(fid6); + + if zerobound == 1 + ypath_bdd = []; + while (ftell(fid16) < num_for) + ypathadd = fread(fid16,[(ndim)*qahead,nsim/jstep],'single')'; + ypath_bdd = [ypath_bdd;ypathadd]; + ftell(fid16); + end + clear ypathadd + fclose(fid16); + end + disp('Loaded Unconditional Forecast') + end + + if any(ismember(plotList,{'Forecast','4Q Forecast','Q4Q4 Table'})) && peachflag + ypath_cond = []; + while ( ftell(fid1) < num_for ) % Read blocks of size nsim + ypathadd = fread(fid1,[(ndim)*qahead,nsim/jstep],'single')'; + ypath_cond = [ypath_cond;ypathadd]; + ftell(fid1); + end; + clear ypathadd; + fclose(fid1); + + if zerobound == 1 + ypath_cond_bdd = []; + while (ftell(fid11) < num_for) + ypathadd = fread(fid11,[(ndim)*qahead,nsim/jstep],'single')'; + ypath_cond_bdd = [ypath_cond_bdd;ypathadd]; + ftell(fid11); + end + clear ypathadd + fclose(fid11); + end + disp('Loaded Conditional Forecast') + + end + + % Calculate means and bands + + if any(ismember(plotList,{'Forecast','4Q Forecast','Counterfactual by Variable','Counterfactual by Shock','Shock Decomposition','Shock Decomposition-noDet','Q4Q4 Table'})) + for peachcount = 0:peachflag + for Ivar = 1:ndim + + switch peachcount + case 1 + yp = getyp(ypath_cond,qahead,Ivar,cum_for_plot,popadj_plot,dlpop_fcst,YY,Idate,q_adj); + case 0 + yp = getyp(ypath,qahead,Ivar,cum_for_plot,popadj_plot,dlpop_fcst,YY,Idate,q_adj); + end + + if exist('medianFlag','var') && medianFlag==1 + Means.forecast(Ivar,:,peachcount+1) = median(yp,1); + else + Means.forecast(Ivar,:,peachcount+1) = mean(yp,1); + end + + + if fancharts + Bands.forecast([1 10],Ivar,:,peachcount+1) = hpdint(yp,0.90,0); + Bands.forecast([2 9],Ivar,:,peachcount+1) = hpdint(yp,0.80,0); + Bands.forecast([3 8],Ivar,:,peachcount+1) = hpdint(yp,0.70,0); + Bands.forecast([4 7],Ivar,:,peachcount+1) = hpdint(yp,0.60,0); + Bands.forecast([5 6],Ivar,:,peachcount+1) = hpdint(yp,0.50,0); + else + Bands.forecast(:,Ivar,:,peachcount+1) = hpdint(yp,percent,0); + end + + if onepctflag, Bands_onepct(:,Ivar,:,peachcount+1) = hpdint(yp,0.99,0); end + + end + + if zerobound + for Ivar = 1:ndim + switch peachcount + case 1 + yp = getyp(ypath_cond_bdd,qahead,Ivar,cum_for_plot,popadj_plot,dlpop_fcst,YY,Idate,q_adj); + case 0 + yp = getyp(ypath_bdd,qahead,Ivar,cum_for_plot,popadj_plot,dlpop_fcst,YY,Idate,q_adj); + + end + if fancharts + Bands.forecast([1 10],Ivar,:,peachcount+1) = hpdint(yp,0.90,0); + Bands.forecast([2 9],Ivar,:,peachcount+1) = hpdint(yp,0.80,0); + Bands.forecast([3 8],Ivar,:,peachcount+1) = hpdint(yp,0.70,0); + Bands.forecast([4 7],Ivar,:,peachcount+1) = hpdint(yp,0.60,0); + Bands.forecast([5 6],Ivar,:,peachcount+1) = hpdint(yp,0.50,0); + else + Bands.forecast(:,Ivar,:,peachcount+1) = hpdint(yp,percent,0); + end + end + + ind_r = find(strcmp(varnames,'Interest Rate')); + + Means_3d = zeros(1,1,size(Means.forecast,2)); + Means_3d(1,1,:) = Means.forecast(ind_r,:,peachcount+1); + + if fancharts + for i = 1:5 + Bands.forecast(i,ind_r,:,peachcount+1) = min(Bands.forecast(i,ind_r,:,peachcount+1),Means_3d(1,1,:)); + end + for i = 6:10 + Bands.forecast(i,ind_r,:,peachcount+1) = max(Bands.forecast(i,ind_r,:,peachcount+1),Means_3d(1,1,:)); + end + else + Bands.forecast(1,ind_r,:,peachcount+1) = min(Bands.forecast(1,ind_r,:,peachcount+1),Means_3d(1,1,:)); + Bands.forecast(2,ind_r,:,peachcount+1) = max(Bands.forecast(2,ind_r,:,peachcount+1),Means_3d(1,1,:)); + end + end + end + + Means.forecast = Means.forecast(1:ndim,:,:); + Bands.forecast = Bands.forecast(:,1:ndim,:,:); + + end + + %% Four Quarter Forecasts and Q4Q4 Table + + % Calculate means and bands + if any(ismember(plotList,{'4Q Forecast','Q4Q4 Table'})) + for peachcount = 0:peachflag + for Ivar = 1:ndim + switch peachcount + case 1 + yp_4q = getyp_4q(ypath_cond,qahead,Ivar,cum_for_4q,popadj,dlpop_fcst,YY,Idate,dlpop_old,q_adj); + case 0 + yp_4q = getyp_4q(ypath,qahead,Ivar,cum_for_4q,popadj,dlpop_fcst,YY,Idate,dlpop_old,q_adj); + end + + Means.forecast4q(Ivar,:,peachcount+1) = mean(yp_4q,1); + if fancharts + Bands.forecast4q([1 10],Ivar,:,peachcount+1) = hpdint(yp_4q,0.90,0); + Bands.forecast4q([2 9],Ivar,:,peachcount+1) = hpdint(yp_4q,0.80,0); + Bands.forecast4q([3 8],Ivar,:,peachcount+1) = hpdint(yp_4q,0.70,0); + Bands.forecast4q([4 7],Ivar,:,peachcount+1) = hpdint(yp_4q,0.60,0); + Bands.forecast4q([5 6],Ivar,:,peachcount+1) = hpdint(yp_4q,0.50,0); + else + Bands.forecast4q(:,Ivar,:,peachcount+1) = hpdint(yp_4q,percent,0); + end + end + + if zerobound + for Ivar = 1:ndim + switch peachcount + case 1 + yp_4q_bdd = getyp_4q(ypath_cond_bdd,qahead,Ivar,cum_for_4q,popadj_plot,dlpop_fcst,YY,Idate,dlpop_old,q_adj); + case 0 + yp_4q_bdd = getyp_4q(ypath_bdd,qahead,Ivar,cum_for_4q,popadj_plot,dlpop_fcst,YY,Idate,dlpop_old,q_adj); + end + if fancharts + Bands.forecast4q([1 10],Ivar,:,peachcount+1) = hpdint(yp_4q_bdd,0.90,0); + Bands.forecast4q([2 9],Ivar,:,peachcount+1) = hpdint(yp_4q_bdd,0.80,0); + Bands.forecast4q([3 8],Ivar,:,peachcount+1) = hpdint(yp_4q_bdd,0.70,0); + Bands.forecast4q([4 7],Ivar,:,peachcount+1) = hpdint(yp_4q_bdd,0.60,0); + Bands.forecast4q([5 6],Ivar,:,peachcount+1) = hpdint(yp_4q_bdd,0.50,0); + else + Bands.forecast4q(:,Ivar,:,peachcount+1) = hpdint(yp_4q_bdd,percent,0); + end + end + + ind_r = find(strcmp(varnames,'Interest Rate')); + + Means_3d_4q = zeros(1,1,size(Means.forecast4q,2)); + Means_3d_4q(1,1,:) = Means.forecast4q(ind_r,:,peachcount+1); + + if fancharts + for i = 1:5 + Bands.forecast4q(i,ind_r,:,peachcount+1) = min(Bands.forecast4q(i,ind_r,:,peachcount+1),Means_3d_4q(1,1,:)); + end + for i = 6:10 + Bands.forecast4q(i,ind_r,:,peachcount+1) = max(Bands.forecast4q(i,ind_r,:,peachcount+1),Means_3d_4q(1,1,:)); + end + else + Bands.forecast4q(1,ind_r,:,peachcount+1) = min(Bands.forecast4q(1,ind_r,:,peachcount+1),Means_3d_4q(1,1,:)); + Bands.forecast4q(2,ind_r,:,peachcount+1) = max(Bands.forecast4q(2,ind_r,:,peachcount+1),Means_3d_4q(1,1,:)); + end + + end + + if any(ismember(plotList,'Q4Q4 Table')) + for Ivar = 1:ndim + switch peachcount + case 1 + yp_4q = getyp_4q(ypath_cond,qahead,Ivar,cum_for_4q,popadj_plot,dlpop_fcst,YY,Idate,dlpop_old,q_adj); + case 0 + yp_4q = getyp_4q(ypath,qahead,Ivar,cum_for_4q,popadj_plot,dlpop_fcst,YY,Idate,dlpop_old,q_adj); + end + + Means.table4q(Ivar,:,peachcount+1) = mean(yp_4q,1); + Bands.table4q(:,Ivar,:,peachcount+1) = hpdint(yp_4q,percent,0); + + if zerobound + switch peachcount + case 1 + yp_4q_bdd = getyp_4q(ypath_cond_bdd,qahead,Ivar,cum_for_4q,popadj_plot,dlpop_fcst,YY,Idate,dlpop_old,q_adj); + case 0 + yp_4q_bdd = getyp_4q(ypath_bdd,qahead,Ivar,cum_for_4q,popadj_plot,dlpop_fcst,YY,Idate,dlpop_old,q_adj); + end + + Bands.table4q(:,Ivar,:,peachcount+1) = hpdint(yp_4q_bdd,percent,0); + % If we report the interest rate forecast in Q4Q4 tables, should we use the means and bands as adjusted above or unadjusted? + end + end + end + end + end + + %% Counterfactual + if any(ismember(plotList,{'Counterfactual by Variable','Counterfactual by Shock'})) + + for peachcount = 0:peachflag + shockcount = 0; + for Shockremove = ShockremoveList + + shockcount = shockcount + 1; + + % Read in data + eval(['fid_ctr = fid1' num2str(peachcount) num2str(Shockremove) ';']); + ypath_counter = loadcounter(fid_ctr,num_counter,ndim,counter_ahead,nsim,jstep); + + + eval(['fclose(fid1' num2str(peachcount) num2str(Shockremove) ');']); + + % Calculate means and bands + for Ivar = 1:ndim + yp_counter = getyp_counter(ypath_counter,counter_ahead,Ivar,cum_for_plot,popadj_plot,mnobss,dlpop_old,dlpop_ctr,repmat(YY(Startdate,:),size(ypath_counter,1),1),q_adj); + Means.counter(Ivar,:,peachcount+1,shockcount) = mean(yp_counter,1); + Bands.counter(:,Ivar,:,peachcount+1,shockcount) = hpdint(yp_counter,percent,0); + end + + disp(['Loaded Counterfactual ' num2str(Shockremove)]) + + end + + switch peachcount + case 0, disp('Loaded All Counterfactuals (Unconditional)') + case 1, disp('Loaded All Counterfactuals (Conditional)') + end + + end + clear ypath_counter yp_counter + end + + %% Shock Decomposition + if any(ismember(plotList,{'Shock Decomposition','Shock Decomposition-noDet'})) + + % Read in data + ytrend = []; + while(ftell(fid200) < num_trend) + ypathadd = fread(fid200,[ndim,nsim/jstep],'single')'; + ytrend = [ytrend;ypathadd]; + ftell(fid200); + end + clear ypathadd + fclose(fid200); + + + ypath_trend = zeros(size(ytrend,1),counter_ahead*ndim); + for Ivar = 1:ndim + ypath_trend(:,counter_ahead*(Ivar-1)+1:counter_ahead*Ivar) = repmat(ytrend(:,Ivar),1,counter_ahead); + end + + % Calculate means and bands + Means_trend_raw = mean(ypath_trend,1); + + for Ivar = 1:ndim + yp_trend = getyp_counter(ypath_trend,counter_ahead,Ivar,cum_for_plot,popadj_plot,mnobss,dlpop_old,dlpop_ctr,ytrend,q_adj); + if exist('medianFlag','var') && medianFlag==1 + Means.trend(Ivar,:) = median(yp_trend,1); + else + Means.trend(Ivar,:) = mean(yp_trend,1); + end + + Bands.trend(:,Ivar,:) = hpdint(yp_trend,percent,0); + end + + clear ypath_trend yp_trend ytrend + + % The lines below load the deterministic trend. + + ypath_dettrend_all = loadcounter(fid300,num_shockdec,ndim,counter_ahead+1,nsim,jstep); + % Explanation of the lines below: To turn log levels of + % hours into a growth rate you need to use the previous + % period's data. However, since the entire counterfactual + % path (from t = 1 on) is different from the data this will + % give you weird numbers. Instead you need to save and load + % the previous period's counterfactual observables and use + % those. This requires the manipulations below... + + yend = zeros(size(ypath_dettrend_all,1),ndim); + ypath_dettrend = zeros(size(ypath_dettrend_all,1),ndim*counter_ahead); + + for Ivar = 1:ndim + yend(:,Ivar) = ypath_dettrend_all(:,(Ivar-1)*(counter_ahead+1)+1); + ypath_dettrend(:,(Ivar-1)*counter_ahead+1:Ivar*counter_ahead) = ypath_dettrend_all(:,(Ivar-1)*(counter_ahead+1)+2:Ivar*(counter_ahead+1)); + end + + fclose(fid300); + + if counter_ahead - mnobss > size(dlMA_pop,1) + dlpop_ctr = [repmat(dlMA_pop',size(yend,1),1), repmat(dlMA_pop(end),size(yend,1),counter_ahead-mnobss-size(dlMA_pop,1))]; + else + dlpop_ctr = repmat(dlMA_pop(1:counter_ahead-mnobss)',size(yend,1),1); + end + dlpop_old = repmat(dlpop(end-mnobss+1:end)',(size(yend,1)),1); + + for Ivar = 1:ndim + yp_dettrend = getyp_counter(ypath_dettrend,counter_ahead,Ivar,cum_for_plot,popadj_plot,mnobss,dlpop_old,dlpop_ctr,yend,q_adj); + Means.dettrend(Ivar,:,1) = mean(yp_dettrend,1); + end + + % The lines below do the same for the determinisic trend smoothed + % with peachdata. + + Means_shockdec_raw = zeros(length(ShockremoveList+1),size(ypath_dettrend,2)); + Means_shockdec_raw(end,:) = mean(ypath_dettrend,1); + + if peachflag + ypath_dettrend_all = loadcounter(fid301,num_shockdec,ndim,counter_ahead+1,nsim,jstep); + yend = zeros(size(ypath_dettrend_all,1),ndim); + ypath_dettrend = zeros(size(ypath_dettrend_all,1),ndim*counter_ahead); + + for Ivar = 1:ndim + yend(:,Ivar) = ypath_dettrend_all(:,(Ivar-1)*(counter_ahead+1)+1); + ypath_dettrend(:,(Ivar-1)*counter_ahead+1:Ivar*counter_ahead) = ypath_dettrend_all(:,(Ivar-1)*(counter_ahead+1)+2:Ivar*(counter_ahead+1)); + end + + if counter_ahead - mnobss > size(dlMA_pop,1) + dlpop_ctr = [repmat(dlMA_pop',size(yend,1),1), repmat(dlMA_pop(end),size(yend,1),counter_ahead-mnobss-size(dlMA_pop,1))]; + else + dlpop_ctr = repmat(dlMA_pop(1:counter_ahead-mnobss)',size(yend,1),1); + end + dlpop_old = repmat(dlpop(end-mnobss+1:end)',(size(yend,1)),1); + + for Ivar = 1:ndim + yp_dettrend = getyp_counter(ypath_dettrend,counter_ahead,Ivar,cum_for_plot,popadj_plot,mnobss,dlpop_old,dlpop_ctr,yend,q_adj); + Means.dettrend(Ivar,:,2) = mean(yp_dettrend,1); + end + end + + clear ypath_dettrend_all ypath_dettrend yp_dettrend + + for peachcount = 0:peachflag + + shockcount = 0; + + for Shockremove = ShockremoveList + + shockcount = shockcount + 1; + + eval(['fid_ctr = fid2' num2str(peachcount) num2str(Shockremove) ';']); + ypath_shockdec_all = loadcounter(fid_ctr,num_shockdec,ndim,counter_ahead+1,nsim,jstep); + yend = zeros(size(ypath_shockdec_all,1),ndim); + ypath_shockdec = zeros(size(ypath_shockdec_all,1),ndim*counter_ahead); + + for Ivar = 1:ndim + yend(:,Ivar) = ypath_shockdec_all(:,(Ivar-1)*(counter_ahead+1)+1); + ypath_shockdec(:,(Ivar-1)*counter_ahead+1:Ivar*counter_ahead) = ypath_shockdec_all(:,(Ivar-1)*(counter_ahead+1)+2:Ivar*(counter_ahead+1)); + end + + Means_shockdec_raw(shockcount,:) = mean(ypath_shockdec,1); + + eval(['fclose(fid2' num2str(peachcount) num2str(Shockremove) ');']); + + if counter_ahead - mnobss > size(dlMA_pop,1) + dlpop_ctr = [repmat(dlMA_pop',size(yend,1),1), repmat(dlMA_pop(end),size(yend,1),counter_ahead-mnobss-size(dlMA_pop,1))]; + else + dlpop_ctr = repmat(dlMA_pop(1:counter_ahead-mnobss)',size(yend,1),1); + end + dlpop_old = repmat(dlpop(end-mnobss+1:end)',(size(yend,1)),1); + + for Ivar = 1:ndim + yp_shockdec = getyp_counter(ypath_shockdec,counter_ahead,Ivar,cum_for_plot,popadj_plot,mnobss,dlpop_old,dlpop_ctr,yend,q_adj); + + if exist('medianFlag','var') && medianFlag==1 + Means.shockdec(Ivar,:,peachcount+1,shockcount) = median(yp_shockdec,1); + else + Means.shockdec(Ivar,:,peachcount+1,shockcount) = mean(yp_shockdec,1); + end + + Bands.shockdec(:,Ivar,:,peachcount+1,shockcount) = hpdint(yp_shockdec,percent,0); + end + + disp(['Loaded Shock Decomposition ' num2str(Shockremove)]) + + end + + switch peachcount + case 0, disp('Loaded All Shock Decompositions (Unconditional)') + case 1, disp('Loaded All Shock Decompositions (Conditional)') + end + + end + + clear ypath_shockdec yp_shockdec ypath_shockdec_all yend + + end + + %% Shock + + if any(ismember(plotList,'Shock')) + + % Read in data + datashocks = []; + dickdatashocks = []; + semidickdatashocks = []; + while ( ftell(fid4) < num_data ) + datashocksadd = fread(fid4,[nshocks*nobs,nsim/jstep],'single')'; + datashocks = [datashocks;datashocksadd]; + + ftell(fid4); + + if peachflag + dickdatashocksadd = fread(fid3,[nshocks*nobs,nsim/jstep],'single')'; + dickdatashocks = [dickdatashocks;dickdatashocksadd]; + clear dickdatashocksadd; + ftell(fid3); + end + end + if peachflag + fclose(fid3); + end + fclose(fid4); + + if peachflag + dickspath = []; + while ( ftell(fid2) < num_forshocks ) + dickspathadd = fread(fid2,[nshocks*psize,nsim/jstep],'single')'; + dickspath = [dickspath;dickspathadd]; + ftell(fid2); + end; + fclose(fid2); + + end + + % Calculate means and bands + for peachcount = 0:peachflag + for III = 1:nshocks + switch peachcount + case 1 + dshockfor = dickspath(:,psize*(III-1)+1:psize*III); + means_dickshocks(III,:) = mean(dshockfor,1); + bands_dickshocks(:,III,:,:) = hpdint(dshockfor,percent,0); + + dshocksample = dickdatashocks(:,III:nshocks:end-mod(size(dickdatashocks,2),nshocks)); + means_dickdatashocks(III,:) = mean(dshocksample,1); + bands_dickdatashocks(:,III,:,:) = hpdint(dshocksample,percent,0); + case 0 + shocksample = datashocks(:,III:nshocks:end-mod(size(datashocks,2),nshocks)); + means_datashocks(III,:) = mean(shocksample,1); + bands_datashocks(:,III,:,:) = hpdint(shocksample,percent,0); + end + end + + switch peachcount, + case 1 + Means.condshocks = [means_dickdatashocks means_dickshocks]; + Bands.condshocks = cat(3,bands_dickdatashocks,bands_dickshocks); + case 0 + Means.uncondshocks = means_datashocks; + Bands.uncondshocks = bands_datashocks; + end + end + + end + if any(ismember(plotList,'ShockAnt')) + + % Read in data + datashocks_ns = []; + dickdatashocks_ns = []; + semidickdatashocks_ns = []; + while ( ftell(fid45) < num_data ) + datashocksadd_ns = fread(fid45,[nshocks*nobs,nsim/jstep],'single')'; + datashocks_ns = [datashocks_ns;datashocksadd_ns]; + + ftell(fid45); + + if peachflag + dickdatashocksadd_ns = fread(fid35,[nshocks*nobs,nsim/jstep],'single')'; + dickdatashocks_ns = [dickdatashocks_ns;dickdatashocksadd_ns]; + clear dickdatashocksadd_ns; + ftell(fid35); + end + end + if peachflag + fclose(fid35); + + end + fclose(fid45); + + if peachflag + dickspath_ns = []; + while ( ftell(fid25) < num_forshocks ) + dickspathadd_ns = fread(fid25,[nshocks*psize,nsim/jstep],'single')'; + dickspath_ns = [dickspath_ns;dickspathadd_ns]; + ftell(fid25); + end; + fclose(fid25); + + end + + % Calculate means and bands + for peachcount = 0:peachflag + for III = 1:nshocks + switch peachcount + case 1 + dshockfor_ns = dickspath_ns(:,psize*(III-1)+1:psize*III); + means_dickshocks_ns(III,:) = mean(dshockfor_ns,1); + bands_dickshocks_ns(:,III,:,:) = hpdint(dshockfor_ns,percent,0); + + dshocksample_ns = dickdatashocks_ns(:,III:nshocks:end-mod(size(dickdatashocks_ns,2),nshocks)); + means_dickdatashocks_ns(III,:) = mean(dshocksample_ns,1); + bands_dickdatashocks_ns(:,III,:,:) = hpdint(dshocksample_ns,percent,0); + case 0 + shocksample_ns = datashocks_ns(:,III:nshocks:end-mod(size(datashocks_ns,2),nshocks)); + means_datashocks_ns(III,:) = mean(shocksample_ns,1); + bands_datashocks_ns(:,III,:,:) = hpdint(shocksample_ns,percent,0); + end + end + + switch peachcount, + case 1 + Means.condshocks_ns = [means_dickdatashocks_ns means_dickshocks_ns]; + Bands.condshocks_ns = cat(3,bands_dickdatashocks_ns,bands_dickshocks_ns); + case 0 + Means.uncondshocks_ns = means_datashocks_ns; + Bands.uncondshocks_ns = bands_datashocks_ns; + end + end + + end + + % Save means and bands + if overwrite, save([spath,'/fcastMeans'],'Means','Bands'); end + +else + + load([spath,'/fcastMeans.mat'],'Means','Bands'); +end + +fprintf('Means and bands are saved in %s. \n', spath) + + diff --git a/plotting/getYs.m b/plotting/getYs.m new file mode 100644 index 0000000..5472b0a --- /dev/null +++ b/plotting/getYs.m @@ -0,0 +1,150 @@ +function Ys = getYs(YY_allvars,YY_p_allvars,dlpop,dlpop_p,cum_for,popadj,nvar,fourq_flag,q_adj,noadj,varargin) + +if nargin == 11 + pop_smth = varargin{1}; +end + +Ys = zeros(size(YY_allvars)); + +if noadj + YY = YY_allvars(:,I); + YY_p = YY_p_allvars(:,I); + + if cum_for(I) == 2 + YYold = [YY_p(end); YY(1:end-1)]; + Ys(:,I) = YY- YYold; + else + Ys(:,I) = YY; + end + +else + + % Commented out bc annoying AF + %if q_adj ~= 400, warning('q_adj is not 400'); end + + % May need to agument YY_p with nans so that the four quarter + % calculations go through + N_p = size(YY_p_allvars,1); + if fourq_flag && N_p < 4 + YY_p_allvars = [nan(4-N_p, size(YY_p_allvars,2)); YY_p_allvars]; + dlpop_p = [nan(4-N_p, size(dlpop_p,2)); dlpop_p]; + end + + + for I = 1:nvar + + YY = YY_allvars(:,I); + YY_p = YY_p_allvars(:,I); + + if cum_for(I) == 1 && popadj(I) == 0 + + if fourq_flag + % Transform from log growth rates to 4Q growth rates. + + YY1 = [YY_p(end); YY(1:end-1)]; + YY2 = [YY_p(end-1:end); YY(1:end-2)]; + YY3 = [YY_p(end-2:end); YY(1:end-3)]; + + Ys(:,I) = 100*(exp((YY + YY1+ YY2 + YY3)/q_adj) - 1); + + else + % Transform from log growth rates to quarterly annualized + % growth rates. + + Ys(:,I) = 100*(exp(YY/q_adj).^4 - 1); + + end + + elseif cum_for(I) == 1 && popadj(I) == 1 + + if fourq_flag + % Transform from log per capita growth rates to 4Q total + % growth rates. + + YYpop = YY/q_adj + dlpop; + YYpop1 = [YY_p(end); YY(1:end-1)]/q_adj + [dlpop_p(end); dlpop(1:end-1)]; + YYpop2 = [YY_p(end-1:end); YY(1:end-2)]/q_adj + [dlpop_p(end-1:end); dlpop(1:end-2)]; + YYpop3 = [YY_p(end-2:end); YY(1:end-3)]/q_adj + [dlpop_p(end-2:end); dlpop(1:end-3)]; + + Ys(:,I) = 100*(exp(YYpop + YYpop1 + YYpop2 + YYpop3) - 1); + + else + % Transform from log per capita growth rates to quarterly + % annualized total growth rates. + + Ys(:,I) = 100*((exp(YY/q_adj + dlpop)).^4-1); + + end + + elseif cum_for(I) == 2 && popadj(I) == 0 + + if fourq_flag + % Transform from log levels to 4Q growth rates. + + YYold = [YY_p(end-3:end); YY(1:end-4)]; + Ys(:,I) = 100*(exp(YY/100 - YYold/100) - 1); + + else + % Transform from log levels to quarterly annualized growth + % rates. + + YYold = [YY_p(end); YY(1:end-1)]; + Ys(:,I) = 100*((exp(YY/100 - YYold/100).^4) - 1); + + end + + elseif cum_for(I) == 2 && popadj(I) == 1 + + if fourq_flag + % Transform from log per capita levels to 4Q total growth + % rates. + + dlpop1 = [dlpop_p(end); dlpop(1:end-1)]; + dlpop2 = [dlpop_p(end-1:end); dlpop(1:end-2)]; + dlpop3 = [dlpop_p(end-2:end); dlpop(1:end-3)]; + + dlpop_4q = dlpop + dlpop1 + dlpop2 + dlpop3; + + YYold = [YY_p(end-3:end); YY(1:end-4)]; + + Ys(:,I) = 100*(exp(YY/100 - YYold/100 + dlpop_4q) - 1); + + else + % Transform from log per capita levels to quarterly annualized + % total growth rates. + + YYold = [YY_p(end); YY(1:end-1)]; + + Ys(:,I) = 100*(exp(YY/100 - YYold/100 + dlpop).^4 - 1); + + end + + elseif cum_for(I) == 3 + % Transform from log levels to levels + + Ys(:,I) = exp(YY/100); + + elseif cum_for(I) == 4 + %This is for unemployment + Ys(:,I)=(exp(YY/100)-1)*100; + elseif cum_for(I) == 5 + Ys(:,I) = YY*4; + elseif cum_for(I) ==6 && popadj(I) ==1 + Ys(:,I) = YY + dlpop*100; + elseif cum_for(I) ==6 && popadj(I) ==0 + Ys(:,I) = YY; + + elseif cum_for(I) == 7 + % Output is in log levels + Ys(:,I) = YY; + elseif cum_for(I) ==0 && popadj(I) ==1 + Ys(:,I) = YY + 100*log(pop_smth); + else + + Ys(:,I) = YY*400/q_adj; + + end + + end + +end \ No newline at end of file diff --git a/plotting/getyp.m b/plotting/getyp.m new file mode 100644 index 0000000..74e96af --- /dev/null +++ b/plotting/getyp.m @@ -0,0 +1,77 @@ +function yp = getyp(ypath,qahead,I,cum_for,popadj,dlpop_fcst,YY,Idate,q_adj,varargin) + +if nargin == 10 + pop_fcst = varargin{1}; +end + +yp = ypath(:,qahead*(I-1)+1:qahead*I); +if cum_for(I) == 1 && popadj(I) == 0 + % Transform from log growth rates to % growth rates (annualized) + + % This should only be used for output, consumption, investment + % and GDP deflator (inflation). If you have any doubt, please + % check the loaddata file. + %yp = 100*4*(exp(yp/100)-1); + + yp = 100*((exp(yp/q_adj)).^4-1); + +elseif cum_for(I) == 1 && popadj(I) == 1 + %transform from log growth rates to total (not per-capita) % growth + %rates (annualized). + % yp = 100*(exp(yp/100 + .01106) - 1); % population estimate + % yp = 100*(exp(yp/q_adj + dlMA_pop(end)).^4 - 1); % + % population estimate + + yp = 100*(exp(yp/q_adj + dlpop_fcst).^4 - 1); % population estimate + + %yp=1/400*yp; + %yp=exp(yp); + %yp=100*(yp-1); + %yp=yp.^4+1.106; + +elseif cum_for(I) ==2 && popadj(I) == 0 + % Transform from log level to 4-quarter annualized percent change + % The lines below specifically applies to labor supply (hours worked + % per capita). Refer to loaddata for the data transformation. + % Be careful of using this for any other observables. + % Some notes on what is happening in the line directly below: + % YY is necessary to get the last data point so that a percent + % change can be computed for the first period. Repmat is used + % to put the data point in each row of the simulations. The + % log levels are subtracted to get the log percent changes and + % then the exponential is used to remove the log from the + % levels. + yp = ((exp(yp(:,1:end)/100 - [repmat(YY(Idate,I), [size(yp,1) 1]) yp(:,1:end-1)]/100).^4)-1)*100; + +elseif cum_for(I) == 2 && popadj(I) == 1 + + yp = ((exp(yp(:,1:end)/100 - [repmat(YY(Idate,I), [size(yp,1) 1]) yp(:,1:end-1)]/100 + dlpop_fcst).^4)-1)*100; + +elseif cum_for(I)==3 + % Transform from log levels to level + % The lines below specifically applies to labor share + % Refer to loaddata for data transformation. + % Be careful of using this for any other observables. + yp = exp(yp/100); +elseif cum_for(I) == 4 + % This transforms log perecentage levels back to + % percentage levels. This is specifically for unemployment + % which enters the model as log-unemployment + yp=(exp(yp/100)-1)*100; +elseif cum_for(I) == 5 + yp = yp*4; + +elseif cum_for(I) ==6 && popadj(I) ==1 + yp = 100*(yp/q_adj + dlpop_fcst); +elseif cum_for(I) ==6 && popadj(I) ==0 + yp = 100*(yp/q_adj); + +elseif cum_for(I) == 7 + % Output is in Log-levels + yp = yp; + +elseif cum_for(I) ==0 && popadj(I) ==1 + yp = yp + 100*log(pop_fcst); +else + yp = yp*400/q_adj; +end; diff --git a/plotting/getyp_4q.m b/plotting/getyp_4q.m new file mode 100644 index 0000000..f5add90 --- /dev/null +++ b/plotting/getyp_4q.m @@ -0,0 +1,72 @@ +function yp = getyp_4q(ypath,qahead,I,cum_for,popadj,dlpop_fcst,YY,Idate,dlpop_old,q_adj) + +yp = ypath(:,qahead*(I-1)+1:qahead*I); +if cum_for(I) == 1 && popadj(I) == 0 + % Transform from log growth rates to 4-Quarter percent growth rates + % This should only be used for output, consumption, investment + % and GDP deflator (inflation). If you have any doubt, please + % check the loaddata file. + + % More data is needed for 4Q growth rates. + yp_all = [repmat(YY(end-2:end,I)',size(yp,1),1) yp]; + yp_4q = yp_all(:,end-qahead+1:end) + yp_all(:,end-qahead:end-1) + yp_all(:,end-qahead-1:end-2) + yp_all(:,end-qahead-2:end-3); + yp = 100*(exp(yp_4q/q_adj) - 1); + +elseif cum_for(I) == 1 && popadj(I) == 1 + %transform from log growth rates to total (not per-capita) % growth + %rates (annualized) + + yp_all = [repmat(YY(end-2:end,I)',size(yp,1),1) yp]; + yp_4q = yp_all(:,end-qahead+1:end) + yp_all(:,end-qahead:end-1) + yp_all(:,end-qahead-1:end-2) + yp_all(:,end-qahead-2:end-3); + + dlpop_all = [dlpop_old(:,end-2:end) dlpop_fcst]; + dlpop_4q = dlpop_all(:,end-qahead+1:end) + dlpop_all(:,end-qahead:end-1) + dlpop_all(:,end-qahead-1:end-2) + dlpop_all(:,end-qahead-2:end-3); + yp = 100*(exp(yp_4q/q_adj + dlpop_4q) - 1); + +elseif cum_for(I) ==2 && popadj(I) == 0 + % Transform from log level to 4-Quarter percent change + % The lines below specifically applies to labor supply (hours worked + % per capita). Refer to loaddata for the data transformation. + % Be careful of using this for any other observables. + % Some notes on what is happening in the line directly below: + % YY is necessary to get the last data point so that a percent + % change can be computed for the first period. Repmat is used + % to put the data point in each row of the simulations. The + % log levels are subtracted to get the log percent changes and + % then the exponential is used to remove the log from the + % levels. + yp_old = [repmat(YY(end-3:end,I)',size(yp,1),1) yp(:,1:end-4)]; + yp_4q = yp - yp_old; + yp = 100*(exp(yp_4q/100)-1); +% yp = ((exp(yp(:,1:end)/100 - [repmat(YY(Idate,I), [size(yp,1) 1]) yp(:,1:end-1)]/100).^4)-1)*100; + +elseif cum_for(I) == 2 && popadj(I) == 1 + +% yp = ((exp(yp(:,1:end)/100 - [repmat(YY(Idate,I), [size(yp,1) 1]) yp(:,1:end-1)]/100 + dlpop_fcst).^4)-1)*100; + + yp_old = [repmat(YY(end-3:end,I)',size(yp,1),1) yp(:,1:end-4)]; + yp_4q = yp - yp_old; + + dlpop_all = [dlpop_old(:,end-2:end) dlpop_fcst]; + dlpop_4q = dlpop_all(:,end-qahead+1:end) + dlpop_all(:,end-qahead:end-1) + dlpop_all(:,end-qahead-1:end-2) + dlpop_all(:,end-qahead-2:end-3); + + yp = 100*(exp(yp_4q/100 + dlpop_4q) - 1); + +elseif cum_for(I)==3 + % Transform from log levels to level + % The lines below specifically applies to labor share + % Refer to loaddata for data transformation. + % Be careful of using this for any other observables. + yp = exp(yp/100); + +elseif cum_for(I) == 4 + + yp_all = [repmat(YY(end-2:end,I)',size(yp,1),1) yp]; + yp = (yp_all(:,end-qahead+1:end) + yp_all(:,end-qahead:end-1) + yp_all(:,end-qahead-1:end-2) + yp_all(:,end-qahead-2:end-3))/4; +elseif cum_for(I) == 5 + yp = yp*4; +else + + yp = yp*400/q_adj; + +end; \ No newline at end of file diff --git a/plotting/getyp_counter.m b/plotting/getyp_counter.m new file mode 100644 index 0000000..3a073a7 --- /dev/null +++ b/plotting/getyp_counter.m @@ -0,0 +1,62 @@ +function yp_counter = getyp_counter(ypath_counter,counter_ahead,I,cum_for,popadj,mnobss,dlpop_old,dlpop_ctr,yend,q_adj) + +% This term should be 400 assuming that growth rates are log quarterly +% growth rates multiplied by 100 +%if q_adj ~= 400, warning('q_adj is not 400'); end + +yp_counter = ypath_counter(:,counter_ahead*(I-1)+1:counter_ahead*I); +if cum_for(I) == 1 && popadj(I) == 0 + % Transform from log growth rates to % growth rates (annualized) + %yp = 100*4*(exp(yp/100)-1); + yp_counter = 100*((exp(yp_counter/q_adj)).^4-1); +elseif cum_for(I) == 1 && popadj(I) == 1 + % Transform from log growth rates to total (not per-capita) % growth + % rates (annualized) +% yp_counter(:,mnobss+1:mnobss+size(peachdata,1)) = 100*(exp(yp_counter(:,mnobss+1:mnobss+size(peachdata,1))/q_adj + dlMA_pop).^4 - 1); % population estimate +% yp_counter(:,1:mnobss) = 100*(exp(yp_counter(:,1:mnobss)/400 + repmat(dlpop(end-mnobss+1:end)',5000,1)).^4 - 1); + + yp_counter(:,mnobss+1:end) = 100*(exp(yp_counter(:,mnobss+1:end)/q_adj + dlpop_ctr).^4 - 1); % population estimate + yp_counter(:,1:mnobss)= 100*(exp(yp_counter(:,1:mnobss)/q_adj + dlpop_old).^4 - 1); +elseif cum_for(I)==2 && popadj(I) == 0 + % Transform from log level to 4-quarter annualized percent change + % The lines below specifically applies to labor supply (hours worked + % per capita). Refer to loaddata for data transformation. + % Be careful of using this for any other observables. + % Some notes on what is happening in the line directly below: + % YY is necessary to get the last data point so that a percent + % change can be computed for the first period. Repmat is used + % to put the data point in each row of the simulations. The + % log levels are subtracted to get the log percent changes and + % then the exponential is used to remove the log from the + % levels. +% yp_counter = ((exp(yp_counter(:,1:end)/100 - [repmat(YY(Startdate,I), [size(yp_counter,1) 1]) yp_counter(:,1:end-1)]/100).^4)-1)*100; + yp_counter = ((exp(yp_counter(:,1:end)/100 - [yend(:,I) yp_counter(:,1:end-1)]/100).^4)-1)*100; + %yp_counter = ((exp(yp_counter(:,1:end)/100 - [repmat(YY(Idate,I), [size(yp_counter,1) 1]) yp_counter(:,1:end-1)]/100).^4)-1)*100; +elseif cum_for(I) == 2 && popadj(I) == 1 + yp_counter(:,mnobss+1:end) = ((exp(yp_counter(:,mnobss+1:end)/100 - yp_counter(:,mnobss:end-1)/100 + dlpop_ctr).^4)-1)*100; + yp_counter(:,1:mnobss) = ((exp(yp_counter(:,1:mnobss)/100 - [yend(:,I) yp_counter(:,1:mnobss-1)]/100 + dlpop_old).^4)-1)*100; +elseif cum_for(I)==3 + % Transform from log levels to level + % The lines below specifically applies to labor share + % Refer to loaddata for data transformation. + % Be careful if using this for any other observables. + yp_counter = exp(yp_counter/100); +elseif cum_for(I) == 4 + % This transforms log perecentage levels back to + % percentage levels. This is specifically for unemployment + % which enters the model as log-unemployment + yp_counter=(exp(yp_counter/100)-1)*100; +elseif cum_for(I) == 5 + yp_counter = yp_counter*4; +elseif cum_for(I) ==6 && popadj(I) ==1 + yp_counter(:,mnobss+1:end) = 100*(yp_counter(:,mnobss+1:end)/q_adj + dlpop_ctr); + yp_counter(:,1:mnobss) = 100*(yp_counter(:,1:mnobss)/q_adj + dlpop_old); + +elseif cum_for(I) ==6 && popadj(I) ==0 + yp_counter(:,mnobss+1:end) = 100*(yp_counter(:,mnobss+1:end)/q_adj); + yp_counter(:,1:mnobss) = 100*(yp_counter(:,1:mnobss)/q_adj); +elseif cum_for(I) ==7 + yp_counter(:,1:mnobss) = yp_counter(:,1:mnobss); +else + yp_counter = yp_counter*400/q_adj; +end; diff --git a/plotting/loadcounter.m b/plotting/loadcounter.m new file mode 100644 index 0000000..89720a9 --- /dev/null +++ b/plotting/loadcounter.m @@ -0,0 +1,9 @@ +function ypath_counter = loadcounter(fid_ctr,num_counter,nvar,counter_ahead,nsim,jstep) + +ypath_counter = []; +while ( ftell(fid_ctr) < num_counter ) + % Read blocks of size nsim + ypathadd_counter = fread(fid_ctr,[nvar*counter_ahead,nsim/jstep],'single')'; + ypath_counter = [ypath_counter;ypathadd_counter]; + ftell(fid_ctr); +end; diff --git a/plotting/matlab.mat b/plotting/matlab.mat new file mode 100644 index 0000000..ac25a03 Binary files /dev/null and b/plotting/matlab.mat differ diff --git a/plotting/plotPresentation.m b/plotting/plotPresentation.m new file mode 100644 index 0000000..a98c56c --- /dev/null +++ b/plotting/plotPresentation.m @@ -0,0 +1,620 @@ +% OVERVIEW (WRITTEN AND INTRODUCED ON FEB 18, 2014) +% plotPresentation.m: Produces figures for presentations only. +% +% BIG UPDATE: Can plot either states or observables depending on the +% value of vars_to_plot, which is set in forplot.m and forplot_mode.m. +% This replaces plotPresentation_states.m and the old plotPresentation.m +% +% IMPORTANT FUNCTIONS +% setVseq.m: a function whose input is the figure type. The output from +% this +% function is a vector that indicates the sequence of variables +% for which we want to produce figures. +% recordFcn.m: a function that records the plotted values. +% The output is a structure variable, record, whose fields +% are different plot types, and whose subfields are the +% plotted +% mean and bands. The variable record is saved and +% written to an output text file. +% figspecs.m: this function outputs the variables Xaxis, Yaxis, Title, line, +% lgnd, and plotSeperate, which are all specifications +% for unique to each figure and model. lgnd contains +% specifications for the legend. plotSeparate is a flag +% indicating whether or not the figures for each variable are +% to be plotted separately. +% setfig.m: this function takes the variable plotType (ie. 'Forecast') as +% input and outputs the scalar variable figmain. All figures of +% this plot type have a figure number that is a function of this +% scalar. For example, if figmain for 'Forecast' figures is 100, +% then the output forecast figure would be figure(101), and +% figure(102) for labor share forecast. +% applyfigspecs.m: this program applies figure specifications for the +% X-axis, Y-axis, title, secondary axis, and gridlines. + +% Set up 'number of' dimension to either nvar or nplotstates + ndim = nvar; + fcast_suffix = ''; + cum_for_plot = cum_for; + popadj_plot = popadj; + + +pres = 1; newsletter = 0; system = 0; +peachloop = [1]; +noTitles = 0; % 1 for no titles on the plots + + +%% Specify outfile for recording plotted values +outfile0 = [gpath,date,'.txt']; +fid0 = fopen(outfile0,'wt+'); + +%% Transform actual data + + Ys = getYs(YY(1:Idate,:),YY_p,dlpop,dlpop_p,cum_for_plot,popadj_plot,ndim,fourq_flag,q_adj,0); + + + if any(ismember(plotList,{'Counterfactual by Variable','Counterfactual by Shock','Shock Decomposition'})) + Ys_counter = Ys(1:Startdate,:); + end + + +%% Loop through figures +for plotnum = 1:length(plotList) + plotType = plotList{plotnum}; + + sirf = Startdate:stime+future; + + [Vseq,Vseq_alt,Shseq,Shseq_alt] = setVseq(plotType,nshocks,nant,ndim,mspec); + + + for peachcount = peachloop + varcount = 0; + V_alt_count = 0; + for V_idx = 1:length(Vseq) + + V_a = Vseq(V_idx); + pass = 0; + + %% Set figure specifications and fignum + [Xaxis,Yaxis,Title,line,lgnd,plotSeparate] = feval(['figspecs', fcast_suffix], ... + V_a,V_idx,mspec,peachcount,plotType,... + varnames,varnames_YL,varnames_YL_4Q,Vseq,Vseq_alt,nobs,Idate,Startdate,Enddate,... + sirf,sirf_shockdec,sirf_counter,sirf_shock_1,datesall,dataset,zerobound,... + ndim,list,Counterforecast,shocksnames,names_shocks_title,pass); + + % This extends the bounds for graphs with the (larger) 99 + % percent bands + if onepctflag && strcmp(plotType,'Forecast') + if any(V_a == [1,2]) + Yaxis.lim = [-15,15]; + elseif any(V_a == [4,5]) + Yaxis.lim = [-5,10]; + end + end + + [figmain] = setfig(plotType); + + %% Specify subplots and orientation + + if plotSeparate + figure(figmain+(250*peachcount)+V_a); + else + if strcmp(plotType,'Shock') + figure(figmain+(250*peachcount)) + end + switch plotType + case {'Shock Decomposition','Forecast','Counterfactual by Variable','Counterfactual by Shock'} % Figures that loop through variables + if any(strcmp(plotType,{'Forecast','Counterfactual by Shock'})) + figure(figmain); % Both conditional and unconditional forecasts are plotted together + %subplot(length(Vseq)-length(Vseq_alt),2,2*V_idx-(1-round(peachcount/2))); + elseif strcmp(plotType,'Shock Decomposition') + figure(figmain+(250*peachcount)); + orient portrait + ax = get(gca,'Position'); + set(gca,'Position',ax); + end + end + end + + %% Plot figures + switch plotType + case {'Forecast'} + % Mean + mlp = [Ys(:,V_a);squeeze(Means.forecast(V_a,:,peachcount+1))']; + + % Bands + num_bands = 2 + 8*fancharts; + bandsp = [repmat(Ys(:,V_a),[1 num_bands]);squeeze(Bands.forecast(:,V_a,:,peachcount+1))']; + + LBands(V_a,:) = bandsp(sirf,1)'; + UBands(V_a,:) = bandsp(sirf,2)'; + + % Record data plotted + if overwrite + [record] = recordFcn(plotType,record,V_idx,V_a,peachcount,peachfile,tiall,Startdate,stime,qahead,varnames,names_shocks,fid0,0,... + bandsp,mlp); + end + + % Fancharts + if fancharts + bandsp = [bandsp(:,1),bandsp(:,2:10)-bandsp(:,1:9)]; + end + + if fancharts + if mspec==990 && isnan(bandsp(stime,1)) + P = area(stime+1:sirf(end),bandsp(stime+1:sirf(end),:)); + else + P = area(sirf,bandsp(sirf,:)); + end + + set(P(1),'FaceColor','none') + for layer = 2:10 + set(P(layer),'FaceColor',[0.4 + 0.12*abs(layer-6),0.4 + 0.12*abs(layer-6),1]); + end + set (P,'LineStyle','none') + if V_a == 3 + set(P,'BaseValue',.52) + end + elseif ~strcmp(parstr,'Mode') + P = plot(sirf,bandsp(sirf,1),'r:',sirf,bandsp(sirf,2),'r:'); + set(P,'LineWidth',line.width); + end + hold on; + + % This adds the 99 percent bands if onepctflag is on + if onepctflag + bandsp_onepct = [repmat(Ys(:,V_a),1,2);squeeze(Bands_onepct(:,V_a,:,peachcount+1))']; + P = plot(sirf,bandsp_onepct(sirf,1),'r:',sirf,bandsp_onepct(sirf,2),'r:'); + set(P,'LineWidth',line.width); + end + + % Forecast + P = plot(sirf,mlp(sirf),'r-'); + set(P,'LineWidth',line.width); + + hold on; + + % Actual data + mlp = [Ys(:,V_a);NaN*squeeze(Means.forecast(V_a,:,peachcount+1))']; + P = plot(sirf,mlp(sirf),'k-'); + set(P,'LineWidth',line.width); + + hold off; + + case 'Shock Decomposition' + + % Means_cat + eval(strcat('states',num2str(mspec))); + Means_cat = zeros(ndim,counter_ahead,length(shockcats)); + for j = 1:length(shockcats) + catmean = zeros(size(Means.trend)); + catshocks = shockcats{j}; + for i2 = 1:length(shockcats{j}) + % Use 0 to indicate deterministic trend + if catshocks(i2) == 0 + catmean = catmean + Means.dettrend(:,:,peachcount+1) - Means.trend; %--> we get Det.Trend for each observable (for each period) + % All other shocks... + else + catmean = catmean + Means.shockdec(:,:,peachcount+1,catshocks(i2)) - Means.trend; %--> we get the other "categorical" shocks + end + end + Means_cat(:,:,j) = catmean(1:ndim,:); + end + if any(strcmp('Residual',list)) + ind_res = find(strcmp('Residual',list)); + Means_cat(:,:,ind_res) = Means_cat(:,:,ind_res) + Means.dettrend(:,:,peachcount+1) - Means.trend; + end + + % Shock decompositions + if size(shockcats,1)==1 + mlp_bar = [NaN(Startdate,size(Means_cat,3)); squeeze(Means_cat(V_a,:,:))']; + else + mlp_bar = [NaN(Startdate,size(Means_cat,3)); squeeze(Means_cat(V_a,:,:))]; + end + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % ---> mlp_bar gives us values for shock decomposition bars + barh = bar(sirf_shockdec,mlp_bar(sirf_shockdec,:),1.5); + % set bar colors + for iList = 1:length(list) + if isnumeric(shockdec_color{iList}) + set(barh(iList),'FaceColor',shockdec_color{iList}); + else + set(barh(iList),'FaceColor',rgb(shockdec_color{iList})); + end + end + + set(barh,'EdgeColor','none') + hold on; + + % Forecast + mlp = [Ys(:,V_a);squeeze(Means.forecast(V_a,:,peachcount+1))']; + mlp = mlp - [NaN(1,size(mlp,1) - size(Means.trend,2)) squeeze(Means.trend(V_a,:))]'; + %---> mlp gives us detrended data + forecast (i.e. we get the deviations from steady state here) + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % Record data plotted + if overwrite + [record] = recordFcn(plotType,record,V_idx,V_a,peachcount,peachfile,tiall,Startdate,stime,qahead,varnames,names_shocks,fid0,0,... + list,mlp,mlp_bar); + end + + P = plot(sirf_shockdec,mlp(sirf_shockdec),'r-'); + set(P,'LineWidth',line.width); + + % Actual data + mlp = [Ys(:,V_a);NaN*squeeze(Means.forecast(V_a,:,peachcount+1))']; + mlp = mlp - [NaN(1,size(mlp,1) - size(Means.trend,2)) squeeze(Means.trend(V_a,:))]'; % This line detrends the data/forecast + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + P = plot(sirf_shockdec,mlp(sirf_shockdec),'k-'); + set(P,'LineWidth',line.width); + + % Legend + legh = legend(list,'Location','SouthOutside','Orientation','horizontal'); + + + legpos = get(legh,'Position'); + plotpos = get(gca,'Position'); + legpos(1) = plotpos(1) + plotpos(3)/2 - legpos(3)/2; + legpos(2) = plotpos(2) - plotpos(4)/6 - legpos(4); + + set(legh,'Position',legpos); + + case 'Counterfactual by Variable' + + + for S_1 = 1:length(Shseq) + S_a = Shseq(S_1); + % to specify title for graphs + pass=1; + [Xaxis,Yaxis,Title,line,lgnd,plotSeparate] = ... + figspecs(V_a,V_idx,mspec,peachcount,plotType,... + varnames,varnames_YL,varnames_YL_4Q,Vseq,Vseq_alt,nobs,Idate,Startdate,Enddate,... + sirf,sirf_shockdec,sirf_counter,sirf_shock_1,datesall,dataset,zerobound,... + ndim,list,Counterforecast,shocksnames,names_shocks_title,pass,S_a); + + if plotSeparate + figure(figmain+(250*peachcount)+(10*V_a)+S_a); + else + thisfignum=figmain+(250*peachcount)+(10*V_a); + if S_1>length(Shseq)/2; + thisfignum=thisfignum+1; + end + figure(thisfignum); + %set(gcf, 'PaperSize', [10 40]); + rows=ceil(length(Shseq))/4; + cols=2; + item_num=mod(S_1,length(Shseq)/2); + if item_num==0; item_num=length(Shseq)/2; end; + s=subplot(rows,cols, item_num); + if rem(S_1,2)==1 % odd + col=1; + else % even + col=2; + end + row=ceil(S_1/2); + %axes('Position',[(col-1)/cols 1-(row-1)/rows 1/cols 1/rows]); + end + + % Counterfactual forecast + mlp_counter_byvar = [Ys_counter(:,V_a);squeeze(Means.counter(V_a,:,peachcount+1,S_a))']; + bandsp_counter_byvar = [repmat(Ys_counter(:,V_a),[1 2]);squeeze(Bands.counter(:,V_a,:,peachcount+1,S_a))']; + LBands_counter_byvar(V_a,:) = bandsp_counter_byvar(sirf_counter,1)'; + UBands_counter_byvar(V_a,:) = bandsp_counter_byvar(sirf_counter,2)'; + + P = plot(sirf_counter,mlp_counter_byvar(sirf_counter),'g-'); + set(P,'LineWidth',line.width); + hold on; + + % Record data plotted + if overwrite + [record] = recordFcn(plotType,record,V_idx,V_a,peachcount,peachfile,tiall,Startdate,stime,qahead,varnames,names_shocks,fid0,0,... + S_1,S_a,Shseq,mlp_counter_byvar); + end + orient tall + set(gcf, 'PaperPosition', [0 0 8 10.5]); + + % Forecast + mlp_counter_byvar = [Ys_counter(:,V_a);NaN*squeeze(Means.counter(V_a,:,peachcount+1,S_a))']; + mlp = [Ys(:,V_a);squeeze(Means.forecast(V_a,:,peachcount+1))']; + + P = plot(sirf_counter,mlp(sirf_counter),'r-'); + set(P,'LineWidth',line.width); + + % Actual Data + mlp = [Ys(:,V_a);NaN*squeeze(Means.forecast(V_a,:,peachcount+1))']; + P = plot(sirf_counter,mlp(sirf_counter),'k-'); + set(P,'LineWidth',line.width); + + % Figure Specifications + applyfigspecs; + end + + case 'Counterfactual by Shock' + + % NOTE: the first loop is Vseq, but these are actually the shocks that we want to remove. + % The second loop is Shseq, but these are the variables that we are plotting counterfactuals for. + + shockcount = 0; % This actually counts the number of variables (not shocks) we've looped through + for S_1 = 1:length(Shseq) + S_a = Shseq(S_1); + + pass=1; + [Xaxis,Yaxis,Title,line,lgnd,plotSeparate] = ... + figspecs(V_a,V_idx,mspec,peachcount,plotType,... + varnames,varnames_YL,varnames_YL_4Q,Vseq,Vseq_alt,nobs,Idate,Startdate,Enddate,... + sirf,sirf_shockdec,sirf_counter,sirf_shock_1,datesall,dataset,zerobound,... + ndim,list,Counterforecast,shocksnames,names_shocks_title,pass,S_a); + + if plotSeparate_counter + fignum = figmain + 250*peachcount + 10*S_a + V_a; + figure(fignum); + else + figure(figmain+250*peachcount+10*V_a); + %set(gcf, 'PaperSize', [10 40]); + s=subplot(ceil(length(Shseq)/2),2,S_1); + end + + + % Counterfactual forecast + mlp_counter = [Ys_counter(:,S_a);squeeze(Means.counter(S_a,:,peachcount+1,V_a))']; + bandsp_counter = [repmat(Ys_counter(:,S_a),[1 2]);squeeze(Bands.counter(:,S_a,:,peachcount+1,V_a))']; + LBands_counter(S_a,:) = bandsp_counter(sirf_counter,1)'; + UBands_counter(S_a,:) = bandsp_counter(sirf_counter,2)'; + + P = plot(sirf_counter,mlp_counter(sirf_counter),'g-'); + set(P,'LineWidth',line.width); + hold on; + + % Record data plotted + if overwrite + [record] = recordFcn(plotType,record,V_idx,V_a,peachcount,peachfile,tiall,Startdate,stime,qahead,varnames,names_shocks,fid0,0,... + S_1,S_a,Shseq,mlp_counter); + end + + orient tall + % Forecast + mlp_counter = [Ys_counter(:,S_a);NaN*squeeze(Means.counter(S_a,:,peachcount+1,V_a))']; + mlp = [Ys(:,S_a);squeeze(Means.forecast(S_a,:,peachcount+1))']; + + P = plot(sirf_counter,mlp(sirf_counter),'r-'); + set(P,'LineWidth',line.width); + + % Actual data + mlp = [Ys(:,S_a);NaN*squeeze(Means.forecast(S_a,:,peachcount+1))']; + P = plot(sirf_counter,mlp(sirf_counter),'k-'); + set(P,'LineWidth',line.width); + + % Figure Specifications + applyfigspecs; + end + + case 'Shock' + sirf_shock = [sirf_shock_1,(repmat(Idate,1,pnobss))+(logical(peachcount)*(1:pnobss))]; % if conditional, adjust sirf_shock to pnobss (psize) periods + + % Dotted line at zero + P = plot(sirf_shock,zeros(size(sirf_shock)),'k--'); + hold on; + + % Shock path + if peachcount + if peachcount == 2 + mlp = squeeze(Means.semicondshocks(V_a,:))'; + bandsp = squeeze(Bands.semicondshocks(:,V_a,:))'; + else + mlp = squeeze(Means.condshocks(V_a,:))'; + bandsp = squeeze(Bands.condshocks(:,V_a,:))'; + end + else + mlp = squeeze(Means.uncondshocks(V_a,:))'; + bandsp = squeeze(Bands.uncondshocks(:,V_a,:))'; + end + P = plot(sirf_shock,mlp(sirf_shock),'r-'); + set(P,'LineWidth',line.width); + hold on; + + % Record data plotted + if overwrite + [record] = recordFcn(plotType,record,V_idx,V_a,peachcount,peachfile,tiall,Startdate,stime,qahead,varnames,names_shocks,fid0,0,... + Vseq,mlp,pnobss); + end + + % In sample + insample = find(sirf_shocknobs); + if ~isempty(insample) + if peachcount + + mlp = [squeeze(Means.condshocks(V_a,sirf_shock(insample)))';NaN*squeeze(Means.condshocks(V_a,sirf_shock(outsample)))']; + else + mlp = [squeeze(Means.uncondshocks(V_a,sirf_shock(insample)))';NaN*squeeze(Means.uncondshocks(V_a,sirf_shock(outsample)))']; + end + P = plot(sirf_shock',mlp,'k-'); + set(P,'LineWidth',line.width); + end; + + P = plot(sirf_shock,bandsp(sirf_shock,1),'k:',sirf_shock,bandsp(sirf_shock,2),'k:'); + + case 'ShockAnt' + sirf_shock = [sirf_shock_1,(repmat(Idate,1,pnobss))+(logical(peachcount)*(1:pnobss))]; % if conditional, adjust sirf_shock to pnobss (psize) periods + + % Dotted line at zero + P = plot(sirf_shock,zeros(size(sirf_shock)),'k--'); + hold on; + + % Shock path + switch peachcount + case 0, + mlp = squeeze(Means.uncondshocks_ns(V_a,:))'; + bandsp = squeeze(Bands.uncondshocks_ns(:,V_a,:))'; + case 1, + mlp = squeeze(Means.condshocks_ns(V_a,:))'; + bandsp = squeeze(Bands.condshocks_ns(:,V_a,:))'; + case 2, + mlp = squeeze(Means.semicondshocks_ns(V_a,:))'; + bandsp = squeeze(Bands.semicondshocks_ns(:,V_a,:))'; + end + P = plot(sirf_shock,mlp(sirf_shock),'r-'); + set(P,'LineWidth',line.width); + hold on; + + % Record data plotted + if overwrite + [record] = recordFcn(plotType,record,V_idx,V_a,peachcount,peachfile,tiall,Startdate,stime,qahead,varnames,names_shocks,fid0,0,... + Vseq,mlp,pnobss); + end + + % In sample + insample = find(sirf_shocknobs); + if ~isempty(insample) + switch peachcount + case 1, mlp = [squeeze(Means.condshocks_ns(V_a,sirf_shock(insample)))';NaN*squeeze(Means.condshocks_ns(V_a,sirf_shock(outsample)))']; + case 0, mlp = [squeeze(Means.uncondshocks_ns(V_a,sirf_shock(insample)))';NaN*squeeze(Means.uncondshocks_ns(V_a,sirf_shock(outsample)))']; + case 2, mlp = [squeeze(Means.semicondshocks_ns(V_a,sirf_shock(insample)))';NaN*squeeze(Means.semicondshocks_ns(V_a,sirf_shock(outsample)))']; + end + P = plot(sirf_shock',mlp,'k-'); + set(P,'LineWidth',line.width); + end; + + P = plot(sirf_shock,bandsp(sirf_shock,1),'k:',sirf_shock,bandsp(sirf_shock,2),'k:'); + set(P,'LineWidth',line.width); + applyfigspecs; + + end + + if any(strcmp(plotType,{'Forecast','Shock Decomposition','Shock'})) + applyfigspecs; % For the counterfactuals (which have another loop in addition to the variable loop), + % applyfigspecs is called within the loop so + % individual figures can be modified + end + end + end +end + +%% Record +% Save plotted values in .txt and .mat +if overwrite + finalRecord = 1; + [record] = recordFcn('',record,V_idx,V_a,peachcount,peachfile,... + tiall,Startdate,stime,qahead,... + varnames,names_shocks,fid0,finalRecord); + + %% Save figures + % Removed lambdas and plotNoShocks from figure names + + for plotnum = 1:length(plotList) + plotType = plotList{plotnum}; + if ~strcmp(plotType,'Q4Q4 Table') + + [figmain] = setfig(plotType); + [Vseq,Vseq_alt,Shseq,Shseq_alt] = setVseq(plotType,nshocks,nant,ndim,mspec); + + + switch plotType + case 'Forecast' + for peachcount = peachloop + for V_a = Vseq + fignum = figmain+(250*peachcount)+V_a; + print(figure(fignum),'-depsc', [gpath,'forecast',peachstr{peachcount+1},char(graph_title(V_a)),'.eps']); + saveas(figure(fignum),[gpath,'forecast',peachstr{peachcount+1},char(graph_title(V_a))],'pdf'); + end + end + + case 'Shock Decomposition' + for peachcount = peachloop + if plotSeparate + for V_a = Vseq + fignum = figmain+(250*peachcount)+V_a; + print(figure(fignum),'-depsc', [gpath,'shockdec',peachstr{peachcount+1},char(graph_title(V_a)),'.eps']); + saveas(figure(fignum),[gpath,'shockdec',peachstr{peachcount+1},char(graph_title(V_a))],'pdf'); + end + else + end + end + + case {'Counterfactual by Shock','Counterfactual by Variable'} + %temp fix + plotSeparate = 0; + if plotSeparate + for peachcount = peachloop + for V_a = Vseq + for S_a = Shseq + if strcmp(plotType,'Counterfactual by Shock') + fignum = figmain+(250*peachcount)+(10*S_a)+V_a; + elseif strcmp(plotType,'Counterfactual by Variable') + fignum = figmain+(250*peachcount)+(10*V_a)+S_a; + end + print(figure(fignum),'-depsc',[gpath,'counter',peachstr{peachcount+1},char(names_shocks_title(S_a)),char(graph_title(V_a)),'.eps']); + saveas(figure(fignum),[gpath,'counter',peachstr{peachcount+1},char(names_shocks_title(S_a)),char(graph_title(V_a))],'pdf'); + end + end + end + else + if strcmp('Counterfactual by Shock',plotType) + for peachcount = peachloop + for S_a = Shseq + fignum = figmain+(250*peachcount)+(10*S_a); + print(figure(fignum),'-depsc',[gpath,'counter_shock',peachstr{peachcount+1},char(names_shocks_title(S_a)),'.eps']); + saveas(figure(fignum),[gpath,'counter_shock',peachstr{peachcount+1},char(names_shocks_title(S_a))],'pdf'); + end + end + + elseif strcmp('Counterfactual by Variable',plotType) + for peachcount = peachloop + for V_a = Vseq + fignum = figmain+(250*peachcount)+(10*V_a); + fignum2= fignum+1; + print(figure(fignum),'-depsc',[gpath,'counter_var',peachstr{peachcount+1},char(graph_title(V_a)),'.eps']); + print(figure(fignum2),'-depsc',[gpath,'counter_var',peachstr{peachcount+1},char(graph_title(V_a)),'_continued','.eps']); + saveas(figure(fignum),[gpath,'counter_var',peachstr{peachcount+1},char(graph_title(V_a))],'pdf'); + saveas(figure(fignum2),[gpath,'counter_var',peachstr{peachcount+1},char(graph_title(V_a)) '_continued'],'pdf'); + end + end + end + end + case 'Shock' + for peachcount = peachloop + plotSeparate=1; + if plotSeparate + for V_a = Vseq + fignum = figmain+(250*peachcount)+V_a; + print(figure(fignum),'-depsc', [gpath,'shock',peachstr{peachcount+1},char(names_shocks_title(V_a)),'.eps']); + saveas(figure(fignum),[gpath,'shock',peachstr{peachcount+1},char(names_shocks_title(V_a))],'pdf'); + end + else + fignum = figmain+(250*peachcount); + print(figure(fignum),'-depsc', [gpath,'shock',peachstr{peachcount+1},'.eps']); + saveas(figure(fignum),[gpath,'shock',peachstr{peachcount+1}],'pdf'); + end + end + + case 'ShockAnt' + for peachcount = peachloop + plotSeparate = 1; + if plotSeparate + for V_a = Vseq + fignum = figmain+(250*peachcount)+V_a; + print(figure(fignum),'-depsc', [gpath,'shockAnt',peachstr{peachcount+1},'_',char(names_shocks_title(V_a)),'.eps']); + saveas(figure(fignum),[gpath,'shockAnt',peachstr{peachcount+1},char(names_shocks_title(V_a))],'pdf'); + end + else + fignum = figmain+(250*peachcount); + print(figure(fignum),'-depsc', [gpath,'shockAnt',peachstr{peachcount+1},'_','.eps']); + saveas(figure(fignum),[gpath,'shockAnt',peachstr{peachcount+1}],'pdf'); + end + end + + end + end + end + fclose(fid0); + + curPath = pwd; + eval(['cd ',curPath]); +end + +fprintf('Figures are saved in gpath (%s) \n',gpath); diff --git a/plotting/recordFcn.m b/plotting/recordFcn.m new file mode 100644 index 0000000..4345f82 --- /dev/null +++ b/plotting/recordFcn.m @@ -0,0 +1,177 @@ +% Record numbers plotted +function [record] = recordFcn(plotType,record,V_1,V_a,peachcount,peachfile,... + tiall,Startdate,stime,qahead,... + varnames,names_shocks,fid0,finalRecord,varargin) + + + if V_1==1, j=1; else j=0; end % Applies to everything except Counterfactual by Shock and Counterfactual by Var + + switch plotType + + case 'Q4Q4 Table' + percent = varargin{1}; + table = varargin{2}; + Means_q4q4 = varargin{3}; + Bands_q4q4 = varargin{4}; + + switch peachcount + case 1, record(end+j).type = 'Conditional Q4Q4 Table'; + case 0, record(end+j).type = 'Unconditional Q4Q4 Table'; + case 2, record(end+j).type = 'Semi-Conditional Q4Q4 Table'; + end + record(end).labels = {'dates',[num2str(100*percent),' %LB'],'mean',[num2str(100*percent),' %UB']}; + record(end).data(:,:,V_1) = [table' squeeze(Bands_q4q4(1,V_1,:,peachcount+1)), Means_q4q4(V_1,:,peachcount+1)',squeeze(Bands_q4q4(2,V_1,:,peachcount+1))]; + + case 'Forecast' + bandsp = varargin{1}; + mlp = varargin{2}; + + switch peachcount + case 1, record(end+j).type = 'Conditional Forecast'; + case 0, record(end+j).type = 'Unconditional Forecast'; + case 2, record(end+j).type = 'Semi-Conditional Forecast'; + end + record(end).labels = {'dates','90%LB','80%LB','70%LB','60%LB','50%LB','50%UB','60%UB','70%UB','80%UB','90%UB','mean'}; + record(end).data(:,:,V_a) = [tiall(Startdate:(stime+qahead),:),bandsp(Startdate:end,:),mlp(Startdate:end)]; + + case 'Exp_Forecast' + bandsp = varargin{1}; + mlp = varargin{2}; + + switch peachcount + case 1, record(end+j).type = 'Conditional Forecast'; + case 0, record(end+j).type = 'Unconditional Forecast'; + case 2, record(end+j).type = 'Semi-Conditional Forecast'; + end + record(end).labels = {'dates','90%LB','80%LB','70%LB','60%LB','50%LB','50%UB','60%UB','70%UB','80%UB','90%UB','mean'}; + record(end).data(:,:,V_a) = [tiall(Startdate:(stime+qahead),:),bandsp(Startdate:end,:),mlp(Startdate:end)]; + bandsp = varargin{1}; + mlp = varargin{2}; + + switch peachcount + case 1, record(end+j).type = 'Conditional Forecast'; + case 0, record(end+j).type = 'Unconditional Forecast'; + case 2, record(end+j).type = 'Semi-Conditional Forecast'; + end + record(end).labels = {'dates','90%LB','80%LB','70%LB','60%LB','50%LB','50%UB','60%UB','70%UB','80%UB','90%UB','mean'}; + record(end).data(:,:,V_a) = [tiall(Startdate:(stime+qahead),:),bandsp(Startdate:end,:),mlp(Startdate:end)]; + + case 'Shock Decomposition' + list = varargin{1}; + mlp = varargin{2}; + mlp_bar = varargin{3}; + + switch peachcount + case 1, record(end+j).type = 'Conditional Shock Decomposition'; + case 0, record(end+j).type = 'Unconditional Shock Decomposition'; + case 2, record(end+j).type = 'Semi-Conditional Shock Decomposition'; + end + record(end).labels= {'dates','deviations from mean',list{:}}; + %record(end).data(:,:,V_a) = [tiall(Startdate:(stime+qahead),:),mlp(Startdate:end),mlp_bar(Startdate:end,:)]; + + case '4Q Forecast' + bandsp = varargin{1}; + mlp = varargin{2}; + + switch peachcount + case 1, record(end+j).type = 'Conditional 4Q Forecast'; + case 0, record(end+j).type = 'Unconditional 4Q Forecast'; + case 2, record(end+j).type = 'Semi-Conditional 4Q Forecast'; + end + record(end).labels= {'dates','90%LB','80%LB','70%LB','60%LB','50%LB','50%UB','60%UB','70%UB','80%UB','90%UB','mean'}; + record(end).data(:,:,V_a) = [tiall(Startdate:(stime+qahead),:),bandsp(Startdate:end,:),mlp(Startdate:end)]; + + case 'Counterfactual by Variable' + S_1 = varargin{1}; + S_a = varargin{2}; + Shseq = varargin{3}; + mlp_counter_byvar = varargin{4}; + + if V_1==1 && S_1==1, j=1; else j=0; end + + switch peachcount + case 1, record(end+j).type = 'Conditional Counterfactual by Variable Forecast'; + case 0, record(end+j).type = 'Unconditional Counterfactual by Variable Forecast'; + case 2, record(end+j).type = 'Semi-Conditional Counterfactual by Variable Forecast'; + end + + shock_label = names_shocks(Shseq); + record(end).labels= {'dates',shock_label{:}}; + if S_1==1 + record(end).data(:,1,V_a) = tiall(Startdate:(stime+qahead),:); + end + record(end).data(:,S_1+1,V_a) = [mlp_counter_byvar(Startdate:end)]; + + case 'Counterfactual by Shock' + S_1 = varargin{1}; + S_a = varargin{2}; + Shseq = varargin{3}; + mlp_counter = varargin{4}; + + if S_1==1 && V_1==1, j=1; else j=0; end + + switch peachcount + case 1, record(end+j).type = 'Conditional Counterfactual by Shock Forecast'; + case 0, record(end+j).type = 'Unconditional Counterfactual by Shock Forecast'; + case 2, record(end+j).type = 'Semi-Conditional Counterfactual by Shock Forecast'; + end + + var_label = varnames(Shseq); + record(end).labels= {'dates',var_label{:}}; + if S_1==1 + record(end).data(:,1,V_a) = tiall(Startdate:(stime+qahead),:); + end + record(end).data(:,S_1+1,V_a) = [mlp_counter(Startdate:end)]; + + case 'Shock' + Vseq = varargin{1}; + mlp = varargin{2}; + pnobss = varargin{3}; + + switch peachcount + case 1, record(end+j).type = 'Conditional Shock Innovation'; + case 0, record(end+j).type = 'Unconditional Shock Innovation'; + case 2, record(end+j).type = 'Semi-Conditional Shock Innovation'; + end + + shock_label = names_shocks(Vseq); + record(end).labels= {'dates',shock_label{:}}; + if V_1==1 + record(end).data(:,1) = tiall(Startdate:(stime+(logical(peachcount)*pnobss)),:); + end + record(end).data(:,V_1+1) = mlp(Startdate:(stime+(logical(peachcount)*pnobss)),:); + + end + +if finalRecord + % Record Dick Peach's forecast + load(peachfile) + fprintf(fid0, 'Conditional Data \n'); + fprintf(fid0, '%s \n', peachfile); + eval(['fprintf(fid0, ''' repmat(' %s',1,length(data)) ' \n '', varnames{:});']) + eval(['fprintf(fid0, ''' repmat(' %4.5f',1,length(data)) ' \n '', data);']) + fprintf(fid0, ' \n'); + + % Record plotted data + for k = 1:length(record) + fprintf(fid0,'%s \n\n', record(k).type); + for v = 1:size(record(k).data,3) + if ~ismember(record(k).type,{'Semi-Conditional Shock Innovation';'Conditional Shock Innovation';'Unconditional Shock Innovation'}) + if ismember(record(k).type,{'Semi-Conditional Counterfactual by Shock Forecast';'Conditional Counterfactual by Shock Forecast';'Unconditional Counterfactual by Shock Forecast'}) + fprintf(fid0,'%s \n', char(names_shocks(v))); + else + fprintf(fid0,'%s \n', char(varnames(v))); + end + end + fprintf(fid0,'%s ', record(k).labels{:}); + fprintf(fid0,' \n'); + for a = 1:size(record(k).data,1) + eval(['fprintf(fid0, ''' repmat(' %4.5f',1,size(record(k).data,2)) ' \n '' ,[record(k).data(a,:,v)]);']); + end + fprintf(fid0,' \n \n'); + end + end +end + + +end diff --git a/plotting/rgb.m b/plotting/rgb.m new file mode 100644 index 0000000..21e42b9 --- /dev/null +++ b/plotting/rgb.m @@ -0,0 +1,279 @@ +% RGB Rgb triple for given CSS color name +% +% RGB = RGB('COLORNAME') returns the red-green-blue triple corresponding +% to the color named COLORNAME by the CSS3 proposed standard [1], which +% contains 139 different colors (an rgb triple is a 1x3 vector of +% numbers between 0 and 1). COLORNAME is case insensitive, and for gray +% colors both spellings (gray and grey) are allowed. +% +% RGB CHART creates a figure window showing all the available colors with +% their names. +% +% EXAMPLES +% c = rgb('DarkRed') gives c = [0.5430 0 0] +% c = rgb('Green') gives c = [0 0.5 0] +% plot(x,y,'color',rgb('orange')) plots an orange line through x and y +% rgb chart shows all the colors +% +% BACKGROUND +% The color names of [1] have already been ratified in [2], and +% according to [3] they are accepted by almost all web browsers and are +% used in Microsoft's .net framework. All but four colors agree with +% the X11 colornames, as detailed in [4]. Of these the most important +% clash is green, defined as [0 0.5 0] by CSS and [0 1 0] by X11. The +% definition of green in Matlab matches the X11 definition and gives a +% very light green, called lime by CSS (many users of Matlab have +% discovered this when trying to color graphs with 'g-'). Note that +% cyan and aqua are synonyms as well as magenta and fuchsia. +% +% ABOUT RGB +% This program is public domain and may be distributed freely. +% Author: Kristján Jónasson, Dept. of Computer Science, University of +% Iceland (jonasson@hi.is). June 2009. +% +% REFERENCES +% [1] "CSS Color module level 3", W3C (World Wide Web Consortium) +% working draft 21 July 2008, http://www.w3.org/TR/css3-color +% +% [2] "Scalable Vector Graphics (SVG) 1.1 specification", W3C +% recommendation 14 January 2003, edited in place 30 April 2009, +% http://www.w3.org/TR/SVG +% +% [3] "Web colors", http://en.wikipedia.org/wiki/Web_colors +% +% [4] "X11 color names" http://en.wikipedia.org/wiki/X11_color_names + +function rgb = rgb(s) + persistent num name + if isempty(num) % First time rgb is called + [num,name] = getcolors(); + name = lower(name); + num = reshape(hex2dec(num), [], 3); + % Divide most numbers by 256 for "aesthetic" reasons (green=[0 0.5 0]) + I = num < 240; % (interpolate F0--FF linearly from 240/256 to 1.0) + num(I) = num(I)/256; + num(~I) = ((num(~I) - 240)/15 + 15)/16; + 240; + end + if strcmpi(s,'chart') + showcolors() + else + k = find(strcmpi(s, name)); + if isempty(k) + error(['Unknown color: ' s]); + else + rgb = num(k(1), :); + end + end +end + +function showcolors() + [num,name] = getcolors(); + grp = {'White', 'Gray', 'Red', 'Pink', 'Orange', 'Yellow', 'Brown'... + , 'Green', 'Blue', 'Purple', 'Grey'}; + J = [1,3,6,8,9,10,11]; + fl = lower(grp); + nl = lower(name); + for i=1:length(grp) + n(i) = strmatch(fl{i}, nl, 'exact'); + end + clf + p = get(0,'screensize'); + wh = 0.6*p(3:4); + xy0 = p(1:2)+0.5*p(3:4) - wh/2; + set(gcf,'position', [xy0 wh]); + axes('position', [0 0 1 1], 'visible', 'off'); + hold on + x = 0; + N = 0; + for i=1:length(J)-1 + N = max(N, n(J(i+1)) - n(J(i)) + (J(i+1) - J(i))*1.3); + end + h = 1/N; + w = 1/(length(J)-1); + d = w/30; + for col = 1:length(J)-1; + y = 1 - h; + for i=J(col):J(col+1)-1 + t = text(x+w/2, y+h/10 , [grp{i} ' colors']); + set(t, 'fontw', 'bold', 'vert','bot', 'horiz','cent', 'fontsize',10); + y = y - h; + for k = n(i):n(i+1)-1 + c = rgb(name{k}); + bright = (c(1)+2*c(2)+c(3))/4; + if bright < 0.5, txtcolor = 'w'; else txtcolor = 'k'; end + rectangle('position',[x+d,y,w-2*d,h],'facecolor',c); + t = text(x+w/2, y+h/2, name{k}, 'color', txtcolor); + set(t, 'vert', 'mid', 'horiz', 'cent', 'fontsize', 9); + y = y - h; + end + y = y - 0.3*h; + end + x = x + w; + end +end + +function [hex,name] = getcolors() + css = { + %White colors + 'FF','FF','FF', 'White' + 'FF','FA','FA', 'Snow' + 'F0','FF','F0', 'Honeydew' + 'F5','FF','FA', 'MintCream' + 'F0','FF','FF', 'Azure' + 'F0','F8','FF', 'AliceBlue' + 'F8','F8','FF', 'GhostWhite' + 'F5','F5','F5', 'WhiteSmoke' + 'FF','F5','EE', 'Seashell' + 'F5','F5','DC', 'Beige' + 'FD','F5','E6', 'OldLace' + 'FF','FA','F0', 'FloralWhite' + 'FF','FF','F0', 'Ivory' + 'FA','EB','D7', 'AntiqueWhite' + 'FA','F0','E6', 'Linen' + 'FF','F0','F5', 'LavenderBlush' + 'FF','E4','E1', 'MistyRose' + %Grey colors' + '80','80','80', 'Gray' + 'DC','DC','DC', 'Gainsboro' + 'D3','D3','D3', 'LightGray' + 'C0','C0','C0', 'Silver' + 'A9','A9','A9', 'DarkGray' + '69','69','69', 'DimGray' + '77','88','99', 'LightSlateGray' + '70','80','90', 'SlateGray' + '2F','4F','4F', 'DarkSlateGray' + '00','00','00', 'Black' + %Red colors + 'FF','00','00', 'Red' + 'FF','A0','7A', 'LightSalmon' + 'FA','80','72', 'Salmon' + 'E9','96','7A', 'DarkSalmon' + 'F0','80','80', 'LightCoral' + 'CD','5C','5C', 'IndianRed' + 'DC','14','3C', 'Crimson' + 'B2','22','22', 'FireBrick' + '8B','00','00', 'DarkRed' + %Pink colors + 'FF','C0','CB', 'Pink' + 'FF','B6','C1', 'LightPink' + 'FF','69','B4', 'HotPink' + 'FF','14','93', 'DeepPink' + 'DB','70','93', 'PaleVioletRed' + 'C7','15','85', 'MediumVioletRed' + %Orange colors + 'FF','A5','00', 'Orange' + 'FF','8C','00', 'DarkOrange' + 'FF','7F','50', 'Coral' + 'FF','63','47', 'Tomato' + 'FF','45','00', 'OrangeRed' + %Yellow colors + 'FF','FF','00', 'Yellow' + 'FF','FF','E0', 'LightYellow' + 'FF','FA','CD', 'LemonChiffon' + 'FA','FA','D2', 'LightGoldenrodYellow' + 'FF','EF','D5', 'PapayaWhip' + 'FF','E4','B5', 'Moccasin' + 'FF','DA','B9', 'PeachPuff' + 'EE','E8','AA', 'PaleGoldenrod' + 'F0','E6','8C', 'Khaki' + 'BD','B7','6B', 'DarkKhaki' + 'FF','D7','00', 'Gold' + %Brown colors + 'A5','2A','2A', 'Brown' + 'FF','F8','DC', 'Cornsilk' + 'FF','EB','CD', 'BlanchedAlmond' + 'FF','E4','C4', 'Bisque' + 'FF','DE','AD', 'NavajoWhite' + 'F5','DE','B3', 'Wheat' + 'DE','B8','87', 'BurlyWood' + 'D2','B4','8C', 'Tan' + 'BC','8F','8F', 'RosyBrown' + 'F4','A4','60', 'SandyBrown' + 'DA','A5','20', 'Goldenrod' + 'B8','86','0B', 'DarkGoldenrod' + 'CD','85','3F', 'Peru' + 'D2','69','1E', 'Chocolate' + '8B','45','13', 'SaddleBrown' + 'A0','52','2D', 'Sienna' + '80','00','00', 'Maroon' + %Green colors + '00','80','00', 'Green' + '98','FB','98', 'PaleGreen' + '90','EE','90', 'LightGreen' + '9A','CD','32', 'YellowGreen' + 'AD','FF','2F', 'GreenYellow' + '7F','FF','00', 'Chartreuse' + '7C','FC','00', 'LawnGreen' + '00','FF','00', 'Lime' + '32','CD','32', 'LimeGreen' + '00','FA','9A', 'MediumSpringGreen' + '00','FF','7F', 'SpringGreen' + '66','CD','AA', 'MediumAquamarine' + '7F','FF','D4', 'Aquamarine' + '20','B2','AA', 'LightSeaGreen' + '3C','B3','71', 'MediumSeaGreen' + '2E','8B','57', 'SeaGreen' + '8F','BC','8F', 'DarkSeaGreen' + '22','8B','22', 'ForestGreen' + '00','64','00', 'DarkGreen' + '6B','8E','23', 'OliveDrab' + '80','80','00', 'Olive' + '55','6B','2F', 'DarkOliveGreen' + '00','80','80', 'Teal' + %Blue colors + '00','00','FF', 'Blue' + 'AD','D8','E6', 'LightBlue' + 'B0','E0','E6', 'PowderBlue' + 'AF','EE','EE', 'PaleTurquoise' + '40','E0','D0', 'Turquoise' + '48','D1','CC', 'MediumTurquoise' + '00','CE','D1', 'DarkTurquoise' + 'E0','FF','FF', 'LightCyan' + '00','FF','FF', 'Cyan' + '00','FF','FF', 'Aqua' + '00','8B','8B', 'DarkCyan' + '5F','9E','A0', 'CadetBlue' + 'B0','C4','DE', 'LightSteelBlue' + '46','82','B4', 'SteelBlue' + '87','CE','FA', 'LightSkyBlue' + '87','CE','EB', 'SkyBlue' + '00','BF','FF', 'DeepSkyBlue' + '1E','90','FF', 'DodgerBlue' + '64','95','ED', 'CornflowerBlue' + '41','69','E1', 'RoyalBlue' + '00','00','CD', 'MediumBlue' + '00','00','8B', 'DarkBlue' + '00','00','80', 'Navy' + '19','19','70', 'MidnightBlue' + %Purple colors + '80','00','80', 'Purple' + 'E6','E6','FA', 'Lavender' + 'D8','BF','D8', 'Thistle' + 'DD','A0','DD', 'Plum' + 'EE','82','EE', 'Violet' + 'DA','70','D6', 'Orchid' + 'FF','00','FF', 'Fuchsia' + 'FF','00','FF', 'Magenta' + 'BA','55','D3', 'MediumOrchid' + '93','70','DB', 'MediumPurple' + '99','66','CC', 'Amethyst' + '8A','2B','E2', 'BlueViolet' + '94','00','D3', 'DarkViolet' + '99','32','CC', 'DarkOrchid' + '8B','00','8B', 'DarkMagenta' + '6A','5A','CD', 'SlateBlue' + '48','3D','8B', 'DarkSlateBlue' + '7B','68','EE', 'MediumSlateBlue' + '4B','00','82', 'Indigo' + %Gray repeated with spelling grey + '80','80','80', 'Grey' + 'D3','D3','D3', 'LightGrey' + 'A9','A9','A9', 'DarkGrey' + '69','69','69', 'DimGrey' + '77','88','99', 'LightSlateGrey' + '70','80','90', 'SlateGrey' + '2F','4F','4F', 'DarkSlateGrey' + }; + hex = css(:,1:3); + name = css(:,4); +end \ No newline at end of file diff --git a/plotting/setVseq.m b/plotting/setVseq.m new file mode 100644 index 0000000..ecac652 --- /dev/null +++ b/plotting/setVseq.m @@ -0,0 +1,81 @@ +function [Vseq,Vseq_alt,Shseq,Shseq_alt] = setVseq(plotType,nshocks,nant,nvar,mspec,varargin) + +class2part +adj = 0; + +%% Preallocate space for memory usage +Vseq=[]; +Vseq_alt=[]; +Shseq=[]; +Shseq_alt=[]; + +%% Settings + switch plotType + case {'Forecast','Shock Decomposition','Shock Decomposition-noDet','Exp_Forecast'} + if any(mspec == class2part_all) + Vseq = 1:(nvar-nant+adj); + Vseq_alt = []; + else + Vseq = 1:nvar; + Vseq_alt = []; + end + case {'Forecast Semicond'} + Vseq = [1 5 6]; + Vseq_alt = []; + Vseq = [Vseq Vseq_alt]; + case {'Forward Guidance'} + Vseq = [14 15 16 17 12 13]; + Vseq_alt = []; + Vseq = [Vseq Vseq_alt]; + case 'Forward Guidance Horizontal' + Vseq = [14 15 12 16 17 13]; + Vseq_alt = []; + Vseq = [Vseq Vseq_alt]; + case {'Counterfactual by Variable'} + Shseq = 1:nshocks-nant; + Shseq_alt = []; + if any(mspec == class2part_all) + Vseq = 1:(nvar-nant+adj); + else + Vseq = 1:nvar; + end + Vseq_alt = []; + case {'Counterfactual by Shock'} + if any(mspec == class2part_all) + Shseq = 1:(nvar-nant+adj); + else + Shseq = 1:nvar; + end + Shseq_alt = []; + Vseq = 1:nshocks-nant; % These are now shocks + Vseq_alt = []; + + case {'Shock','Shock Squared','Htil','Eta Squared','Sigma'} + if any(mspec == class2part_all) + Vseq = 1:nshocks-nant; % These are now shocks + else + Vseq = 1:nshocks; % These are now shocks + end + Vseq_alt = []; + + case {'ShockAnt'} + if is2part(mspec) + Vseq = [nshocks-nant+1:nshocks]; + Vseq_alt = []; + else + Vseq = 1:nshocks; + Vseq_alt = []; + end + + case {'Forecast Comparison', '4Q Forecast', 'Forecast Comparison Separate', '4Q Forecast Separate'} + + Vseq = 1:nvar; + Vseq_alt = []; + + + case 'ImpObs' + nimpVar = varargin{1}; + Vseq = nvar+1:nvar+nimpVar; + end + + \ No newline at end of file diff --git a/plotting/setYaxis.m b/plotting/setYaxis.m new file mode 100644 index 0000000..fe75ac8 --- /dev/null +++ b/plotting/setYaxis.m @@ -0,0 +1,210 @@ +function [Yaxis] = setYaxis(mspec,dataset,zerobound,nvar,plotType,V_a) + +switch plotType + case {'Forecast','Forecast Comparison','Exp_Forecast','Forward Guidance','Forward Guidance Horizontal','Forecast Semicond'} + switch V_a + case 1 %% output + Yaxis.lim = [-9 9]; + Yaxis.freq = 3; + case 2 %% hours + Yaxis.lim = [-9 12]; + Yaxis.freq = 1; + case 3 %% labor share + Yaxis.lim = [0.5 0.6]; + Yaxis.freq = 0.01; + case 4 %% inflation + Yaxis.lim = [0 4]; + Yaxis.freq = 1; + case 5 %% interest rate + if zerobound + Yaxis.lim = [0 6]; + Yaxis.freq = 1; + else + Yaxis.lim = [-4 6]; + Yaxis.freq = 1; + end + case 6 + Yaxis.lim = [-3 6]; + Yaxis.freq = 1; + case 7 + Yaxis.lim = [-10 10]; + Yaxis.freq = 2; + case 8 + if zerobound + Yaxis.lim = [-4 2]; + Yaxis.freq = 1; + else + Yaxis.lim = [-6 2]; + Yaxis.freq = 2; + end + case 9 + Yaxis.lim = [-8 8]; + Yaxis.freq = 2; + case 10 + Yaxis.lim = [-3 18]; + Yaxis.freq = 3; + case 11 + Yaxis.lim = [-4 23]; + Yaxis.freq = 3; + case 12 + Yaxis.lim = [0 11]; + Yaxis.freq = 1; + case 13 %% interest rate + if zerobound + Yaxis.lim = [0 6]; + Yaxis.freq = 1; + else + Yaxis.lim = [-4 6]; + Yaxis.freq = 1; + end + case 14 %% 4q output growth + Yaxis.lim = [-5 13]; + Yaxis.freq = 1; + case 15 %% Cumulative output growth + Yaxis.lim = [-4 26]; + Yaxis.freq = 2; + case 16 + Yaxis.lim = [0 5]; + Yaxis.freq = 0.5; + case 17 + Yaxis.lim = [0 30]; + Yaxis.freq = 2; + + end +case {'4Q Forecast'} + switch V_a + case 1, + Yaxis.lim = [-6 10]; + Yaxis.freq = 1; + case 2, + Yaxis.lim = [-15 6]; + Yaxis.freq = 4; + case 3 %% labor share + Yaxis.lim = [0.50 0.6]; + Yaxis.freq = 0.02; + case 4 + Yaxis.lim = [-1 3.5]; + Yaxis.freq = 0.5; + case 5 + if zerobound + Yaxis.lim = [0 5.5]; + Yaxis.freq = 0.5; + end + case 6 + Yaxis.lim = [-3 6]; + Yaxis.freq = 1; + case 7 %% investment in mspec 6 + Yaxis.lim = [0 14]; + Yaxis.freq = 2; + case 8 + if zerobound + Yaxis.lim = [-4 2]; + Yaxis.freq = 1; + else + Yaxis.lim = [-6 2]; + Yaxis.freq = 2; + end + case 9 + Yaxis.lim = [-8 8]; + Yaxis.freq = 2; + case 10 + Yaxis.lim = [-3 18]; + Yaxis.freq = 3; + case 11 + Yaxis.lim = [-4 23]; + Yaxis.freq = 3; + case 12 + Yaxis.lim = [0 11]; + Yaxis.freq = 1; + case 13 %% interest rate + if zerobound + Yaxis.lim = [0 6]; + Yaxis.freq = 1; + else + Yaxis.lim = [-4 6]; + Yaxis.freq = 1; + end + case 14 %% 4q output growth + Yaxis.lim = [-5 13]; + Yaxis.freq = 1; + case 15 %% Cumulative output growth + Yaxis.lim = [-4 26]; + Yaxis.freq = 2; + case 16 + Yaxis.lim = [0 5]; + Yaxis.freq = 0.5; + case 17 + Yaxis.lim = [0 30]; + Yaxis.freq = 2; + end +case {'Counterfactual','Counterfactual by Variable','Counterfactual by Shock'} + switch V_a + case 1 %% output + Yaxis.lim = [-10 10]; + Yaxis.freq = 4; + case 2 %% hours + Yaxis.lim = [-15 6]; +%Yaxis.lim = [530 560]; % Use for levels + Yaxis.freq = 4; + %Yaxis.freq = 5; % Use for levels + case 3 %% labor share + Yaxis.lim = [0.50 0.6]; + Yaxis.freq = 0.02; + case 4 %% inflation + Yaxis.lim = [-1 5]; + Yaxis.freq = 2; + case 5 %% interest rate + Yaxis.lim = [-2 7]; + Yaxis.freq = 2; + case 6 + Yaxis.lim = [-3 6]; + Yaxis.freq = 1; + case 7 + Yaxis.lim = [-40 30]; + Yaxis.freq = 10; + otherwise + Yaxis.lim = [-40 30]; + Yaxis.freq = 10; + end + +case {'Shock Decomposition','Shock Decomposition-noDet'} + switch V_a + case 1 %% output + Yaxis.freq = 2; + Yaxis.lim = [-12 5]; + case 2 %% hours + Yaxis.lim = [-9 6]; + Yaxis.freq = 1; + case 3 %% labor share + Yaxis.lim = [-4 3]; + Yaxis.freq = 0.5; + case 4 %% inflation + Yaxis.lim = [-2 2]; + Yaxis.freq = 1; + case 5 %% interest rate + Yaxis.lim = [-5 2]; + Yaxis.freq = 1; + case 6 + Yaxis.lim = [-1 5]; + Yaxis.freq = 1; + case 7 + Yaxis.lim = [-40 15]; + Yaxis.freq = 5; + case 8 + Yaxis.lim = [-1 1]; + Yaxis.freq = 0.25; + end +case {'Shock'} + Yaxis.lim = [-4,4]; + if V_a==7, Yaxis.lim = [-7,7]; end + Yaxis.freq = 0.5; +case {'ShockAnt'} + Yaxis.lim = [-0.4,0.2]; + Yaxis.freq = 0.1; +case {'Shock Squared','Htil','Eta Squared','Sigma'} + Yaxis.lim = []; +otherwise + Yaxis.lim = []; +end + +end diff --git a/plotting/set_paths.m b/plotting/set_paths.m new file mode 100644 index 0000000..6eede3c --- /dev/null +++ b/plotting/set_paths.m @@ -0,0 +1,10 @@ +paths = {'data/'; 'dsgesolv/'; 'estimation/'; 'forecast/'; 'forlater/';... + 'gensys/';'initialization/'; 'save/'; 'toolbox/'; 'plotting'}; +addpath(paths{:}); + +spath = 'save/'; % save location for parameter draws +gpath = 'graphs/'; % save location for graphs + + + + diff --git a/plotting/setfig.m b/plotting/setfig.m new file mode 100644 index 0000000..10df886 --- /dev/null +++ b/plotting/setfig.m @@ -0,0 +1,45 @@ +function [figmain] = setfig(plotType) + switch plotType + case 'Forecast' + figmain = 1000; + case 'Shock Decomposition' + figmain = 2000; + case 'Forecast Comparison' + figmain = 3000; + case '4Q Forecast' + figmain = 4000; + case 'Counterfactual by Shock' + figmain = 5000; + case 'Counterfactual by Variable' + figmain = 6000; + case 'Shock' + figmain = 7000; + case 'Exp_Forecast' + figmain = 8000; + case 'Shock Decomposition-noDet' + figmain = 9000; + case 'Shock Squared' + figmain = 10000; + case 'Htil' + figmain = 11000; + case 'Eta Squared' + figmain = 12000; + case 'Sigma' + figmain = 13000; + case 'Forecast Comparison Separate' + figmain = 15000; + case '4Q Forecast Separate' + figmain = 16000; + case 'ShockAnt' + figmain = 17000; + case 'Forward Guidance' + figmain = 18000; + case 'Forward Guidance Horizontal' + figmain = 19000; + case 'Forecast Semicond' + figmain = 20000; + end +end + + + diff --git a/save/mode_in b/save/mode_in new file mode 100644 index 0000000..73f363e Binary files /dev/null and b/save/mode_in differ diff --git a/set_paths.m b/set_paths.m new file mode 100644 index 0000000..6749b67 --- /dev/null +++ b/set_paths.m @@ -0,0 +1,11 @@ +% Paths needed to run the code +paths = {'data/'; 'dsgesolv/'; 'estimation/'; 'forecast/'; ... + 'initialization/'; 'kalman/'; 'toolbox/'; 'plotting/'}; +addpath(paths{:}); + +spath = ['save/']; % save location for parameter draws (and input mode) + +gpath = ['graphs/']; % save location for graphs + +fpath = ['figures/']; % save location for figures/tables + diff --git a/spec_990.m b/spec_990.m new file mode 100644 index 0000000..0d00654 --- /dev/null +++ b/spec_990.m @@ -0,0 +1,34 @@ +%% MODEL-SPECIFIC SPECIFICATIONS (Defaults) + mspec = 990; % Model to run + subspec = 2; % Subspecifications to change parameter values + mprior = 9; % Prior Specifications + pf_mod = '90'; % Prior Specifications + dataset = 715; % Dataset number; can be used to reference alternative + % datasets + nant = 6; % Number of anticipated policy shocks + +%% SAVE SETTINGS + overwrite = 1; % Overwrite old output? + +%% ESTIMATION SETTINGS + reoptimize = 0; % Whether to reoptimize or use the mode as is + CH = 0; % Compute Hessian again + nsim = 10000; % Number of draws per posterior simulation block + nblocks = 22; % Number of blocks + nburn = nsim*2; % How many draws to discard as burn-in + jstep = 10; % From the blocks, we take every jstep-th element + +%% FORECAST SETTINGS + + zerobound = 1; % Incorporate anticipated policy shocks + antpolflag=1; + + % CONDITIONAL DATA + % Indicates whether we are doing a forecast conditional on an + % additional quarter of data for certain variables. + peachflag = 1; + + % PARALLEL SETTINGS + distr = 1; % Run forecasting in parallel; requires parallel toobox + nMaxWorkers=40; % If run in parallel, how many workers? + diff --git a/toolbox/Hpfilter.m b/toolbox/Hpfilter.m new file mode 100644 index 0000000..dab8240 --- /dev/null +++ b/toolbox/Hpfilter.m @@ -0,0 +1,37 @@ +% hpdata.m +% Larry Christiano +% June 21, 1990 + +function [yf,yt] = hpfilter(y,lam); + +% This program applies the hp filter to data + +d = length(y); +a = sparse(d,d); +for i = 3:d-2 + a(i,i) = 6*lam+1; + a(i,i+1) = -4*lam; + a(i,i+2) = lam; + a(i,i-2) = lam; + a(i,i-1) = -4*lam; + end + +a(2,2) = 1+5*lam; +a(2,3) = -4*lam; +a(2,4) = lam; +a(2,1) = -2*lam; +a(1,1) = 1+lam; +a(1,2) = -2*lam; +a(1,3) = lam; + +a(d-1,d-1) = 1+5*lam; +a(d-1,d-2) = -4*lam; +a(d-1,d-3) = lam; +a(d-1,d) = -2*lam; +a(d,d) = 1+lam; +a(d,d-1) = -2*lam; +a(d,d-2) = lam; + +yt = a\y; +yf = y-yt; + diff --git a/toolbox/bfgsi.m b/toolbox/bfgsi.m new file mode 100644 index 0000000..be2ef0e --- /dev/null +++ b/toolbox/bfgsi.m @@ -0,0 +1,25 @@ +function H = bfgsi(H0,dg,dx) +% H = bfgsi(H0,dg,dx) +% dg is previous change in gradient; dx is previous change in x; +% 6/8/93 version that updates inverse hessian instead of hessian +% itself. +% Copyright by Christopher Sims 1996. This material may be freely +% reproduced and modified. +if size(dg,2)>1 + dg=dg'; +end +if size(dx,2)>1 + dx=dx'; +end +Hdg = H0*dg; +dgdx = dg'*dx; +if (abs(dgdx) >1e-12) + H = H0 + (1+(dg'*Hdg)/dgdx)*(dx*dx')/dgdx - (dx*Hdg'+Hdg*dx')/dgdx; +else + disp('bfgs update failed.') + disp(['|dg| = ' num2str(sqrt(dg'*dg)) '|dx| = ' num2str(sqrt(dx'*dx))]); + disp(['dg''*dx = ' num2str(dgdx)]) + disp(['|H*dg| = ' num2str(Hdg'*Hdg)]) + H=H0; +end +save H.dat H diff --git a/toolbox/csminit.m b/toolbox/csminit.m new file mode 100644 index 0000000..689d3e6 --- /dev/null +++ b/toolbox/csminit.m @@ -0,0 +1,219 @@ +function [fhat,xhat,fcount,retcode] = csminit(fcn,x0,f0,g0,badg,H0,Verbose,varargin) +% [fhat,xhat,fcount,retcode] = csminit(fcn,x0,f0,g0,badg,H0,... +% P1,P2,P3,P4,P5,P6,P7,P8) +% retcodes: 0, normal step. 5, largest step still improves too fast. +% 4,2 back and forth adjustment of stepsize didn't finish. 3, smallest +% stepsize still improves too slow. 6, no improvement found. 1, zero +% gradient. +%--------------------- +% Modified 7/22/96 to omit variable-length P list, for efficiency and compilation. +% Places where the number of P's need to be altered or the code could be returned to +% its old form are marked with ARGLIST comments. +% +% Fixed 7/17/93 to use inverse-hessian instead of hessian itself in bfgs +% update. +% +% Fixed 7/19/93 to flip eigenvalues of H to get better performance when +% it's not psd. +% +%tailstr = ')'; +%for i=nargin-6:-1:1 +% tailstr=[ ',P' num2str(i) tailstr]; +%end +%Verbose = 0; + +%ANGLE = .03; +ANGLE = .005; +%THETA = .03; +THETA = .3; %(0 1e12 + % disp('Bad, small gradient problem.') + % dx = dx*FCHANGE/dxnorm; + % end + %else + % Gauss-Newton step; + %---------- Start of 7/19/93 mod --------------- + %[v d] = eig(H0); + %toc + %d=max(1e-10,abs(diag(d))); + %d=abs(diag(d)); + %dx = -(v.*(ones(size(v,1),1)*d'))*(v'*g); +% toc + dx = -H0*g; + +% toc + dxnorm = norm(dx); + if dxnorm > 1e12 + disp('Near-singular H problem.') + dx = dx*FCHANGE/dxnorm; + end + + dfhat = dx'*g0; + %end + % + % + if ~badg + % test for alignment of dx with gradient and fix if necessary + a = -dfhat/(gnorm*dxnorm); + if a1 + dxtest=x0+dx'*lambda; + else + dxtest=x0+dx*lambda; + end + % home + f = eval([fcn '(dxtest,varargin{:})']); + %ARGLIST + %f = feval(fcn,dxtest,P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13); + % f = feval(fcn,x0+dx*lambda,P1,P2,P3,P4,P5,P6,P7,P8); + if Verbose + disp(sprintf('lambda = %10.5g; f = %20.7f',lambda,f )) + end + %debug + %disp(sprintf('Improvement too great? f0-f: %g, criterion: %g',f0-f,-(1-THETA)*dfhat*lambda)) + if f -THETA*dfhat*lambda (see Berndt et al.) + %%%% If that's not the case and grad is good, OR if grad is bad and f is not going down, shrinkSignal = 1 + growSignal = ~badg & ( (lambda > 0) & (f0-f > -(1-THETA)*dfhat*lambda) ); + %%%% the optimal lambda should also be such that f0-f<-(1-THETA)*dfhat*lambda + %%%% If that's not the case with lambda>0, AND grad is good, growthSignal = 1 + + + if shrinkSignal & ( (lambda>lambdaPeak) | (lambda<0) ) + %%%% If shrinkSignal=1 AND ( lambda>lambdaPeak or lambda negative ) + %%%% (note when lambdaPeak=0 the second part only excludes lambda=0) + %%%% try shrinking lambda + if (lambda>0) & ((~shrink) | (lambda/factor <= lambdaPeak)) + %%%% if shrink=0 OR lambda/factor is already smaller than lambdaPeak, increase factor + shrink=1; + factor=factor^.6; + while lambda/factor <= lambdaPeak + factor=factor^.6; + end + %if (abs(lambda)*(factor-1)*dxnorm < MINDX) | (abs(lambda)*(factor-1) < MINLAMB) + if abs(factor-1)lambdaPeak) + lambdaMax=lambda; + end + lambda=lambda/factor; + %%%% shrink lambda + if abs(lambda) < MINLAMB + %%%% if lambda has already been shrunk as much as possible + if (lambda > 0) & (f0 <= fhat) + %%%% if lambda is positive AND you have not made any improvement + % try going against gradient, which may be inaccurate + lambda = -lambda*factor^6; + else + if lambda < 0 + %%%% if lambda is negative: let it be known and quit trying + retcode = 6; + else + %%%% if you have not made any imporvement: let it be known and quit trying + retcode = 3; + end + done = 1; + end + end + + + elseif (growSignal & lambda>0) | (shrinkSignal & ((lambda <= lambdaPeak) & (lambda>0))) + %%%% If growthSignal=1 and lambda positive OR ( lambda>lambdaPeak or lambda negative ) + %%%% (note when lambdaPeak=0 the second part only excludes lambda=0) + %%%% try increase lambda + + if shrink + shrink=0; + factor = factor^.6; + %if ( abs(lambda)*(factor-1)*dxnorm< MINDX ) | ( abs(lambda)*(factor-1)< MINLAMB) + if abs(factor-1) < MINDFAC + retcode = 4; + done=1; + end + end + if ( f0) + fPeak=f; + lambdaPeak=lambda; + if lambdaMax<=lambdaPeak + lambdaMax=lambdaPeak*factor*factor; + end + end + lambda=lambda*factor; + %%%% increase lambda (up to 1e20) + if abs(lambda) > 1e20; + %%%% if lambda has been increased up to the limit and you have not made any imporvement: + %%%% let it be known and quit trying + retcode = 5; + done =1; + end + + else + %%%% If growthSignal=shrinkSignal=0 you found a good lambda + %%%% you are done + + done=1; + if factor < 1.2 + retcode=7; + else + retcode=0; + end + end + end +end +if Verbose + disp(sprintf('Norm of dx %10.5g', dxnorm)) +end \ No newline at end of file diff --git a/toolbox/hpdint.m b/toolbox/hpdint.m new file mode 100644 index 0000000..c373a00 --- /dev/null +++ b/toolbox/hpdint.m @@ -0,0 +1,37 @@ +function hpdband = hpdint(draws,percent,short); +%% input: +%% draws: [ndraws x drawdim] matrix +%% percent: peremtage WITHIN bands (say .9 to have 90% of mass within the bands) +%% short = 1, if choose shortest interval, otherwise just chop off lowest and highest percent/2 +%% output: +%% hpbands: [2 x drawdim] matrix, first row: lower band, second row: upper band + +[ndraws,drawdim] = size(draws); +hpdband = zeros(2,drawdim); +nwidth = round(percent*ndraws); + +for i = 1:drawdim; + drawcoli = draws(:,i); + % sort response for period i, element 1 is max + drawcoli = flipud(sort(drawcoli)); + if short + bup = 1; + minwidth = drawcoli(1) - drawcoli(nwidth); + done = 0; + j = 2; + while j <= (ndraws-nwidth+1) + newwidth = drawcoli(j) - drawcoli(j+nwidth-1); + if newwidth < minwidth; + bup = j; + minwidth = newwidth; + end; + j = j+1; + end; + + else + bup = ndraws-nwidth-floor(.5*(ndraws-nwidth)); + end + + hpdband(2,i) = drawcoli(bup); + hpdband(1,i) = drawcoli(bup+nwidth-1); +end; diff --git a/toolbox/invtrans.m b/toolbox/invtrans.m new file mode 100644 index 0000000..225344b --- /dev/null +++ b/toolbox/invtrans.m @@ -0,0 +1,20 @@ +function para = invtrans(para,trspec); +% this procedure transforms variables from model to max +% Note that the max parameter do not contain para 8 and 9 + + npara = size(para,1); + + for i = 1:npara + + a = trspec(i,2); + b = trspec(i,3); + c = trspec(i,4); + + if trspec(i,1) == 1; + cx = 2*(para(i)-(a+b)/2)/(b-a); + para(i) = (1/c)*cx/sqrt(1-cx^2); + elseif trspec(i,1) == 2; + para(i) = b + (1/c)*log(para(i)-a); + end + + end diff --git a/toolbox/lyap_nonstationary.m b/toolbox/lyap_nonstationary.m new file mode 100644 index 0000000..cdaadde --- /dev/null +++ b/toolbox/lyap_nonstationary.m @@ -0,0 +1,53 @@ +function [A0,P0] = lyap_nonstationary(mspec,para,T,R,Q) + +switch mspec + case {557 5571 558} + i = getState(mspec,0,'zlev_t'); + A0 = zeros(size(T,1),1); + A0(i) = para(5); + + T_tr = T([1:i-1 i+1:end],[1:i-1 i+1:end]); + R_tr = R([1:i-1 i+1:end],:); + + P0_tr = dlyap(T_tr,R_tr*Q*R_tr'); + + P0 = zeros(size(T)); + + P0(1:i-1,1:i-1) = P0_tr(1:i-1,1:i-1); + P0(1:i-1,i+1:end) = P0_tr(1:i-1,i:end); + P0(i+1:end,1:i-1) = P0_tr(i:end,1:i-1); + P0(i+1:end,i+1:end) = P0_tr(i:end,i:end); + case {904, 9043, 90451} + if mspec == 90451 + i1 = getState(mspec,0,'ztil_t'); + A0 = zeros(size(T,1),1); + + + [nrT, ncT] = size(T); + nrR = size(R,1); + + irT = 1:nrT; + irT([i1]) = []; + icT = 1:ncT; + icT([i1]) = []; + + irR = 1:nrR; + irR([i1]) = []; + + T_tr = T(irT, icT); + R_tr = R(irR,:); + + P0_tr = dlyap(T_tr,R_tr*Q*R_tr'); + + P0 = zeros(size(T)); + + P0(irT, icT) = P0_tr; + else + A0 = zeros(size(T,1),1); + P0 = dlyap(T,R*Q*R'); + end + otherwise + A0 = zeros(size(T,1),1); + P0 = dlyap(T,R*Q*R'); +end + diff --git a/toolbox/numgrad.m b/toolbox/numgrad.m new file mode 100644 index 0000000..023282e --- /dev/null +++ b/toolbox/numgrad.m @@ -0,0 +1,104 @@ +function [g, badg] = numgrad(fcn,x,varargin) +% function [g badg] = numgrad(fcn,xvarargin) +% +delta = 1e-6; +n=length(x); +tvec=delta*eye(n); +g=zeros(n,1); +%--------------------old way to deal with variable # of P's-------------- +%tailstr = ')'; +%stailstr = []; +%for i=nargin-2:-1:1 +% tailstr=[ ',P' num2str(i) tailstr]; +% stailstr=[' P' num2str(i) stailstr]; +%end +%f0 = eval([fcn '(x' tailstr]); % Is there a way not to do this? +%---------------------------------------------------------------^yes +f0 = eval([fcn '(x,varargin{:})']); + +%fprintf(1,'f0= %2.4f ',f0) + +% disp(' first fcn in numgrad.m ------------------') +%home +% disp('numgrad.m is working. ----') % Jiinil on 9/5/95 +% sizex=size(x),sizetvec=size(tvec),x, % Jinill on 9/6/95 +badg=0; +for i=1:n + scale=1; % originally 1 + % i,tveci=tvec(:,i)% ,plus=x+scale*tvec(:,i) % Jinill Kim on 9/6/95 + if size(x,1)>size(x,2) + tvecv=tvec(i,:); + else + tvecv=tvec(:,i); + end + +%f1 = eval([fcn '(x+scale*tvecv'', varargin{:})']); +%fprintf(1,'i = %2.0f f1= %2.4f f0= %2.4f f1-f0= %2.4f (f1-f0)/delta= %2.4f \n',[i,f0,f1,f1-f0,(f1-f0)/delta]) +%if abs(f1-f0) > 1e-10; pause; end; + + g0 = (eval([fcn '(x+scale*tvecv'', varargin{:})']) - f0) ... + /(scale*delta); + % disp(' fcn in the i=1:n loop of numgrad.m ------------------')% Jinill 9/6/95 + % disp(' and i is') % Jinill + % i % Jinill + % fprintf('Gradient w.r.t. %3d: %10g\n',i,g0) %see below Jinill 9/6/95 +% -------------------------- special code to essentially quit here + % absg0=abs(g0) % Jinill on 9/6/95 + if abs(g0)< 1e15 + g(i)=g0; + % disp('good gradient') % Jinill Kim + else + disp('bad gradient ------------------------') % Jinill Kim + % fprintf('Gradient w.r.t. %3d: %10g\n',i,g0) %see above + g(i)=0; + badg=1; + % return + % can return here to save time if the gradient will never be + % used when badg returns as true. + end +end +%------------------------------------------------------------- +% if g0 > 0 +% sided=2; +% g1 = -(eval([fcn '(x-scale*tvec(:,i)''' tailstr]) - f0) ... +% /(scale*delta); +% if g1<0 +% scale = scale/10; +% else +% break +% end +% else +% sided=1; +% break +% end +% end +% if sided==1 +% g(i)=g0; +% else +% if (g0<1e20) +% if (g1>-1e20) +% g(i)=(g0+g1)/2; +% else +% g(i)=0; +% badg=1; +% disp( ['Banging against wall, parameter ' int2str(i)] ); +% end +% else +% if g1>-1e20 +% if g1<0 +% g(i)=0; +% badg=1; +% disp( ['Banging against wall, parameter ' int2str(i)] ); +% else +% g(i)=g1; +% end +% else +% g(i)=0; +% badg=1; +% disp(['Valley around parameter ' int2str(i)]) +% end +% end +% end +%end +%save g.dat g x f0 +%eval(['save g g x f0 ' stailstr]); diff --git a/toolbox/priodens.m b/toolbox/priodens.m new file mode 100644 index 0000000..54cd504 --- /dev/null +++ b/toolbox/priodens.m @@ -0,0 +1,70 @@ +function lnprior = priodens(para,pmean,pstdd,pshape); +% This procedure computes a prior density for +% the structural parameters of the DSGE models +% pshape: 0 is point mass, both para and pstdd are ignored +% 1 is BETA(mean,stdd) +% 2 is GAMMA(mean,stdd) +% 3 is NORMAL(mean,stdd) +% 4 is INVGAMMA(s^2,nu) + + lnprior = 0; + a = 0; + b = 0; + + nprio = size(pshape,1); + prioinfo = [zeros(nprio,2),pshape]; + + for i = 1:nprio; + if prioinfo(i,3) == 1; % BETA Prior %%check this distr + a = (1-pmean(i))*pmean(i)^2/pstdd(i)^2 - pmean(i); + b = a*(1/pmean(i) - 1); + lnprior = lnprior + (a-1)*log(para(i))+(b-1)*log((1-para(i)))-betaln(a,b); + + elseif prioinfo(i,3) == 2; % GAMMA PRIOR + b = pstdd(i)^2/pmean(i); + a = pmean(i)/b; + lnprior = lnprior + (a-1)*log(para(i))-(para(i)/b)-gammaln(a)-a*log(b); + elseif prioinfo(i,3) == 3; % GAUSSIAN PRIOR + a = pmean(i); + b = pstdd(i); + lnprior = lnprior -0.5*log(2*pi)-log(b)-0.5*(para(i)-a)^2/b^2; + elseif prioinfo(i,3) == 4; % INVGAMMA PRIOR + a = pmean(i); + b = pstdd(i); + %a= (.0264/b).^.5 + %para(i) + lnprior = lnprior +log(2)-gammaln(b/2)+(b/2)*log(b*a^2/2)-((b+1)/2)*log(para(i)^2)-b*a^2/(2*para(i)^2); + %v =log(2)-gammaln(b/2)+(b/2)*log(b*a^2/2)-((b+1)/2)*log(para(i)^2)-b*a^2/(2*para(i)^2) + elseif prioinfo(i,3) == 5; % UNIFORM PRIOR pmean(i)=leftbound, pstdd(i)=rightbound + a = pmean(i);% - sqrt(3)*pstdd(i); + b = pstdd(i);% + sqrt(3)*pstdd(i); + if para(i)>=a && para(i)<=b + lnprior = lnprior + log(1/(b-a)); + else + lnprior = lnprior + log(0); + end + end + + prioinfo(i,1) = a; + prioinfo(i,2) = b; + end + + % + %prioinfo; + % + % to run this part, introduce local variables x and y + %graphset; + %begwind; + %window(3,3,0); + %i = 1; + %do until i > nprio; + % if prioinfo(i,3) == 1; + % x = seqa(0.01,0.01,98); + % y = exp(lpdfbeta(x,prioinfo(i,1),prioinfo(i,2))); + % xy(x,y); + % endif; + % nextwind; + % i=i+1; + %endo; + %endwind; + diff --git a/toolbox/trans.m b/toolbox/trans.m new file mode 100644 index 0000000..163509c --- /dev/null +++ b/toolbox/trans.m @@ -0,0 +1,22 @@ +function para = trans(para,trspec); +% this procedure transforms variables from max to model + + npara = size(para,1); + + for i = 1:npara + + a = trspec(i,2); + b = trspec(i,3); + c = trspec(i,4); + + if trspec(i,1) == 1; + + para(i) = (a+b)/2 + 0.5*(b-a)*c*para(i)/sqrt(1+c^2*para(i)^2); + + % para(i) = a + (b-a)*cdfn(c*para(i)); + + elseif trspec(i,1) ==2; + para(i) = a + exp(c*(para(i)-b)); + end + + end \ No newline at end of file