cs_rank¶
Defined in fynance.features.cross_section
- cs_rank(X, pct=True)[source]
Per-bar cross-sectional rank, NaN-aware.
At each bar
t, then_validnon-NaNassets are ranked from smallest (rank 1) to largest (rankn_valid); ties get the average of the ranks they span (e.g. two tied values at ranks 2 and 3 both get 2.5). Missing assets are excluded from the ranking and stayNaN.- Parameters:
- Xarray_like
Panel, shape
(T, N).- pctbool, optional
If
True(default), rescale ranks to[0, 1]per bar. IfFalse, return the raw average rank in[1, n_valid].
- Returns:
- np.ndarray
(T, N)array of ranks,NaNwhereXisNaN.
See also
cs_zscore,cs_winsorize
Notes
The tie-averaged rank is computed without SciPy: values are sorted with
numpy.argsort, then each run of equal values in sorted order is assigned the mean of the 1-based ranks it occupies.With
pct=Truethe rank is rescaled to[0, 1]:\[cs\_rank^{pct}_t(i) = \frac{rank_t(i) - 1}{n\_valid_t - 1}\]so the smallest valid value maps to 0, the largest to 1. When
n_valid_t == 1there is no spread to normalize against, so the single valid entry maps to 0.5 by convention.Examples
>>> import numpy as np >>> X = np.array([[3., 1., 2.]]) >>> cs_rank(X, pct=True) array([[1. , 0. , 0.5]]) >>> cs_rank(X, pct=False) array([[3., 1., 2.]])
Ties get the average rank, e.g. the two tied 1’s here share ranks 1 and 2:
>>> cs_rank(np.array([[1., 1., 2.]]), pct=False) array([[1.5, 1.5, 3. ]])
A single valid asset in the bar maps to 0.5 under
pct=True:>>> cs_rank(np.array([[5., np.nan, np.nan]])) array([[0.5, nan, nan]])