В статистике и машинном обучении есть любопытный факт: среднее арифметическое нескольких прогнозов зачастую превосходит прогнозы большинства отдельных моделей — и это воспроизводится на данных из разных областей: от метеорологии до финансов. Этот эффект не интуитивен: кажется, что усреднение хорошей модели с плохой только ухудшит результат. На практике все работает иначе.
В этой статье мы разберем механику этого явления: почему математика гарантирует улучшение при определенных условиях, как выбрать тип ансамбля под задачу, где метод ломается и как его правильно реализовать для задач прогнозирования временных рядов и торговых сигналов.
Почему среднее работает: статистическая основа
Интуиция подсказывает, что лучшая модель должна побеждать ансамбль. Статистика говорит обратное: при выполнении нескольких условий среднее прогнозов математически гарантирует снижение ошибки. Понимание этого механизма — основа для правильного применения метода.
Декомпозиция ошибки прогноза: смещение и дисперсия
Ошибка любой модели раскладывается на три компоненты. Для среднеквадратичной ошибки (MSE):
MSE = Bias² + Variance + Noise
где:
- Bias² — систематическое смещение: насколько в среднем модель отклоняется от истинного значения;
- Variance — дисперсия: насколько сильно прогнозы модели разбросаны вокруг ее среднего;
- Noise — неустранимый шум данных, не зависящий от модели.
Усреднение N независимых несмещенных моделей с одинаковой дисперсией σ² дает дисперсию ансамбля σ²/N. Это ключевой результат: смещение не меняется, шум не меняется, однако при этом дисперсия падает пропорционально количеству моделей. При N=10 независимых моделях дисперсия ансамбля в 10 раз ниже, чем у каждой отдельной модели.
Смещение при усреднении тоже может снижаться — если смещения разных моделей разнонаправлены. Одна модель систематически завышает прогноз, другая занижает: их среднее компенсирует оба смещения. Это дополнительный бонус, но на него нельзя полагаться как на гарантированный эффект.

