← Voltar aos artigos
August 3, 2026
5 min read

Métodos Ensemble: Combinando Alunos Fracos para um Alfa Robusto

Métodos Ensemble: Combinando Alunos Fracos para um Alfa Robusto
#machine-learning
#ensemble
#bagging
#stacking
#alpha

A maioria dos escritos sobre conjuntos de negociação argumenta que mais modelos são melhores. Esse é o eixo errado. O erro de um conjunto se decompõe em três termos e, na negociação, apenas um deles é a restrição vinculativa.

Este artigo é sobre esse termo e sobre duas consequências dele que o restante deste blog não cobre: ​​empilhamento como uma camada explícita de combinação de sinais e se a combinação de muitos sinais realmente reduz o volume de negócios antes que as negociações cheguem ao mercado.

O termo que realmente vincula: polarização-variância-covariância

Para um conjunto de regressão de NN modelos, o erro quadrático esperado da previsão média fˉ\bar{f} se decompõe como:

E[(fˉy)2]=bias2+1Nvariance+(11N)covarianceE\left[\left(\bar{f} - y\right)^2\right] = \overline{\text{bias}^2} + \frac{1}{N}\overline{\text{variance}} + \left(1 - \frac{1}{N}\right)\overline{\text{covariance}}

Três termos, três alavancas:

  • Bagging ataca o termo de variação calculando a média das amostras de bootstrap.
  • Boosting ataca o termo de polarização corrigindo iterativamente os resíduos.
  • Stacking ataca o termo de covariância aprendendo pesos de combinação em vez de assumir pesos iguais.
  • Aumentando NN reduz apenas a contribuição da variância. Não faz absolutamente nada para a covariância - o (11/N)(1 - 1/N) coeficiente já é 0,99 em N=100N = 100.

Esse último ponto é todo o argumento. Na negociação, os modelos são treinados nos mesmos instrumentos, ao longo do mesmo histórico, contra alvos que são, eles próprios, transformações quase idênticas da mesma série de preços. Seus erros não são nem de perto independentes. Portanto, o termo de covariância é grande e o termo de variância já está esgotado, o que significa que a contagem de modelos não compra quase nada e a diferença estrutural compra tudo.

A forma concreta e falsificável da afirmação: adicionar a 101ª árvore com gradiente aumentado deve mover a métrica do conjunto menos do que adicionar um modelo estruturalmente diferente - um LSTM, um modelo linear em um domínio de recurso disjunto, qualquer coisa com um viés indutivo diferente. A árvore marginal está quase colinear com as árvores já presentes no livro; o modelo estruturalmente diferente não o é.

A correlação, e não a contagem de modelos, define a amplitude efetiva de um conjunto — a derivação, os fatores de correlação medidos por criptografia por classe de ativo e a simulação contra dados de pares reais estão em Correlação de sinal: quantos pares monitorar.

Não reduza a diversidade do conjunto a um único número. A Razão de Sharpe Deflacionada calcula cincoNN estimadores (correlação média, taxa de participação, PCA-95%, Kaiser, Cheverud-Nyholt) em uma grade real de 640 células, mostra que eles abrangem NeffN_{\text{eff}} de 1,6 a 370, e argumenta que a faixa — e não qualquer estimativa pontual — é o produto final. Denuncie a banda.

Empilhamento como uma camada de combinação de sinal

Bagging e boosting são bem abordados em outros lugares. Modelagem de propagação com aprendizado de máquina fornece a configuração de aumento de gradiente, a seleção de perdas para alvos distorcidos, as descobertas de importância do SHAP, a taxonomia de recursos e uma divisão de avanço eliminada com a sobreposição da janela de avanço que motiva a lacuna. Comece por aí; esta seção assume isso.

O que não é abordado é o nível acima: um meta-aluno que toma as previsões do modelo básico como recursos de entrada e aprende como combiná-las.

  • Nível 0 (alunos básicos): diversos modelos que produzem previsões a partir de recursos brutos.
  • Nível 1 (meta-aluno): um modelo que aprende em quais alunos base confiar e quando.

O mecanismo que torna isso seguro são meta-recursos fora de uso. O meta-aluno nunca deve ver uma previsão do modelo base que foi feita com base nos dados nos quais o modelo base foi treinado – essas previsões são tendenciosas de forma otimista de uma forma que não sobrevive à negociação ao vivo, e o meta-aluno irá ponderá-las de acordo.

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)

A disciplina de divisão aqui não é opcional nem nova – use um guia purgado e embargado e entenda quanto vale cada classe de vazamento no Sharpe inflado antes de confiar em qualquer um desses números. Ambos já foram medidos: a taxonomia de viés look-ahead quantifica a execução, o indicador e o vazamento de normalização em um simulador controlado, e otimização walk-forward cobre janelas ancoradas versus janelas rolantes, CPCV, purga e diagnóstico de degradação WFER.

Três decisões de design são específicas para empilhamento e vale a pena mencioná-las.

Simplicidade do meta-aluno. Use um modelo linear — cume, laço, regressão logística. Os alunos básicos lidam com a não linearidade; o meta-aluno lida apenas com combinações. Um meta-aluno complexo sobre alunos básicos complexos é um overfitting de segunda ordem, e a regularização L1 na camada de combinação tem o efeito colateral útil de zerar os modelos básicos que contribuem apenas com ruído.

Saídas de probabilidade sobre rótulos rígidos. predict_proba carrega informações de confiança que um rótulo de classe descarta e permite que o meta-aluno pondere previsões de base confiantes com mais intensidade.

