Методы глубокого машинного обучения для финансов, практические модели для трейдинга на Python. Обзор книги: Deep Learning for Finance

Финансовые рынки становятся ареной алгоритмов. Те, кто умеет эффективно анализировать данные — зарабатывает огромные деньги. Эта статья — о том, как шаг за шагом построить на Python торговые стратегии на основе глубокого машинного обучения.

Deep Learning for Finance: Creating Machine & Deep Learning Models for Trading in Python. Sofien Kaabar. 2024.02.13
Deep Learning for Finance: Creating Machine & Deep Learning Models for Trading in Python. Sofien Kaabar. 2024.02.13

4.9 🌕🌕🌕🌕🌖 4 017

🥇Бестселлер: методы глубокого машинного обучения

Софиен Каабар в книге «Deep Learning for Finance» демонстрирует, как связать машинное обучение, глубокие нейросети и технический анализ. Перед вами не академический учебник, а практическое руководство — от простых индикаторов до продвинутых методов обучения с подкреплением. В книге представлены:

  • построение моделей ML и DL для временных рядов;

  • применение методов обучения с подкреплением к торговле;

  • метрики качества и риск‑метрики (Sharpe, Max Drawdown, CAGR);

  • создание технических индикаторов на Python;

  • оптимизация и тестирование стратегий, оценка доходности.

1. Загрузка данных и базовые утилиты

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

import yfinance as yf import pandas as pd import numpy as np df = yf.download("AAPL", start="2017-01-01", end="2024-01-01") df = df.sort_index() df["ret"] = df["Close"].pct_change().fillna(0)

2. Технические индикаторы как признаки

Машинное обучение любит признаки. В трейдинге это индикаторы: RSI, EMA, Bollinger Bands.

Пример RSI с корректной обработкой:

def rsi(series: pd.Series, period: int = 14) -> pd.Series: delta = series.diff() gain = delta.clip(lower=0) loss = -delta.clip(upper=0) avg_gain = gain.ewm(alpha=1/period, adjust=False).mean() avg_loss = loss.ewm(alpha=1/period, adjust=False).mean() rs = avg_gain / (avg_loss + 1e-12) return 100 - (100 / (1 + rs)) df["RSI"] = rsi(df["Close"]) df["EMA20"] = df["Close"].ewm(span=20, adjust=False).mean()

Теперь у нас есть «фичи», которые можно подать в модель.

3. ML-модель: логистическая регрессия

Начнём с классики: логистическая регрессия предсказывает, вырастет ли цена завтра.

from sklearn.linear_model import LogisticRegression from sklearn.model_selection import TimeSeriesSplit from sklearn.preprocessing import StandardScaler from sklearn.pipeline import Pipeline X = df[["RSI", "EMA20"]].dropna() y = (df["Close"].pct_change().shift(-1) > 0).astype(int).reindex(X.index).fillna(0).astype(int) pipe = Pipeline([ ("scaler", StandardScaler()), ("clf", LogisticRegression(max_iter=1000)) ]) tscv = TimeSeriesSplit(n_splits=5) scores = [] for train_idx, test_idx in tscv.split(X): pipe.fit(X.iloc[train_idx], y.iloc[train_idx]) scores.append(pipe.score(X.iloc[test_idx], y.iloc[test_idx])) print(f"Средняя точность: {np.mean(scores):.3f}")

Используем TimeSeriesSplit, чтобы не «подсматривать в будущее».

4. DL-модель: LSTM для временных рядов

Глубокое обучение позволяет ловить нелинейные зависимости. LSTM‑сеть учится предсказывать цену на основе последних 60 дней.

from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense from sklearn.preprocessing import MinMaxScaler import numpy as np prices = df["Close"].dropna().values.reshape(-1, 1) scaler = MinMaxScaler() scaled = scaler.fit_transform(prices) window = 60 X, y = [], [] for i in range(len(scaled) - window): X.append(scaled[i:i+window]) y.append(scaled[i+window]) X, y = np.array(X), np.array(y) split = int(len(X) * 0.8) X_train, y_train = X[:split], y[:split] X_test, y_test = X[split:], y[split:] model = Sequential([LSTM(64, input_shape=(window, 1)), Dense(1)]) model.compile(optimizer="adam", loss="mse") model.fit(X_train, y_train, epochs=10, batch_size=64, verbose=1, validation_data=(X_test, y_test))

