Skip to content

Meta-Labeling: Side and Size

Two models are better than one. The primary model decides the side (long, short, no-trade). The secondary model decides the size (full, half, zero). Meta-labeling separates direction from confidence.

5 of 12 ~14 min

Meta-Labeling: Why Two Models Beat One

A single model that predicts “buy” or “sell” is doing two jobs at once. It is deciding both the direction of the trade and the size of the position. These are different decisions with different information requirements. A model that is right 60% of the time is not the same as a model that is right 60% of the time at full size. The same model, applied at half size, has half the expected P&L but also half the variance. Whether you should size up or size down depends on confidence, not direction.

Meta-labeling splits the problem in two. The primary model predicts the side: should I be long, short, or out? The secondary model predicts the meta-label: is the primary model’s prediction correct? The output of the secondary model becomes the position size.

The reference is AFML, Chapter 3, §3.6-3.7. The section is short and dense. Most of the value is in the framing, not the math.

(López de Prado, M., Advances in Financial Machine Learning, Ch. 3, §3.6-3.7. ISBN 978-1119482086.)

The Architecture

Three components.

Primary model: predicts the side. Output is −1-1, 00, or +1+1. Trained on triple-barrier labels. The primary model’s job is to identify trading opportunities. It does not need to be calibrated. It just needs to be directionally correct more often than not.

Secondary model: predicts whether the primary model is correct. Output is a probability in [0,1][0, 1]. Trained on the meta-labels: was the primary model’s prediction correct, given that the primary model made a prediction? The secondary model’s job is to estimate confidence.

Bet sizing: maps the secondary model’s output to a position size. A probability of 0.70.7 might map to 70%70\% of capital. A probability of 0.550.55 might map to 10%10\%. The mapping is a hyperparameter.

The architecture in pseudocode:


side = primary_model.predict(X[t])             # -1, 0, or +1
if side != 0:
    confidence = secondary_model.predict_proba(X[t])
    size = confidence_to_size(confidence)
    execute_trade(side=side, size=size)

The primary model is binary classification (or three-class, if you include no-trade). The secondary model is binary classification on the conditional set “primary model predicted non-zero.”

Why This Works

Three reasons, each grounded in how financial data actually behaves.

Reason 1: The two models have different objectives.

The primary model wants to maximize directional accuracy. It wants to be right as often as possible. It does not care about confidence: a 51% confident prediction and a 99% confident prediction both get the same +1+1 label.

The secondary model wants to predict whether the primary model is right, conditional on the primary model predicting something. It cares about confidence. A 51% confident primary prediction should be down-weighted; a 99% confident primary prediction should be sized up.

This separation makes each model easier to train. The primary model has a simpler loss (cross-entropy on side). The secondary model has a different loss (cross-entropy on correctness). Combining them into a single multi-objective model is harder than training two specialists.

Reason 2: The two models can use different features.

The primary model uses features that predict direction: momentum, value, sentiment, macro. The secondary model uses features that predict confidence: regime indicators, volatility, time-of-day, market microstructure. The two feature sets are often disjoint.

For example, the primary model might use a 20-day momentum signal. The secondary model might use the realized volatility of the past 5 days, because high recent volatility suggests the primary model’s signal is less reliable. The features are different because the targets are different.

Reason 3: The bet sizing handles the risk management.

A common failure mode of single-model strategies: every trade is the same size. Win or lose, the strategy deploys the same capital. This is optimal only if every prediction has the same confidence, which is rarely true.

Meta-labeling fixes this. A primary prediction that the secondary model rates at 0.550.55 confidence is a half-size trade. A primary prediction rated at 0.950.95 is a full-size trade. The expected P&L per unit of risk is more uniform across trades, and the strategy’s overall Sharpe is higher.

(AFML, §3.6.1-3.6.2.)

The Meta-Label

The meta-label is defined as: was the primary model’s prediction correct?

mi=1[primary prediction at time ti matches realized outcome at ti+h]m_i = \mathbb{1}[\text{primary prediction at time } t_i \text{ matches realized outcome at } t_i + h]

For a long-short strategy: mi=1m_i = 1 if the primary model said “long” and the price went up (or said “short” and the price went down), and mi=0m_i = 0 otherwise.

