What is the triple-barrier method?
From Marcos López de Prado (Advances in Financial Machine Learning, 2018). A method for labeling the outcome of an event — i.e. the target variable for ML research. For each event timestamp (e.g. a breakout, a CUSUM event, an entry candidate) you set three barriers and check which one is touched first:
- Upper barrier — take-profit, e.g. +k·ATR above the entry
- Lower barrier — stop-loss, e.g. −k·ATR below the entry
- Vertical barrier — time limit, after N bars it's over
for each event at t0:
upper = price[t0] * (1 + k_up * atr_pct[t0])
lower = price[t0] * (1 - k_dn * atr_pct[t0])
window = prices[t0 .. t0+N]
label = +1 if upper is hit first (move realized)
-1 if lower is hit first (stopped out)
0 if the time limit comes first (or sign(return) at the end)
Skinner (Delta Trend Trading) uses its little sister in his quant-process video — double-barrier (without the time limit) — to label the outcomes of his sweeps.
Why it beats 'return after N bars'
Botty's ml/labels.py currently labels with fixed-horizon forward returns. That has three weaknesses which triple-barrier fixes:
- Path realism. Fixed-horizon ignores that a trade would long since have been stopped out along the way. Triple-barrier asks: "If I had actually traded this with a stop + target — what happens first?" → the labels become consistent with Botty's actual execution (we trade with stops/targets, not 'hold for exactly N bars').
- Vol scaling. Barriers as ATR/vol multiples adapt to the regime. A fixed % threshold is too tight in high vol (hit immediately) and too wide in low vol (never hit). Consistent with the finding that 'the vol regime is the actual signal'.
- Discriminative power. The return at an arbitrary horizon N is noisy; 'move realizes before the reversal — yes/no' is a much clearer label for whether a feature has tradable predictive power.
Where it sits in Botty
ml/labels.py— as a new labeling function alongside the existing forward-return/sign/vol-norm labels. The ml/ module is pattern discovery (event → context features → outcome); triple-barrier is the better outcome.- Paired with event-based sampling (CUSUM filter): first define events, then label each event via triple-barrier — exactly the 'event-defining + outcome features' pipeline from the quant methodology.
- In
ml/experiments/a feature's discriminative power is then measured against the triple-barrier label instead of the raw forward return.
Honest assessment
- Research-only: it improves how we measure whether something works — it does not directly change the live bot. Belongs to the live-readiness discipline.
- The eval moves with it: the label is categorical ({−1,0,+1}) instead of continuous → the Spearman IC does not carry over 1:1; use classification/quantile metrics or hit rate × payoff instead.
- Overlapping labels: simultaneous events create temporally overlapping label windows → clean ML requires López de Prado's uniqueness/concurrency weighting (otherwise hidden bias from multiply counted, correlated observations).
- Meta-labeling is the related follow-up technique: a second model decides whether to follow a primary signal (sizing/filter) after triple-barrier has supplied the direction.
Status in Botty: implemented in ml/labels.py (triple_barrier_labels + average_uniqueness for the concurrency weighting); pilot pipeline in ml/experiments/cusum_triple_barrier/ (vol-scaled barriers, intrabar via high/low, pilot label split ~49/51 +1/−1).