Advanced Economic Methods

Exercise 7: Exploring dynamic econometric models

Overview

The following tutorial will introduce you to working with dynamic econometric models using a macroeconomic data set as an example. If you have not done the previous tutorials, go back to the introductory lesson here to learn how to set up the appropriate working paths for the code to work.

Setup

Loading data

d <- read_excel("dat/money_ita.xls")

As always, let’s take a look at the data:

head(d)
## # A tibble: 6 × 5
##   obs      CPI   GDP    M2     R
##   <chr>  <dbl> <dbl> <dbl> <dbl>
## 1 1975Q1  18     131   96      8
## 2 1975Q2  18.5   136  101.     7
## 3 1975Q3  18.9   141  108.     6
## 4 1975Q4  19.4   146  114.     6
## 5 1976Q1  20.2   155  120.    12
## 6 1976Q2  21.5   168  126.    12

Analysis

Our analysis will require some data transformations prior to the analysis. The following code produces three transformations:

  • Converts GDP and M2 to real GDP and real money balances using the consumer price index
  • Transforms real GDP and money balance to log values (for interpretation as % change)
  • Generates a lag term for the log money balance
  • Drops any observations with missing values (the lag term will be missing in the first observation)
d <- d %>%
  mutate(lGDP = log(CPI/GDP),
         lR = log(R),
         lM2 = log(M2/CPI),
         lM2_l1 = lag(lM2, 1)) %>%
  na.omit(d)

Note: The transformation of \(CPI/GDP\) is actually incorrect. It should be \(GDP/CPI\), but this would have resulted in a sign reversal that does not match the example in the textbook, nor would it have reflected real economic theory. The reason for this is unclear, but is likely an error in the data provided by the textbook.

Partial adjustment model

We will test the partial adjustment model, which includes a lagged term of the dependent (Y) variable as an independent (X) variable. We can write the model statement as:

\[ log(M_t) = \beta_0 + \beta_1 log(Y_t) + \beta_2 log(R_t) + \beta_3 log(M_{t-1}) + u_t\]

Since we already did the log and lag transformations in the code above, we can simply enter those variables into the regression code as:

reg1 <- lm(lM2 ~ lGDP + lR + lM2_l1, data = d)
summary(reg1)
## 
## Call:
## lm(formula = lM2 ~ lGDP + lR + lM2_l1, data = d)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.044847 -0.010097  0.001123  0.012441  0.026430 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  0.184265   0.049705   3.707 0.000368 ***
## lGDP         0.026614   0.010571   2.518 0.013642 *  
## lR          -0.017358   0.005859  -2.962 0.003935 ** 
## lM2_l1       0.959451   0.030822  31.129  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.01561 on 87 degrees of freedom
## Multiple R-squared:  0.9335, Adjusted R-squared:  0.9312 
## F-statistic: 406.9 on 3 and 87 DF,  p-value: < 2.2e-16

Interpretations: We can interpret the results as the following:

  • A 1% increase in real GDP leads to a 0.027% increase in real money demand in the short run
  • A 1% increase in the interest rate decreases log money demand by 0.017%. It’s a small change, but the relationship follows economic theory because higher interest rates increase the opportunity cost of holding money, thereby reducing money demand

On the adjustment coefficient \(\lambda\):

  • \(\lambda\) = 1 - 0.959 = 0.041 (or 4.1%)
  • This indicates very slow adjustment: only 4.1% of the gap between actual and desired money demand closes each quarter (16.4% per year)
  • This finding suggests that people don’t immediately adjust their money balances to desired levels due to adjustment costs

Testing for autocorrelation

Autocorrelation (i.e. serial correlation) is always an important consideration when running time series analyses, particularly when working with lagged terms. We will run through a couple tests to see if serial correction is a problem in our model.

Extracting the residuals

As in the previous tutorial, we will first extract the residuals, then create two variables: res1 for the residual, and res2 for a lagged residual:

residual <- residuals(reg1)

d <- d %>%
  mutate(res1 = residual,
         res2 = lag(residual, 1))

Graphical analysis

Now we will generate a couple plots to look at the the residuals over time and the first residual compared to the lagged residual.

If autocorrelation is present in the model, we would likely see a wave pattern that switches signs in the case of positive autocorrelation, or a sawtooth pattern for negative correlation:

ggplot(d, aes(x = obs, y = res1)) +
  geom_point(shape = 16, color="darkblue", size = 3) + 
  geom_hline(yintercept = 0, color = "darkred", linetype = "dashed") +
  labs(title = "Residuals over time",
       x = "Time", y = "Residual") +
theme_minimal()

The first plot does not show anything concerning. It all looks quite random. In the second plot, autocorrelation would should up as an upward or downward trend depending on the sign of the effect:

ggplot(d, aes(x = res2, y = res1)) +
  geom_point(shape = 16, color = "darkblue", size = 3) +
  geom_hline(yintercept = 0, color = "darkred", linetype = "dashed") +
  labs(title = "Residuals vs lagged residuals",
       x = "Lagged residuals", y = "Residuals") + 
theme_minimal()
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).

This also looks good.

BG test

As a final assurance test, we will run the Breusch-Godfrey test with an order of 4 since it is quarterly data:

bgtest(reg1, order = 4)
## 
##  Breusch-Godfrey test for serial correlation of order up to 4
## 
## data:  reg1
## LM test = 18.751, df = 4, p-value = 0.0008798

Unfortunately, we do a problem here. The null hypothesis for the test is that autocorrelation is not present, and a low p-value (in this case, p=0.00088) means we reject the null hypothesis. As such, it will be important to adjust the standard errors before we can make inferences on the results. This is a fairly involved process, so refer back to Exercise 4 to get the code.