Вы когда-нибудь задумывались, можно ли предсказать курс акций и стать следующим Воином с Уолл-стрит? Тогда возьмите чашку кофе и пристегните ремни безопасности, потому что мы собираемся погрузиться в увлекательный мир прогнозирования цен на акции с помощью сетей LSTM и TensorFlow. Предупреждаю: мы не сделаем вас богатым за одну ночь, но точно сделаем умнее!

Прогнозирование фондового рынка десятилетиями было святой грааль финансового анализа. Хотя мы не можем гарантировать, что вы обыграете Уоррена Баффета в его собственной игре, мы можем научить вас, как построить сложную нейронную сеть, которая учится на исторических данных и пытается предсказывать будущие цены. Представьте, что вы даёте своему компьютеру магический шар — правда, работающий на математике, а не на магии.

Почему LSTM для прогнозирования акций?

Сети долговременной краткосрочной памяти (LSTM) подобны слонам в мире нейронных сетей — они никогда не забывают того, что важно. В отличие от традиционных нейронных сетей, которые страдают от краткосрочной потери памяти, LSTM могут запоминать информацию в течение длительных периодов, что делает их идеальными для анализа данных временных рядов, таких как цены на акции.

Фондовый рынок по своей природе последователен — сегодняшняя цена зависит от вчерашних показателей, тенденций прошлой недели и даже событий, произошедших несколько месяцев назад. LSTM отлично справляются с захватом этих долгосрочных зависимостей, что делает прогнозирование акций возможным (хотя и не обязательно прибыльным — помните, прошлые результаты не гарантируют будущих!).

graph TD A[Исторические данные о ценах на акции] --> B[Предварительная обработка данных] B --> C[Создание временных окон] C --> D[Сеть LSTM] D --> E[Плотный слой] E --> F[Прогнозирование цены] F --> G[Оценка модели] G --> H{Удовлетворительно?} H -->|Нет| I[Настройка параметров] I --> D H -->|Да| J[Развёртывание модели]

Настройка вашего финансового предсказателя

Давайте начнём с импорта необходимых библиотек. Это похоже на сбор инструментов перед тем, как приступить к ремонту сложного механизма — за исключением того, что в данном случае механизм — это хаотическое существо, которое мы называем фондовым рынком.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout, Input
from tensorflow.keras.optimizers import Adam
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error, mean_absolute_error
import warnings
warnings.filterwarnings("ignore")
# Установить начальные значения случайных чисел для воспроизводимости
np.random.seed(42)
tf.random.set_seed(42)

Подготовка данных: основа успеха

Качество вашего прогноза зависит от качества ваших данных. Мы будем работать с историческими данными о ценах на акции, которые обычно включают цены открытия, максимума, минимума, закрытия и объём. Для нашей модели LSTM мы сосредоточимся в основном на ценах закрытия, поскольку они представляют собой конечный консенсус рыночной стоимости за каждый торговый день.

def load_and_prepare_data(file_path, symbol=None):
    """
    Загрузить данные о ценах на акции и подготовить их для обучения LSTM
    """
    # Загрузить набор данных
    data = pd.read_csv(file_path, delimiter=',', on_bad_lines='skip')
    # Преобразовать столбец даты в формат datetime
    data['date'] = pd.to_datetime(data['date'])
    # Отфильтровать данные по конкретному символу, если указан
    if symbol:
        data = data[data['Name'] == symbol].copy()
    # Отсортировать по дате
    data = data.sort_values('date').reset_index(drop=True)
    # Вывести основную информацию
    print(f"Форма набора данных: {data.shape}")
    print(f"Диапазон дат: {data['date'].min()} до {data['date'].max()}")
    return data
# Загрузить ваши данные
data = load_and_prepare_data('all_stocks_5yr.csv', symbol='AAPL')