Рис. 1: Визуализация эффекта ансамблирования моделей. Слева — MSE каждой модели и ансамбля (красный); в центре — теоретическое снижение дисперсии при добавлении моделей (убывающая отдача после N≈10); справа — распределение прогнозов одной модели и ансамбля: ансамбль концентрируется вокруг истинного значения
Условия эффективности ансамблирования
Математическая гарантия снижения ошибки держится на двух условиях.
Первое — несмещенность моделей: E[ŷᵢ] = y для каждой модели i. Если все модели имеют одинаковое систематическое смещение, ансамбль его не устраняет.
Второе — некоррелированность ошибок: Cov(εᵢ, εⱼ) = 0 для i ≠ j. Именно это условие определяет, насколько сильно падает дисперсия. В общем случае:
Var(ε̄) = (1/N²) · [N·σ² + N·(N-1)·ρ·σ²] = σ²/N · [1 + (N-1)·ρ]
где:
- σ² — дисперсия отдельной модели;
- ρ — средняя попарная корреляция ошибок;
- N — число моделей.
При ρ=0 получаем σ²/N — идеальный случай. При ρ=1 ансамбль не дает никакого выигрыша: Var(ε̄) = σ². На практике ρ никогда не равна нулю, но даже ρ=0.3–0.5 позволяет получить существенное снижение дисперсии.
Отсюда главный практический вывод: максимизировать разнообразие моделей важнее, чем включать в ансамбль только лучшие модели. Слабая модель с низкой корреляцией ошибок с остальными приносит больше пользы, чем сильная модель, дублирующая ошибки лидера.
Когда усреднение не помогает?
Метод ломается в нескольких типичных ситуациях:
- Структурный сдвиг данных: если все модели обучены на одних и тех же данных одного режима рынка, их ошибки в новом режиме окажутся скоррелированными. Диверсификация по архитектурам не спасает от корреляции ошибок, вызванной общим источником данных;
- Все модели используют один и тот же набор фич: разные алгоритмы (градиентный бустинг, нейросеть, случайный лес) на идентичных фичах производят коррелированные прогнозы, потому что опираются на одну и ту же информацию;
- Утечка данных из будущего хотя бы в одной модели: усреднение с «заглянувшей в будущее» моделью портит весь ансамбль. Ошибки такой модели имеют другую природу и не усредняются с честными;
- Целевая переменная имеет высокое смещение у всех компонент: если задача плохо специфицирована или данные систематически зашумлены, усреднение снижает только дисперсию, но не устраняет главную проблему.
Типы ансамблей и их сравнение
Простое среднее — лишь один из способов агрегации. Выбор метода зависит от объема данных для обучения, различий в качестве моделей и задачи — регрессия, классификация или ранжирование сигналов.
Простое среднее vs. взвешенное: когда что выбирать?
Простое среднее устойчивее взвешенного в большинстве реальных сценариев. Причина — оверфиттинг весов. Если качество моделей оценивается на конечной выборке, оптимальные веса адаптируются к шуму этой выборки. На отложенных выборках взвешенный ансамбль часто проигрывает равновзвешенному.
Взвешенное среднее оправдано, когда:
- модели значительно различаются по качеству (Sharpe ratio или RMSE на валидации отличается в 2+ раза);
- есть достаточный объем отложенных данных для надежной оценки весов;
- качество моделей нестационарно и требует динамической переоценки весов.
Динамическое взвешивание по скользящему окну — компромисс между стабильностью равных весов и адаптивностью: вес модели пересчитывается на последних K периодах. Для финансовых временных рядов K=60–120 баров (дней) обычно достаточен для стабильной оценки без чрезмерного шума.
Оптимизация весов как задача квадратичного программирования (минимизация дисперсии ансамбля с ограничением на сумму весов) формально корректна, но требует стабильной матрицы ковариаций ошибок. На коротких выборках матрица ковариаций вырождается. Практически: регуляризация весов в сторону равных (shrinkage к 1/N) улучшает результаты на тестовых выборках.
Бэггинг, стэкинг и другие подходы к агрегации
Бэггинг (Bagging, Bootstrap Aggregating) — это генерация разнообразия через случайные подвыборки обучающих данных. Каждая модель обучается на бутстрап-выборке (с возвращением), прогнозы усредняются.
Случайный лес — частный случай бэггинга с дополнительной рандомизацией признаков. Важно помнить, что бэггинг снижает именно дисперсию, смещение при этом не меняется.
Стэкинг (Stacking, Stacked Generalization) — это когда мета-модель обучается предсказывать целевую переменную по прогнозам базовых моделей. Формально это более мощный метод: мета-модель может научиться, в каких режимах данных доверять каждой базовой модели.
На практике стэкинг требует аккуратного разбиения данных: базовые модели должны делать прогнозы на отложенной выборке, иначе мета-модель переобучится. Для временных рядов — только forward-walking splits, никаких random CV.

Рис. 2: Три архитектуры ансамблирования: Бэггинг генерирует разнообразие через бутстрап-подвыборки; Стэкинг использует прогнозы на тестовой выборке как признаки для мета-модели; Метод динамической развесовки Dynamic Weighting пересчитывает веса по скользящему окну производительности
Специфика временных рядов: ансамбли для прогнозирования
Временные ряды нарушают базовое предположение большинства ансамблевых методов — независимость и одинаковое распределение наблюдений (i.i.d., independent and identically distributed). Поэтому нужны две адаптации.
Во-первых, данные нужно делить только по времени, без перемешивания. Модель обучается на интервале [t₀, t], а проверяется на [t+1, t+h]. Если перемешать данные, возникает смещение из-за заглядывания в будущее (look-ahead bias). Стандартный подход здесь — скользящая проверка по времени (walk-forward validation).
Во-вторых, важно создавать разнообразие моделей внутри ансамбля. Для временных рядов это достигается несколькими способами:
- разные окна истории: 20, 60, 120 наблюдений;
- разные частоты данных: внутридневные (интрадей) и дневные;
- разные целевые переменные: логарифмическая доходность и абсолютные изменения;
- разные типы моделей: градиентный бустинг, нейронные сети, факторные модели.
Если комбинировать несколько таких источников разнообразия, ошибки моделей становятся менее зависимыми. Это работает лучше, чем менять только тип модели (архитектуру).
Практическое применение в трейдинге и финансах
Финансовые временные ряды — одна из наиболее сложных областей применения прогнозных ансамблей. Соотношение сигнал/шум здесь крайне низкое, режимы рынка нестационарны, а корреляция ошибок моделей в стрессовых периодах резко возрастает.
При этом выигрыш от ансамблирования здесь особенно ценен: небольшое улучшение точности прогноза направления движения цены транслируется в значительное улучшение метрик стратегии, в первую очередь коэффициента Шарпа.
Ансамбли моделей цены и волатильности
Прогноз доходности и прогноз волатильности — это разные задачи. У них разная природа сигнала и разный подход к ансамблям.
Прогноз доходности
Сигнал слабый, шума много. Одна модель обычно нестабильна. Ансамбль из 5–10 моделей работает лучше, если их прогнозы слабо связаны между собой.
При отборе моделей важно смотреть не только на информационный коэффициент (IC, information coefficient — корреляция прогноза с фактической доходностью), но и на корреляцию прогнозов между моделями.
Модель с IC = 0.05, но слабо связанная с другими, может быть полезнее, чем модель с IC = 0.08, если она дублирует уже существующие прогнозы. В ансамбле важна не только сила сигнала, но и его уникальность.
Прогноз волатильности
Здесь сигнал сильнее, потому что волатильность имеет свойство кластеризации (volatility clustering). Модели сами по себе уже дают устойчивые оценки.
Ансамбли используются не для усиления сигнала, а для сглаживания оценок, особенно при структурных изменениях рынка.
Простой и эффективный подход — объединять реализованную волатильность (realized volatility), рассчитанную на разных окнах: 5, 21, 63 дня. Такой ансамбль устойчив к выбросам и резким изменениям режима.