После обучения можно сравнить прогнозы с реальными ценами и посчитать RMSE.

5. Backtest и метрики

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

Пример простого бэктеста стратегии:

import numpy as np def sharpe(returns, periods_per_year=252): excess_ret = returns - 0 # при отсутствии безрисковой ставки return np.sqrt(periods_per_year) * excess_ret.mean() / (excess_ret.std() + 1e-12) def max_drawdown(equity_curve): peak = np.maximum.accumulate(equity_curve) drawdown = (equity_curve - peak) / (peak + 1e-12) return drawdown.min() def cagr(equity_curve, periods_per_year=252): n_periods = len(equity_curve) total_return = equity_curve[-1] / equity_curve[0] years = n_periods / periods_per_year return total_return ** (1 / years) - 1 signal = (df["RSI"] < 30).astype(int) # покупаем при перепроданности strat_ret = signal.shift(1).fillna(0) * df["ret"] equity = (1 + strat_ret).cumprod().fillna(method="ffill") print("Sharpe:", sharpe(strat_ret.dropna())) print("MaxDD:", max_drawdown(equity.values)) print("CAGR:", cagr(equity.values))

Теперь видно, насколько стратегия устойчива.

6. Обучение с подкреплением: Q-learning (простейшая иллюстрация)

Подходы RL позволяют напрямую оптимизировать экономический результат, но требуют аккуратного оформления среды и стабильного обучения. Важно понимать, что классический Q‑learning подойдёт только для сильно упрощённой среды с дискретным и небольшим пространством состояний. Для реальных задач чаще используют Deep RL (DQN, PPO), сложные среды и симуляции комиссий/ликвидности.

Простейший пример Q‑learning на дискретном состоянии (RSI‑бинов):

states = pd.cut(df["RSI"].dropna(), bins=[0,30,50,70,100], labels=False) n_states = states.max() + 1 n_actions = 2 # 0 = нет позиции, 1 = держать/купить Q = np.zeros((n_states, n_actions)) alpha, gamma, epsilon = 0.1, 0.9, 0.1 rewards = [] for t in range(1, len(states)): s = states.iloc[t-1] if np.random.rand() > epsilon: a = np.argmax(Q[s]) else: a = np.random.randint(n_actions) r = df["ret"].iloc[t] * (1 if a == 1 else 0) rewards.append(r) s_next = states.iloc[t] Q[s, a] += alpha * (r + gamma * np.max(Q[s_next]) - Q[s, a])

Такой агент постепенно учится, какие состояния выгоднее для входа в позицию.

7. Вывод и дисклеймер

  • Представленный пайплайн — это базовый скелет. Для реальных торговых систем его нужно расширять: дополнительные признаки (фундаментальные, объёмные, рыночные‑микроструктурные), мультиинструментальные модели, учёт комиссий, оптимизация размера позиции и риск‑менеджмент.
  • Проверяйте устойчивость моделей: кросс‑валидация по времени, walk‑forward, стресс‑тесты на разных рыночных режимах.
  • Следите за переобучением: простые модели часто дают более стабильные экономические результаты, чем объёмистые нейросети, без должной регуляризации и контроля.
  • Прежде чем применять на реальных деньгах, моделируйте комиссии, проскальзывание и лимиты ликвидности. Теоретические метрики часто переоценивают реальную прибыль.

Дисклеймер: материалы носят информационный характер. Торговля на финансовых рынках связана с высоким уровнем риска. Автор статьи не даёт инвестиционных рекомендаций и не призывает к совершению операций с финансовыми инструментами.

• Купить книгу «Deep Learning for Finance» в оригинале

• Заказать перевод книги «Глубокое обучение в финансах» на русском

Начать дискуссию