A subtlety: the meta-label is computed only at times where the primary model made a prediction. If the primary model said “no-trade” at time tt, there is no meta-label for tt. This is important: the secondary model is trained on the conditional distribution P(correct∣primary predicts)P(\text{correct} | \text{primary predicts}), not on the marginal P(correct)P(\text{correct}).

In practice:

meta_labels = []
for t in times_when_primary_predicted:
    prediction = primary_model.predict(X[t])
    actual = realized_outcome(t)
    meta_labels.append(1 if sign(prediction) == sign(actual) else 0)

The secondary model is trained on these meta-labels.

(AFML, §3.6.3.)

Training the Secondary Model

Three steps.

Step 1: Generate primary predictions on out-of-sample data.

The primary model should be fit on a training set, and the meta-labels should be computed on a separate set (typically the validation set used for hyperparameter selection of the primary model). If you compute meta-labels on the primary model’s training set, the secondary model learns to predict in-sample accuracy, which is always high.

A clean approach: walk-forward cross-validation. Fit the primary model on data [0,T1][0, T_1], predict on [T1,T2][T_1, T_2], record primary predictions and actual outcomes. Then refit the primary model on [0,T2][0, T_2], predict on [T2,T3][T_2, T_3], etc. Each primary prediction is genuinely out-of-sample. The meta-labels are computed from these out-of-sample predictions.

Step 2: Train the secondary model on the meta-labels.

The secondary model’s features are typically the same as the primary model’s features, plus some additional confidence-related features (volatility, regime indicators). The target is the meta-label.

A common practice: use a simple, regularized model for the secondary model (logistic regression with L2 regularization). The primary model can be more complex (gradient boosting, neural network); the secondary model should be conservative.

Step 3: Calibrate the secondary model.

The secondary model’s output should be a calibrated probability: when it says 0.7, the primary model should be right 70% of the time on out-of-sample data. Use Platt scaling or isotonic regression to calibrate.

Why calibration matters: the bet sizing is a function of the secondary model’s output. If the output is miscalibrated, the sizing is wrong, and the strategy’s risk profile is not what you designed.

(AFML, §3.6.5.)

The Bet Sizing Function

The mapping from secondary-model output to position size. Three common forms.

Linear: size=p\text{size} = p where pp is the secondary model’s output. A 0.7 probability becomes a 70% size. Simple, but a 0.51 probability still gets a 51% size, which may be too aggressive.

Thresholded: size=0\text{size} = 0 if p<pmin⁡p < p_{\min}, 11 if p>pmax⁡p > p_{\max}, linear in between. The thresholds are hyperparameters. This avoids sizing on marginal trades.

Power: size=pk\text{size} = p^k for some k>1k > 1. A 0.7 probability becomes 0.72=0.490.7^2 = 0.49 size. The power function down-weights low-confidence predictions more aggressively. Useful when you want to concentrate capital on high-conviction trades.

A practical choice: thresholded with pmin⁡=0.55p_{\min} = 0.55 and pmax⁡=0.85p_{\max} = 0.85. Below 0.55, no trade (this filters out marginal predictions). Above 0.85, full size (you are confident enough to deploy all capital). Between, linear interpolation.

A more sophisticated choice: optimize the thresholds and the form simultaneously on a validation set, using Sharpe ratio or another risk-adjusted return metric as the objective.

An Important Property: Size Doesn’t Affect Direction

The meta-labeling architecture has an important property: the size does not affect the side. A trade that is sized at 10% is still a long (or short). The primary model’s prediction is unchanged.

This is important because it means the primary model’s accuracy is unchanged by the sizing. If the primary model is right 55% of the time, it is right 55% of the time regardless of how you size the wins and losses. The Sharpe improvement from meta-labeling comes entirely from sizing: full size on high-confidence wins, small size on low-confidence wins, zero size on the low-confidence losses (which become no-trades).

Compare this to a single-model architecture where the model outputs a continuous prediction in [−1,+1][-1, +1] and the position size is the absolute value of the prediction. In this architecture, the side and size are entangled: a prediction of −0.3-0.3 is a small short, while a prediction of −0.9-0.9 is a large short. If the model is well-calibrated, this works. But most models are not well-calibrated, and the entanglement creates issues.

Meta-labeling decouples them, which makes each model easier to reason about.

