0

I'm trying to create a program that uses the Hannan-Rissanen algorithm to compute the sample parameters for an ARMA(p, q) auto-regressive moving average stochastic process.

The main step I'm having difficulty with is calculating the autocovariance function of the time series.

The program should take in an n×1-dimensional column vector Y and compute a k×1-dimensional column vector γ^hat given by:

acvf equation image

where Ybar is the average of the elements of Y.

How can I compute the above sum efficiently? (obviously for loops would work, but I'm trying to get better at vectorized numpy operations) Since I'm using this as a learning experience, I would prefer not to use any numpy functions other than very basic ones like np.sum or np.mean.

The following previous similar question has been asked, but doesn't quite answer my question:

Computing autocorrelation of vectors with numpy (uses np.correlate)

(a few others suffer the same problem of using more advanced numpy functions, or aren't spitting out vectors as I wish to do here.)

1 Answers1

0

Here is one way to replace np.correlate (which I assume is the main difficulty; I'm also assuming you have no desire to hand code an fft):

def autocorr_direct(a, debug=False):
    n, _ = a.shape
    out = np.zeros((n+1, 2*n-1), a.dtype)
    out.reshape(-1)[:2*n*n].reshape(n, 2*n)[::-1, :n] = a*a.T
    if debug:
        print(out.reshape(-1)[:2*n*n].reshape(n, 2*n))
        print(out)
    return out.sum(0)

For example:

>>> a = np.array([[1, 1, 2, -1]]).T
>>> autocorr_direct(a, True)
[[-1 -1 -2  1  0  0  0  0]
 [ 2  2  4 -2  0  0  0  0]
 [ 1  1  2 -1  0  0  0  0]
 [ 1  1  2 -1  0  0  0  0]]
[[-1 -1 -2  1  0  0  0]
 [ 0  2  2  4 -2  0  0]
 [ 0  0  1  1  2 -1  0]
 [ 0  0  0  1  1  2 -1]
 [ 0  0  0  0  0  0  0]]
array([-1,  1,  1,  7,  1,  1, -1])
>>> np.correlate(a[:, 0], a[:, 0], 'full')
array([-1,  1,  1,  7,  1,  1, -1])

Note the reshape trick that shears the square array a[::-1]*a.T.

Note 2; to get a column vector from a 1D vector X use X[:, None].

Paul Panzer
  • 51,835
  • 3
  • 54
  • 99