ols: further simplifications
parent
a35fd291c5
commit
a477075825
|
@ -1,15 +1,19 @@
|
||||||
function [X, Y, startdates, enddates, startidxs, residnames, pbeta, vars, surpidxs, surconstrainedparams] = pooled_sur_common(ds, jsonmodel)
|
function [Y, lhssub, X, startdates, enddates, startidxs, residnames, pbeta, vars, surpidxs, surconestrainedparams] = common_parsing(ds, ast, jsonmodel, overlapping_dates)
|
||||||
%function [X, Y, startdates, enddates, startidxs, residnames, pbeta, vars, surpidxs, surconstrainedparams] = pooled_sur_common(ds, jsonmodel)
|
%function [Y, lhssub, X, startdates, enddates, startidxs, residnames, pbeta, vars, surpidxs, surconstrainedparams] = common_parsing(ds, ast, jsonmodel, overlapping_dates)
|
||||||
%
|
%
|
||||||
% Code common to sur.m and pooled_ols.m
|
% Code common to sur.m and pooled_ols.m
|
||||||
%
|
%
|
||||||
% INPUTS
|
% INPUTS
|
||||||
% ds [dseries] dataset
|
% ds [dseries] dataset
|
||||||
|
% ast [cell array] JSON representation of abstract syntax tree
|
||||||
% jsonmodel [cell array] JSON representation of model block
|
% jsonmodel [cell array] JSON representation of model block
|
||||||
|
% overlapping_dates [boolean] if true, dates are same across
|
||||||
|
% equations
|
||||||
%
|
%
|
||||||
% OUTPUTS
|
% OUTPUTS
|
||||||
% X [matrix] regressors
|
% Y [cell array] dependent variables
|
||||||
% Y [vector] dependent variables
|
% lhssub [cell array] RHS to subtract from Y
|
||||||
|
% X [cell array] regressors
|
||||||
% startdates [cell array] first observed period for each
|
% startdates [cell array] first observed period for each
|
||||||
% equation
|
% equation
|
||||||
% enddates [cell array] last observed period for each
|
% enddates [cell array] last observed period for each
|
||||||
|
@ -29,7 +33,7 @@ function [X, Y, startdates, enddates, startidxs, residnames, pbeta, vars, surpid
|
||||||
% SPECIAL REQUIREMENTS
|
% SPECIAL REQUIREMENTS
|
||||||
% none
|
% none
|
||||||
|
|
||||||
% Copyright (C) 2017-2018 Dynare Team
|
% Copyright (C) 2019 Dynare Team
|
||||||
%
|
%
|
||||||
% This file is part of Dynare.
|
% This file is part of Dynare.
|
||||||
%
|
%
|
||||||
|
@ -46,7 +50,43 @@ function [X, Y, startdates, enddates, startidxs, residnames, pbeta, vars, surpid
|
||||||
% You should have received a copy of the GNU General Public License
|
% You should have received a copy of the GNU General Public License
|
||||||
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
global M_
|
|
||||||
|
%% Initialize variables
|
||||||
|
Y = cell(length(ast), 1);
|
||||||
|
lhssub = cell(length(ast), 1);
|
||||||
|
X = cell(length(ast), 1);
|
||||||
|
startdates = cell(length(ast), 1);
|
||||||
|
enddates = cell(length(ast), 1);
|
||||||
|
|
||||||
|
%% Loop over equations
|
||||||
|
neqs = length(ast);
|
||||||
|
for i = 1:neqs
|
||||||
|
%% Parse equation i
|
||||||
|
[Y{i}, lhssub{i}, X{i}] = parse_ols_style_equation(ds, ast{i}, jsonmodel{i}.line);
|
||||||
|
|
||||||
|
%% Set start and end dates
|
||||||
|
if overlapping_dates
|
||||||
|
[startdates{i}, enddates{i}] = get_ols_start_end_dates(Y{i}, lhssub{i}, X{i}, jsonmodel{i});
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if overlapping_dates
|
||||||
|
maxfp = max([startdates{:}]);
|
||||||
|
minlp = min([enddates{:}]);
|
||||||
|
for i = 1:neqs
|
||||||
|
Y{i} = Y{i}(maxfp:minlp);
|
||||||
|
X{i} = X{i}(maxfp:minlp);
|
||||||
|
if ~isempty(lhssub{i})
|
||||||
|
lhssub{i} = lhssub{i}(maxfp:minlp);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return
|
||||||
|
%%
|
||||||
|
|
||||||
|
|
||||||
M_endo_exo_names_trim = [M_.endo_names; M_.exo_names];
|
M_endo_exo_names_trim = [M_.endo_names; M_.exo_names];
|
||||||
[junk, idxs] = sort(cellfun(@length, M_endo_exo_names_trim), 'descend');
|
[junk, idxs] = sort(cellfun(@length, M_endo_exo_names_trim), 'descend');
|
|
@ -41,7 +41,7 @@ function varargout = dyn_ols(ds, fitted_names_dict, eqtags)
|
||||||
|
|
||||||
global M_ oo_ options_
|
global M_ oo_ options_
|
||||||
|
|
||||||
assert(nargin >= 1 && nargin <= 3, 'dyn_ols: takes between 1 and 3 arguments');
|
assert(nargin >= 1 && nargin <= 3, 'dyn_ols() takes between 1 and 3 arguments');
|
||||||
assert(~isempty(ds) && isdseries(ds), 'dyn_ols: the first argument must be a dseries');
|
assert(~isempty(ds) && isdseries(ds), 'dyn_ols: the first argument must be a dseries');
|
||||||
|
|
||||||
jsonfile = [M_.fname filesep() 'model' filesep() 'json' filesep() 'modfile-original.json'];
|
jsonfile = [M_.fname filesep() 'model' filesep() 'json' filesep() 'modfile-original.json'];
|
||||||
|
@ -77,54 +77,21 @@ if strcmp(st(1).name, 'olsgibbs')
|
||||||
assert(length(ast) == 1);
|
assert(length(ast) == 1);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
%% Parse equations
|
||||||
|
[Y, lhssub, X, fp, lp ] = common_parsing(ds, ast, jsonmodel, true);
|
||||||
|
|
||||||
%% Loop over equations
|
%% Loop over equations
|
||||||
for i = 1:length(ast)
|
for i = 1:length(Y)
|
||||||
%% Parse equation i
|
pnames = X{i}.name;
|
||||||
[Y, lhssub, X] = parse_ols_style_equation(ds, ast{i}, jsonmodel{i}.line);
|
[nobs, nvars] = size(X{i}.data);
|
||||||
|
|
||||||
%% Set dates
|
|
||||||
fp = max(Y.firstobservedperiod, X.firstobservedperiod);
|
|
||||||
lp = min(Y.lastobservedperiod, X.lastobservedperiod);
|
|
||||||
if ~isempty(lhssub)
|
|
||||||
fp = max(fp, lhssub.firstobservedperiod);
|
|
||||||
lp = min(lp, lhssub.lastobservedperiod);
|
|
||||||
end
|
|
||||||
if isfield(jsonmodel{i}, 'tags') ...
|
|
||||||
&& isfield(jsonmodel{i}.tags, 'sample') ...
|
|
||||||
&& ~isempty(jsonmodel{i}.tags.sample)
|
|
||||||
colon_idx = strfind(jsonmodel{i}.tags.sample, ':');
|
|
||||||
fsd = dates(jsonmodel{i}.tags.sample(1:colon_idx-1));
|
|
||||||
lsd = dates(jsonmodel{i}.tags.sample(colon_idx+1:end));
|
|
||||||
if fp > fsd
|
|
||||||
warning(['The sample over which you want to estimate contains NaNs. '...
|
|
||||||
'Adjusting estimation range to begin on: ' fp.char])
|
|
||||||
else
|
|
||||||
fp = fsd;
|
|
||||||
end
|
|
||||||
if lp < lsd
|
|
||||||
warning(['The sample over which you want to estimate contains NaNs. '...
|
|
||||||
'Adjusting estimation range to end on: ' lp.char])
|
|
||||||
else
|
|
||||||
lp = lsd;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Y = Y(fp:lp);
|
|
||||||
if ~isempty(lhssub)
|
|
||||||
lhssub = lhssub(fp:lp);
|
|
||||||
end
|
|
||||||
pnames = X.name;
|
|
||||||
X = X(fp:lp).data;
|
|
||||||
|
|
||||||
[nobs, nvars] = size(X);
|
|
||||||
if called_from_olsgibbs
|
if called_from_olsgibbs
|
||||||
varargout{1} = nobs;
|
varargout{1} = nobs;
|
||||||
varargout{2} = pnames;
|
varargout{2} = pnames;
|
||||||
varargout{3} = X;
|
varargout{3} = X{i}.data;
|
||||||
varargout{4} = Y.data;
|
varargout{4} = Y{i}.data;
|
||||||
varargout{5} = jsonmodel;
|
varargout{5} = jsonmodel;
|
||||||
varargout{6} = fp;
|
varargout{6} = fp{i};
|
||||||
varargout{7} = lp;
|
varargout{7} = lp{i};
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -140,9 +107,9 @@ for i = 1:length(ast)
|
||||||
oo_.ols.(tag).dof = nobs - nvars;
|
oo_.ols.(tag).dof = nobs - nvars;
|
||||||
|
|
||||||
% Estimated Parameters
|
% Estimated Parameters
|
||||||
[q, r] = qr(X, 0);
|
[q, r] = qr(X{i}.data, 0);
|
||||||
xpxi = (r'*r)\eye(nvars);
|
xpxi = (r'*r)\eye(nvars);
|
||||||
oo_.ols.(tag).beta = r\(q'*Y.data);
|
oo_.ols.(tag).beta = r\(q'*Y{i}.data);
|
||||||
oo_.ols.(tag).param_idxs = zeros(length(pnames), 1);
|
oo_.ols.(tag).param_idxs = zeros(length(pnames), 1);
|
||||||
for j = 1:length(pnames)
|
for j = 1:length(pnames)
|
||||||
if ~strcmp(pnames{j}, 'intercept')
|
if ~strcmp(pnames{j}, 'intercept')
|
||||||
|
@ -160,14 +127,14 @@ for i = 1:length(ast)
|
||||||
yhatname = fitted_names_dict{idx, 2};
|
yhatname = fitted_names_dict{idx, 2};
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
oo_.ols.(tag).Yhat = dseries(X*oo_.ols.(tag).beta, fp, yhatname);
|
oo_.ols.(tag).Yhat = dseries(X{i}.data*oo_.ols.(tag).beta, fp{i}, yhatname);
|
||||||
|
|
||||||
% Residuals
|
% Residuals
|
||||||
oo_.ols.(tag).resid = Y - oo_.ols.(tag).Yhat;
|
oo_.ols.(tag).resid = Y{i} - oo_.ols.(tag).Yhat;
|
||||||
|
|
||||||
% Correct Yhat reported back to user
|
% Correct Yhat reported back to user
|
||||||
Y = Y + lhssub;
|
Y{i} = Y{i} + lhssub{i};
|
||||||
oo_.ols.(tag).Yhat = oo_.ols.(tag).Yhat + lhssub;
|
oo_.ols.(tag).Yhat = oo_.ols.(tag).Yhat + lhssub{i};
|
||||||
|
|
||||||
% Apply correcting function for Yhat if it was passed
|
% Apply correcting function for Yhat if it was passed
|
||||||
if any(idx) ...
|
if any(idx) ...
|
||||||
|
@ -184,7 +151,7 @@ for i = 1:length(ast)
|
||||||
oo_.ols.(tag).s2 = SS_res/oo_.ols.(tag).dof;
|
oo_.ols.(tag).s2 = SS_res/oo_.ols.(tag).dof;
|
||||||
|
|
||||||
% R^2
|
% R^2
|
||||||
ym = Y.data - mean(Y);
|
ym = Y{i}.data - mean(Y{i});
|
||||||
SS_tot = ym'*ym;
|
SS_tot = ym'*ym;
|
||||||
oo_.ols.(tag).R2 = 1 - SS_res/SS_tot;
|
oo_.ols.(tag).R2 = 1 - SS_res/SS_tot;
|
||||||
|
|
||||||
|
@ -211,7 +178,7 @@ for i = 1:length(ast)
|
||||||
|
|
||||||
preamble = {sprintf('Dependent Variable: %s', jsonmodel{i}.lhs), ...
|
preamble = {sprintf('Dependent Variable: %s', jsonmodel{i}.lhs), ...
|
||||||
sprintf('No. Independent Variables: %d', nvars), ...
|
sprintf('No. Independent Variables: %d', nvars), ...
|
||||||
sprintf('Observations: %d from %s to %s\n', nobs, fp.char, lp.char)};
|
sprintf('Observations: %d from %s to %s\n', nobs, fp{i}.char, lp{i}.char)};
|
||||||
|
|
||||||
afterward = {sprintf('R^2: %f', oo_.ols.(tag).R2), ...
|
afterward = {sprintf('R^2: %f', oo_.ols.(tag).R2), ...
|
||||||
sprintf('R^2 Adjusted: %f', oo_.ols.(tag).adjR2), ...
|
sprintf('R^2 Adjusted: %f', oo_.ols.(tag).adjR2), ...
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
function [ast, jsonmodel] = get_ast_jsonmodel(eqtags)
|
||||||
|
% function [ast, jsonmodel] = get_ast_jsonmodel(eqtags)
|
||||||
|
% return AST and jsonmodel from json output of preprocessor for the given
|
||||||
|
% equation tags.
|
||||||
|
%
|
||||||
|
% INPUTS
|
||||||
|
% eqtags [cellstr] names of equation tags for which to get info.
|
||||||
|
% If empty, get all
|
||||||
|
%
|
||||||
|
% OUTPUTS
|
||||||
|
% ast [cell array] JSON representation of the abstract syntax tree
|
||||||
|
% jsonmodel [cell array] JSON representation of the model block
|
||||||
|
%
|
||||||
|
% SPECIAL REQUIREMENTS
|
||||||
|
% none
|
||||||
|
|
||||||
|
% Copyright (C) 2019 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
global M_
|
||||||
|
|
||||||
|
if ~isempty(eqtags) && ~(ischar(eqtags) || iscell(eqtags))
|
||||||
|
error('get_ast_jsonmodel: eqtags not passed correctly')
|
||||||
|
end
|
||||||
|
|
||||||
|
jsonfile = [M_.fname filesep() 'model' filesep() 'json' filesep() 'modfile-original.json'];
|
||||||
|
if exist(jsonfile, 'file') ~= 2
|
||||||
|
error('Could not find %s! Please use the json=compute option (See the Dynare invocation section in the reference manual).', jsonfile);
|
||||||
|
end
|
||||||
|
|
||||||
|
jsonmodel = loadjson(jsonfile);
|
||||||
|
ast = jsonmodel.abstract_syntax_tree;
|
||||||
|
jsonmodel = jsonmodel.model;
|
||||||
|
if ~isempty(eqtags)
|
||||||
|
ast = getEquationsByTags(ast, 'name', eqtags);
|
||||||
|
jsonmodel = getEquationsByTags(jsonmodel, 'name', eqtags);
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,30 @@
|
||||||
|
function [fp, lp] = get_ols_start_end_dates(Y, lhssub, X, jsonmodel)
|
||||||
|
% function [fp, lp] = get_ols_start_end_dates(Y, lhssub, X, jsonmodel)
|
||||||
|
|
||||||
|
fp = max(Y.firstobservedperiod, X.firstobservedperiod);
|
||||||
|
lp = min(Y.lastobservedperiod, X.lastobservedperiod);
|
||||||
|
if ~isempty(lhssub)
|
||||||
|
fp = max(fp, lhssub.firstobservedperiod);
|
||||||
|
lp = min(lp, lhssub.lastobservedperiod);
|
||||||
|
end
|
||||||
|
if isfield(jsonmodel, 'tags') ...
|
||||||
|
&& isfield(jsonmodel.tags, 'sample') ...
|
||||||
|
&& ~isempty(jsonmodel.tags.sample)
|
||||||
|
colon_idx = strfind(jsonmodel.tags.sample, ':');
|
||||||
|
fsd = dates(jsonmodel.tags.sample(1:colon_idx-1));
|
||||||
|
lsd = dates(jsonmodel.tags.sample(colon_idx+1:end));
|
||||||
|
if fp > fsd
|
||||||
|
warning(['The sample over which you want to estimate contains NaNs. '...
|
||||||
|
'Adjusting estimation range to begin on: ' fp.char])
|
||||||
|
else
|
||||||
|
fp = fsd;
|
||||||
|
end
|
||||||
|
if lp < lsd
|
||||||
|
warning(['The sample over which you want to estimate contains NaNs. '...
|
||||||
|
'Adjusting estimation range to end on: ' lp.char])
|
||||||
|
else
|
||||||
|
lp = lsd;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in New Issue