tsa ols python pandas statsmodels

python - ols - ¿Cuál es la diferencia entre pandas ACF y statsmodel ACF?



statsmodels time series (2)

Estoy calculando la función de autocorrelación para las devoluciones de una acción. Para ello, probé dos funciones, la función de statsmodels.tsa incorporada en Pandas y la función acf proporcionada por statsmodels.tsa . Esto se hace en el siguiente MWE:

import pandas as pd from pandas_datareader import data import matplotlib.pyplot as plt import datetime from dateutil.relativedelta import relativedelta from statsmodels.tsa.stattools import acf, pacf ticker = ''AAPL'' time_ago = datetime.datetime.today().date() - relativedelta(months = 6) ticker_data = data.get_data_yahoo(ticker, time_ago)[''Adj Close''].pct_change().dropna() ticker_data_len = len(ticker_data) ticker_data_acf_1 = acf(ticker_data)[1:32] ticker_data_acf_2 = [ticker_data.autocorr(i) for i in range(1,32)] test_df = pd.DataFrame([ticker_data_acf_1, ticker_data_acf_2]).T test_df.columns = [''Pandas Autocorr'', ''Statsmodels Autocorr''] test_df.index += 1 test_df.plot(kind=''bar'')

Lo que noté fue que los valores que predijeron no eran idénticos:

¿Qué explica esta diferencia y qué valores deben usarse?


Como se sugiere en los comentarios, el problema puede reducirse, pero no resolverse por completo, proporcionando unbiased=True a la función de statsmodels . Usando una entrada aleatoria:

import statistics import numpy as np import pandas as pd from statsmodels.tsa.stattools import acf DATA_LEN = 100 N_TESTS = 100 N_LAGS = 32 def test(unbiased): data = pd.Series(np.random.random(DATA_LEN)) data_acf_1 = acf(data, unbiased=unbiased, nlags=N_LAGS) data_acf_2 = [data.autocorr(i) for i in range(N_LAGS+1)] # return difference between results return sum(abs(data_acf_1 - data_acf_2)) for value in (False, True): diffs = [test(value) for _ in range(N_TESTS)] print(value, statistics.mean(diffs))

Salida:

False 0.464562410987 True 0.0820847168593


La diferencia entre las versiones de Pandas y Statsmodels se encuentra en la resta media y la división de normalización / varianza:

  • autocorr no hace nada más que pasar una subserie de la serie original a np.corrcoef . Dentro de este método, la media muestral y la varianza muestral de estas subseries se utilizan para determinar el coeficiente de correlación.
  • acf , por el contrario, utiliza la media muestral de la serie global y la varianza muestral para determinar el coeficiente de correlación.

Las diferencias pueden reducirse para series de tiempo más largas, pero son bastante grandes para series cortas.

En comparación con Matlab, la función de autocorr Pandas probablemente corresponde a hacer Matlabs xcorr (cross-corr) con la propia serie (retrasada), en lugar de autocorr de Matlab, que calcula la autocorrelación de la muestra (adivinando de los documentos; no puedo validar esto porque tengo No hay acceso a Matlab).

Ver este MWE para la aclaración:

import numpy as np import pandas as pd from statsmodels.tsa.stattools import acf import matplotlib.pyplot as plt plt.style.use("seaborn-colorblind") def autocorr_by_hand(x, lag): # Slice the relevant subseries based on the lag y1 = x[:(len(x)-lag)] y2 = x[lag:] # Subtract the subseries means sum_product = np.sum((y1-np.mean(y1))*(y2-np.mean(y2))) # Normalize with the subseries stds return sum_product / ((len(x) - lag) * np.std(y1) * np.std(y2)) def acf_by_hand(x, lag): # Slice the relevant subseries based on the lag y1 = x[:(len(x)-lag)] y2 = x[lag:] # Subtract the mean of the whole series x to calculate Cov sum_product = np.sum((y1-np.mean(x))*(y2-np.mean(x))) # Normalize with var of whole series return sum_product / ((len(x) - lag) * np.var(x)) x = np.linspace(0,100,101) results = {} nlags=10 results["acf_by_hand"] = [acf_by_hand(x, lag) for lag in range(nlags)] results["autocorr_by_hand"] = [autocorr_by_hand(x, lag) for lag in range(nlags)] results["autocorr"] = [pd.Series(x).autocorr(lag) for lag in range(nlags)] results["acf"] = acf(x, unbiased=True, nlags=nlags-1) pd.DataFrame(results).plot(kind="bar", figsize=(10,5), grid=True) plt.xlabel("lag") plt.ylim([-1.2, 1.2]) plt.ylabel("value") plt.show()

Statsmodels usa np.correlate para optimizar esto, pero así es básicamente cómo funciona.