(AFML, §3.6.4.)

A Worked Example

Setup: a long-short equity strategy on US large caps, daily rebalance, holding period 5 days. Primary model is a gradient-boosted classifier trained on triple-barrier labels. Features are 20-day momentum, 60-day mean-reversion, value, quality, and a few sector dummies.

Primary model output: −1-1 (short), 00 (no-trade), or +1+1 (long). Trained on triple-barrier labels with k=1k = 1 barriers.

Secondary model: logistic regression with L2 regularization, fit on the meta-labels. Features are the same as the primary model plus realized volatility and a regime indicator (bull/bear based on 200-day moving average).

Bet sizing: size=0\text{size} = 0 if p<0.55p < 0.55, size=(p−0.55)/0.30\text{size} = (p - 0.55) / 0.30 if 0.55≤p≤0.850.55 \leq p \leq 0.85, size=1\text{size} = 1 if p>0.85p > 0.85.

Walk-forward validation over 2010-2024, primary model retrained every quarter, secondary model retrained annually.

Results (illustrative, not from a real backtest):

  • Primary model alone: 53% accuracy, 1.2 Sharpe.
  • Primary + equal sizing: same as above.
  • Primary + meta-labeling: 53% accuracy (unchanged), but with sizing, 1.7 Sharpe.

The accuracy is unchanged because the primary model’s predictions are unchanged. The Sharpe improves because capital is concentrated on the high-confidence trades. Trades where the secondary model is uncertain become no-trades. Trades where the secondary model is confident get full size.

The Sharpe improvement of 0.50.5 is typical. In some strategies, it can be 1.01.0 or more.

Common Pitfalls

Five pitfalls that come up repeatedly.

Pitfall 1: Training the secondary model on in-sample primary predictions.

If the primary model is fit on data [0,T][0, T] and the secondary model is also fit on the primary model’s predictions on [0,T][0, T], the secondary model learns to predict in-sample accuracy, which is high and uninformative. Use walk-forward: primary model fit on [0,T1][0, T_1], primary predictions on [T1,T2][T_1, T_2], secondary model fit on these out-of-sample predictions.

Pitfall 2: Using the same features for both models.

The primary model uses direction-predictive features. The secondary model should use confidence-predictive features, which may overlap but should not be identical. Add at least 2-3 features specific to confidence: volatility, regime, time-of-day, market microstructure.

Pitfall 3: Confusing meta-label with side prediction.

The meta-label is whether the primary model was right, not whether the market went up. If the primary model says “long” and the market goes up, the meta-label is 1 (correct). If the primary model says “long” and the market goes down, the meta-label is 0 (incorrect). If the primary model says “no-trade,” there is no meta-label.

Pitfall 4: Forgetting to size the no-trade.

If the primary model says “no-trade,” the secondary model does not run. The size is zero. This is correct.

Pitfall 5: Using meta-labeling on a low-accuracy primary model.

Meta-labeling improves a 53%-accurate primary model. It does not turn a 51%-accurate primary model into a winning strategy. The base rate of the primary model needs to be above 50%, ideally above 53%, before meta-labeling adds value. Below 50%, the secondary model is essentially noise.

When NOT to Use Meta-Labeling

Three cases.

Case 1: The primary model is highly accurate (>70%). If the primary model is right 70%+ of the time, sizing is less important. You can size uniformly and still get good Sharpe.

Case 2: Continuous position sizing is required. If your strategy sizes continuously (e.g., risk-parity or volatility-targeted), meta-labeling’s binary sizing may not fit. Use a continuous sizing model instead.

Case 3: Transaction costs dominate. If your strategy’s turnover is so high that transaction costs exceed the meta-labeling benefit, skip the secondary model. The primary model’s high turnover will eat the gain.

In most other cases (particularly for daily-rebalance long-short equity, FX, or futures strategies), meta-labeling is worth the additional complexity.

A Subtle Implementation Detail

When training the secondary model, you need to be careful about one thing: the secondary model should be trained on out-of-sample primary predictions, not in-sample ones.

The typical workflow:

  1. Split the data into training and test sets using purged walk-forward CV (see the cross-validation article).
  2. Fit the primary model on the training set.
  3. Generate primary predictions on the test set.
  4. Compute meta-labels from the test set outcomes.
  5. Fit the secondary model on (test-set features, meta-labels).

