triple_barrier¶
Defined in fynance.features.labels
- triple_barrier(prices, events=None, pt=1.0, sl=1.0, max_holding=21, vol=None)[source]
Path-dependent triple-barrier labels (AFML ch. 3).
Warning
This is a label, not a feature — it is only known at
t_out, strictly aftert_in. Never use it as a model input; see the module warning and route it throughfynance.data.split.From each event start
i(t_in), two horizontal barriers are set on the simple return ofpricesrelative toprices[i]: an upper barrier at+pt * scale_iand a lower barrier at-sl * scale_i. The path is then walked forward one bar at a time over(i, i + max_holding](clipped to the last index): the first bar that touches a barrier sets the label (+1upper,-1lower); if neither is touched before the vertical barrier, the label is0at that vertical bar.\[\tau_i = \min\{t > i : r_{i,t} \geq pt \cdot scale_i \text{ or } r_{i,t} \leq -sl \cdot scale_i\} \wedge (i + max\_holding)\]with \(r_{i,t} = prices_t / prices_i - 1\).
- Parameters:
- pricesnp.ndarray[dtype, ndim=1]
One-dimensional series of price levels, length
T.- eventsnp.ndarray[int], optional
Integer indices of label start times (
t_in). Must lie in[0, T - 2]so that at least one future bar exists. Default isnp.arange(T - 1)(one label per bar, except the last).- pt, slfloat, optional
Profit-take / stop-loss barrier width, as a multiple of
scale_i. Both must be strictly positive. Default1.0for both.- max_holdingint, optional
Maximum holding period (vertical barrier), in bars. Must be
>= 1. Default 21.- volnp.ndarray[dtype, ndim=1], optional
Per-bar, return-scale volatility, shape
(T,)(e.g. a causal trailing realized volatility of simple returns — seerealized_volatilityorsmstdon returns).scale_iisvol[i]. IfNone(default),scale_iis the constant standard deviation of the 1-bar simple returns computed over the whole series — this is an in-sample quantity (it peeks at the entire history, future included) kept only as a convenience default; pass a causalvolfor a genuinely leakage-free label.
- Returns:
- np.ndarray[LABEL_DTYPE, ndim=1]
Structured array of length
len(events)with fields:t_in(int64) — label start index (==events).t_out(int64) — index where the label was resolved.label(int8) —+1upper barrier,-1lower barrier,0vertical barrier (timeout).ret(float64) — simple return fromt_intot_out.
- Raises:
- ValueError
If
priceshas fewer than 2 observations; if anyeventsindex is outside[0, T - 2]; ifpt <= 0orsl <= 0; ifmax_holding < 1; or ifvolis given with a shape other than(T,).
See also
meta_labels,label_concurrency,uniqueness_weightsfynance.data.split.train_test_split,fynance.data.split.walk_forward
Notes
Barrier checks favor the upper barrier on a tie (both touched on the same bar, which can only happen with
scale_i = 0).References
[1]Lopez de Prado, M. (2018). Advances in Financial Machine Learning. Wiley. Chapter 3, “Labeling”.
Examples
>>> import numpy as np >>> prices = np.array([100., 101., 105., 101., 98., 97.]) >>> vol = np.full(6, 0.02) >>> out = triple_barrier(prices, events=np.array([0]), max_holding=4, vol=vol) >>> out['t_in'], out['t_out'], out['label'], out['ret'] (array([0]), array([2]), array([1], dtype=int8), array([0.05]))
A path that never touches either barrier resolves at the vertical bar:
>>> flat = np.array([100., 100.5, 100.2, 100.8, 100.1]) >>> out = triple_barrier(flat, events=np.array([0]), max_holding=3, vol=np.full(5, 1.0)) >>> out['t_out'], out['label'] (array([3]), array([0], dtype=int8))