Из-за множества экономических, политических и социальных факторов, влияющих на цены акций, прогнозирование тенденций фондового рынка является очень сложной задачей. Тем не менее, достижения в области глубокого обучения открыли новые возможности для прогнозирования цен на акции на основе исторических данных.
Цель этой статьи — продемонстрировать, как использовать методы глубокого обучения, в частности модели LSTM, для прогнозирования будущих цен на акции с использованием Python. Основываясь на ценах закрытия предыдущих девяти дней, мы спрогнозируем цену закрытия одной акции на следующий день и оценим цену закрытия всех акций в S&P 500 на основе исторических данных.
Для начала мы сосредоточимся на более простом сценарии прогнозирования цены закрытия отдельной акции на основе цен закрытия за предыдущие девять дней.
В качестве следующего шага мы рассмотрим все акции в S&P 500. В этом руководстве мы покажем, как получить исторические цены для всех компонентов S&P 500 из Википедии и Yahoo Finance, предварительно обработать данные, обучить модель и генерировать прогнозы. Кроме того, мы проиллюстрируем, как можно визуализировать производительность модели, сравнивая прогнозируемые и фактические цены.
Прочитав эту статью, вы получите полное представление о том, как можно использовать глубокое обучение для прогнозирования цен на акции с помощью Python и как эти методы можно применить к реальному набору данных.
ЧАСТЬ 1: Прогноз для отдельной акции Во-первых, мы можем получить исторические данные из Yahoo Finance, используя библиотеку yfinance. Пример того, как загрузить исторические данные для отдельного символа акции, показан в следующей ячейке кода.
import yfinance as yf symbol = 'AAPL' start_date = '2010-01-01' end_date = '2023-02-17' data = yf.download(symbol, start=start_date, end=end_date)
Визуальное отображение исторических данных возможно с помощью функции построения графика.
import matplotlib.pyplot as plt plt.plot(data['Close']) plt.title(symbol + ' Close Price') plt.xlabel('Date') plt.ylabel('Price') plt.show()
Основываясь на исторических данных, теперь мы можем построить модель LSTM для прогнозирования будущих цен. LSTM — это рекуррентные нейронные сети, способные учиться на последовательных данных, таких как данные временных рядов. Используя Keras, широко используемую библиотеку глубокого обучения, следующая ячейка кода создает модель LSTM.
from keras.models import Sequential from keras.layers import LSTM, Dense import numpy as np from sklearn.preprocessing import MinMaxScaler lookback = 9 def create_dataset(dataset): X, Y = [], [] for i in range(len(dataset)-lookback-1): X.append(dataset[i:(i+lookback), 0]) Y.append(dataset[i+lookback, 0]) return np.array(X), np.array(Y) # Scale data data = np.array(data['Close']).reshape(-1, 1) scaler = MinMaxScaler(feature_range=(0, 1)) data = scaler.fit_transform(data) # Train and test split train_size = int(len(data) * 0.8) train_data = data[:train_size] test_data = data[train_size:] train_X, train_Y = create_dataset(train_data) test_X, test_Y = create_dataset(test_data) train_X = np.reshape(train_X, (train_X.shape[0], train_X.shape[1], 1)) test_X = np.reshape(test_X, (test_X.shape[0], test_X.shape[1], 1)) # Create model model = Sequential() model.add(LSTM(50, input_shape=(lookback, 1))) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') model.fit(train_X, train_Y, epochs=50, batch_size=64, verbose=2)
С помощью функции create_dataset мы генерируем последовательности предыдущих цен вместе с соответствующими им будущими ценами на основе данных, разделенных на наборы для обучения и тестирования. После нормализации данных мы изменяем их форму, чтобы они соответствовали входному формату модели LSTM, используя MinMaxScaler.
Модель LSTM состоит из входного слоя, слоя LSTM, содержащего 50 единиц, и плотного выходного слоя. Подгонка модели к обучающим данным выполняется с использованием функции потери среднеквадратичной ошибки и оптимизатора Адама.
Модель можно применять к тестовым данным после ее обучения. На основе 9 предыдущих цен следующая ячейка кода иллюстрирует, как предсказать 10-ю цену.
# Reshape the test data test_X = test_X.reshape((test_X.shape[0], lookback, 1)) # Use the trained model to make predictions on the test data predictions = model.predict(test_X) # Convert the predicted values back to their original scale predictions = scaler.inverse_transform(predictions) # Convert the actual values back to their original scale actuals = scaler.inverse_transform(test_Y.reshape(-1, 1)) # Print the first 10 predicted and actual values for i in range(10): print(f"Predicted: {predictions[i][0]:.2f} Actual: {actuals[i][0]:.2f}")
В качестве первого шага мы изменяем тестовые данные в соответствии с входным форматом модели LSTM. Затем мы используем функцию прогнозирования для создания прогнозов и обращаем масштабирование для получения фактических цен. Ниже приведены первые 10 прогнозируемых цен и их фактические цены.
Используя следующую ячейку кода, мы также можем визуализировать прогнозируемые цены с течением времени.
plt.plot(actuals, label='Actual') plt.plot(predictions, label='Predicted') plt.title(symbol + ' Close Price') plt.xlabel('Date') plt.ylabel('Price') plt.legend() plt.show()
Оранжевый цвет представляет прогнозируемые цены, а синий — фактические цены. Хотя модель не может предсказать точную цену, она фиксирует общую тенденцию цены акций.
ЧАСТЬ 2: Прогноз для всех символов акций
В предыдущем разделе использовалась модель LSTM для прогнозирования будущей цены отдельной акции. Наш анализ всех акций S&P 500 будет расширен в этом разделе.
Используя те же даты начала и окончания, что и раньше, нам нужно получить исторические данные от Yahoo Finance для всех компонентов S&P 500.
# Import necessary libraries import yfinance as yf import pandas as pd # Download the list of S&P 500 components from Wikipedia url = 'https://en.wikipedia.org/wiki/List_of_S%26P_500_companies' table = pd.read_html(url, header=0)[0] symbols = list(table.Symbol) # Define the start and end dates for the historical data start_date = '2010-01-01' end_date = '2023-02-17' # Download historical data for all S&P 500 components data = {} for symbol in symbols: print(f"Downloading data for {symbol}") df = yf.download(symbol, start=start_date, end=end_date) if len(df) >= 50: data[symbol] = df
Используя приведенный выше код, мы загружаем исторические данные по всем компонентам S&P 500 и сохраняем их в виде фреймов данных в словаре, где ключевые значения представляют собой символы. Данные символа сохраняются только в том случае, если их длина составляет 50 или больше.
Теперь для каждого символа мы можем использовать те же функции create_dataset и train_test_split, что и раньше. LSTM будет обучаться на всех данных, кроме последнего дня, и использоваться для прогнозирования цены каждого символа в последний день.
# Import necessary libraries from sklearn.preprocessing import MinMaxScaler import numpy as np from tensorflow import keras # Define functions to create and split the dataset def create_dataset(data, lookback=9): X, Y = [], [] for i in range(lookback, len(data)): X.append(data[i-lookback:i, 0]) Y.append(data[i, 0]) return np.array(X), np.array(Y) def train_test_split(data, test_size=0.2, lookback=9): train_size = int(len(data) * (1 - test_size)) train, test = data[:train_size], data[train_size-lookback:] return train, test # Define the lookback and test size lookback = 9 test_size = 0.2 # Create an empty list to store the results results = [] # Iterate through each symbol and its corresponding data for symbol, df in dfs.items(): print(f"Processing {symbol}") # Prepare the data data = df['Close'].values.reshape(-1, 1) scaler = MinMaxScaler(feature_range=(0, 1)) data = scaler.fit_transform(data) train, test = train_test_split(data, test_size=test_size, lookback=lookback) train_X, train_Y = create_dataset(train, lookback=lookback) test_X, test_Y = create_dataset(test, lookback=lookback) # Train the model train_X = train_X.reshape((train_X.shape[0], train_X.shape[1], 1)) test_X = test_X.reshape((test_X.shape[0], test_X.shape[1], 1)) model = keras.models.Sequential([ keras.layers.LSTM(50, input_shape=(lookback, 1)), keras.layers.Dense(1) ]) model.compile(loss='mse', optimizer='adam') model.fit(train_X, train_Y, epochs=100, batch_size=32, verbose=0) # Make predictions on the test data test_X = test_X.reshape((test_X.shape[0], lookback, 1)) predictions = model.predict(test_X)[-1] predictions = scaler.inverse_transform(predictions.reshape(-1, 1))[0] actual = df['Close'][-1] # Append the results to the list results.append((symbol, actual, predictions))
Используя исторические данные для каждой акции, приведенный выше код перебирает все компоненты S&P 500 и обучает модель LSTM. В результате модель предсказывает цену закрытия для каждой акции в последний день доступности данных.
Каждый кортеж содержит символ, фактическую цену и прогнозируемую цену. Следующий код можно использовать для сравнения прогнозируемых цен с фактическими:
import matplotlib.pyplot as plt plt.figure(figsize=(16, 12)) for symbol, actual, predicted in results: plt.plot([symbol]*2, [actual, predicted], 'o-', label=symbol) # plt.legend() plt.title('Predicted vs Actual Prices for S&P 500 Stocks') plt.ylabel('Price ($)') plt.show()
В приведенном выше коде прогнозируемые и фактические цены отображаются в последний день данных, доступных для каждой акции. Ось X представляет символ, а ось Y представляет цену. Синяя точка указывает фактическую цену, а оранжевая линия указывает прогнозируемую цену.
Для некоторых акций модель LSTM предлагает достаточно точные прогнозы, в то время как для других прогнозы менее точны. Фондовые рынки по своей природе непредсказуемы и подвержены влиянию множества внешних факторов, чего и следовало ожидать.
В этой статье мы продемонстрировали, как использовать глубокое обучение, в частности модели LSTM, для прогнозирования будущих цен на акции с использованием Python. Этот анализ также может быть расширен, чтобы охватить все акции S&P 500, а прогнозируемые цены можно сравнить с фактическими ценами.