Рис. 3: Визуализация прогнозов отдельных моделей и ансамбля. Rolling IC ансамбля стабильнее и в среднем выше, чем у каждой компонентной модели — особенно в периодах высокой волатильности сигнала
Диверсификация сигналов и стратегий
На уровне торговых сигналов ансамблирование применяется двумя способами:
- Агрегация прогнозных моделей в единый сигнал позиции перед исполнением;
- Параллельный запуск нескольких стратегий с распределением капитала.
Параллельный запуск стратегий — это тот же принцип, примененный к кривым доходности: диверсификация снижает дисперсию совокупного результата. Условие то же: стратегии должны иметь некоррелированные просадки.
Стратегии на одном инструменте, но разных таймфреймах (H1 и D1), часто имеют корреляцию просадок 0.4–0.6 — недостаточную для эффективной диверсификации. Стратегии на разных классах активов или с принципиально разной логикой входа (mean reversion vs. momentum) дают корреляцию 0.1–0.3.
Размер позиции при агрегации сигналов: если N моделей дают сигнал от -1 до +1, простое среднее автоматически масштабирует позицию пропорционально консенсусу. При consensus=1.0 (все модели согласны) — полный размер позиции. При consensus=0.3 — соответственно 30% от целевого размера. Это встроенный механизм управления неопределенностью без дополнительной логики.
Ограничения метода и подводные камни
Ансамблирование — не универсальное средство улучшения результатов. Большинство провалов при его применении объясняются нарушением базовых предпосылок, а не фундаментальными недостатками метода. Знание этих ситуаций позволяет избежать ложного чувства безопасности от «большого числа моделей».
Корреляция ошибок как главный враг ансамбля
Из формулы Var(ε̄) = σ²/N · [1 + (N-1)·ρ] следует: при ρ → 1 ансамбль из 100 моделей не лучше одной. На практике корреляция ошибок скрытно высокая, когда:
- все модели используют одинаковые или сильно пересекающиеся фичи;
- модели обучены на одном датасете без разбиения на независимые подвыборки;
- ансамбль строится из топ-N моделей по одной метрике — они похожи именно потому, что оптимизированы под один критерий;
- данные содержат структурный разрыв (смена режима), на который все модели реагируют одинаково.
Диагностика: матрица попарных корреляций прогнозов на hold-out выборке. Если средняя попарная корреляция > 0.7, разнообразие ансамбля недостаточно. Добавление новых моделей той же архитектуры с другими гиперпараметрами проблему не решает — нужны принципиально разные источники информации.
Переобучение на уровне ансамбля
Ансамбль может переобучиться, даже если каждая отдельная модель регуляризована. Это происходит при оптимизации весов ансамбля на train или validation данных. Если веса подбираются на той же выборке, где оценивалось качество компонент, возникает двойное использование данных.
Правильная схема: строгое трехуровневое разбиение:
- Train set — для обучения базовых моделей;
- Validation set — для подбора весов ансамбля;
- Test set — для финальной оценки (используется один раз).
Для временных рядов все три сета последовательны во времени.
Еще одна форма переобучения — смещение из-за отбора моделей (selection bias). Оно возникает при выборе моделей в ансамбль. Если из 100 кандидатов выбрать 10 лучших по валидации, эти модели частично подгоняются под шум валидационной выборки. Их качество оказывается завышенным.
Решение — использовать полностью отложенную тестовую выборку (held-out test). Она не должна участвовать ни в обучении, ни в отборе моделей. Только на ней оценивается итоговое качество ансамбля.
Реализация: от теории к коду
Практическая реализация ансамбля прогнозов для финансовых временных рядов включает несколько нетривиальных моментов: корректное разбиение по времени, диагностику разнообразия и выбор метода агрегации.
Базовый пайплайн ансамбля прогнозов может выглядеть так:
import numpy as np
import pandas as pd
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
from scipy.optimize import minimize
import matplotlib.pyplot as plt
# Генерация синтетического временного ряда
np.random.seed(42)
n = 1000
t = np.arange(n)
comp1 = 1.2 * np.sin(2 * np.pi * t / 25)
comp2 = 1.0 * np.sin(2 * np.pi * t / 70)
comp3 = 0.8 * np.cos(2 * np.pi * t / 150)
target = comp1 + comp2 + comp3 + 0.3 * np.random.randn(n)
# Каждый экзогенный ряд = своя компонента + независимый шум
exog1 = comp1 + 0.6 * np.random.randn(n)
exog2 = comp2 + 0.6 * np.random.randn(n)
exog3 = comp3 + 0.6 * np.random.randn(n)
# Фичи: лаги и rolling stats от одного экзогенного ряда
def make_features_from(exog, target_series, lags=(1, 2, 3, 5, 10), window=10):
df = pd.DataFrame({'y': target_series})
s = pd.Series(exog)
for lag in lags:
df[f'lag_{lag}'] = s.shift(lag)
df['roll_mean'] = s.shift(1).rolling(window).mean()
df['roll_std'] = s.shift(1).rolling(window).std()
return df.dropna()
df1 = make_features_from(exog1, target)
df2 = make_features_from(exog2, target)
df3 = make_features_from(exog3, target)
# Общий индекс после dropna
idx = df1.index.intersection(df2.index).intersection(df3.index)
df1 = df1.loc[idx]
df2 = df2.loc[idx]
df3 = df3.loc[idx]
y = df1['y'].values
feat_cols = [c for c in df1.columns if c != 'y']
X1 = df1[feat_cols].values
X2 = df2[feat_cols].values
X3 = df3[feat_cols].values
# Walk-forward split
n_total = len(y)
train_end = int(n_total * 0.6)
val_end = int(n_total * 0.8)
def split(X):
return (X[:train_end], X[train_end:val_end], X[val_end:])
X1_tr, X1_va, X1_te = split(X1)
X2_tr, X2_va, X2_te = split(X2)
X3_tr, X3_va, X3_te = split(X3)
y_tr = y[:train_end]
y_va = y[train_end:val_end]
y_te = y[val_end:]
# Три GBM-модели на независимых источниках
def fit_gbm(X_tr, y_tr, X_va, X_te):
sc = StandardScaler()
X_tr_ = sc.fit_transform(X_tr)
X_va_ = sc.transform(X_va)
X_te_ = sc.transform(X_te)
m = GradientBoostingRegressor(
n_estimators=200, max_depth=3,
learning_rate=0.05, subsample=0.8,
random_state=42
)
m.fit(X_tr_, y_tr)
return m.predict(X_va_), m.predict(X_te_)
va_A, te_A = fit_gbm(X1_tr, y_tr, X1_va, X1_te)
va_B, te_B = fit_gbm(X2_tr, y_tr, X2_va, X2_te)
va_C, te_C = fit_gbm(X3_tr, y_tr, X3_va, X3_te)
val_preds = {'GBM-A (exog1)': va_A, 'GBM-B (exog2)': va_B, 'GBM-C (exog3)': va_C}
test_preds = {'GBM-A (exog1)': te_A, 'GBM-B (exog2)': te_B, 'GBM-C (exog3)': te_C}
# Корреляция прогнозов
corr_matrix = pd.DataFrame(val_preds).corr()
# Равновзвешенный (Equal-weight) ансамбль
val_ensemble_eq = np.mean(list(val_preds.values()), axis=0)
test_ensemble_eq = np.mean(list(test_preds.values()), axis=0)
# Взвешенный ансамбль: оптимизация весов на val
def ensemble_mse(weights, preds_dict, y_true):
names = list(preds_dict.keys())
w = np.array(weights) / np.sum(weights)
combined = sum(w[i] * preds_dict[names[i]] for i in range(len(names)))
return mean_squared_error(y_true, combined)
result = minimize(
ensemble_mse,
x0=[1/3, 1/3, 1/3],
args=(val_preds, y_va),
method='SLSQP',
bounds=[(0.05, 0.9)] * 3,
constraints={'type': 'eq', 'fun': lambda w: sum(w) - 1},
)
opt_weights = result.x / result.x.sum()
test_ensemble_wt = sum(
opt_weights[i] * list(test_preds.values())[i]
for i in range(len(opt_weights))
)
# Результаты
results = {}
for name, preds in test_preds.items():
results[name] = mean_squared_error(y_te, preds)
results['Ensemble (equal)'] = mean_squared_error(y_te, test_ensemble_eq)
results['Ensemble (weighted)'] = mean_squared_error(y_te, test_ensemble_wt)
best_single = min(results[k] for k in test_preds.keys())
# Визуализация
fig, axes = plt.subplots(1, 3, figsize=(15, 5), facecolor='white')
# MSE
ax = axes[0]
ax.set_facecolor('#f8f8f8')
names = list(results.keys())
values = list(results.values())
colors = ['#4878CF', '#6ABF69', '#F0A500', '#D65F5F', '#9B59B6']
bars = ax.bar(names, values, color=colors, alpha=0.85,
edgecolor='white', linewidth=0.8)
for bar, val in zip(bars, values):
ax.text(bar.get_x() + bar.get_width() / 2,
bar.get_height() + 0.005,
f'{val:.3f}', ha='center', va='bottom', fontsize=8.5, color='#333')
ax.axhline(best_single, color='gray', linestyle='--', linewidth=1.0,
label=f'Best single: {best_single:.3f}')
ax.legend(fontsize=8, framealpha=0.8)
ax.set_title('MSE на тесте', fontsize=11, fontweight='bold')
ax.set_ylabel('MSE', fontsize=10)
ax.tick_params(axis='x', rotation=25, labelsize=8)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
# Корреляционная матрица
ax = axes[1]
ax.set_facecolor('#f8f8f8')
im = ax.imshow(corr_matrix.values, cmap='RdYlGn', vmin=-1, vmax=1, aspect='auto')
ax.set_xticks(range(len(corr_matrix)))
ax.set_yticks(range(len(corr_matrix)))
ax.set_xticklabels(corr_matrix.columns, fontsize=8.5, rotation=15)
ax.set_yticklabels(corr_matrix.index, fontsize=8.5)
for i in range(len(corr_matrix)):
for j in range(len(corr_matrix)):
val = corr_matrix.values[i, j]
ax.text(j, i, f'{val:.2f}', ha='center', va='center',
fontsize=10, fontweight='bold',
color='white' if abs(val) > 0.7 else 'black')
plt.colorbar(im, ax=ax, shrink=0.8)
ax.set_title('Корреляция прогнозов (val)', fontsize=11, fontweight='bold')
# Прогнозы на тест-сете
ax = axes[2]
ax.set_facecolor('#f8f8f8')
show = min(150, len(y_te))
x_range = np.arange(show)
ax.plot(x_range, y_te[:show], color='black', linewidth=1.3,
label='True', zorder=7)
ax.plot(x_range, test_ensemble_eq[:show], color='#D65F5F', linewidth=2.2,
label='Ensemble (equal)', zorder=6)
ax.plot(x_range, te_A[:show], color='#4878CF', linewidth=0.9,
alpha=0.55, label='GBM-A')
ax.plot(x_range, te_B[:show], color='#6ABF69', linewidth=0.9,
alpha=0.55, label='GBM-B')
ax.plot(x_range, te_C[:show], color='#F0A500', linewidth=0.9,
alpha=0.55, label='GBM-C')
ax.legend(fontsize=8.5, framealpha=0.85)
ax.set_title('Прогнозы на тест-сете', fontsize=11, fontweight='bold')
ax.set_xlabel('Время', fontsize=10)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
fig.suptitle('Рис. 4: Walk-forward ансамбль: диагностика и результаты',
fontsize=12, fontweight='bold', y=1.01)
plt.tight_layout()
plt.savefig('ensemble_pipeline.png', dpi=150, bbox_inches='tight', facecolor='white')
plt.show()
print("\nМатрица корреляций прогнозов (val):")
print(corr_matrix.round(3))
print(f"\nОптимальные веса: {dict(zip(test_preds.keys(), opt_weights.round(3)))}")
print("\nMSE на тесте:")
for k, v in results.items():
marker = " ← best" if v == min(results.values()) else ""
print(f" {k}: {v:.5f}{marker}")
ens_eq = results['Ensemble (equal)']
ens_wt = results['Ensemble (weighted)']
print(f"\nУлучшение equal vs best single: {(best_single - ens_eq) / best_single * 100:+.2f}%")
print(f"Улучшение weighted vs best single: {(best_single - ens_wt) / best_single * 100:+.2f}%")