Step 5 uses the test set, which is out-of-sample for the primary model but in-sample for the secondary model. To avoid leakage, use a nested cross-validation:

  1. Outer CV: split into train/test.
  2. Inner CV on the train set: fit the primary model, generate predictions on the inner validation fold, compute meta-labels, fit the secondary model.
  3. Apply both models to the outer test set.

This is computationally expensive but produces an honest meta-labeling system. The simpler one-level approach is acceptable in practice but introduces some optimistic bias.

A compromise: use a single walk-forward split. Fit the primary model on data [0,T1][0, T_1], generate primary predictions on [T1,T2][T_1, T_2], fit the secondary model on these predictions. This produces an honest secondary model with one level of CV. The bias is small.

(AFML, §3.6.5.)

The Multi-Class Meta-Labeling

The standard meta-labeling has two classes (correct, incorrect). For multi-class primary models (e.g., long, short, no-trade), the meta-labeling can be extended to multiple classes:

  • Meta-label = 1 if the primary model picked the winning class.
  • Meta-label = 0 if the primary model picked a losing class.

For three classes (long, short, no-trade), the meta-label is binary: was the primary model’s class the winning one? The secondary model is a binary classifier on (features, primary class).

The bet sizing depends on the meta-label and the primary class. A high-confidence “long” prediction (meta-label prob = 0.7) gets full size. A high-confidence “short” prediction (meta-label prob = 0.7) gets full size. A high-confidence “no-trade” prediction (meta-label prob = 0.7) gets… no size, because the primary model already said no-trade.

The multi-class extension is straightforward and applies the same principle: separate side from size.

The SNO Framework

A related framework from AFML is Sequential No-Trade (SNO). The idea: instead of having the primary model output three classes (long, short, no-trade), have it output two (long, short) and use a meta-model to predict whether to trade at all.

The SNO framework:

  1. Primary model: predicts long vs short (binary).
  2. Secondary model: predicts whether to trade at all (binary: trade or not-trade).
  3. Bet sizing: combine both predictions.

The advantage: the primary model is simpler (binary instead of three-class). The secondary model can use features that the primary model is not aware of.

A typical implementation: primary model trained on triple-barrier labels with long=+1, short=-1, no-trade dropped. Secondary model trained on whether the primary model’s prediction was profitable. Bet sizing based on the secondary model’s confidence.

This is similar to meta-labeling but separates the “should I trade?” question from the “which direction?” question. Some practitioners find this cleaner than the standard meta-labeling.

(AFML, §3.6.6.)

What Meta-Labeling Does Not Solve

Three things meta-labeling does not address.

It does not generate alpha. Meta-labeling improves the size of the bet, not the direction. If your primary model is no better than random, meta-labeling cannot help. You need a primary model with positive expected accuracy.

It does not reduce transaction costs. If the primary model has high turnover, meta-labeling will not reduce it. In fact, meta-labeling may increase turnover if the secondary model is volatile. Use a turnover constraint or a holding-period constraint in addition.

It does not handle capacity constraints. If the strategy is large enough to move prices, meta-labeling does not address the market impact. Use execution algorithms or position-size constraints.

These are limitations of meta-labeling, not criticisms. No single technique addresses every problem. Meta-labeling is one tool in the kit, and it works well for its intended purpose: improving bet sizing.

The Bigger Picture

Meta-labeling is one application of a broader principle: separate what you are predicting from how much you should bet on the prediction. The principle applies to many areas of quant ML:

  • Side vs size (this article): direction vs confidence.
  • Entry vs exit: when to enter vs when to exit.
  • Selection vs weighting: which assets to include vs how to weight them.
  • Alpha vs risk: expected return vs expected risk.

Each separation lets you train a specialist model on a more focused problem, which usually beats a single model trying to do everything.

The meta-labeling architecture is also the foundation of stacking in classical ML: train several base models, then train a meta-model on their predictions. The meta-model learns to combine the base models. In financial ML, the base models predict the side, and the meta-model predicts the size. Same idea, different labels.

(López de Prado, M., Advances in Financial Machine Learning, Ch. 3, §3.6-3.7. ISBN 978-1119482086.)