I am trying to learn ARIMA and so far I am working on this dataset Huge Stock Market Dataset i used intel stocks as you can see from the code, I was able to make it work with LSTM and that went smooth, but i dont have any experience with ARIMA my current problem is the forecast is a flat line, and can't figure out the problem import numpy as np import pandas as pd from pmdarima import auto_arima from statsmodels.tsa.stattools import adfuller from statsmodels.tsa.arima.model import ARIMA from sklearn.metrics import mean_squared_error, mean_absolute_error import matplotlib.pyplot as plt import warnings warnings.filterwarnings("ignore") # Load and preprocess data def load_data(filepath, start_date): df = pd.read_csv(filepath, sep=',') df = df[df['Date'] > start_date] df['Date'] = pd.to_datetime(df['Date']) df.set_index('Date', inplace=True) return df[['Close']] # ADF Test def adf_test(series): result = adfuller(series) print(f"ADF Statistic: {result[0]}, p-value: {result[1]}") return result[1] <= 0.05 # Stationary if p-value <= 0.05 # Plot data def plot_series(series, title): plt.figure(figsize=(12, 6)) plt.plot(series, label=title, color='blue', alpha=0.7) plt.title(title) plt.legend() plt.show() # Split data def split_data(data, split_ratio=0.8): train_size = int(len(data) * split_ratio) train, test = data[:train_size], data[train_size:] return train, test # Fit ARIMA model def fit_arima(train, order=None): if not order: stepwise_fit = auto_arima(train, seasonal=False, trace=True, error_action='ignore', suppress_warnings=True) order = stepwise_fit.order print(f"Selected ARIMA Order: {order}") model = ARIMA(train, order=order) return model.fit() # Forecast and evaluate def forecast_and_evaluate(model_fit, test, original_series=None, diff_order=0): forecast = model_fit.forecast(steps=len(test)) forecast = pd.Series(forecast, index=test.index, name='Forecast') # Reverse differencing if applicable if diff_order > 0 and original_series is not None: last_train_value = original_series.iloc[-1] # Last value from original (non-differenced) training series forecast = forecast.cumsum() + last_train_value # Debugging forecast values print(f"First 5 forecast values (before adjustments):\n{forecast.head()}") # Remove negative values forecast[forecast < 0] = 0 # Remove non-numeric values forecast = forecast.fillna(0) # Calculate metrics rmse = np.sqrt(mean_squared_error(test, forecast)) mae = mean_absolute_error(test, forecast) print(f"\nRoot Mean Squared Error: {rmse}") print(f"Mean Absolute Error: {mae}") return forecast, rmse, mae # Plot comparison def plot_forecast(test, forecast, title='Actual vs Forecast'): plt.figure(figsize=(12, 6)) plt.plot(test, label='Actual Test Data', color='blue', alpha=0.7) plt.plot(forecast, label='Forecast', color='red', linestyle='--', alpha=0.7) plt.title(title) plt.legend() plt.show() # Residual diagnostics def residual_diagnostics(residuals): plt.figure(figsize=(12, 6)) plt.subplot(211) plt.plot(residuals, label='Residuals', color='purple', alpha=0.7) plt.title('Residuals') plt.legend() plt.subplot(212) plt.hist(residuals, bins=20, alpha=0.7, color='green', label='Residual Histogram') plt.title('Residual Histogram') plt.legend() plt.tight_layout() plt.show() # Main script if __name__ == "__main__": # Load data filepath = "../Datasets/Stocks/intc.us.txt" data = load_data(filepath, start_date='1990-01-01') # Check stationarity if not adf_test(data['Close']): print("Data is non-stationary. Differencing...") data_diff = data['Close'].diff().dropna() diff_order = 1 print(f"First 5 values after differencing:\n{data_diff.head()}") else: print("Data is stationary.") data_diff = data['Close'] diff_order = 0 plot_series(data_diff, "Differenced Data") # Split data train, test = split_data(data_diff) original_train, original_test = split_data(data['Close']) # Fit ARIMA model model_fit = fit_arima(train) # Residual diagnostics residual_diagnostics(model_fit.resid) # Forecast and evaluate forecast, rmse, mae = forecast_and_evaluate( model_fit, test, original_series=original_train if diff_order > 0 else None, diff_order=diff_order ) # Plot forecast vs actual plot_forecast(test, forecast, title="Actual vs Forecast") # Print forecast head print(forecast.head()) here is the log ADF Statistic: -1.2717375543756217, p-value: 0.642001214544929 Data is non-stationary. Differencing... First 5 values after differencing: Date 1990-01-03 -0.0242 1990-01-04 0.0164 1990-01-05 -0.0084 1990-01-08 0.0162 1990-01-09 0.0240 Name: Close, dtype: float64 Performing stepwise search to minimize aic ARIMA(2,0,2)(0,0,0)[0] : AIC=9193.905, Time=0.56 sec ARIMA(0,0,0)(0,0,0)[0] : AIC=9200.647, Time=0.08 sec ARIMA(1,0,0)(0,0,0)[0] : AIC=9198.553, Time=0.06 sec ARIMA(0,0,1)(0,0,0)[0] : AIC=9198.409, Time=0.08 sec ARIMA(1,0,2)(0,0,0)[0] : AIC=9192.284, Time=0.35 sec ARIMA(0,0,2)(0,0,0)[0] : AIC=9198.467, Time=0.12 sec ARIMA(1,0,1)(0,0,0)[0] : AIC=9191.738, Time=0.23 sec ARIMA(2,0,1)(0,0,0)[0] : AIC=9192.008, Time=0.29 sec ARIMA(2,0,0)(0,0,0)[0] : AIC=9199.273, Time=0.09 sec ARIMA(1,0,1)(0,0,0)[0] intercept : AIC=9193.371, Time=0.64 sec Best model: ARIMA(1,0,1)(0,0,0)[0] Total fit time: 2.495 seconds Selected ARIMA Order: (1, 0, 1) First 5 forecast values (before adjustments): Date 2012-04-16 NaN 2012-04-17 NaN 2012-04-18 NaN 2012-04-19 NaN 2012-04-20 NaN Name: Forecast, dtype: float64 Root Mean Squared Error: 0.38750459255687414 Mean Absolute Error: 0.2705679715302491 Date 2012-04-16 0.0 2012-04-17 0.0 2012-04-18 0.0 2012-04-19 0.0 2012-04-20 0.0 Name: Forecast, dtype: float64 Continue reading...