Рис. 4: Визуализация прогнозирования временных рядов моделями GBM и ансамблями моделей. Слева — MSE на тест-сете: оба ансамбля уверенно превосходят лучшую одиночную модель (пунктир). В центре — матрица корреляций прогнозов на валидационной выборке: значения близки к нулю и даже отрицательны, что подтверждает статистическую независимость ошибок. Справа — прогнозы на тест-сете: ансамбль (красный) заметно плотнее следует истинному ряду, чем каждая отдельная модель
Матрица корреляций прогнозов (val):
GBM-A (exog1) GBM-B (exog2) GBM-C (exog3)
GBM-A (exog1) 1.000 -0.004 -0.097
GBM-B (exog2) -0.004 1.000 -0.300
GBM-C (exog3) -0.097 -0.300 1.000
Оптимальные веса: {'GBM-A (exog1)': np.float64(0.622), 'GBM-B (exog2)': np.float64(0.328), 'GBM-C (exog3)': np.float64(0.05)}
MSE на тесте:
GBM-A (exog1): 1.24364
GBM-B (exog2): 1.35532
GBM-C (exog3): 1.57900
Ensemble (equal): 0.96963
Ensemble (weighted): 0.94572 ← best
Улучшение equal vs best single: +22.03%
Улучшение weighted vs best single: +23.96%
Представленный выше код генерирует временной ряд с тремя независимыми экзогенными сигналами, создает для каждого ряда лаговые признаки и скользящие статистики, затем обучает три модели градиентного бустинга (GBM, gradient boosting machine) на разных источниках данных.
После разделения данных на обучающую, валидационную и тестовую выборки проводится скользящая оценка (walk-forward), рассчитываются прогнозы моделей на валидации и тесте, а также корреляция между прогнозами. Создаются два ансамбля: равновзвешенный (equal-weight) и взвешенный с оптимизацией весов на валидации.
Итогом являются метрики MSE на тесте, визуализация ошибок, корреляций и прогнозов, а также вывод оптимальных весов и прироста ансамблей относительно лучшей одиночной модели.
Интерпретировать полученные данные можно так. Корреляция прогнозов между моделями лежит в диапазоне от -0.30 до -0.004. Это близко к теоретическому идеалу ρ = 0. При таких значениях дисперсия снижается почти пропорционально числу моделей N.
Практический результат:
- ансамбль с равными весами (equal-weight) улучшает лучшую модель на 22%;
- ансамбль с оптимальными весами (weighted) — на 24%.
Разница между ними небольшая — около 1.9 процентного пункта. Это типичная ситуация: если модели хорошо различаются, равные веса уже дают почти максимум. Подбор весов добавляет лишь небольшой прирост.
Ключевой момент — источник улучшения. Он связан не с алгоритмом, а с данными. Модели обучены на независимых источниках информации. Если взять три модели градиентного бустинга (GBM, gradient boosting machine) на одинаковых признаках (фичах), корреляция прогнозов будет выше 0.9. В этом случае выигрыш от ансамбля будет намного скромнее — порядка 2-5%.
Заключение
Среднее прогнозов работает не потому что «много лучше одной», а из-за математики: дисперсия ансамбля некоррелированных моделей падает почти как 1/N. Главное условие — ошибки моделей должны быть слабо связаны. Без этого даже сотня моделей сводится к одной.
На практике это значит: важнее строить разнообразный ансамбль, чем искать «ту самую» идеальную модель. Модель с невысоким информационным критерием, но независимыми ошибками, полезнее, чем дублирующая топ-модель.
Также важно помнить, что взвешенное среднее редко превосходит равновзвешенное на отложенной выборке. Диверсификация по источникам информации (признаки, таймфреймы, активы) надежнее, чем по архитектурам. Это не магия, а статистика, стабильно работающая при соблюдении условий.