Широко признанным методом прогнозирования линейных временных рядов является 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, специально разработаны для управления данными временных рядов и могут обеспечить лучшие результаты.