Chapter 7 · Modern Statistical Learning in Practice
Section 7.5 · Chapter 7 · Learning Statistics with Python
Modern Statistical Learning in Practice
Prof. Xuhu Wan
ISOM, HKUST Business School · 2026 Edition
Every classifier in Chapter 4 needed a label, and every label so far was “the return over the next \(h\) days was positive”. A trader who set a stop-loss would not recognise that label. You will build López de Prado’s triple-barrier label on the S&P 500, scaled by the §6.5 volatility; give a moving-average rule the job of choosing the side; and train a second model — the meta-model — to decide the size.
The fixed-horizon label \(\mathbb 1[r_{t \to t+10} > 0]\) ignores…
Triple-barrier label (López de Prado, 2018). From entry at close \(t\), three barriers: an upper profit-take at \(+m_{pt}\,\hat\sigma_t\), a lower stop-loss at \(-m_{sl}\,\hat\sigma_t\), and a vertical barrier at \(t + h\). Label +1 if the upper barrier is touched first, −1 if the lower, and the sign of the return at \(t+h\) if neither. \(\hat\sigma_t\) is the §6.5-style volatility estimate at \(t\) — barriers are wider in stormy markets.
60 % of entries are labelled +1 against 64 % for the fixed-horizon label; 76 % of entries hit a horizontal barrier within ten days, on average after six. The two labels disagree on 11.5 % of days — those are the trades where the path and the end point tell different stories, and they are the ones a stop-loss decides.
Entering on 24 February 2020 with \(\hat\sigma\) = 1.22 %: the stop at −2.44 % is hit on day 1 (label −1) — the fixed-horizon label agrees here, but the barrier label closed the trade nine days earlier. The vertical barrier caps how long a bet is allowed to be wrong; the horizontal ones cap how wrong.
A 50/200-day moving-average crossover — one of the §7.6 family — goes long when the fast average is above the slow one and short otherwise. The meta-label asks: did the side the primary chose pay, in the triple-barrier sense?
2 307 days from October 2015. The primary is long 79 % of the time and its trade “works” on 55.7 % of days — 60 % when long, 38 % when short. Seven features, all known at the close of \(t\), including the side itself: the meta-model may learn that the primary is only worth backing in some states.
Refitting each January on all earlier rows — what leaks?
1 500 test days, AUC 0.545 — the meta-model separates good from bad primary trades a little better than a coin (0.5), which is what one should expect from seven price features (§6.2). It says “back the trade” (p > 0.5) on 71 % of days.
Bet size \(b_t = \max\big(0,\; 2(p_t - \tfrac12)\big)\): nothing when the meta-model is unsure, a full position at \(p = 1\). Position \(= \text{side}_t \times b_t\), applied to the next day’s return.
Primary alone: Sharpe 0.20, drawdown −46 % (the 2020 whipsaw: the crossover went short in April and stayed short through the recovery; 2020 Sharpe −0.68). Meta-labelled and sized: Sharpe 0.77, drawdown −3.9 %, but cumulative return only 13.9 % because the mean bet is 0.16. The on/off version (full size when p > 0.5) earns 63.5 % at Sharpe 0.74 — level with buy-and-hold (0.73) at half the drawdown. The gain is the meta-model declining the 2020 shorts (2020: −0.68 → +0.79); 2022 got worse (−0.22 → −1.11). Meta-labeling improves a signal’s quality; it cannot create a signal.
Replace the logistic meta-model by HistGradientBoostingClassifier(max_depth=2, learning_rate=0.05, max_iter=150, min_samples_leaf=50, random_state=0). Does a more flexible meta-model improve the AUC or the Sharpe ratio?
Boosting: AUC 0.528, Sharpe 0.14, drawdown −11.3 % — worse than the logistic model’s 0.545 and 0.77. Seven features and about 800 training days per class are not enough for trees to find a stable state dependence, and the meta-model’s Sharpe swings by 0.6 with the choice of learner. That swing is the honest error bar on the previous slide.
Next: §7.6 — the crossover was one of 42 rules we could have picked. What is the best of 42 worth?
Prof. Xuhu Wan · HKUST ISOM · Learning Statistics with Python