def plot_acf_pacf(x, sym, securities, lags=10): fig, axes = plt.subplots(1, 2, figsize=(9, 4)) smt.graphics.plot_acf(x, lags=lags, ax=axes[0], alpha=None, color=primary) acf_x, confint = smt.acf(x, nlags=lags, alpha=0.05) confint -= np.array([acf_x, acf_x]).T confint = np.concatenate([confint, confint[-1:, :]]) axes[0].fill_between(np.arange(lags + 2), confint[:, 0], confint[:, 1], alpha=.25, color=primary) axes[0].set_xlim((-0.2, 5.2)) axes[0].set_ylim((-0.2, 0.4)) axes[0].set_ylabel('ACF') axes[0].set_xlabel('lag') smt.graphics.plot_pacf(x, lags=lags, ax=axes[1], alpha=None, color=primary) pacf_x, confint = smt.pacf(x, nlags=lags, alpha=0.05) confint -= np.array([pacf_x, pacf_x]).T confint = np.concatenate([confint, confint[-1:, :]]) axes[1].fill_between(np.arange(lags + 2), confint[:, 0], confint[:, 1], alpha=.25, color=primary) axes[1].set_xlim((-0.2, 5.2)) axes[1].set_ylim((-0.2, 0.4)) axes[1].set_ylabel('PACF') axes[1].set_xlabel('lag') fig.suptitle(f'{securities.get_company_name(sym)} ({sym})') fig.tight_layout() fig.subplots_adjust(top=0.8) return fig, axes
def q_stat(timeseries): """ autocorrelation function docs: https://www.statsmodels.org/stable/generated/statsmodels.tsa.stattools.acf.html#statsmodels.tsa.stattools.acf Ljung-Box Q statistic docs: https://www.statsmodels.org/stable/generated/statsmodels.tsa.stattools.q_stat.html#statsmodels.tsa.stattools.q_stat Tests whether any group of autocorrelations of a time series are different from zero. Specifically tests the overall randomness based on a number of lags. Null Hypothesis: The data are independently distributed Alternative Hypothesis: The data is not independently distributed, I.E. they exhibit serial correlation. Parameters ---------- * timeseries : pd.Series The observations of the time series Returns ------- Calculates the Ljung Box Q Statistics """ autocorrelation_coefs = acf(timeseries) result = q_stat(autocorrelation_coefs) QstatResult = namedtuple('QstatResult', 'statistic pvalue') return QstatResult(result[0], result[1])
def neff_mcmc_univ(chains, burn_in=1000, min_neff=50, max_lag=200): n_dims = len(chains.shape) if n_dims == 2: chains = np.expand_dims(chains, axis=0) neffs = np.zeros(chains.shape[0] * chains.shape[2]) # Main loop that computes statistics of interest for i in range(chains.shape[0]): for j in range(chains.shape[2]): # Get Autoregression coefficients for each part of split of chain acf_vals_tmp = acf(t_swapped[0, 1000:, 0], nlags=max_lag) pos_id = np.argwhere(acf_vals_tmp < 0) if len(pos_id) > 1: max_lag_tmp = np.min(pos_id) else: max_lag_tmp = max_lag neffs[i + chains.shape[2] + j] = chains.shape[1] / (1 + (2 * np.sum(acf_vals_tmp[:max_lag]))) # Continuation check: All absolute z scores below 2? If yes stop sampling continue_ = int((np.sum(neffs < 50)) > 0) return continue_, neffs # -----------------------------------------------------------------------
def compute_acf(self, NLAGS=None): """Computes the autocovariance function of the trajectory.""" self.NLAGS = NLAGS self.acf = np.zeros((self.NLAGS+1, self.N_COMPONENTS)) for d in xrange(self.N_COMPONENTS): self.acf[:,d] = acf(self.traj[:,d], nlags=NLAGS, unbiased=True, \ fft=True) * np.var(self.traj[:,d]) self.acfm = np.mean(self.acf, axis=1) # average acf return
def residuos(data): modelo = sm.tsa.ARMA(x, (p, q)) modelo = modelo.fit() resid = modelo.resid ACF, q, pq = ts.acf(resid, qstat=True, fft=False) tabela = np.c_[range(1, 41), ACF[1:], q, pq] tabela = pd.DataFrame(tabela, columns=['lag', "ACF", "Q", "Prob(>Q)"]) fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(15, 5.5)) fig = plot_acf(resid, lags=40, zero=False, ax=ax1) fig = plot_pacf(resid, lags=40, zero=False, ax=ax2) plt.show() return tabela
def lmtestcheck(df,col,max1): "To perform and LM test for autocorrelation and find significant lags . 1 to determine a significant lag and 0 to determine insignificant lag " qstat, pval = sm.stattools.q_stat(sm.acf(df[col]), max1) j = [] for i in pval: if(i<0.05): j.append(0) else: j.append(1) print pd.DataFrame({"Q statistic: ": qstat, "P value: ": pval}) plt.scatter(qstat, pval) plt.hlines(0.05, min(qstat), max(qstat), colors = "r") plt.xlabel("Q statistic") plt.ylabel("p-value") plt.show() return j
def check(df,col): "To check whether a given series is Periodic or not using AutoCorrelation function :" x1acf = sm.acf(df[col]) ##print x1acf plt.plot(x1acf) plt.xlabel("lags") plt.ylabel("ACF") plt.show() count=0 for i in range(0,len(x1acf)): if((x1acf[i]<0.1 and x1acf[i]>0) or (x1acf[i]>-0.1 and x1acf[i]<0)): count=count+1 print count if(count>len(x1acf)/2): print "Data is random, 0 correlation " else: print "Data is periodic "
def test(self, test, plot=False): fc, se, conf = self.fit.forecast(len(test), alpha=.05) fc_df = pd.DataFrame(conf, columns=['lower', 'upper'], index=test.index) fc_df['fc'] = fc fc_df['test'] = test mape = np.mean(np.abs(fc - test) / np.abs(test)) # MAPE me = np.mean(fc - test) # ME mae = np.mean(np.abs(fc - test)) # MAE mpe = np.mean((fc - test) / test) # MPE rmse = np.mean((fc - test)**2)**.5 # RMSE corr = np.corrcoef(fc, test)[0, 1] # corr mins = np.amin(np.hstack([fc[:, None], test[:, None]]), axis=1) maxs = np.amax(np.hstack([fc[:, None], test[:, None]]), axis=1) minmax = 1 - np.mean(mins / maxs) # minmax acf1 = ts.acf(fc - test)[1] # ACF1 accuracy = pd.Series({ 'mape': mape, 'me': me, 'mae': mae, 'mpe': mpe, 'rmse': rmse, 'acf1': acf1, 'corr': corr, 'minmax': minmax }) if plot: plt.figure(figsize=(7, 5), dpi=120) plt.title("Forecasts vs Actual") plt.plot(self.data, label='training') plt.plot(fc_df.fc, label='forecast') plt.fill_between(fc_df.index, fc_df.lower, fc_df.upper, color='k', alpha=.15) plt.plot(test, label='test') plt.legend(loc="upper left", fontsize=8) plt.show() return fc_df, accuracy
def analysis(self): """http://necochan.com/2014/06/07/python-for-economist-6/""" eq = self.criterion_column + "~" + "+".join(self.explanatory_columns) self.rm = smf.ols(formula=eq, data=self.data).fit() print(self.rm.summary()) # ADF test, H0: Non-stationary tsa.adfuller(self.rm.resid, regression='nc') # Autocorrel plot of resid autocorrelation_plot(self.rm.resid) # Show ACF of residuals ACF_resid = tsa.acf(self.rm.resid) # Keep ACF of residuals # Checking Multicolinearity by VIF VIF = pd.DataFrame([ oti.variance_inflation_factor(self.rm.model.exog, i) for i in range(1, self.rm.model.exog.shape[1]) ], index=self.rm.model.exog_names[1:], columns=['VIF']) # VIF>10 should be cared
def determine_model_params(ts, nlags=10, plot=False): pacf_vals, pconfint = smt.pacf(ts, nlags=nlags, alpha=0.05) pacf_vals, pconfint = pacf_vals[1:], pconfint[1:] acf_vals, confint = smt.acf(ts, nlags=nlags, alpha=0.05) acf_vals, confint = acf_vals[1:], confint[1:] # conf = stats.norm.ppf(1. - 0.05 / 2.) * np.sqrt(1 / len(ts)) p, q = 0, 0 while p < 10 and np.sign(pconfint[p, 0]) == np.sign(pconfint[p, 1]): p += 1 while q < 10 and np.sign(confint[q, 0]) == np.sign(confint[q, 1]): q += 1 if plot: fig, axes = plt.subplots(1, 2, figsize=(14, 6)) smt.graphics.plot_acf(ts, lags=nlags, alpha=0.05, ax=axes[0]) axes[0].axvline(q, alpha=0.2, linestyle='dashed') smt.graphics.plot_pacf(ts, lags=nlags, alpha=0.05, ax=axes[1]) axes[1].axvline(p, alpha=0.2, linestyle='dashed') return p, q
def forecast_accuracy(forecast, actual): mape = np.mean(np.abs(forecast - actual) / np.abs(actual)) # MAPE me = np.mean(forecast - actual) # ME mae = np.mean(np.abs(forecast - actual)) # MAE mpe = np.mean((forecast - actual) / actual) # MPE rmse = np.mean((forecast - actual)**2)**.5 # RMSE corr = np.corrcoef(forecast, actual)[0, 1] # corr mins = np.amin(np.hstack([forecast[:, None], actual[:, None]]), axis=1) maxs = np.amax(np.hstack([forecast[:, None], actual[:, None]]), axis=1) minmax = 1 - np.mean(mins / maxs) # minmax acf1 = ts.acf(forecast - actual)[1] # ACF1 return pd.Series({ 'mape': mape, 'me': me, 'mae': mae, 'mpe': mpe, 'rmse': rmse, 'acf1': acf1, 'corr': corr, 'minmax': minmax }).round(3)
def get_acf(data): return pd.Series(tsa.acf(ts(data))).reset_index().to_dict(orient='records')
def f_features_end(p_datos): """ :param p_datos: pd.DataFrae : dataframe con 5 columnas 'timestamp', 'open', 'high', 'low', 'close' :return: r_features : dataframe con 5 columnas, nombres cohercionados + Features generados # Debuging p_datos = df_precios p_datos = pd.DataFrame({''timestamp': {}, 'open': np.random.normal(1.1400, 0.0050, 20). 'high': np.random.normal(1.1400, 0.0050, 20), 'low': np.random.normal(1.1400, 0.0050, 20), 'close': np.random.normal(1.1400, 0.0050, 20)}) """ datos = p_datos datos.columns = ['timestamp', 'open', 'high', 'low', 'close'] cols = list(datos.columns)[1:] datos[cols] = datos[cols].apply(pd.to_numeric, errors='coerce') # formato columna timestamp como 'datetime' datos['timestamp'] = pd.to_datetime(datos['timestamp']) # datos['timestamp'] = datos['timestamp'].dt.tz_localize('UTC') # rendimiento logaritmico de ventana 1 datos['logrend'] = np.log(datos['close'] / datos['close'].shift(1)).dropna() # pips descontados al cierre datos['co'] = (datos['close'] - datos['open']) * 10000 # pips descontados alcistas datos['ho'] = (datos['high'] - datos['open']) * 10000 # pips descontados bajistas datos['ol'] = (datos['open'] - datos['low']) * 10000 # pips descontados en total (medida de volatilidad) datos['hl'] = (datos['high'] - datos['low']) * 10000 # funciones de ACF y PACF para determinar ancho de ventana historica data_acf = acf(datos['logrend'].dropna(), nlags=12, fft=True) data_pac = pacf(datos['logrend'].dropna(), nlags=12) sig = round(1.96 / np.sqrt(len(datos['logrend'])), 4) # componentes AR y MA maxs = list( set( list(np.where((data_pac > sig) | (data_pac < -sig))[0]) + list(np.where((data_acf > sig) | (data_acf < -sig))[0]))) # encontrar la componente maxima como indicativo de informacion historica autorelacionada max_n = maxs[np.argmax(maxs)] # condicion arbitraria: 5 resagos minimos para calcular variables moviles if max_n <= 2: max_n = 5 # ciclo para calcular N features con logica de "Ventanas de tamaño n" for n in range(0, max_n): # resago n de ho datos['lag_ho_' + str(n + 1)] = np.log(datos['ho'].shift(n + 1)) # resago n de ol datos['lag_ol_' + str(n + 1)] = np.log(datos['ol'].shift(n + 1)) # promedio movil de ventana n datos['ma_ol_' + str(n + 2)] = datos['ol'].rolling(n + 2).mean() # promedio movil de ventana n datos['ma_ho_' + str(n + 2)] = datos['ho'].rolling(n + 2).mean() # asignar timestamp como index datos.index = pd.to_datetime(datos['timestamp']) # quitar columnas no necesarias para modelos de ML datos = datos.drop( ['timestamp', 'open', 'high', 'low', 'close', 'hl', 'logrend'], axis=1) # borrar columnas donde exista solo NAs r_features = datos.dropna(axis='columns', how='all') # borrar renglones donde exista algun NA r_features = r_features.dropna(axis='rows') # convertir a numeros tipo float las columnas r_features.iloc[:, 1:] = r_features.iloc[:, 1:].astype(float) # estandarizacion de todas las variables independientes lista = r_features[list(r_features.columns[1:])] r_features[list( r_features.columns[1:])] = StandardScaler().fit_transform(lista) return r_features
import numpy as np import matplotlib.pyplot as plt from statsmodels.tsa.api import acf from statsmodels.graphics.tsaplots import plot_acf w = np.random.normal(loc=0,scale=1000,size=1000) print(acf(w,fft=False)) plot_acf(w) plt.show()
Summaryで特筆すべきはDurbin-Watson比率です。これが2よりも十分に大きい時は負の系列相関。2より十分小さいときには正の系列相関が疑われます。経済時系列データを使った回帰分析では、系列相関が頻繁に生じますから、特に注意が必要です。 ちなみに、系列相関をはじめ、古典的な回帰モデルの診断手続きは経済企画庁[1988]が詳しいです。だいぶ昔のレポートですが、線形回帰モデルは古典的な方法ですので、その基本は変わっていません。http://www.esri.go.jp/jp/archive/bun/bun112/bun112a.pdf 誤差項に系列相関が残っている場合、トレンドも含めて、モデルに含まれていない要因が大きい影響を持っている可能性がありますので、思い当たる説明変数を加えてみたり、タイム・トレンドやラグ項を足したり、変分を取るなりして、コントロールしたほうがよいでしょう。 このような系列相関のチェックには、ADF検定によって誤差項の定常性を確認するのも有効だと思います。 """ # ADF test, H0: Non-stationary tsa.adfuller(rlt.resid, regression='nc') # Autocorrel plot of resid autocorrelation_plot(rlt.resid) # Show ACF of residuals ACF_resid = tsa.acf(rlt.resid) # Keep ACF of residuals """ 誤差項が定常であれば、モデル内の説明変数と被説明変数との間に安定した(一時的に外れても帰ってくるような)関係があることが保証されます。また、多くの経済変数はそもそも非定常ですので、残差が定常の場合、重要な要因がモデルから脱落している可能性も低くなります。 系列相関以外に大切なのは、多重共線性(マルチコリニアリティ)のチェックでしょう。これは、説明変数の間に強い相関がある場合に生じるもので、推定される係数の符号が反転してしまったりしますので厄介です。 以下のようにVIF統計量を計算して、10を大きく上回っていなければ、ひとまず安心と考えます。また、VIFを参照して機械的に判定しなくても、想定される符号と逆の符号を持った説明変数が現れれば、経験的にマルチコに気づくと思います。もっとも、マルチコの解決策は強相関している説明変数のどれかを取り除くくらいしか解決策がありません。 リッジ回帰など、パラメター空間を制約するやり方はそもそもパラメターの不偏性を犠牲にする上に、必ずしもマルチコを解消させる保障がないため、歪めますので、計量経済学では推奨されていません。 """ # Checking Multicolinearity by VIF VIF = pd.DataFrame([ oti.variance_inflation_factor(rlt.model.exog, i) for i in range(1, rlt.model.exog.shape[1])
returns = spClose.apply(np.log) - spClose.shift(1).apply(np.log) returns.plot() # Exercise 2 print(returns.mean()) print(returns.std()) print(returns.skew()) print(returns.kurt()) sb.distplot(returns, fit=stats.norm) # Exercise 3 print(tsa.acf(returns.dropna(), nlags=100)) sm.graphics.tsa.plot_acf(returns.dropna(), lags=100) # Exercise 4 returns2 = returns**2 returns2.plot() print(tsa.acf(returns2.dropna(), nlags=100)) sm.graphics.tsa.plot_acf(returns2.dropna(), lags=100) # Exercise 5 sigma0 = returns.std()
def acf_pacf(x, lag=41): ACF, q, pq = ts.acf(x, qstat=True, fft=False) tabela = np.c_[range(1, lag), ACF[1:], q, pq] tabela = pd.DataFrame(tabela, columns=['lag', "AC", "Q", "Prob(>Q)"]) return tabela
誤差項に系列相関が残っている場合、トレンドも含めて、モデルに含まれていない要因が大きい影響を持っている可能性がありますので、思い当たる説明変数を加えてみたり、タイム・トレンドやラグ項を足したり、変分を取るなりして、コントロールしたほうがよいでしょう。 このような系列相関のチェックには、ADF検定によって誤差項の定常性を確認するのも有効だと思います。 """ # ADF test, H0: Non-stationary tsa.adfuller(rlt.resid,regression='nc') # Autocorrel plot of resid autocorrelation_plot(rlt.resid) # Show ACF of residuals ACF_resid=tsa.acf(rlt.resid) # Keep ACF of residuals """ 誤差項が定常であれば、モデル内の説明変数と被説明変数との間に安定した(一時的に外れても帰ってくるような)関係があることが保証されます。また、多くの経済変数はそもそも非定常ですので、残差が定常の場合、重要な要因がモデルから脱落している可能性も低くなります。 系列相関以外に大切なのは、多重共線性(マルチコリニアリティ)のチェックでしょう。これは、説明変数の間に強い相関がある場合に生じるもので、推定される係数の符号が反転してしまったりしますので厄介です。 以下のようにVIF統計量を計算して、10を大きく上回っていなければ、ひとまず安心と考えます。また、VIFを参照して機械的に判定しなくても、想定される符号と逆の符号を持った説明変数が現れれば、経験的にマルチコに気づくと思います。もっとも、マルチコの解決策は強相関している説明変数のどれかを取り除くくらいしか解決策がありません。 リッジ回帰など、パラメター空間を制約するやり方はそもそもパラメターの不偏性を犠牲にする上に、必ずしもマルチコを解消させる保障がないため、歪めますので、計量経済学では推奨されていません。 """ # Checking Multicolinearity by VIF VIF=pd.DataFrame([oti.variance_inflation_factor(rlt.model.exog,i) for i in range(1,rlt.model.exog.shape[1])],index=rlt.model.exog_names[1:],columns=['VIF']) # VIF>10 should be cared
import pandas as pd import matplotlib.pyplot as plt from statsmodels.graphics.tsaplots import plot_acf from statsmodels.tsa.api import acf wave = pd.read_csv("data/wave.dat") print(acf(wave["waveht"],fft=False)) plt.figure() wave["waveht"].plot() plt.figure() wave["waveht"][0:60].plot() plot_acf(wave["waveht"]) plt.show()