GMM

From ECLR
Revision as of 08:37, 8 February 2022 by Rb (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

The code below performs a standard 2 step GMM estimation. In this code the estimation is exactly identified (number of moments = number of parameters). This code requires numgrad.m in your working directory. This is a function to calculate numerical gradients.

%=========================================================================
%
% Program to estimate level effect in interest rates by GMM
%
% Code based on Martin, Hurn and Harris, Econometric Time Series Modelling
% Specification, Estimation and Testing
% https://www.cambridge.org/features/econmodelling/chapter10.htm
% 
% This code by Ralf Becker, March 2021
% http://eclr.humanities.manchester.ac.uk/index.php/MATLAB
%=========================================================================


clear all;
clc;
cd 'YOUR DIRECTORY'

% Load data --- monthly December 1946 to February 1991
%     3 month maturity
% extracted from the datafile provided by 
% Martin, Hurn and Harris
% https://www.cambridge.org/features/econmodelling/chapter10.htm

[rt, ~, ~] = xlsread('US3monthRate.xlsx');

drt = trimr(rt,2,0) - trimr(rt,1,1); % creates \Delta r_{t+1}
r1t = trimr(rt,1,1);                 % creates r_t
r2t = trimr(rt,0,2);
t   = length(drt);

%% It is typically good practice to visualise the data
tt = seqa(1946+12/12,1/12,t); % Creates year sequence

subplot(1,2,1);
plot(tt,r1t);
title('r_t')
box off
axis tight

subplot(1,2,2);
plot(tt,drt);
title('\Delta r_{t+1}')
box off
axis tight


%% Estimate the model in the first stage with idendity weighting matrix

ops  = optimset('LargeScale','off','Display','off');
b0   = [0.1;0.1;0.1;1.0];
w0 = eye(length(b0));
bgmm1 = fminunc(@(b) qw(b,drt,r1t,w0),b0,ops);

disp('First Stage GMM estimates')
disp(bgmm1)

%% Now estimate the optimal weighting matrix
% using Newey-West estimator
lmax = 5;   % lag for the NW estimate 
d = meqn(bgmm1,drt,r1t);

% this will calculate Newey-West VCM using lmax lags
s   = d'*d;
tau = 1;
while tau <= lmax
    wtau = d((tau+1):size(d,1),:)'*d(1:(size(d,1)-tau),:);
    s    = s + (1.0-tau/(lmax+1))*(wtau + wtau');
    tau  = tau + 1;
end
w1 = s./t;

% Use this as the weighting matrix for the next pass to the optimisation
% function

%% 2nd Stage 

bgmm2 = fminunc(@(b) qw(b,drt,r1t,w1),bgmm1,ops);

disp('Second Stage GMM estimates')
disp(bgmm2)

%% Further Iterations
% You could run further iterations
% 1) Re-calculate d
% 2) Re-calculate the optimal weighting matrix w based on the new d
% 3) Re-estimate using the new w
%
% For now we stop here
bgmm = bgmm2;
obj = qw(bgmm,drt,r1t,w1);

%% Calculate standard errors
% Compute optimal weigthing matrix at GMM estimates
% using Newey-West estimator
lmax = 5;   % lag for the NW estimate 
d = meqn(bgmm,drt,r1t);

% this will calculate Newey-West VCM using lmax lags
s   = d'*d;
tau = 1;
while tau <= lmax
    wtau = d((tau+1):size(d,1),:)'*d(1:(size(d,1)-tau),:);
    s    = s + (1.0-tau/(lmax+1))*(wtau + wtau');
    tau  = tau + 1;
end
s = s./t;

% Compute standard errors of GMM estimates
dg = numgrad(@meaneqn,bgmm,drt,r1t);
v  = dg'*inv(s)*dg;
cov = inv(v)/t;
se = sqrt(diag(cov));

disp(' ');
disp(['The value of the objective function  = ', num2str(obj) ]);
disp(['J-test                               = ', num2str(t*obj) ]);
disp('Estimates     Std err.   t-stats');
disp( [ bgmm  se  bgmm./se ])
disp(['Newey-West estimator with max lag    = ', num2str(lmax) ]);
disp(' ');


%% Inference t-tests

% Test of gam = 0.0
stat = (bgmm(4) - 0.0)/se(4);
disp(['Test of (gam=0.0) = ', num2str(stat) ]);
disp(['p-value           = ', num2str(2*(1-normcdf(abs(stat)))) ]);
disp(' ');

% Test of gam = 0.5
stat = (bgmm(4) - 0.5)/se(4);
disp(['Test of (gam=0.5) = ', num2str(stat) ]);
disp(['p-value           = ', num2str(2*(1-normcdf(abs(stat)))) ]);
disp(' ');

% Test of gam = 1.0
stat = (bgmm(4) - 1.0)/se(4);
disp(['Test of (gam=1.0) = ', num2str(stat) ]);
disp(['p-value           = ', num2str(2*(1-normcdf(abs(stat)))) ]);
disp(' ');

% Test of gam = 1.5
stat = (bgmm(4) - 1.5)/se(4);
disp(['Test of (gam=1.5) = ', num2str(stat) ]);
disp(['p-value           = ', num2str(2*(1-normcdf(abs(stat)))) ]);
disp(' ');

%% Inference - Overidentifying restrictions

%% Plot volatility function for alternative values of gam
tt = seqa(1946+12/12,1/12,t);
figure(1)

subplot(2,2,1);
plot(tt,drt./r1t.^0.0);
title('$\gamma=0.0$')
box off
axis tight

subplot(2,2,2);
plot(tt,drt./r1t.^0.5);
title('$\gamma=0.5$')
box off
axis tight

subplot(2,2,3);
plot(tt,drt./r1t.^1.0);
title('$\gamma=1.0$')
box off
axis tight

subplot(2,2,4);
plot(tt,drt./r1t.^1.5);
title('$\gamma=1.5$')
box off
axis tight

%
%------------------------- Functions -------------------------------------%
%
%-------------------------------------------------------------------------%
% Define the moment equations 
%-------------------------------------------------------------------------%
function dt = meqn(b,drt,r1t)
    
        ut = drt - b(1) - b(2)*r1t;
        zt = [ones(size(ut,1),1),r1t];
        dt = repmat(ut,1,2).*zt;
        dt = [dt,repmat((ut.^2 - (b(3)^2)*r1t.^(2*b(4)) ),1,2).*zt];
   
end
%-------------------------------------------------------------------------%
% Defines the mean of the moment conditions  
%-------------------------------------------------------------------------%
function ret = meaneqn(b,drt,r1t)

        ret = (mean(meqn(b,drt,r1t)))';

end

%-------------------------------------------------------------------------%
% GMM objective function with  user defined 
% weighting matrix, w
%-------------------------------------------------------------------------%   
function ret = qw(b,drt,r1t,w)
        
    t = length(drt);
    d = meqn(b,drt,r1t);
    g = mean(d)';

    ret = g'*inv(w)*g;
end