Ensemble voting for trading models: why agreement beats tuning

One model says buy. You can spend a week tuning it until it says buy more accurately — or you can ask two other models that think differently, and only act when all three agree. The second takes an afternoon and usually works better.

Ensembling — combining several models' predictions — is one of the oldest reliable results in machine learning, and it maps onto trading unusually well, because trading has an option most classification problems do not: you can decline to act. A vote that splits is not a wrong answer. It is a bar to sit out. This guide is about how to use that, what it costs, and the ways it goes wrong.

Why it works

Every model makes errors, and a model's errors have a shape. A boosted tree overfits interactions; a k-nearest-neighbour model gets lost when the current bar resembles nothing in history; a linear model misses curvature. Where those shapes differ, the errors are uncorrelated — and averaging uncorrelated errors shrinks them. Where the models agree, the signal is the part they all found. Where they disagree, at least one is wrong, and you do not know which.

What it costs

Precision goes up; trade count goes down. Requiring three models to agree means trading only on the bars where the signal is clearest, which are fewer than the bars where any one model would have fired. That is a real cost. A strategy that trades a third as often with twice the precision may or may not come out ahead — it depends on the payoff per trade and the costs per trade, and the expectancy arithmetic settles it. Usually it comes out ahead, because the bars the ensemble rejected were the marginal ones, and marginal trades are where costs eat the edge.

It also costs sample size. Fewer trades means wider error bars on every metric, and a beautifully precise strategy that has only fired forty times has not yet been measured. The sample-size guide applies with extra force.

Three ways to combine votes

Voting schemes
SchemeHow it worksStrengthWeakness
MajorityTrade if more than half the models agreeSimple; robust to one bad memberTreats a weak model's vote like a strong one's
UnanimousTrade only if every model agreesHighest precisionFewest trades; one broken member vetoes everything
WeightedEach model's vote counts in proportion to its measured skillUses what you know about each memberThe weights are parameters, and parameters overfit

Weight by skill, never by profit

If you weight votes, the weight must come from something that measures whether the model can classify — precision, or better, the Matthews correlation coefficient, computed out of sample — and never from how much money the model's trades made in the backtest. Profit is a function of the trades that happened to fire, the costs, and the sequence; a model with modest skill can show a large backtested profit by catching two big moves. Weight by that and you have handed the ensemble to luck. Weight by MCC and you have handed it to the member that actually distinguishes up from down.

When an ensemble is worse than its best member

  1. The members are near-copies. Three boosted trees with slightly different seeds make the same mistakes. Their agreement is not evidence; it is the same opinion three times. Diversity across families is the point.
  2. A weak member gets an equal vote. A model that barely beats the base rate, given a full vote, adds noise to every decision. Either weight it down or drop it.
  3. The ensemble is rescuing failures. If no single member beats a regularised linear benchmark out of sample, combining them does not create skill that none of them has.
  4. The vote threshold was tuned on the test set. "Trade at 2 of 3" versus "3 of 3" is a parameter. Choosing it by looking at out-of-sample results is optimisation, and the multiple-testing discount applies.

The score behind the vote

A useful side-effect of voting is a number: how many members agreed, or the weighted sum of their votes, on each bar. That number is a conviction score, and it is more useful than a binary signal. You can size positions by it — the meta-labeling guide covers the more formal version of that idea — or use it as a filter: take the signal only when conviction is above a threshold you fixed in advance. It is also the most honest way to see how much the members disagree, which is a measure of how confident you should be in the whole apparatus.

A workable procedure

  1. Train four or five models from different families on the same features and the same chronological, purged split.
  2. Score each out of sample on precision and MCC. Drop any that do not beat the base rate and a regularised linear benchmark.
  3. Decide the voting scheme and threshold before looking at the combined result, and write it down.
  4. Compute the ensemble's out-of-sample precision, trade count and expectancy after costs. Compare to the best single member on the same windows.
  5. Walk it forward. An ensemble that only agrees in one regime has found one regime.

A worked example

Three models on the same features and the same purged split: a boosted tree, a random forest and a kNN. Out of sample, each fires a long signal on roughly 200 of 2,500 bars, and each has a precision of about 55% — when it says buy, price hits the target before the stop 55% of the time. Individually, none is exciting.

Now require all three to agree. If their errors were independent, the bars where all three fire would be the bars where the signal is strongest, and the precision on those bars rises — to something in the mid-60s is typical in our experience, though the exact number is whatever your data says. The trade count falls to perhaps 60 or 70. Run the expectancy arithmetic on both: 200 trades at 55% with a 1.5:1 payoff gives (0.55 × 1.5) − (0.45 × 1) = +0.375R per trade, about 75R total; 65 trades at 65% with the same payoff gives (0.65 × 1.5) − (0.35 × 1) = +0.625R per trade, about 41R total.

The ensemble made less in total and more per trade. Whether that is better depends on costs — 200 round trips pay 200 spreads — and on what you do with the bars it declined. That is the honest shape of the trade-off, and it is why the decision is arithmetic rather than a rule.

Checking the members are actually different

Diversity is the whole mechanism, and it is measurable. For each pair of members, count the out-of-sample bars where both were wrong in the same direction, and compare it to what you would expect if their errors were independent — the product of their individual error rates. If two members are wrong together far more often than that, they are the same opinion twice, and one of them is not adding information. Families that share a mechanism — two boosted-tree implementations, a random forest and a bagged tree — tend to fail this check; a tree, a kNN and a linear model tend to pass it.

How Wise Apple votes

Ensemble voting is a first-class run mode in Wise Apple rather than a post-processing step. Pick any subset of the nineteen models on the bench, and the Ensemble Voting setting combines them per bar; vote weights come from each model's MCC-based skill score on the out-of-sample windows, never from its profit. The report shows the vote margin, so the conviction behind each trade is visible, and the ensemble's AUC is reported only when the voting scheme records a real margin. Because every member trains on your own machine, a five-model ensemble walked forward over ten windows is a lunch break, not a compute bill — which is what makes step five above something people actually do.

Questions traders ask about ensemble models

What is ensemble voting in trading?

Training several different models on the same data and acting only when they agree — by majority, unanimously, or by a weighted sum of their votes. Because different model families make different mistakes, agreement between them is evidence the pattern is real, and disagreement is a bar to sit out. It typically raises precision and lowers trade count.

Is an ensemble always better than a single model?

No. It is worse when the members are near-copies (their agreement is one opinion repeated), when a weak member gets an equal vote, when it is used to rescue models that individually cannot beat a linear benchmark, or when the vote threshold was tuned by looking at test results. Diversity across families and a threshold fixed in advance are what make it work.

How should I weight the models in an ensemble?

By classification skill measured out of sample — precision or, better, the Matthews correlation coefficient — and never by backtested profit. Profit depends on which trades happened to fire and in what sequence; a modest model can show a large profit by catching two big moves. Weighting by profit hands the ensemble to luck.

Does ensemble voting reduce overfitting?

It reduces the overfitting of any single member, because members' idiosyncratic errors partly cancel. It does not prevent overfitting of the ensemble itself — the choice of members, weights and threshold are all parameters. Fix them before looking at results, walk the ensemble forward, and count the configurations you tried.