Ансамблевые методы: объединение слабых учащихся для надежной альфа-версии
Большинство авторов, пишущих о торговых ансамблях, утверждают, что чем больше моделей, тем лучше. Это неправильная ось. Ошибка ансамбля распадается на три члена, и в торговле только один из них всегда является обязательным ограничением.
Эта статья посвящена этому одному термину и двум его последствиям, которые не рассматриваются в остальной части этого блога: стекирование как явный уровень комбинации сигналов и действительно ли объединение многих сигналов снижает оборот до того, как сделки достигают рынка.
Термин, который действительно связывает: смещение-дисперсия-ковариация
Для регрессионного ансамбля модели, ожидаемая квадратичная ошибка среднего прогноза разлагается как:
Три термина, три рычага:
- Бэггинг атакует термин дисперсии, усредняя по бутстреп-выборкам.
- Усиление устраняет смещение, итеративно исправляя остатки.
- Стекирование атакует термин ковариации, изучая веса комбинаций, а не предполагая, что они равны.
- Повышается уменьшает только вклад дисперсии. Это вообще не влияет на ковариацию — коэффициент уже 0,99 при .
В этом последнем пункте и заключается весь аргумент. В трейдинге модели обучаются на одних и тех же инструментах, на одной и той же истории, против целей, которые сами по себе являются почти идентичными преобразованиями одного и того же ценового ряда. Их ошибки не близки к независимым. Таким образом, термин ковариации велик, а термин дисперсии уже исчерпан, а это означает, что количество моделей не дает вам почти ничего, а структурные различия дают вам все.
Конкретная, фальсифицируемая форма утверждения: добавление 101-го дерева с градиентным усилением должно сдвинуть метрику ансамбля меньше, чем добавление одной структурно отличной модели — LSTM, линейной модели в непересекающейся области признаков, чего-либо с другим индуктивным смещением. Краевое дерево почти совпадает с деревьями, уже упомянутыми в книге; структурно другая модель - нет.
Корреляция, а не количество моделей, определяет эффективную ширину ансамбля — вывод, криптоизмеренные коэффициенты корреляции по классам активов и моделирование на основе данных реальных пар приведены в Корреляция сигналов: сколько пар отслеживать.
Не сводите разнообразие ансамбля к одному числу. Дефлированный коэффициент Шарпа рассчитывает пять эффективных оценки (средняя корреляция, коэффициент участия, PCA-95%, Кайзер, Чеверуд-Нюхолт) на реальной сетке из 640 ячеек показывает, что они охватывают от 1,6 до 370, и утверждает, что диапазон, а не какая-то одноточечная оценка, является результатом. Сообщите о группе.
Стекирование как уровень комбинации сигналов
Бэггинг и буст хорошо описаны в других разделах. Моделирование распространения с помощью машинного обучения включает в себя настройку повышения градиента, выбор потерь для асимметричных целей, выводы о важности SHAP, таксономию объектов и очищенное разделение с перекрытием прямого окна, которое мотивирует разрыв. Начните с этого; в этом разделе это предполагается.
Что не рассматривается, так это уровень выше: мета-обучающийся, который принимает прогнозы базовой модели в качестве входных характеристик и учится, как их комбинировать.
– Уровень 0 (базовые учащиеся): разнообразные модели, дающие прогнозы на основе необработанных признаков.
- Уровень 1 (мета-обучение): модель, которая учит, какой базе учащихся следует доверять и когда.
Механизм, который делает это безопасным, — это необычные метафункции. Мета-обучающийся никогда не должен видеть прогноз базовой модели, сделанный на основе данных, на которых базовая модель обучалась — эти прогнозы оптимистически смещены таким образом, что не выживают в реальной торговле, и мета-обучающийся будет соответствующим образом взвешивать их.
import numpy as np
import pandas as pd
from sklearn.base import clone
from sklearn.model_selection import TimeSeriesSplit
class TradingStackingEnsemble:
"""
Two-level stacking ensemble for return prediction.
Level 0: base learners, each on its own feature domain
Level 1: meta-learner trained on out-of-fold base predictions
"""
def __init__(self, base_models: list, meta_model, n_splits: int = 5):
self.base_models = base_models # list of (name, model, feature_cols)
self.meta_model = meta_model
self.n_splits = n_splits
self.fitted_base_models_ = {}
def _generate_meta_features(
self,
X: pd.DataFrame,
y: pd.Series
) -> pd.DataFrame:
"""Out-of-fold predictions from each base model."""
tscv = TimeSeriesSplit(n_splits=self.n_splits)
meta_features = pd.DataFrame(index=X.index)
for name, model, feature_cols in self.base_models:
oof_preds = pd.Series(np.nan, index=X.index)
for train_idx, val_idx in tscv.split(X):
X_train = X.iloc[train_idx][feature_cols]
y_train = y.iloc[train_idx]
X_val = X.iloc[val_idx][feature_cols]
fold_model = clone(model)
fold_model.fit(X_train, y_train)
if hasattr(fold_model, 'predict_proba'):
oof_preds.iloc[val_idx] = fold_model.predict_proba(X_val)[:, 1]
else:
oof_preds.iloc[val_idx] = fold_model.predict(X_val)
meta_features[name] = oof_preds
return meta_features.dropna()
def fit(self, X: pd.DataFrame, y: pd.Series):
meta_features = self._generate_meta_features(X, y)
y_meta = y.loc[meta_features.index]
self.meta_model.fit(meta_features, y_meta)
for name, model, feature_cols in self.base_models:
model.fit(X[feature_cols], y)
self.fitted_base_models_[name] = model
return self
def predict(self, X: pd.DataFrame) -> np.ndarray:
meta_features = pd.DataFrame()
for name, model, feature_cols in self.base_models:
fitted = self.fitted_base_models_[name]
if hasattr(fitted, 'predict_proba'):
meta_features[name] = fitted.predict_proba(X[feature_cols])[:, 1]
else:
meta_features[name] = fitted.predict(X[feature_cols])
return self.meta_model.predict(meta_features)
Дисциплина разделения здесь не является необязательной и не новой — используйте очищенный, запрещенный шаг вперед и поймите, чего стоит каждый класс утечек в завышенном Шарпе, прежде чем доверять каким-либо из этих цифр. Оба уже измерены: таксономия упреждающего смещения количественно определяет исполнение, утечку индикаторов и нормализации в управляемом симуляторе, а упреждающая оптимизация охватывает привязанные и скользящие окна, CPCV, очистку и диагностику деградации WFER.
Три конструктивных решения являются специфическими для штабелирования и заслуживают упоминания.
Простота метаобучения. Используйте линейную модель — гребень, лассо, логистическую регрессию. Базовые учащиеся справляются с нелинейностью; мета-ученик обрабатывает только комбинации. Сложный мета-обучающийся поверх сложных базовых обучающихся представляет собой переобучение второго порядка, а регуляризация L1 на комбинированном уровне имеет полезный побочный эффект, заключающийся в обнулении базовых моделей, которые вносят только шум.
Вероятность выводится с помощью жестких меток. predict_proba несет в себе достоверную информацию, которую отбрасывает метка класса, и позволяет мета-учащемуся более серьезно оценивать уверенные базовые прогнозы.
Разделение функциональной области. Это самый эффективный рычаг разнообразия, который следует непосредственно из аргумента ковариации: модели, которые видят одни и те же функции, производят коррелированные ошибки независимо от алгоритма.
FEATURE_GROUPS = {
'momentum': ['ret_5d', 'ret_10d', 'ret_21d', 'ret_63d'],
'volatility': ['vol_21d', 'vol_ratio', 'vol_skew', 'garch_vol'],
'volume': ['volume_ratio', 'obv_slope', 'vwap_dist', 'adv_ratio'],
'mean_reversion': ['dist_from_ma21', 'dist_from_ma63', 'rsi_14', 'bb_pct'],
'microstructure': ['bid_ask_spread', 'kyle_lambda', 'amihud_illiq'],
'fundamental': ['ep_ratio', 'bp_ratio', 'roe', 'accruals'],
}
base_models = []
for domain, features in FEATURE_GROUPS.items():
model = GradientBoostingClassifier(
n_estimators=200, max_depth=3,
learning_rate=0.05, subsample=0.7
)
base_models.append((domain, model, features))
Каждая базовая модель становится экспертом предметной области: модель импульса изучает закономерности импульса без вмешательства объемного шума, а мета-обучающийся узнает, какому эксперту доверять и при каких условиях.
Два предостережения по поводу последнего пункта. Во-первых, условное взвешивание режима — это решенная и опубликованная проблема — обнаружение режима с помощью HMM правильно выводит режимы с помощью Форварда/Витерби/Баума-Уэлча и передает их как признаки в нижестоящий ансамбль, а динамическое объединение стратегий охватывает взвешенное по режиму среднее значение-возврат против импульс с сообщенными результатами. Не заменяйте ни то, ни другое специальным прокси-символом импульса. Во-вторых, отбор по результатам внутривыборки приводит к появлению победителей, которые не выживают; Общий механизм и защита CSCV измеряются в вероятности переоснащения бэктеста. Укладка является более узким примером именно этой проблемы.
Для взвешивания обратных потоков, а не прогнозов модели, не рассчитывайте повторно среднее отклонение. 12 алгоритмов оптимизации портфеля, сравнение расы HRP, HERC, GHRP, MHRP, Black-Litterman, NCO, MVO, паритет рисков и равный вес с измеренными результатами и открытым исходным кодом; Теория портфеля Марковица для криптовалюты имеет реализацию среднего отклонения SLSQP; и результат 1/N-сложно превзойти уже проверен на соответствие HRP и CVaR в конвейере портфеля HRP/CVaR.
Неттинг оборота: утверждение, которое стоит проверить
Вот часть аргумента альфа-библиотеки, которую в настоящее время не охватывает кластер стоимости выполнения этого блога.
Когда Альфа № 4721 говорит «покупать MSFT», а Альфа № 8392 говорит «продавать MSFT» в ходе одной и той же ребалансировки, эти сделки внутренне пересекаются. На рынок попадает только чистая позиция. Утверждается, что при наличии достаточного количества сигналов значительная часть валового предполагаемого оборота аннулируется до того, как возникнут спреды, комиссии или влияние на рынок, а это будет означать, что эксплуатация ансамбля обходится дешевле, чем сумма его компонентов, а не просто более стабильна.
Это механизм, отличный от того, что уже использует оркестровка каскадных стратегий. Каскад разрешает конфликты на уровне слота: одна и та же пара, противоположное направление запрещено и разрешается по счету, вытеснение перекрестных пар происходит через приоритетную очередь, а статья эмпирически доказывает, что PnL по каждой стратегии не может быть просто суммирован из-за перекрытия времени и ограничений капитала. Неттинг – это арифметика общей позиции к чистой, уменьшающая сам объем торгов.
Фальсифицировать также дешево: вычислите валовой и чистый оборот при реальных исполнениях, когда сигналы компонентов объединяются, а затем оцените оба показателя с помощью существующего механизма затрат — комиссионные сборы и скидки мейкера-получателя, дефицит реализации и TCA и стоимость проскальзывания модели.
Примечание о масштабе, поскольку обрамление альфа-библиотеки этого требует. WorldQuant сообщает, что создал очень большую альфа-библиотеку, а также [101 формульную альфу] Какушадзе.https://arxiv.org/pdf/1601.00991) документирует форму отдельных сигналов. Но майнинг альфа-версий в промышленном масштабе также является крупнейшей машиной для многократного тестирования, какую только можно себе представить, и позиция этого блога по этому вопросу устоялась: поиск размера должно быть уменьшено по сравнению с ожидаемой удачей поиска такого размера. Дефлированный коэффициент Шарпа показывает сетку из 640 ячеек, которая уже нарушает наивное тестирование значимости, а The Honest Negative показывает поиск с ~37 000 попыток, дающий +16,35% победителя вне выборки, который сдувается до DSR 0,00. Размер библиотеки не является показателем преимущества. Это знаменатель, который вам придется заплатить.
Собираем воедино
Raw Data
|
v
Feature Engineering
|
v
Feature Subsets (partitioned by domain -> decorrelated errors)
|
+---> Base Model 1: RF on momentum features
+---> Base Model 2: GBM on volatility features
+---> Base Model 3: LSTM on price sequences
+---> Base Model 4: Lasso on fundamental features
+---> Base Model 5: XGBoost on microstructure features
|
v
Out-of-Fold Predictions (purged walk-forward)
|
v
Meta-Learner (Ridge)
|
v
Combined Signal -> Net Position -> Execution
|
v
DSR >= 0.95 and PBO <= 0.2 gate, or it does not ship
Последняя коробочка не является украшением. Складывание базовые модели – это процедура подбора размера , а ансамблевая статья, которая не сдувается, не может быть оправдана.
Выводы
- Структурная разница превосходит количество моделей. Ковариационный член не уменьшается с увеличением . Добавление шестого коррелированного дерева не является диверсификацией; добавление другого класса модели или несвязанной области объектов.
- Сообщите об эффективном полоса, а не балл. Пять оценок, пять ответов, иногда с разницей в два порядка.
- Сохраняйте мета-обучаемый линейным. Сложность на комбинированном уровне почти всегда переоснащается, и L1 там выполняет полезный автоматический выбор модели.
- Выход за рамки или ничего. Мета-обучающийся, обученный базовым предсказаниям в выборке, с высокой уверенностью усваивает неправильные веса.
- Сдуйте сам ансамбль. Укладка – это поиск. Цена как одна.
Дальнейшее чтение:
- Какушадзе, З. (2016). 101 формульная альфа
- [Ансамбльное обучение инвестициям] (https://rpc.cfainstitute.org/research/foundation/2025/chapter-4-ensemble-learning-investment) - Исследовательский фонд Института CFA, 2025 г.
- [Прогнозирование доходности акций: сочетание различных моделей] (https://www.sciencedirect.com/science/article/abs/pii/S0927539822000342) - Журнал финансовой экономики
- Янсен, С. [Машинное обучение для алгоритмической торговли] (https://github.com/stefan-jansen/machine-learning-for-trading), 2-е издание.
Авторы
Инженер торговых систем
Разработка торговых ботов с 2017 года: межбиржевой арбитраж (подключал до 30 бирж), парный арбитраж на коинтеграции между спотом и фьючерсами, скальпинг, фронтраннинг, торговля по новостям, сентиментный анализ, трендовые алгоритмы, а также алгоритмы управления и балансировки портфелей. Делает выставление ордеров до 1 мс, warehouse для big data, бэктестинг-движки, AI-агентов и интерфейсы для ботов (в т.ч. open-source profitmaker.cc). Стек: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, архитектура.