function result = thsls(neqs,y,Y,X,xall) % PURPOSE: computes Three-Stage Least-squares Regression % for a model with neqs-equations %--------------------------------------------------- % USAGE: results = thsls(neqs,y,Y,X,xall) % where: % neqs = # of equations % y = an 'eq' structure containing dependent variables % e.g. y(1).eq = y1; y(2).eq = y2; y(3).eq = y3; % Y = an 'eq' structure containing RHS endogenous % e.g. Y(1).eq = []; Y(2).eq = [y1 y3]; Y(3).eq = y2; % X = an 'eq' structure containing exogenous/lagged endogenous % e.g. X(1).eq = [iota x1 x2]; % X(2).eq = [iota x1]; % X(3).eq = [iota x1 x2 x3]; % % xall = matrix of all exogenous variables in the system (defalut % % is to construct xall from exogenous variables in X); % % Richard Just added xall to the argument list to consider the case where % % exogenous variables enter the system only through identity equations. %--------------------------------------------------- % NOTE: X(i), i=1,...,G should include a constant vector % if you want one in the equation %--------------------------------------------------- % RETURNS a structure: % result.meth = 'thsls' % result(eq).beta = bhat for each equation % result(eq).tstat = tstat for each equation % result(eq).tprob = tprobs for each equation % result(eq).resid = residuals for each equation % result(eq).yhat = yhats for each equation % result(eq).y = y for each equation % result(eq).rsqr = r-squared for each equation % result(eq).rbar = r-squared adj for each equation % result(eq).nvar = nvar in each equation % result(eq).sige = e'e/nobs for each equation % result(eq).dw = Durbin-Watson % result.nobs = nobs % result.neqs = neqs % result.sigma = sig(i,j) across equations % result.ccor = correlation of residuals across equations % -------------------------------------------------- % SEE ALSO: prt, prt_eqs, plt, plt_eqs %--------------------------------------------------- % written by: % James P. LeSage, Dept of Economics % University of Toledo % 2801 W. Bancroft St, % Toledo, OH 43606 % jlesage@spatial-econometrics.com % Richard Just removed the following statement to allow for specifing xall. % if (nargin ~=4); error('Wrong # of arguments to thsls'); end; result.meth = 'thsls'; result.neqs = neqs; % find the # of equations chk = fieldnames(y); if (strcmp(chk,'eq') ~= 1) error('Use eq as the fieldname for y'); end; chk = fieldnames(Y); if (strcmp(chk,'eq') ~= 1) error('Use eq as the fieldname for Y'); end; chk = fieldnames(X); if (strcmp(chk,'eq') ~= 1) error('Use eq as the fieldname for X'); end; nobs = length(y(1).eq); ymat = zeros(nobs,neqs); yi = zeros(neqs,1); xi = zeros(neqs,1); for i=1:neqs; ymat(:,i) = y(i).eq; % ymat contains dependent variables [junk yi(i,1)] = size(Y(i).eq); % yi contains # RHS endogenous [junk xi(i,1)] = size(X(i).eq); % xi contains # RHS exogenous result(i).nvar = yi(i,1)+xi(i,1); end; % % Richard Just added the following two statements to forgo the succeeding % % 15 statements if xall is passed into the function as a 4th argument. if nargin == 5 xinst = xall; else % now we have to form xall containing all exogenous in the system % trick is to find constant term vectors so we end up with only 1 xall = ones(nobs,1); for i=1:neqs for j=1:xi(i,1); % % Richard Just changed the following statement because the test for % % X(i).eq(:,j) ~= ones(nobs,1) would fail to treat the two vectors % % as ~= when any two corresponding elements were =. Thus, relevant % % exogenous variables such as dummy variables and any variable that % % happened to be equal to 1 in at least one observation were excluded. if sum((X(i).eq(:,j)-ones(nobs,1)).^2) > 0 xall = [xall X(i).eq(:,j)]; end; end; end; % make it unique [junk,I,J] = unique(xall','rows'); Is = sort(I); xinst = xall(:,Is); end nrhs = sum(yi)-neqs; Ymat = zeros(nobs,nrhs); XX = xinst*inv(xinst'*xinst)*xinst'; Z = zeros(nobs*neqs,sum(xi)+nrhs); emat = zeros(nobs,neqs); cnts = 0; for i=1:neqs; nexog = xi(i,1); nendog = yi(i,1); Rmat = zeros(nobs,nendog); Zmat = zeros(nobs,nexog); if nexog > 0 % case of exogenous variables for j=1:nexog; Zmat(:,j) = X(i).eq(:,j); end; end; if nendog > 0 % case of rhs endogenous variables for j=1:nendog Rmat(:,j) = Y(i).eq(:,j); end; end; % do 2sls and get residuals if nendog > 0 & nexog > 0 res2s = tsls(y(i).eq(:),Rmat,Zmat,xinst); emat(:,i) = res2s.resid; elseif nendog ==0 reso = ols(y(i).eq(:),Zmat); emat(:,i) = reso.resid; elseif nexog == 0 error('thsls: no exogenous variables in one equation - not even a constant?'); end; % form matrix [Yi Xi] for this equation if nendog > 0 & nexog > 0 Z((i-1)*nobs+1:(i-1)*nobs+nobs,cnts+1:cnts+nexog+nendog) = [Rmat Zmat]; elseif nendog > 0 & nexog == 0 Z((i-1)*nobs+1:(i-1)*nobs+nobs,cnts+1:cnts+nexog+nendog) = [Rmat]; elseif nendog == 0 & nexog > 0 Z((i-1)*nobs+1:(i-1)*nobs+nobs,cnts+1:cnts+nexog+nendog) = [Zmat]; end; cnts = cnts + nexog+nendog; end; % determine sig(i,j) using of 2sls residuals sig = (1/nobs)*emat'*emat; SIGI = kron(inv(sig),XX); % turn ymat into a stacked vector yvec = []; for i=1:neqs; yvec = [yvec y(i).eq]; end; % compute bhat [nk1 junk] = size(Z'*SIGI*Z); xpxi = inv(Z'*SIGI*Z); bhat = xpxi*(Z'*SIGI*yvec); nvar = length(bhat); yhat = Z*bhat; resid = yvec - yhat; for i=1:neqs result(i).resid = resid((i-1)*nobs+1:i*nobs,1); % % Richard Just corrected the following line that had resid'*resid instead % % of result(i).resid'*result(i).resid. result(i).sige = (result(i).resid'*result(i).resid)/(nobs); result(i).yhat = yhat((i-1)*nobs+1:i*nobs,1); result(i).y = yvec((i-1)*nobs+1:i*nobs,1); end; tstat = zeros(nk1,1); cnt =1; for i=1:neqs; nexog = xi(i,1); nendog = yi(i,1); for j=1:nexog+nendog tmp = (xpxi(cnt,cnt)); tstat(cnt,1) = bhat(cnt,1)/sqrt(tmp); cnt = cnt + 1; end; end; tprob = tdis_prb(tstat,nobs); % use asymptotic tprobs cnt = 1; for i=1:neqs; nvar = result(i).nvar; result(i).beta = bhat(cnt:cnt+nvar-1,1); result(i).tstat = tstat(cnt:cnt+nvar-1,1); result(i).tprob = tprob(cnt:cnt+nvar-1,1); yhatg = result(i).yhat; residg = result(i).resid; sigu = residg'*residg; ygm = mean(result(i).y); yd = result(i).y - ones(nobs,1)*ygm; rsqr2 = yd'*yd; result(i).rsqr = 1 - sigu/rsqr2; rsqr1 = sigu/(nobs-result(i).nvar); rsqr2 = rsqr2/(nobs-1.0); result(i).rbar = 1 - (rsqr1/rsqr2); ediff = residg(2:nobs) - residg(1:nobs-1); result(i).dw = diag((ediff'*ediff)./(sigu))'; % durbin-watson cnt = cnt+nvar; end; result(1).nobs = nobs; result(1).sigma = sig; % return croos-equation covariances result(1).ccor = corrcoef(emat); % return cross-equation correlations