Методы глубокого машинного обучения для финансов | Софиен Каабар | Обзор и покупка книги | Booken.ru

Методы глубокого машинного обучения для финансов: Deep Learning for Finance

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

Обложка книги Deep Learning for Finance
Deep Learning for Finance: Creating Machine & Deep Learning Models for Trading in Python. Софиен Каабар. 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»