def confidence_interval(data: np.ndarray, predicts: int = 7, confidence: float = 0.1, p: int = 1, d: int = 0, q: int = 0): """Function to find confidence interval of prediction for graph. Args: data (np.ndarray): Time series data predicts (int, optional): [description]. Defaults to 7. confidence (float, optional): [description]. Defaults to 0.1. p (int, optional): 1st order of ARIMA. Defaults to 1. d (int, optional): 2nd order of ARIMA. Defaults to 0. q (int, optional): 3rd order of ARIMA. Defaults to 0. Returns: list, list: Lower bound, upper bound. """ import statsmodels.tsa.api as sm if len(data) <= 10: return order = (p, d, q) try: model = sm.ARIMA(data, order=order) model_fit = model.fit(disp=0) predictions = model_fit.forecast(steps=predicts, alpha=confidence) bounds = predictions[2].T lower_bound = bounds[0] upper_bound = bounds[1] except Exception: last_value = data[-1] data = preprocessing.do_difference(data) model = sm.ARIMA(data, order=order) model_fit = model.fit(disp=0) predictions = model_fit.forecast(steps=predicts, alpha=confidence) bounds = predictions[2].T lower_bound = preprocessing.inverse_difference(bounds[0], last_value) upper_bound = preprocessing.inverse_difference(bounds[1], last_value) return lower_bound, upper_bound
def generate_arima(self, order): '''order is the d p q paramter to fit an arima model to generate feature by arima, we purpose a bidirectional arima we generate the second half of data by the correct direction, and we generate the first half of the data by the reverse direction''' stock = self.target #let's get the first half done half_time = int(self.data.shape[0] * 0.5) #this is half data train = self.data[stock].values[:half_time].tolist( ) #hence train and test will be just numpy array #print(len(train)) test = self.data[stock].values[half_time:].tolist() #generate our prediction prediction = list() history = copy.deepcopy(train) for t in range(len(test)): model = smt.ARIMA(history, order=order) model_fit = model.fit(disp=0) output = model_fit.forecast() yhat = float(output[0]) prediction.append(yhat) obs = test[t] history.append(obs) #print(len(train)) print("first half implementation finished") #now let's do the second half partition (test, train) = (train, test) #switch order test.reverse() train.reverse() prediction2 = list() history = copy.deepcopy(train) for t in range(len(test)): model = smt.ARIMA(history, order=order) model_fit = model.fit(disp=0) output = model_fit.forecast() yhat = float(output[0]) prediction2.append(yhat) obs = test[t] history.append(obs) prediction2.reverse() test.reverse() pred = prediction2 + prediction ypred_df = pd.DataFrame(pred, index=self.data['Date'], columns=['arima']) return (ypred_df)
def get_best_arima(ts, p=range(1, 5), d=range(1), q=range(5), exog=None, debug=False, verbose=True): aic_values = pd.Series(index=pd.MultiIndex.from_product([p, d, q])) combinations = itertools.product(p, d, q) for i, j, k in (tqdm(list(combinations)) if verbose else combinations): if i == j == k == 0: continue try: tmp_mdl = smt.ARIMA(ts, exog=exog, order=(i, j, k)).fit( method='mle', trend='nc', disp=0, ) aic_values[i, j, k] = tmp_mdl.aic except ValueError: continue # e.g. "ValueError: The computed initial AR coefficients are not stationary" (p==q) # except BaseException as e: # raise e # continue if verbose: print('Best AIC: {:.4f} (worst: {:.4f}) | params: {}, {}, {}'.format( aic_values.max(), aic_values.min(), *aic_values.idxmax())) if debug: return aic_values return aic_values.max(), aic_values.idxmax()
def model_select_fit(y, order,VERBOSE): """ The original signals and the detrending residuals are modeled using ARIMA(p,d,q) models. The best model is selected by grid searching around the pre-chosen (p,_,q) while keeping d fixed. The AIC is used to compare models with the same d. Asymptotically, minimizing the AIC is equivalent to minimizing the out-of-sample one-step forecast MSE for time series models. """ best_aic = np.inf best_mdl = None p = order[0] d = order[1] q = order[2] p_rng = range(p, max(-1, p - 3), -1) q_rng = range(q, max(-1, q - 3), -1) trend='nc' # c will be very close to zero for most detrended or differenced variables. for i in p_rng: for j in q_rng: try: tmp_mdl = smt.ARIMA(y, order=(i, d, j)).fit(method='mle', trend=trend,disp=VERBOSE) tmp_aic = tmp_mdl.aic if tmp_aic < best_aic: best_aic = tmp_aic best_mdl = tmp_mdl except: continue return d,best_mdl
def get_best_arma(TS): best_aic = np.inf best_order = None best_mdl = None pq_rng = range(5) # [0,1,2,3,4] d_rng = range(2) # [0,1] print('Solving arima model ...') time.sleep(1) for i in tqdm(pq_rng): for d in d_rng: for j in pq_rng: try: tmp_mdl = smt.ARIMA(TS, order=(i, d, j)).fit(method='mle', trend='nc') tmp_aic = tmp_mdl.aic if tmp_aic < best_aic: best_aic = tmp_aic best_order = (i, d, j) best_mdl = tmp_mdl except Exception as e: #print(e) continue print('aic: {:6.5f} | order: {}'.format(best_aic, best_order)) return best_aic, best_order, best_mdl
def analyse_ts_arima(self, data): ts = data.LSPY best_ic = np.inf best_order = None best_mdl = None pq_rng = range(5) # orders greater than 5 are not practically useful d_rng = range(2) # [0,1] for i in pq_rng: for d in d_rng: for j in pq_rng: try: tmp_mdl = smt.ARIMA(ts, order=(i, d, j)).fit( method='mle', trend='nc' ) tmp_ic = tmp_mdl.aic # using aic here logn('ic={}, order=({}, {}, {})'.format(tmp_ic,i,d,j)) if tmp_ic < best_ic: best_ic = tmp_ic best_order = (i, d, j) best_mdl = tmp_mdl except: continue logn(best_mdl.summary()) logn('using AIC', '='*20, sep='\n') logn('ic: {:6.5f} | estimated order: {}'.format(best_ic, best_order)) logn('estimated alphas = {}'.format(best_mdl.arparams)) logn('estimated betas = {}'.format(best_mdl.maparams)) self.g.tsplot(best_mdl.resid, lags=self.__n_lags, saveas='ts_arima{}{}{}_residuals.png'.format( best_order[0], best_order[1], best_order[2] ) ) # forecasting on the basis of best fit arima model self.forecast_ts_arima(ts, best_mdl, best_order) # ts should have index
def getbestarima(self, data, symbol): best_aic = np.inf best_order = None best_mdl = None pq_rng = range(5) # [0,1,2,3,4] d_rng = range(2) # [0,1] for i in pq_rng: for d in d_rng: for j in pq_rng: try: tmp_mdl = smt.ARIMA(data.get(symbol), order=(i, d, j)).fit(method='mle', trend='nc') tmp_aic = tmp_mdl.aic if tmp_aic < best_aic: best_aic = tmp_aic best_order = (i, d, j) best_mdl = tmp_mdl except: continue self.label_dikiful_2.setText('aic: {:6.5f} | order: {}'.format( best_aic, best_order)) if self.checkBox_forecast.isChecked( ) & self.radioButton_arima.isChecked(): self.forecast(data, symbol, best_mdl, int(self.sdiffspinBox_2.text())) elif not self.checkBox_forecast.isChecked( ) & self.radioButton_arima.isChecked(): self.tsplot(best_mdl.resid, symbol) return best_aic, best_order, best_mdl
def best_arima_model(TS, arima_order): best_aic = np.inf best_order = None best_mdl = None p_, d_, q_ = arima_order p_rng = range(1, p_ + 1) # [0,1,2,3,4] q_rng = range(1, q_ + 1) d_rng = range(d_ + 1) # [0,1] for i in p_rng: for d in d_rng: for j in q_rng: with warnings.catch_warnings(): warnings.filterwarnings("ignore") try: tmp_mdl = smt.ARIMA(TS, order=(i, d, j)).fit(method='mle', trend='nc', disp=False) tmp_aic = tmp_mdl.aic if tmp_aic < best_aic: best_aic = tmp_aic best_order = (i, d, j) best_mdl = tmp_mdl # except Exception as e: # continue # except RuntimeWarning as rw: # continue except (ConvergenceWarning, RuntimeWarning, ValueError, LinAlgError): continue # p('aic: {:6.5f} | order: {}'.format(best_aic, best_order)) return best_aic, best_order, best_mdl
def _get_best_model(self, TS): import statsmodels.tsa.api as smt import numpy as np best_aic = np.inf best_order = None best_mdl = None pq_rng = range(5) d_rng = range(2) for i in pq_rng: for d in d_rng: for j in pq_rng: try: tmp_mdl = smt.ARIMA(TS, order=(i, d, j)).fit(method='mle', trend='c', disp=-1) tmp_aic = tmp_mdl.aic if tmp_aic < best_aic: best_aic = tmp_aic best_order = (i, d, j) best_mdl = tmp_mdl except Exception: continue # print('aic: {:6.5f} | order: {}'.format(best_aic, best_order)) return best_aic, best_order, best_mdl
def get_best_garch_model(df): """ loops through all garch models and returns the best one based on the dataframe passed :param df: :return: """ best_aic = np.inf best_order = None best_mdl = None pq_rng = range(5) # [0,1,2,3,4] d_rng = range(2) # [0,1] for i in pq_rng: for d in d_rng: for j in pq_rng: try: tmp_mdl = smt.ARIMA(df, order=(i, d, j)).fit(method='mle', trend='nc') tmp_aic = tmp_mdl.aic if tmp_aic < best_aic: best_aic = tmp_aic best_order = (i, d, j) best_mdl = tmp_mdl except: continue print('aic: {:6.5f} | order: {}'.format(best_aic, best_order)) return best_aic, best_order, best_mdl
def predict_rolling_forward(train_ts, val_ts, arima_params): history = list(train_ts) ex_sample_predictions = pd.DataFrame( 0, columns=['value', 'std', 'confLow', 'confUp'], index=val_ts.index) for t in tqdm(range(len(val_ts))): model = smt.ARIMA(history, order=arima_params) model_fit = model.fit(method='mle', trend='nc', update_freq=5, disp=0) guess, std, confs = model_fit.forecast() ex_sample_predictions.iloc[t] = (guess, std[0], *confs[0]) history.append(val_ts[t]) return ex_sample_predictions
def fit_model(self, order): """ Args: order (tuple[int]): a three tuple for the arima orders Returns: """ model = smt.ARIMA(self._data, order).fit(method='mle', trend='nc') return model
def model_ARMA(ts, p=None, q=None): if p is None or q is None: p, q = determine_model_params(ts) if p != 0 or q != 0: try: resid = smt.ARIMA(ts, order=(p, 0, q)).fit(method='mle', trend='nc', update_freq=5, disp=0).resid except ValueError as e: if (str(e).find('coefficients are not stationary') == -1 and str(e).find('coefficients are not invertible') == -1): raise p += 1 resid = smt.ARIMA(ts, order=(p, 0, q)).fit(method='mle', trend='nc', update_freq=5, disp=0).resid else: resid = ts return resid, p, q
def __init__(self, time_series, order): self.model = ts.ARIMA(time_series, order) self.fit = self.model.fit(disp=-1) self.params = pd.DataFrame({ 'param': self.fit.params, 'p-val': self.fit.pvalues }) self.gofs = pd.Series({ 'AIC': self.fit.aic, 'BIC': self.fit.bic, 'HQIC': self.fit.hqic }) self._resids_tests()
def __init__(self, data, p=1, d=0, q=1, r=3, s=3, vol_model='HARCH'): self.arima = smt.ARIMA(data, order=(p, d, q)) self.arima_fit = self.arima.fit(method='mle', trend='nc', update_freq=5) # Use ARIMAs residuals self.garch = arch_model(self.arima_fit.resid, mean='Zero', vol=vol_model, p=r, q=s) self.garch_fit = self.garch.fit(update_freq=5, disp='off') # https://arch.readthedocs.io/en/latest/univariate/introduction.html self.in_sample_predictions = self.garch_fit.conditional_volatility self.p, self.d, self.q, self.r, self.s = p, d, q, r, s
def plot_arima_predictions(train_ts, val_ts, arima_params): model_name = f'ARIMA{arima_params}' model = smt.ARIMA(train_ts, order=arima_params) model_fit = model.fit(method='mle', trend='nc', update_freq=5) in_sample_predictions = model_fit.predict() # .fittedvalues ex_sample_predictions = predict_rolling_forward(train_ts, val_ts, arima_params) ax = train_ts.plot(label='Train', alpha=0.3, title=f'Model & Rolling Forecast of {model_name}', figsize=(12, 4)) ax.plot(train_ts.index, in_sample_predictions, label='In-Sample') val_ts.plot(ax=ax, label='Validation', alpha=0.3) ex_sample_predictions.value.plot(ax=ax, label='Ex-Sample') plt.xlim((train_ts.index[0], val_ts.index[-1])) plt.axvline(val_ts.index[0], color='black', linestyle='dashed') ax.legend() ax.set_ylabel('Link Relatives') ax.set_xlabel('') # plt.gcf().savefig('{symbol} - {model_name}.pdf') fig, axes = plt.subplots(1, 2, figsize=(12, 4)) print('Training data:') print(f'> {model_name}, RMS = ', rms(train_ts, in_sample_predictions)) print('> Persistence Model, RMS = ', rms(train_ts, train_ts.shift(1).fillna(0))) print('Validation data:') print(f'> {model_name}, RMS = ', rms(val_ts, ex_sample_predictions.value)) print('> Persistence Model, RMS = ', rms(val_ts, val_ts.shift(1).fillna(0))) axes[0].plot(train_ts - train_ts.shift(1), alpha=0.4, label='Persistence Model Error') (train_ts - in_sample_predictions).plot(ax=axes[0], alpha=0.8, label='ARIMA Error') axes[0].legend() axes[0].set_title('Model Errors vs. Baseline') axes[1].hist(train_ts, alpha=0.4, bins=100, color='gray', label='Original') plot.compare_with_normal(model_fit.resid, title='Distribution of ARIMA Errors', ax=axes[1])
def backtest(Y, foreLength, window, signal, order=''): for d in range(foreLength): # create a rolling window by selecting # values between d+1 and d+T of S&P500 returns TS = Y[(1 + d):(window + d)] if order: best_order = order best_mdl = smt.ARIMA(TS, order=(best_order[0], best_order[1], best_order[2]), freq=freq).fit(method='mle', trend='nc') else: # Find the best ARIMA fit # set d = 0 since we've already taken log return of the series _, best_order, best_mdl = _get_best_arima(TS) #now that we have our ARIMA fit, we feed this to GARCH model p_ = best_order[0] o_ = best_order[1] q_ = best_order[2] if p_ == o_ == 0: p_ = 1 am = arch.arch_model(best_mdl.resid, p=p_, o=o_, q=q_, dist='StudentsT') res = am.fit(update_freq=5, disp='off') # Generate a forecast of next day return using our fitted model out = res.forecast(horizon=1, start=None, align='origin') #Set trading signal equal to the sign of forecasted return # Buy if we expect positive returns, sell if negative signal.iloc[d] = np.sign(out.mean['h.1'].iloc[-1]) return signal
def _get_best_model(TS): best_aic = np.inf best_order = None best_mdl = None for i in range(5): for d in range(5): for j in range(5): try: tmp_mdl = smt.ARIMA(TS, order=(i, d, j)).fit(method='mle', trend='nc') tmp_aic = tmp_mdl.aic if tmp_aic < best_aic: best_aic = tmp_aic best_order = (i, d, j) best_mdl = tmp_mdl except: continue print('aic: {:6.5f} | order: {}'.format(best_aic, best_order)) return best_aic, best_order, best_mdl
def _get_best_model(TS, upper_=6): best_aic = np.inf best_order = None best_mdl = None pq_rng = range(1, upper_) d_rng = range(3) for i in pq_rng: for d in d_rng: for j in pq_rng: try: tmp_mdl = smt.ARIMA(TS, order=(i, d, j)).fit(method='mle', trend='nc') tmp_aic = tmp_mdl.aic if tmp_aic < best_aic: best_aic = tmp_aic best_order = (i, d, j) best_mdl = tmp_mdl except: continue return best_aic, best_order, best_mdl
def find_best_order(X): best_bic = np.inf best_order = None best_mdl = None max_p = 1 max_d = 2 max_q = 1 #Creates the biggest range possible for the gridsearch with likely convergance. while len(X) > 5 * (max_p + max_d + max_q) or max_p > 10: max_p += 1 max_q += 1 p_rng = range(max_p) # [0, 1, 2,..., max_p] q_rng = range(max_d) # [0, 1] d_rng = range(max_q) # [0, 1, 2,..., max_q] for i in p_rng: for d in d_rng: for j in q_rng: try: tmp_mdl = smt.ARIMA(X, order=(i, d, j)).fit(method='mle', disp=0, trend='nc') tmp_bic = tmp_mdl.bic if tmp_bic < best_bic: best_bic = tmp_bic best_order = (i, d, j) best_mdl = tmp_mdl except: continue p('bic: {:6.5f} | order: {}'.format(best_bic, best_order)) # aic: -11518.22902 | order: (4, 0, 4) # ARIMA model resid plot #_ = tsplot(best_mdl.resid, lags=30) print("best_order: " + str(best_order)) return best_order
def find_best_arima_model(time_series): """ Return best ARIMA model for provided Time Series. Parameters ========== time_series : series One-dimensional ndarray with axis labels (including time series). Returns ======= best_aic : float best_order : float best_mdl : ARIMAResultWrapper """ best_aic = np.inf best_order = None pq_rng = range(5) # [0,1,2,3,4] d_rng = range(2) # [0,1] for i in pq_rng: for d in d_rng: for j in pq_rng: try: tmp_mdl = smt.ARIMA(time_series.dropna(), order=(i, d, j)).fit(method='mle', trend='nc', disp=False) tmp_aic = tmp_mdl.aic if tmp_aic < best_aic: best_aic = tmp_aic best_order = (i, d, j) best_mdl = tmp_mdl except: continue return best_aic, best_order, best_mdl
def _get_best_model(TS): best_aic = np.inf best_order = None best_mdl = None pq_rng = range(5) # [0,1,2,3,4] d_rng = range(2) # [0,1] for i in pq_rng: for d in d_rng: for j in pq_rng: try: tmp_mdl = smt.ARIMA(TS, order=(i,d,j)).fit( method='mle', trend='nc' ) tmp_aic = tmp_mdl.aic if tmp_aic < best_aic: best_aic = tmp_aic best_order = (i, d, j) best_mdl = tmp_mdl except: continue p('aic: {:6.5f} | order: {}'.format(best_aic, best_order)) return best_aic, best_order, best_mdl
def seek_garch_model(TS): """ TS is returns of a price-series numpy array or array # Seek Best GARCH Model res_tup = seek_garch_model(ts) order = res_tup[1] p_ = order[0] o_ = order[1] q_ = order[2] # Using student T distribution usually provides better fit am = arch_model(ts, p=p_, o=o_, q=q_, dist='StudentsT') res = am.fit(update_freq=5, disp='off') fig = res.plot(annualize='D') print(res.summary()) ts_plot(res.resid, lags=30) """ best_aic = np.inf best_order = None best_mdl = None pq_rng = range(5) # [0,1,2,3,4] d_rng = range(2) # [0,1] for i in pq_rng: for d in d_rng: for j in pq_rng: try: tmp_mdl = smt.ARIMA(TS, order=(i, d, j)).fit(method='mle', trend='nc') tmp_aic = tmp_mdl.aic if tmp_aic < best_aic: best_aic = tmp_aic best_order = (i, d, j) best_mdl = tmp_mdl except: continue print('aic: {:6.5f} | order: {}'.format(best_aic, best_order)) return best_aic, best_order, best_mdl
def best_fit_model(ts): best_aic = np.inf best_order = None best_model = None pq_range = range(7) d_range = range(2) for p in pq_range: for d in d_range: for q in pq_range: try: temp_model = smt.ARIMA(ts, order=(p, d, q)).fit(method="mle", trend="nc") temp_aic = temp_model.aic if temp_aic < best_aic: best_aic = temp_aic best_order = (p, d, q) best_model = temp_model except: continue print("Best AIC: {:6.5f} | Best Order: {}".format(best_aic, best_order)) return best_model, best_order, best_aic
def _get_best_model(TS, pq_rng=5, d_rng=2): '''Finds best parameters for given series to be used in GARCH Model fitting. Parameters are suggested based on lowest AIC. best_aic, best_order, best_mdl = _get_best_model(TS,pq_rng,d_rng) --------------- Returns: best_aic: Lowest AIC obtained in grid search best_order: (p,d,q) values giving the lowest AIC best_mdl: statsmodels.tsa.api.ARIMA object with best parameters --------------- Parameters: TS: time series object pq_rng: (p,q) range to perform search within d_rng: d range to perform search within''' best_aic = np.inf best_order = None best_mdl = None pq_rng = range(pq_rng) # [0,1,2,3,4] d_rng = range(d_rng) # [0,1] for i in pq_rng: for d in d_rng: for j in pq_rng: try: tmp_mdl = smt.ARIMA(TS, order=(i, d, j)).fit(method='mle', trend='nc') tmp_aic = tmp_mdl.aic if tmp_aic < best_aic: best_aic = tmp_aic best_order = (i, d, j) best_mdl = tmp_mdl except: continue print('aic: {:6.5f} | order: {}'.format(best_aic, best_order)) return best_aic, best_order, best_mdl
def best_model(series, week): best_aic = np.inf best_order = None best_mdl = None pq_rng = range(5) # [0,1,2,3] d_rng = range(2) # [0,1] for i in pq_rng: for d in d_rng: for j in pq_rng: try: tmp_mdl = smt.ARIMA(y_train[series, :week], order=(i, d, j)).fit(method='mle', trend='nc') tmp_aic = tmp_mdl.aic if tmp_aic < best_aic: best_aic = tmp_aic best_order = (i, d, j) best_mdl = tmp_mdl except: continue return best_mdl
# %% cres_d = cresc['Preco'].diff(1) # %% plt.figure(figsize=(10,4)) plt.plot(cresc['Data'],cres_d) plt.xticks(rotation=70); # %% # %% modelo_cresc = smtsa.ARIMA(cresc_p1['Preco'].values, order=(1,1,2)).fit() # %% import numpy as np # %% modelo_cresc.plot_predict(26,35); plt.plot(np.linspace(0,9,10),cresc_p2['Preco']) # %% from pmdarima import auto_arima
import numpy as np import pandas as pd import matplotlib.pyplot as plt import statsmodels.tsa.api as smt white_noise = np.random.normal(size=500) time_series = np.zeros_like(white_noise) for t, noise in enumerate(white_noise): time_series[t] = 0.5*time_series[t-1] + 0.25*time_series[t-2] + noise - 1*white_noise[t-1] + 0.6*white_noise[t-2] time_series = pd.Series(time_series.cumsum()) train = time_series[:70] test = time_series[70:] p, d, q = 2, 1, 2 model = smt.ARIMA(train, order=(p,d,q)).fit(trend='c') _, axes = plt.subplots(1,1, figsize=(12,5)) model.plot_predict(start=d, end=100-1, ax=axes) values = model.forecast(30)[0] low_bound = model.forecast(30)[2][:,0] high_bound = model.forecast(30)[2][:,1] train.plot(label='train', ax=axes) test.plot(label='test', ax=axes) axes.plot(time_series, c='black', lw=0.5, ls='--', label='train+test') axes.plot(range(70,100), values, label='model.forecast') axes.plot(range(70,100), low_bound, c='red', ls='--', lw=1) axes.plot(range(70,100), high_bound, c='red', ls='--', lw=1) axes.grid(True) axes.legend() plt.show()
p('aic: {:6.5f} | order: {}'.format(best_aic, best_order)) # Fit ARIMA(p, d, q) model to SPY Returns # pick best order and final model based on aic best_aic = np.inf best_order = None best_mdl = None pq_rng = range(5) # [0,1,2,3,4] d_rng = range(2) # [0,1] for i in pq_rng: for d in d_rng: for j in pq_rng: try: tmp_mdl = smt.ARIMA(Disk_Avg.Disk_Free_Space_Avg, order=(i,d,j)).fit(method='mle', trend='nc') tmp_aic = tmp_mdl.aic if tmp_aic < best_aic: best_aic = tmp_aic best_order = (i, d, j) best_mdl = tmp_mdl except: continue p('aic: {:6.5f} | order: {}'.format(best_aic, best_order)) # Fit ARIMA(p, d, q) model to SPY Returns # pick best order and final model based on aic
#%% # Fit ARIMA(p, d, q) model to SP500 Returns # pick best order and final model based on aic best_aic = np.inf best_order = None best_mdl = None pq_rng = range(5) # [0,1,2,3,4] d_rng = range(2) # [0,1] for i in pq_rng: for d in d_rng: for j in pq_rng: try: tmp_mdl = smt.ARIMA(log_returns, order=(i, d, j)).fit(method='mle', trend='nc') tmp_aic = tmp_mdl.aic if tmp_aic < best_aic: best_aic = tmp_aic best_order = (i, d, j) best_mdl = tmp_mdl except: continue print('aic: {:6.5f} | order: {}'.format(best_aic, best_order)) # aic: -11518.22902 | order: (4, 0, 4) # ARIMA model resid plot _ = tsplot(best_mdl.resid, lags=30) #%%