2018-01-24 15:22:30 +01:00
|
|
|
function varargout = sur(ds, param_names, eqtags)
|
|
|
|
%function varargout = sur(ds, param_names, eqtags)
|
2017-11-17 14:41:27 +01:00
|
|
|
% Seemingly Unrelated Regressions
|
|
|
|
%
|
|
|
|
% INPUTS
|
2018-01-16 18:42:15 +01:00
|
|
|
% ds [dseries] data to use in estimation
|
2018-01-24 15:22:30 +01:00
|
|
|
% param_names [cellstr] list of parameters to estimate
|
2018-01-16 18:42:15 +01:00
|
|
|
% eqtags [cellstr] names of equation tags to estimate. If empty,
|
|
|
|
% estimate all equations
|
2017-11-17 14:41:27 +01:00
|
|
|
%
|
|
|
|
% OUTPUTS
|
|
|
|
% none
|
|
|
|
%
|
|
|
|
% SPECIAL REQUIREMENTS
|
2019-01-24 12:42:08 +01:00
|
|
|
% dynare must have been run with the option: json=compute
|
2017-11-17 14:41:27 +01:00
|
|
|
|
2019-01-11 11:47:55 +01:00
|
|
|
% Copyright (C) 2017-2019 Dynare Team
|
2017-11-17 14:41:27 +01:00
|
|
|
%
|
|
|
|
% 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_ oo_ options_
|
|
|
|
|
|
|
|
%% Check input argument
|
2019-01-22 16:11:03 +01:00
|
|
|
if nargin < 1 || nargin > 3
|
|
|
|
error('function takes between 1 and 3 arguments');
|
|
|
|
end
|
2017-11-17 14:41:27 +01:00
|
|
|
|
2019-01-11 11:47:55 +01:00
|
|
|
if nargin < 3
|
|
|
|
eqtags = {};
|
2017-11-17 14:41:27 +01:00
|
|
|
end
|
|
|
|
|
2019-01-11 11:47:55 +01:00
|
|
|
if nargin < 2
|
|
|
|
param_names = {};
|
|
|
|
else
|
2019-01-22 16:11:03 +01:00
|
|
|
assert(iscellstr(param_names), 'the 2nd argument must be a cellstr');
|
2018-01-16 18:42:15 +01:00
|
|
|
end
|
2017-11-17 14:41:27 +01:00
|
|
|
|
2019-01-11 11:47:55 +01:00
|
|
|
%% Get Equation(s)
|
2019-01-22 00:57:24 +01:00
|
|
|
ast = get_ast(eqtags);
|
|
|
|
[ast, ds] = handle_constant_eqs(ast, ds);
|
|
|
|
neqs = length(ast);
|
2019-01-11 11:47:55 +01:00
|
|
|
|
2017-11-17 14:41:27 +01:00
|
|
|
%% Find parameters and variable names in equations and setup estimation matrices
|
2019-01-24 12:21:36 +01:00
|
|
|
[Y, lhssub, X] = common_parsing(ds, ast, true);
|
2019-01-22 00:57:24 +01:00
|
|
|
clear ast
|
2019-01-11 11:47:55 +01:00
|
|
|
nobs = Y{1}.nobs;
|
2019-01-24 12:21:36 +01:00
|
|
|
[Y, lhssub, X, constrained] = put_in_sur_form(Y, lhssub, X);
|
2017-11-17 14:41:27 +01:00
|
|
|
|
2018-01-16 18:42:15 +01:00
|
|
|
if nargin == 1 && size(X, 2) ~= M_.param_nbr
|
2019-01-11 11:47:55 +01:00
|
|
|
warning(['Not all parameters were used in model: ' strjoin(setdiff(M_.param_names, X.name), ', ')]);
|
2017-11-17 14:41:27 +01:00
|
|
|
end
|
|
|
|
|
2018-01-24 15:22:30 +01:00
|
|
|
if ~isempty(param_names)
|
2019-01-11 11:47:55 +01:00
|
|
|
newX = dseries();
|
2018-01-24 15:22:30 +01:00
|
|
|
nparams = length(param_names);
|
|
|
|
pidxs = zeros(nparams, 1);
|
2019-01-23 15:27:07 +01:00
|
|
|
names = X.name;
|
2018-01-24 15:22:30 +01:00
|
|
|
for i = 1:nparams
|
2019-01-23 15:27:07 +01:00
|
|
|
idx = find(strcmp(param_names{i}, names));
|
2019-01-11 11:47:55 +01:00
|
|
|
if isempty(idx)
|
2018-01-24 15:22:30 +01:00
|
|
|
if ~isempty(eqtags)
|
|
|
|
error(['Could not find ' param_names{i} ...
|
|
|
|
' in the provided equations specified by ' strjoin(eqtags, ',')]);
|
|
|
|
end
|
|
|
|
error('Unspecified error. Please report');
|
|
|
|
end
|
2019-01-11 11:47:55 +01:00
|
|
|
pidxs(i) = idx;
|
2019-01-23 15:27:07 +01:00
|
|
|
newX = [newX X.(names{idx})];
|
2019-01-11 11:47:55 +01:00
|
|
|
end
|
2019-01-23 15:25:49 +01:00
|
|
|
subcols = setdiff(1:X.vobs, pidxs);
|
2019-01-11 11:47:55 +01:00
|
|
|
for i = length(subcols):-1:1
|
2019-01-23 15:27:07 +01:00
|
|
|
Y = Y - M_.params(strcmp(names{subcols(i)}, M_.param_names))*X.(names{subcols(i)});
|
2018-01-24 15:22:30 +01:00
|
|
|
end
|
2019-01-11 11:47:55 +01:00
|
|
|
X = newX;
|
|
|
|
end
|
|
|
|
|
|
|
|
% opidxs: indexes in M_.params associated with columns of X
|
2019-01-23 15:25:49 +01:00
|
|
|
opidxs = zeros(X.vobs, 1);
|
|
|
|
for i = 1:X.vobs
|
2019-01-11 11:47:55 +01:00
|
|
|
opidxs(i, 1) = find(strcmp(X.name{i}, M_.param_names));
|
2018-01-24 15:22:30 +01:00
|
|
|
end
|
|
|
|
|
2018-01-11 11:18:47 +01:00
|
|
|
%% Return to surgibbs if called from there
|
|
|
|
st = dbstack(1);
|
|
|
|
if strcmp(st(1).name, 'surgibbs')
|
2019-01-11 16:44:49 +01:00
|
|
|
varargout{1} = nobs;
|
2018-01-29 15:26:28 +01:00
|
|
|
varargout{2} = opidxs;
|
2019-01-11 11:47:55 +01:00
|
|
|
varargout{3} = X.data;
|
|
|
|
varargout{4} = Y.data;
|
|
|
|
varargout{5} = neqs;
|
2018-01-11 11:18:47 +01:00
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2019-01-11 16:44:49 +01:00
|
|
|
% constrained_param_idxs: indexes in X.name of parameters that were constrained
|
|
|
|
constrained_param_idxs = [];
|
|
|
|
for i = 1:length(constrained)
|
|
|
|
idx = find(strcmp(X.name, constrained{i}));
|
|
|
|
if ~isempty(idx)
|
|
|
|
constrained_param_idxs(end+1, 1) = idx;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-11-17 14:41:27 +01:00
|
|
|
%% Estimation
|
2019-01-11 11:47:55 +01:00
|
|
|
oo_.sur.dof = nobs;
|
|
|
|
|
2017-11-17 14:41:27 +01:00
|
|
|
% Estimated Parameters
|
2019-01-11 11:47:55 +01:00
|
|
|
[q, r] = qr(X.data, 0);
|
|
|
|
xpxi = (r'*r)\eye(size(X.data, 2));
|
|
|
|
resid = Y.data - X.data * (r\(q'*Y.data));
|
|
|
|
resid = reshape(resid, oo_.sur.dof, neqs);
|
2017-11-17 14:41:27 +01:00
|
|
|
|
|
|
|
M_.Sigma_e = resid'*resid/oo_.sur.dof;
|
2017-12-18 15:01:09 +01:00
|
|
|
kLeye = kron(chol(inv(M_.Sigma_e)), eye(oo_.sur.dof));
|
2019-01-11 11:47:55 +01:00
|
|
|
[q, r] = qr(kLeye*X.data, 0);
|
|
|
|
oo_.sur.beta = r\(q'*kLeye*Y.data);
|
2017-11-17 14:41:27 +01:00
|
|
|
|
2018-01-29 15:26:28 +01:00
|
|
|
M_.params(opidxs) = oo_.sur.beta;
|
2018-01-05 17:13:46 +01:00
|
|
|
|
|
|
|
% Yhat
|
2019-01-11 11:47:55 +01:00
|
|
|
oo_.sur.Yhat = X.data * oo_.sur.beta;
|
2018-01-05 17:13:46 +01:00
|
|
|
|
|
|
|
% Residuals
|
2019-01-11 11:47:55 +01:00
|
|
|
oo_.sur.resid = Y.data - oo_.sur.Yhat;
|
2018-01-05 17:13:46 +01:00
|
|
|
|
2019-01-24 12:21:36 +01:00
|
|
|
% Correct Yhat reported back to user
|
|
|
|
oo_.sur.Yhat = oo_.sur.Yhat + lhssub;
|
|
|
|
|
2017-11-17 14:41:27 +01:00
|
|
|
%% Calculate statistics
|
|
|
|
% Estimate for sigma^2
|
|
|
|
SS_res = oo_.sur.resid'*oo_.sur.resid;
|
|
|
|
oo_.sur.s2 = SS_res/oo_.sur.dof;
|
|
|
|
|
|
|
|
% R^2
|
2019-01-11 11:47:55 +01:00
|
|
|
ym = Y.data - mean(Y.data);
|
2017-11-17 14:41:27 +01:00
|
|
|
SS_tot = ym'*ym;
|
|
|
|
oo_.sur.R2 = 1 - SS_res/SS_tot;
|
|
|
|
|
|
|
|
% Adjusted R^2
|
|
|
|
oo_.sur.adjR2 = oo_.sur.R2 - (1 - oo_.sur.R2)*M_.param_nbr/(oo_.sur.dof - 1);
|
|
|
|
|
|
|
|
% Durbin-Watson
|
|
|
|
ediff = oo_.sur.resid(2:oo_.sur.dof) - oo_.sur.resid(1:oo_.sur.dof - 1);
|
|
|
|
oo_.sur.dw = (ediff'*ediff)/SS_res;
|
|
|
|
|
|
|
|
% Standard Error
|
|
|
|
oo_.sur.stderr = sqrt(oo_.sur.s2*diag(xpxi));
|
|
|
|
|
|
|
|
% T-Stat
|
|
|
|
oo_.sur.tstat = oo_.sur.beta./oo_.sur.stderr;
|
|
|
|
|
|
|
|
%% Print Output
|
|
|
|
if ~options_.noprint
|
2019-01-11 11:47:55 +01:00
|
|
|
preamble = {sprintf('No. Equations: %d', neqs), ...
|
2018-01-29 15:36:56 +01:00
|
|
|
sprintf('No. Independent Variables: %d', size(X, 2)), ...
|
2017-11-17 14:41:27 +01:00
|
|
|
sprintf('Observations: %d', oo_.sur.dof)};
|
|
|
|
|
|
|
|
afterward = {sprintf('R^2: %f', oo_.sur.R2), ...
|
|
|
|
sprintf('R^2 Adjusted: %f', oo_.sur.adjR2), ...
|
|
|
|
sprintf('s^2: %f', oo_.sur.s2), ...
|
|
|
|
sprintf('Durbin-Watson: %f', oo_.sur.dw)};
|
|
|
|
|
2019-01-11 11:47:55 +01:00
|
|
|
if ~isempty(constrained_param_idxs)
|
2019-01-11 16:44:49 +01:00
|
|
|
afterward = [afterward, ['Constrained parameters: ' ...
|
|
|
|
strjoin(X.name(constrained_param_idxs), ', ')]];
|
2017-12-12 13:07:25 +01:00
|
|
|
end
|
|
|
|
|
2019-01-11 11:47:55 +01:00
|
|
|
dyn_table('SUR Estimation', preamble, afterward, X.name, ...
|
|
|
|
{'Estimates','t-statistic','Std. Error'}, 4, ...
|
2017-11-17 14:41:27 +01:00
|
|
|
[oo_.sur.beta oo_.sur.tstat oo_.sur.stderr]);
|
|
|
|
end
|
|
|
|
end
|