Particionamento por domínio de recursos. Esta é a alavanca de diversidade de maior aproveitamento e segue diretamente do argumento de covariância: modelos que veem os mesmos recursos produzem erros correlacionados, independentemente do algoritmo.

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))

Cada modelo básico torna-se um especialista no domínio: o modelo de momentum aprende padrões de momentum sem interferência de ruído de volume, e o meta-aluno aprende em qual especialista confiar sob quais condições.

Duas advertências sobre a última cláusula. Primeiro, a ponderação condicional do regime é um problema resolvido e publicado - detecção de regime com HMMs deriva regimes adequadamente via Forward/Viterbi/Baum-Welch e os alimenta como recursos para um conjunto downstream, e estratégias de combinação dinâmica cobre a reversão média ponderada pelo regime vs impulso com resultados relatados. Não substitua nenhum deles por um proxy de sinal de impulso ad-hoc. Em segundo lugar, a seleção baseada no desempenho dentro da amostra produz vencedores que não sobrevivem; o mecanismo genérico e a defesa CSCV são medidos em a probabilidade de overfitting de backtest. O empilhamento é um exemplo mais restrito exatamente desse problema.

Para ponderar fluxos de retorno em vez de previsões do modelo, não derivar novamente a média-variância. 12 algoritmos de otimização de portfólio, comparados competem com HRP, HERC, GHRP, MHRP, Black-Litterman, NCO, MVO, paridade de risco e peso igual com resultados medidos e código-fonte aberto; Teoria de portfólio de Markowitz para criptografia tem a implementação de média-variância SLSQP; e o resultado 1/N é difícil de superar já foi testado em relação ao HRP e ao CVaR no pipeline do portfólio HRP/CVaR.

Rede de rotatividade: a afirmação que vale a pena testar

Aqui está a parte do argumento da biblioteca alfa que o cluster de custo de execução deste blog não cobre atualmente.

Quando Alpha #4.721 diz “comprar MSFT” e Alpha #8.392 diz “vender MSFT” no mesmo rebalanceamento, essas negociações se cruzam internamente. Somente a posição líquida chega ao mercado. A alegação é que, com sinais suficientes, uma grande fração do volume de negócios bruto pretendido é cancelada antes de incorrer em spreads, taxas ou impacto no mercado – o que significaria que um conjunto seria mais barato de gerir do que a soma dos seus componentes, e não apenas mais estável.

Este é um mecanismo distinto daquele que a orquestração de estratégia em cascata já trata. O Cascade resolve conflitos no nível do slot: o mesmo par, a direção oposta é proibida e resolvida por pontuação, o despejo de pares cruzados passa por uma fila de prioridade e o artigo prova empiricamente que o PnL por estratégia não pode ser simplesmente somado devido à sobreposição de tempo e às restrições de capital. A compensação consiste na aritmética da posição bruta/líquida, reduzindo a própria quantidade negociada.

Também é barato falsificar: calcular o faturamento bruto versus líquido em preenchimentos reais quando os sinais dos componentes são combinados e, em seguida, precificar ambos por meio do mecanismo de custos existente - taxas e descontos do maker-taker, déficit de implementação e TCA e custo de derrapagem modelos.

Uma nota em escala, já que o enquadramento da biblioteca alfa o convida. A WorldQuant relata ter produzido uma biblioteca alfa muito grande, e os [101 Alphas Formulaicos] de Kakushadze (https://arxiv.org/pdf/1601.00991) documenta a forma dos sinais individuais. Mas a mineração de alfas em escala industrial também é a maior máquina de testes múltiplos imaginável, e a posição deste blog sobre isso está estabelecida: uma busca pelo tamanho KK deve ser deflacionado em relação ao melhor resultado esperado de uma pesquisa desse tamanho. The Deflated Sharpe Ratio mostra uma grade de 640 células já quebrando o teste de significância ingênuo, e The Honest Negative mostra uma pesquisa de aproximadamente 37.000 tentativas produzindo um vencedor fora da amostra de +16,35% que desinfla para DSR 0,00. O tamanho da biblioteca não é evidência de vantagem. É o denominador que você tem que pagar.

Juntando tudo

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

A última caixa não é decoração. Empilhando KK modelos básicos é um procedimento de seleção de tamanho KK, e um artigo de conjunto que não murcha é indefensável.

Conclusões

  1. A diferença estrutural supera a contagem do modelo. O termo de covariância não diminui com NN. Adicionar uma sexta árvore correlacionada não é diversificação; adicionar uma classe de modelo diferente ou um domínio de recurso disjunto é.
  2. **Relate a eficáciaNN banda, não um ponto. ** Cinco estimadores, cinco respostas, às vezes com duas ordens de magnitude de diferença.
  3. Mantenha o meta-aluno linear. A complexidade na camada de combinação é quase sempre superajustada, e L1 faz uma seleção automática de modelo útil.
  4. Fora da dobra ou nada. Um meta-aluno treinado em previsões baseadas na amostra aprende os pesos errados com alta confiança.
  5. Esvazie o próprio conjunto. Empilhar é uma pesquisa. Preço como um.

Leitura adicional:

blog.disclaimer

Authors

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

Fique à frente do mercado

Assine nossa newsletter para insights exclusivos sobre trading com IA, análises de mercado e atualizações da plataforma.

Respeitamos sua privacidade. Cancele a inscrição a qualquer momento.