From 8541579d482feb64fcf676875096c9058382418e Mon Sep 17 00:00:00 2001 From: Houtan Bastani Date: Tue, 5 Dec 2017 17:44:23 +0100 Subject: [PATCH] pooled_ols: support endogenous without parameters on RHS --- matlab/ols/dyn_ols.m | 32 +-------- matlab/ols/getRhsToSubFromLhs.m | 72 +++++++++++++++++++++ matlab/ols/pooled_ols.m | 40 +++++++++--- tests/ECB/pooled_fgls/run_simulation_test.m | 8 +++ tests/ECB/pooled_ols/run_simulation_test.m | 8 +++ 5 files changed, 122 insertions(+), 38 deletions(-) create mode 100644 matlab/ols/getRhsToSubFromLhs.m diff --git a/matlab/ols/dyn_ols.m b/matlab/ols/dyn_ols.m index 4a735cf7e..ddcaace57 100644 --- a/matlab/ols/dyn_ols.m +++ b/matlab/ols/dyn_ols.m @@ -143,36 +143,8 @@ for i = 1:length(lhs) X = [X Xtmp]; end - lhssub = dseries(); - rhs_ = strsplit(rhs{i}, [splitstrings; pnames]); - for j = 1:length(rhs_) - rhsj = rhs_{j}; - while ~isempty(rhsj) - minusstr = ''; - if strcmp(rhsj(1), '-') || strcmp(rhsj(1), '+') - if length(rhsj) == 1 - break - end - if strcmp(rhsj(1), '-') - minusstr = '-'; - end - rhsj = rhsj(2:end); - end - str = getStrMoveRight(rhsj); - if ~isempty(str) - try - lhssub = [lhssub eval(regexprep([minusstr str], regex, 'ds.$&'))]; - lhssub.rename_(lhssub{lhssub.vobs}.name{:}, [minusstr str]); - catch - if ~any(strcmp(M_exo_trim, str)) - error(['dyn_ols: problem evaluating ' minusstr str]); - end - end - rhsj = rhsj(length(str)+1:end); - end - end - end - + lhssub = getRhsToSubFromLhs(ds, rhs{i}, regex, [splitstrings; pnames]); + Y = eval(regexprep(lhs{i}, regex, 'ds.$&')); for j = 1:lhssub.vobs Y = Y - lhssub{j}; diff --git a/matlab/ols/getRhsToSubFromLhs.m b/matlab/ols/getRhsToSubFromLhs.m new file mode 100644 index 000000000..9fa0674ac --- /dev/null +++ b/matlab/ols/getRhsToSubFromLhs.m @@ -0,0 +1,72 @@ +function lhssub = getRhsToSubFromLhs(ds, rhs, regex, splits) +%function lhssub = getRhsToSubFromLhs(ds, rhs, regex, splits) +% Helper function that identifies variables on RHS that need to be +% subtracted from LHS of OLS-style equation +% +% INPUTS +% ds [dseries] data +% rhs [string] RHS as a string +% regex [string] regex expressing valid list of variables +% splits [cell array] strings to split out of equation on RHS +% +% OUTPUTS +% lhssub [dseries] data to subtract from LHS +% +% SPECIAL REQUIREMENTS +% none + +% Copyright (C) 2017 Dynare Team +% +% This file is part of Dynare. +% +% Dynare is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% Dynare is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with Dynare. If not, see . + +global M_ + +assert(isdseries(ds), 'The first argument must be a dseries'); +assert(ischar(rhs), 'The second argument must be a string'); +assert(ischar(regex), 'The third argument must be a string'); +assert(iscell(splits), 'The fourth argument must be a cell'); + +M_exo_trim = cellstr(M_.exo_names); +lhssub = dseries(); +rhs_ = strsplit(rhs, splits); +for j = 1:length(rhs_) + rhsj = rhs_{j}; + while ~isempty(rhsj) + minusstr = ''; + if strcmp(rhsj(1), '-') || strcmp(rhsj(1), '+') + if length(rhsj) == 1 + break + end + if strcmp(rhsj(1), '-') + minusstr = '-'; + end + rhsj = rhsj(2:end); + end + str = getStrMoveRight(rhsj); + if ~isempty(str) + try + lhssub = [lhssub eval(regexprep([minusstr str], regex, 'ds.$&'))]; + lhssub.rename_(lhssub{lhssub.vobs}.name{:}, [minusstr str]); + catch + if ~any(strcmp(M_exo_trim, str)) + error(['pooled_ols: problem evaluating ' minusstr str]); + end + end + rhsj = rhsj(length(str)+1:end); + end + end +end +end \ No newline at end of file diff --git a/matlab/ols/pooled_ols.m b/matlab/ols/pooled_ols.m index 4fe671fc8..32b04090b 100644 --- a/matlab/ols/pooled_ols.m +++ b/matlab/ols/pooled_ols.m @@ -114,6 +114,7 @@ for i = 1:length(lhs) pnames = intersect(rhs_, M_param_names_trim); pidxs = zeros(length(pnames), 1); vnames = cell(1, length(pnames)); + splitstrings = cell(length(pnames), 1); xjdata = dseries; for j = 1:length(pnames) createdvar = false; @@ -137,8 +138,14 @@ for i = 1:length(lhs) getStrMoveRight(rhs{i}(endidx+1:end))]; elseif rhs{i}(startidx) == '*' vnames{j} = getStrMoveLeft(rhs{i}(1:startidx-1)); + splitstrings{j} = [vnames{j} '*' pnames{j}]; elseif rhs{i}(endidx) == '*' vnames{j} = getStrMoveRight(rhs{i}(endidx+1:end)); + splitstrings{j} = [pnames{j} '*' vnames{j}]; + if rhs{i}(startidx) == '-' + vnames{j} = ['-' vnames{j}]; + splitstrings{j} = ['-' splitstrings{j}]; + end elseif rhs{i}(startidx) == '+' ... || rhs{i}(startidx) == '-' ... || rhs{i}(endidx) == '+' ... @@ -152,6 +159,7 @@ for i = 1:length(lhs) else vnames{j} = 'intercept'; end + splitstrings{j} = vnames{j}; else error('pooled_ols: Shouldn''t arrive here'); end @@ -165,6 +173,8 @@ for i = 1:length(lhs) xjdata = [xjdata xjdatatmp]; end + lhssub = getRhsToSubFromLhs(ds, rhs{i}, regex, [splitstrings; pnames]); + residuals = intersect(rhs_, cellstr(M_.exo_names)); justvnames = regexprep(vnames, '\(-\d\)|log|exp|log10|[\(\)]', ''); justvnames = regexp(justvnames, '[-+]', 'split'); @@ -183,15 +193,29 @@ for i = 1:length(lhs) vars{i} = [vnames{:}]; ydata = eval(regexprep(lhs{i}, regex, 'ds.$&')); + for j = 1:lhssub.vobs + ydata = ydata - lhssub{j}; + end - fp = max(ydata.firstobservedperiod, xjdata.firstobservedperiod); - lp = min(ydata.lastobservedperiod, xjdata.lastobservedperiod); - - startidxs(i) = length(Y) + 1; - startdates{i} = fp; - enddates{i} = lp; - Y(startidxs(i):startidxs(i)+lp-fp, 1) = ydata(fp:lp).data; - X(startidxs(i):startidxs(i)+lp-fp, pidxs) = xjdata(fp:lp).data; + if isempty(xjdata) + % AR(1) case + fp = ydata.firstobservedperiod; + lp = ydata.lastobservedperiod; + startidxs(i) = length(Y) + 1; + startdates{i} = fp; + enddates{i} = lp; + Y(startidxs(i):startidxs(i)+lp-fp, 1) = ydata(fp:lp).data; + X(startidxs(i):startidxs(i)+lp-fp, :) = zeros(ydata(fp:lp).nobs, columns(X)); + else + fp = max(ydata.firstobservedperiod, xjdata.firstobservedperiod); + lp = min(ydata.lastobservedperiod, xjdata.lastobservedperiod); + + startidxs(i) = length(Y) + 1; + startdates{i} = fp; + enddates{i} = lp; + Y(startidxs(i):startidxs(i)+lp-fp, 1) = ydata(fp:lp).data; + X(startidxs(i):startidxs(i)+lp-fp, pidxs) = xjdata(fp:lp).data; + end end if overlapping_dates diff --git a/tests/ECB/pooled_fgls/run_simulation_test.m b/tests/ECB/pooled_fgls/run_simulation_test.m index f2a94c933..e3a27459f 100644 --- a/tests/ECB/pooled_fgls/run_simulation_test.m +++ b/tests/ECB/pooled_fgls/run_simulation_test.m @@ -19,6 +19,14 @@ for i=1:NSIMS M_.Sigma_e = Sigma_e; simdata = simul_backward_model(dseries(firstobs, dates('1995Q1'), M_endo_names_trim), 10000); simdata = simdata(simdata.dates(5001:6000)); + names=regexp(simdata.name, 'res\w*'); + idxs = []; + for i=1:length(names) + if isempty(names{i}) + idxs = [idxs i]; + end + end + simdata = simdata{idxs}; pooled_fgls(simdata, ... {'de','u2'}, ... {'*_q_yed_ecm_*_q_yed_L1', ... diff --git a/tests/ECB/pooled_ols/run_simulation_test.m b/tests/ECB/pooled_ols/run_simulation_test.m index 4896c8855..181b03e3b 100644 --- a/tests/ECB/pooled_ols/run_simulation_test.m +++ b/tests/ECB/pooled_ols/run_simulation_test.m @@ -19,6 +19,14 @@ for i=1:NSIMS M_.Sigma_e = Sigma_e; simdata = simul_backward_model(dseries(firstobs, dates('1995Q1'), M_endo_names_trim), 10000); simdata = simdata(simdata.dates(5001:6000)); + names=regexp(simdata.name, 'res\w*'); + idxs = []; + for j=1:length(names) + if isempty(names{j}) + idxs = [idxs j]; + end + end + simdata = simdata{idxs}; pooled_ols(simdata, ... {'de','u2'}, ... {'*_q_yed_ecm_*_q_yed_L1', ...