I have a matrix with two columns that have many prices (750). In the image below I plotted the residuals of the follow linear regression:

lm(prices[,1] ~ prices[,2])

Looking at image, seems to be a very strong autocorrelation of the residuals.

However how can I test if the autocorrelation of those residuals is strong? What method should I use?

Residuals of the linear regression

Thank you!

  • 8
    $\begingroup$ You don't need to test for autocorrelation. It is there. The plot shows that. You could look at the autocorrelation function of these residuals (function acf()), but this will simply confirm what can be seen by plain eye: the correlations between lagged residuals are very high. $\endgroup$
    – Wolfgang
    Aug 28, 2011 at 20:23
  • $\begingroup$ @Wolfgang, yes, correct, but I have to check it programmatically.. I will take a look at acf function. Thanks! $\endgroup$
    – Dail
    Aug 28, 2011 at 22:12
  • $\begingroup$ @Wolfgang, I'm seeing acf() but I don't see a sort of p-value to understand if there is a strong correlation or not. How to interpret its result? Thanks $\endgroup$
    – Dail
    Aug 28, 2011 at 22:16
  • $\begingroup$ With H0: correlation (r) = 0, then r follows a normal/t dist with mean 0 and variance of sqrt(number of observations). So you could get the 95% confidence interval using +/- qt(0.75, numberofobs)/sqrt(numberofobs) $\endgroup$
    – Jim
    Mar 17, 2013 at 5:46
  • $\begingroup$ @Jim The variance of the correlation is not $\sqrt{n}$. Nor is the standard deviation $\sqrt{n}$. But it does have an $n$ in it. $\endgroup$
    – Glen_b
    Jun 20, 2014 at 5:13

4 Answers 4


There are probably many ways to do this but the first one that comes to mind is based on linear regression. You can regress the consecutive residuals against each other and test for a significant slope. If there is auto-correlation, then there should be a linear relationship between consecutive residuals. To finish the code you've written, you could do:

mod = lm(prices[,1] ~ prices[,2])
res = mod$res 
n = length(res) 
mod2 = lm(res[-n] ~ res[-1]) 

mod2 is a linear regression of the time $t$ error, $\varepsilon_{t}$, against the time $t-1$ error, $\varepsilon_{t-1}$. If the coefficient for res[-1] is significant, you have evidence of autocorrelation in the residuals.

Note: This implicitly assumes that the residuals are autoregressive in the sense that only $\varepsilon_{t-1}$ is important when predicting $\varepsilon_{t}$. In reality there could be longer range dependencies. In that case, this method I've described should be interpreted as the one-lag autoregressive approximation to the true autocorrelation structure in $\varepsilon$.

  • $\begingroup$ thank you so much for the example. Only one doubt, How can I test if res[-1] is significant? $\endgroup$
    – Dail
    Aug 28, 2011 at 22:10
  • $\begingroup$ you'd test it the same way you would any other regression coefficient - look at the $t$-statistic and $p$-value $\endgroup$
    – Macro
    Aug 28, 2011 at 22:22
  • $\begingroup$ doing a fast test with: lm(rnorm(1000)~jitter(1:1000)) I get: Residual standard error: 1.006 on 997 degrees of freedom Multiple R-squared: 0.0003463, Adjusted R-squared: -0.0006564 F-statistic: 0.3454 on 1 and 997 DF, p-value: 0.5569 the p-value can't reject the null hypothesis $\endgroup$
    – Dail
    Aug 28, 2011 at 22:29
  • $\begingroup$ Macro, I have tested the residuals of the chart I plotted above, and the result is: Residual standard error: 0.04514 on 747 degrees of freedom Multiple R-squared: 0.9241, Adjusted R-squared: 0.924 F-statistic: 9093 on 1 and 747 DF, p-value: < 2.2e-16, It doesn't seem very good, It is very strange because there is a strong autocorrelation, what could I do? $\endgroup$
    – Dail
    Aug 28, 2011 at 22:44
  • 3
    $\begingroup$ This is called a Breusch-Godfrey test for autocorrelation. $\endgroup$
    – Charlie
    Sep 7, 2011 at 16:53

Use the Durbin-Watson test, implemented in the lmtest package.

