Широко признанным методом прогнозирования линейных временных рядов является ARIMA (авторегрессионное интегрированное скользящее среднее). Цель этой статьи — дать обзор ARIMA с помощью иллюстрации, ориентированной на финансы, и прояснить важность параметров p, d и q.
Цель состоит в том, чтобы предсказать цены закрытия на следующие несколько дней на основе набора данных с ежедневными ценами акций закрытия. Этот набор данных можно использовать для прогнозирования с использованием модели ARIMA.
Перед применением модели ARIMA важно убедиться, что временной ряд является стационарным, что означает, что его статистические свойства (среднее значение, дисперсия и автокорреляция) остаются постоянными. Нестационарные данные можно преобразовать в стационарные путем разности или вычитания предыдущего значения из текущего значения.
Давайте посмотрим на параметры p, d и q в модели ARIMA(p, d, q):
p (термин авторегрессии): Порядок членов авторегрессии (p) указывает, сколько предыдущих временных шагов (лагов) использовалось для моделирования текущего значения. Используя два предыдущих значения, модель ARIMA(2, 0, 0) может прогнозировать текущее значение следующим образом:
X(t) = c + φ1 * X(t-1) + φ2 * X(t-2) + ε(t)
В этом уравнении X(t) представляет текущее значение, X(t-1) и X(t-2) обозначают два предыдущих значения, φ1 и φ2 — коэффициенты, c — константа, а ε(t) — срок ошибки.
d (Интегральный член): Интегральный член (d) представляет собой величину разности, примененную к временному ряду, чтобы сделать его стационарным. Если исходный временной ряд нестационарен и становится стационарным после однократного дифференцирования, d равно 1. Чтобы стать стационарным, дифференцированному ряду потребуется еще один раунд дифференцирования и так далее.
Порядок члена скользящего среднего (q) указывает, сколько членов с запаздывающими ошибками используется для моделирования текущего значения во временном ряду. Модель ARIMA(0, 0, 2) будет прогнозировать текущее значение, используя два предыдущих члена ошибки:
X(t) = c + θ1 * ε(t-1) + θ2 * ε(t-2) + ε(t)
В этом уравнении θ1 и θ2 представляют собой коэффициенты членов запаздывающей ошибки ε(t-1) и ε(t-2), а ε(t) обозначает текущий член ошибки.
Чтобы выбрать подходящие значения для p, d и q, можно использовать несколько методов, включая изучение функции автокорреляции и графиков частичной функции автокорреляции, или использование поиска по сетке и показателей оценки модели, таких как информационный критерий Акаике (AIC) или байесовская информация. критерий (БИК).
Подбирая модель ARIMA к данным временных рядов и используя результаты для прогнозирования будущих цен закрытия акций, можно определить оптимальные значения p, d и q.
Чтобы предсказать будущие цены закрытия, следующий код использует библиотеку statsmodels для подбора модели ARIMA(1,1,1) к ценам закрытия акций. В этом примере предполагается модель ARIMA(1,1,1) без оптимизации параметров (p, d, q). Чтобы выбрать лучшую модель, эти параметры должны быть оптимизированы в соответствии с такими критериями, как информационный критерий Акаике (AIC) или байесовский информационный критерий (BIC).
Используя объект model_fit, возвращаемый методом fit() модели ARIMA, можно вычислить информационный критерий Акаике (AIC) или байесовский информационный критерий (BIC). Эти значения хранятся в атрибутах aic и bic объекта model_fit. Чтобы оценить производительность модели, код вычисляет среднеквадратичную ошибку (RMSE) и отображает фактические цены закрытия в сравнении с прогнозируемыми.
!pip install pandas numpy matplotlib pandas-datareader yfinance statsmodels import pandas as pd import numpy as np import matplotlib.pyplot as plt from pandas_datareader import data as pdr import yfinance as yf from statsmodels.tsa.arima.model import ARIMA from sklearn.metrics import mean_squared_error from math import sqrt # Set up Yahoo Finance data source yf.pdr_override() # Get historical stock data symbol = "AAPL" start_date = "2020-01-01" end_date = "2021-01-01" stock_data = pdr.get_data_yahoo(symbol, start=start_date, end=end_date) # Extract closing prices closing_prices = stock_data["Close"] # Divide data into training and testing sets train_data = closing_prices[:int(len(closing_prices) * 0.8)] test_data = closing_prices[int(len(closing_prices) * 0.8):] # Train ARIMA model model = ARIMA(train_data, order=(1, 2, 1)) model_fit = model.fit() # Output AIC and BIC values print("AIC: ", model_fit.aic) print("BIC: ", model_fit.bic) # Forecast stock prices with ARIMA model predictions = model_fit.forecast(steps=len(test_data)) # Compute root mean squared error (RMSE) rmse = sqrt(mean_squared_error(test_data, predictions)) print("RMSE: ", rmse) # Display actual vs. predicted closing prices plt.figure(figsize=(12, 6)) plt.plot(train_data, label="Training data") plt.plot(test_data, label="Actual closing prices") plt.plot(test_data.index, predictions, label="Predicted closing prices") plt.xlabel("Date") plt.ylabel("Closing Price") plt.title(f"{symbol} Stock Closing Price Prediction using ARIMA") plt.legend() plt.show()
Оптимизируя параметры модели ARIMA, можно повысить производительность модели. При наличии нестационарных данных необходима модель ARIMA с минимальным значением d, равным 1. В идеале это должно выполнять ту же самую процедуру разности внутри! На основе наименьшего значения AIC и оптимального процента разделения приведенный ниже код делит данные на наборы для обучения и тестирования. Чтобы предсказать разницу цен акций для тестового набора данных, определяется наилучшая модель ARIMA.
import pandas as pd import numpy as np import matplotlib.pyplot as plt from pandas_datareader import data as pdr import yfinance as yf from statsmodels.tsa.arima.model import ARIMA from sklearn.metrics import mean_squared_error from math import sqrt import itertools import warnings # Ignore warnings warnings.filterwarnings("ignore") # Set up Yahoo Finance data source yf.pdr_override() # Get historical stock data symbol = "AAPL" start_date = "2020-01-01" end_date = "2021-01-01" stock_data = pdr.get_data_yahoo(symbol, start=start_date, end=end_date) # Extract closing prices closing_prices = stock_data["Close"] # Divide data into training and testing sets train_data = closing_prices[:int(len(closing_prices) * 0.8)] test_data = closing_prices[int(len(closing_prices) * 0.8):] # Determine optimal ARIMA parameters with grid search p_values = range(0, 5) d_values = range(0, 5) q_values = range(0, 5) pdq_combinations = list(itertools.product(p_values, d_values, q_values)) best_aic = float("inf") best_order = None best_model = None # Iterate through possible parameter combinations for order in pdq_combinations: try: model = ARIMA(train_data, order=order) model_fit = model.fit() if model_fit.aic < best_aic: best_aic = model_fit.aic best_order = order best_model = model_fit except Exception as e: print(f"Error fitting ARIMA model with order {order}") print(f"Optimal ARIMA order: {best_order}") print("AIC: ", best_aic) print("BIC: ", best_model.bic) # Forecast stock prices using optimal ARIMA model predictions = best_model.forecast(steps=len(test_data)) # Compute root mean squared error (RMSE) rmse = sqrt(mean_squared_error(test_data, predictions)) print("RMSE: ", rmse) # Display actual vs. predicted closing prices plt.figure(figsize=(12, 6)) plt.plot(train_data, label="Training data") plt.plot(test_data, label="Actual closing prices") plt.plot(test_data.index, predictions, label="Predicted closing prices") plt.xlabel("Date") plt.ylabel("Closing Price") plt.title(f"{symbol} Stock Closing Price Prediction using ARIMA") plt.legend() plt.show()
Для оценки точности прогноза вычисляется среднеквадратическая ошибка (RMSE) и создается график, отображающий фактические и прогнозируемые цены закрытия.
Модели ARIMA работают лучше всего, когда данные показывают линейные тренды и не содержат сложных нелинейных связей. Данные, демонстрирующие нелинейные закономерности, лучше прогнозировать с помощью более сложных моделей, таких как нейронные сети или алгоритмы машинного обучения.
В следующем коде Python модель Long Short-Term Memory (LSTM) используется для прогнозирования цен закрытия акций и сравнивается с моделью ARIMA. Установите библиотеки TensorFlow и Keras, если они еще не установлены.
import numpy as np import pandas as pd import matplotlib.pyplot as plt from pandas_datareader import data as pdr import yfinance as yf from sklearn.preprocessing import MinMaxScaler from sklearn.metrics import mean_squared_error from math import sqrt from keras.models import Sequential from keras.layers import Dense, LSTM # Set up Yahoo Finance data source yf.pdr_override() # Retrieve historical stock data symbol = "AAPL" start_date = "2020-01-01" end_date = "2021-01-01" stock_data = pdr.get_data_yahoo(symbol, start=start_date, end=end_date) # Extract closing prices closing_prices = stock_data["Close"] # Scale the data scaler = MinMaxScaler(feature_range=(0, 1)) scaled_data = scaler.fit_transform(closing_prices.values.reshape(-1, 1)) # Divide data into training and testing sets train_size = int(len(scaled_data) * 0.8) train_data, test_data = scaled_data[0:train_size, :], scaled_data[train_size:, :] test_data_index = closing_prices[train_size:].index # Function to generate time series dataset for LSTM def create_dataset(dataset, window_size=1): data_x, data_y = [], [] for i in range(len(dataset) - window_size - 1): data_x.append(dataset[i:(i + window_size), 0]) data_y.append(dataset[i + window_size, 0]) return np.array(data_x), np.array(data_y) # Generate time series dataset for LSTM window_size = 5 train_x, train_y = create_dataset(train_data, window_size) test_x, test_y = create_dataset(test_data, window_size) # Reshape input to [samples, time steps, features] train_x = np.reshape(train_x, (train_x.shape[0], 1, train_x.shape[1])) test_x = np.reshape(test_x, (test_x.shape[0], 1, test_x.shape[1])) # Construct LSTM model model = Sequential() model.add(LSTM(50, input_shape=(1, window_size))) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') # Train LSTM model model.fit(train_x, train_y, epochs=100, batch_size=1, verbose=0) # Make predictions with LSTM model train_predict = model.predict(train_x) test_predict = model.predict(test_x) # Revert predictions to original scale train_predict = scaler.inverse_transform(train_predict) train_y = scaler.inverse_transform([train_y]) test_predict = scaler.inverse_transform(test_predict) test_y = scaler.inverse_transform([test_y]) # Compute root mean squared error (RMSE) for LSTM test_rmse = sqrt(mean_squared_error(test_y[0], test_predict[:, 0])) print("LSTM Test RMSE: ", test_rmse) # Display actual vs. predicted closing prices plt.figure(figsize=(12, 6)) plt.plot(closing_prices[:-len(test_data_index)], label="Training data Closing prices") plt.plot(closing_prices[-len(test_data_index):], label="Actual closing prices") plt.plot(test_data_index[7:], test_predict[:-1], label="LSTM Predicted closing prices") plt.xlabel("Date") plt.ylabel("Closing Price") plt.title(f"{symbol} Stock Closing Price Prediction using LSTM") plt.legend() plt.show()
В статье показано, что прогнозирование цен на акции является сложной задачей, и метод ARIMA может быть не самым подходящим методом. Такие модели, как сети с долговременной кратковременной памятью (LSTM) и Facebook Prophet, специально разработаны для управления данными временных рядов и могут обеспечить лучшие результаты.