uniqueness_weights¶
Defined in fynance.features.labels
- uniqueness_weights(t_in, t_out, T)[source]
Average-uniqueness sample weights for overlapping labels (AFML ch. 4).
Warning
This produces sample weights derived from labels, not a feature — see the module warning.
Overlapping
triple_barrierlabels are drawn from overlapping price paths, so they are not i.i.d.: a bar covered by many concurrent labels gets diluted “credit” in each of them. For each label, the uniqueness at a bar is1 / concurrencythere (seelabel_concurrency); the weight is the label’s average uniqueness over its own[t_in, t_out]span, rescaled so the weights sum ton(the number of labels) — the AFML convention, so the mean weight is 1 regardless of how much overlap there is.\[\bar u_i = \frac{1}{t_{out,i} - t_{in,i} + 1} \sum_{t=t_{in,i}}^{t_{out,i}} \frac{1}{c_t}, \qquad w_i = \bar u_i \cdot \frac{n}{\sum_j \bar u_j}\]where \(c_t\) is
label_concurrency.This composes multiplicatively with a recency scheme such as
fynance.models.training.exp_sample_weights: multiply the two weight vectors together (both already convey “importance”, one for overlap and one for recency) rather than choosing one over the other.- Parameters:
- t_in, t_outnp.ndarray[int, ndim=1]
Label start / end indices, as in
label_concurrency.- Tint
Number of bars in the underlying series.
- Returns:
- np.ndarray[np.float64, ndim=1]
Shape
(n,)wheren = len(t_in), non-negative, summing ton(up to floating-point error). Disjoint labels all get weight1.0; more overlap means a smaller weight.
- Raises:
- ValueError
Propagated from
label_concurrencyfor malformed spans.
See also
label_concurrency,triple_barrierfynance.models.training.exp_sample_weights
References
[1]Lopez de Prado, M. (2018). Advances in Financial Machine Learning. Wiley. Chapter 4, “Sample Weights”.
Examples
Disjoint labels share no overlap, so every weight is 1:
>>> import numpy as np >>> uniqueness_weights(np.array([0, 2]), np.array([1, 3]), T=4) array([1., 1.])
Two identical, fully overlapping labels split their combined uniqueness evenly, and a third, disjoint label keeps its full weight – rescaled so all three sum to 3:
>>> uniqueness_weights(np.array([0, 0, 2]), np.array([1, 1, 3]), T=4) array([0.75, 0.75, 1.5 ])