dwtest(prices[,1] ~ prices[,2])
  • $\begingroup$ very strange I get: p-value < 2.2e-16, How it is possible? the data seems very correlated! $\endgroup$
    – Dail
    Aug 29, 2011 at 7:50
  • 5
    $\begingroup$ The p-value is the probably of getting as much correlation as that observed if there is no real correlation. So if the p is very small, as it is, that suggests there is a lot of correlation present in the sample. $\endgroup$ Aug 29, 2011 at 10:03
  • $\begingroup$ Do you mean a p-value like this indicates that the residuals are very autocorrelated? $\endgroup$
    – Dail
    Aug 29, 2011 at 11:41
  • $\begingroup$ hmm strange, take a look at: imageshack.us/f/59/17671620.png how is it possible that the right image is not autocorrelated? $\endgroup$
    – Dail
    Aug 29, 2011 at 13:35
  • $\begingroup$ :dail It would appear that the left image has a structural change in variance ( see Ruey Tsay's article "Outliers, Level Shifts, and Variance Changes in Time Series" , Journal of Forecasting, VOl 7, 1-20 (1988) for details ) which in this case does not "confuse" the DW perhaps due the fact the entire distribution is still normal while the right image has some visually obvious ( and empirically identifiable ) anomalies (Pulses) creating a non-normal ( leptokurtotic see wikopedia : A distribution with positive excess kurtosis is called leptokurtic ) distribution which causes havoc with the DW $\endgroup$
    – IrishStat
    Aug 29, 2011 at 15:41

The DW Test or the Linear Regression test are not robust to anomalies in the data. If you have Pulses, Seasonal Pulses , Level Shifts or Local Time Trends these tests are useless as these untreated components inflate the variance of the errors thus downward biasing the tests causing you ( as you have found out ) to incorrectly accept the null hypothesis of no auto-correlation. Before these two tests or any other parametric test that I am aware of can be used one has to "prove" that the mean of the residuals is not statistically significantly different from 0.0 EVERYWHERE otherwise the underlying assumptions are invalid. It is well known that one of the constraints of the DW test is its assumption that the regression errors are normally distributed. Note normally distributed means among other things : No anomalies ( see http://homepage.newschool.edu/~canjels/permdw12.pdf ). Additionally the DW test only test for auto-correlation of lag 1. Your data might have a weekly/seasonal effect and this would go undiagnosed and furthermore , untreated , would downward bias the DW test.

  • 1
    $\begingroup$ what are the tests for testing that residuals are significantly different from zero? If regression includes intercept, then residual mean is algebraicaly zero, so I am curious how is it possible to circumvent this problem. $\endgroup$
    – mpiktas
    Aug 29, 2011 at 7:47
  • $\begingroup$ :mpkitas As you said when you include a constant the mean of the errors is guaranteed to be 0.0 but that doesn't guarantee that the mean of the errors is Zero everywhere. For example if a series has a change in mean , the overall mean will be a constant but will yield tw0 "clumps" of residuals , each with a different mean. You can pursue Ruey Tsay's article "Outliers, Level Shifts, and Variance Changes in Time Series" , Journal of Forecasting, VOl 7, 1-20 (1988) for details. OR faculty.chicagobooth.edu/ruey.tsay/teaching/uts/lec10-08.pdf OR Google "automatic intervention detection" $\endgroup$
    – IrishStat
    Aug 29, 2011 at 10:53
  • 1
    $\begingroup$ This is just the standard "no omitted variables" assumption that is implicit in all regression analysis. $\endgroup$
    – Charlie
    Sep 7, 2011 at 16:55

2021: R Provides an Autocorrelation Function - acf

I'm assuming that the other answers posted were created before the acf function existed in R.

However, in 2021, there is a dedicated function for calculating the autocorrelation.

Here's how to use it:

# calculate the ACF for lags between 1 and 20 (inclusive)
autocorrelation <- acf(your.data.here, lag.max=20, plot=FALSE)

# Plot figure
     xlab="Lag Parameter",



  • $\begingroup$ That link was put online in 2018, so acf() was available at least by that year instead of 2021. Not sure why you separate the two lines, as acf can directly plot using main, ylab and xlab without calling to plot() i.e. acf(your.data.here, lag.max=20, plot=FALSE), main="Autocorrelation", xlab="Lag Parameter", ylab="ACF") $\endgroup$
    – MBorg
    Apr 25 at 3:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.