3.4 Estimation by method of moments MM

As said in the previous chapter, this method is based on the similarity between sample moments and population moments. The orthogonality condition assumption states that the population moment \(E(X^t\varepsilon)\) with \(k\) elements is equal to zero, and based on this method, its corresponding sample moment \(X^te\) should also equal to zero. So it follows that:

\[\begin{align} X^te=0&\implies X^t(y-X\beta_{MM})=0\notag\\ &\implies X^ty-X^tX\beta_{MM}=0\notag\\ &\implies X^tX\beta_{MM}=X^ty\notag\\ &\implies \beta_{MM}=\big(X^tX\big)^{-1}X^ty \tag{3.30} \end{align}\]

Again, the MM estimators are the same as those of the OLS method.

In the MM terms, the orthogonality condition is called the moment condition. In most cases this method uses many moment conditions to derive estimators.

In R:

For method of moments we use the R package gmm.

# load the package to the workspace
library(gmm)
mod_R_MM <- gmm(y ~ x2+x3+x4, df_R_sample[, -1] , data=df_R_sample)
tidy(mod_R_MM)
Table 3.6: the method of moments estimates in R
term estimate std.error statistic p.value
(Intercept) 7.913295 2.5608499 3.090105 0.0020009
x2 1.395749 0.0955842 14.602300 0.0000000
x3 -0.818892 0.1576716 -5.193657 0.0000002
x4 2.008222 0.1713599 11.719323 0.0000000

As expected, we gat the same estimates.

In Python:
import statsmodels.api as sm
from statsmodels.sandbox.regression.gmm import GMM
import numpy as np
# We create a subclass of GMM class to handle
# the moment conditions
class Mmm(GMM):
  def momcond(self, params):
      b0, b1, b2, b3 = params
      endog = self.endog
      exog = self.exog
      exog=self.instrument
      err0=endog-b0-b1*exog[:,1]-b2*exog[:,2]-b3*exog[:,3]
      err1=exog[:,1]*(endog-b0-b1*exog[:,1]-b2*exog[:,2]-b3*exog[:,3])
      err2=exog[:,2]*(endog-b0-b1*exog[:,1]-b2*exog[:,2]-b3*exog[:,3])
      err3=exog[:,3]*(endog-b0-b1*exog[:,1]-b2*exog[:,2]-b3*exog[:,3])
      err=np.column_stack((err0, err1, err2, err3))
      return err

Y = df_p_sample['Y']
X = df_p_sample[['X2','X3','X4']]
X = sm.add_constant(X)
# We use the same regressor as an instrument
mod_p_gmm = Mmm(Y.values, X.values, X.values, k_moms=4, k_params=4 )
res_p_mm = mod_p_gmm.fit(start_params=np.array([1., 1., 1., 1.]))
res_p_mm.model.exog_names[:] = 'beta0 beta1 beta2 beta3 '.split()
print(res_p_mm.summary())
[out]                                  Mmm Results                                  
[out] ==============================================================================
[out] Dep. Variable:                      y   Hansen J:                    2.884e-19
[out] Model:                            Mmm   Prob (Hansen J):                   nan
[out] Method:                           GMM                                         
[out] Date:               Thu, 17 Sept 2026                                         
[out] Time:                        11:12:57                                         
[out] No. Observations:                  30                                         
[out] ==============================================================================
[out]                  coef    std err          z      P>|z|      [0.025      0.975]
[out] ------------------------------------------------------------------------------
[out] beta0          3.5782      3.138      1.140      0.254      -2.572       9.729
[out] beta1          1.1923      0.116     10.272      0.000       0.965       1.420
[out] beta2         -0.4177      0.172     -2.428      0.015      -0.755      -0.081
[out] beta3          2.0368      0.144     14.125      0.000       1.754       2.319
[out] ==============================================================================

As expected, the estimates are the same as the OLS estimates.