Теперь самое интересное — создание временных окон. Нам нужно преобразовать наши последовательные данные в задачу обучения с учителем. Представьте, что мы учим модель смотреть на последние несколько дней, чтобы предсказать следующий день, точно так же, как метеоролог использует недавние закономерности для прогнозирования предстоящих условий.

def create_sequences(data, seq_length=60):
    """
    Создать последовательности для обучения LSTM
    seq_length: количество предыдущих дней для использования в прогнозе
    """
    # Извлечь цены закрытия
    prices = data['close'].values
    # Нормализовать данные
    scaler = MinMaxScaler(feature_range=(0, 1))
    scaled_prices = scaler.fit_transform(prices.reshape(-1, 1))
    # Создать последовательности
    X, y = [], []
    for i in range(seq_length, len(scaled_prices)):
        X.append(scaled_prices[i-seq_length:i, 0])
        y.append(scaled_prices[i, 0])
    X, y = np.array(X), np.array(y)
    # Изменить форму X для ввода в LSTM (образцы, временные шаги, признаки)
    X = np.reshape(X, (X.shape, X.shape, 1))
    return X, y, scaler
# Создать последовательности
sequence_length = 60  # Использовать 60 дней для прогнозирования следующего дня
X, y, scaler = create_sequences(data, sequence_length)
print(f"Форма признаков: {X.shape}")
print(f"Форма меток: {y.shape}")

Разделение данных: обучение, проверка, победа

Как и вы бы не стали сдавать итоговый экзамен без подготовки, мы не можем оценивать производительность нашей модели на данных, которые она уже видела. Мы разделим наши данные на обучающую и тестовую выборки, с одним нюансом — мы должны уважать хронологический порядок, поскольку мы имеем дело с данными временного ряда.

def split_data(X, y, train_size=0.8):
    """
    Разделить данные на обучающую и тестовую выборки, сохраняя хронологический порядок
    """
    split_index = int(len(X) * train_size)
    X_train, X_test = X[:split_index], X[split_index:]
    y_train, y_test = y[:split_index], y[split_index:]
    return X_train, X_test, y_train, y_test
X_train, X_test, y_train, y_test = split_data(X, y)
print(f"Обучающие данные: {X_train.shape} образцов")
print(f"Тестовые данные: {X_test.shape} образцов")

Построение архитектуры LSTM: ваш нейронный магический шар

Теперь переходим к главному блюду — построению нашей модели LSTM. Представьте, что это создание сложного механизма времени, который может заглядывать в закономерности прошлого, чтобы предугадать будущее. Наша архитектура будет тщательно продуманным стеком слоёв, каждый из которых служит определённой цели в процессе прогнозирования.

def build_lstm_model(input_shape):
    """
    Построить и скомпилировать модель LSTM для прогнозирования цен на акции
    """
    model = Sequential([
        # Входной слой
        Input(shape=input_shape),
        # Первый слой LSTM с возвратом последовательностей
        LSTM(units=50, return_sequences=True, activation='tanh'),
        Dropout(0.2),  # Предотвратить переобучение
        # Второй слой LSTM
        LSTM(units=50, return_sequences=True, activation='tanh'),
        Dropout(0.2),
        # Третий слой LSTM
        LSTM(units=50, return_sequences=False, activation='tanh'),
        Dropout(0.2),
        # Плотные слои для финального прогноза
        Dense(units=25, activation='relu'),
        Dense(units=1)  # Один выход для прогнозирования цены акции
    ])
    # Скомпилировать модель
    model.compile(
        optimizer=Adam(learning_rate=0.001),
        loss='mean_squared_error',
        metrics=['mae']
    )
    return model
# Построить модель
input_shape = (X_train.shape, X_train.shape)
model = build_lstm_model(input_shape)
# Вывести архитектуру модели
model.summary()

Давайте разберём, что делает каждый слой в нашем стеке нейронных сетей:

Слои LSTM: Это рабочие лошадки нашей модели. Каждый слой