cs_zscore

Defined in fynance.features.cross_section

cs_zscore(X, ddof=0)[source]

Per-bar cross-sectional z-score, NaN-aware.

At each bar t, standardizes the valid entries against their own bar’s mean and standard deviation:

\[cs\_zscore_t(i) = \frac{X_t(i) - \mu_t}{\sigma_t}\]

where \(\mu_t\) and \(\sigma_t\) are the mean and standard deviation of the non-NaN entries of bar t. A bar with zero cross-sectional dispersion (\(\sigma_t = 0\), e.g. all valid assets tied) maps every valid entry to 0.0 rather than dividing by zero.

Parameters:
Xarray_like

Panel, shape (T, N).

ddofint, optional

Delta degrees of freedom used for \(\sigma_t\) (ddof=0 is the population standard deviation, ddof=1 the sample one). Default 0.

Returns:
np.ndarray

(T, N) array of z-scores, NaN where X is NaN.

See also

cs_rank, cs_demean

Examples

>>> import numpy as np
>>> X = np.array([[1., 2., 3.]])
>>> cs_zscore(X)
array([[-1.22474487,  0.        ,  1.22474487]])

A tied (zero-variance) bar maps every valid entry to 0:

>>> cs_zscore(np.array([[5., 5., 5.]]))
array([[0., 0., 0.]])

NaN-aware: the missing asset is excluded from the bar’s mean/std and stays NaN:

>>> cs_zscore(np.array([[1., np.nan, 3.]]))
array([[-1., nan,  1.]])