cs_demean¶
Defined in fynance.features.cross_section
- cs_demean(X, weights=None)[source]
Per-bar cross-sectional demeaning, NaN-aware.
Subtracts, from each valid entry of bar
t, the (optionally weighted) mean of the valid entries of that bar:\[cs\_demean_t(i) = X_t(i) - \bar{X}_t, \qquad \bar{X}_t = \frac{\sum_{j \in valid_t} w_t(j) X_t(j)} {\sum_{j \in valid_t} w_t(j)}\]With
weights=Noneevery valid asset gets equal weight (a plain cross-sectional mean) — the usual “dollar-neutral” transform. If the total weight of the valid assets in a bar is zero (e.g. long/short weights that happen to cancel, or all-zero weights), the bar falls back to an equal-weighted mean over its valid assets.- Parameters:
- Xarray_like
Panel, shape
(T, N).- weightsarray_like, optional
Weights, either
(N,)(applied identically at every bar) or(T, N)(time-varying). Weights at positions whereXisNaNare ignored. DefaultNone(equal weight).
- Returns:
- np.ndarray
(T, N)demeaned panel,NaNwhereXisNaN.
See also
cs_zscore,cs_neutralize
Examples
>>> import numpy as np >>> X = np.array([[1., 2., 3.]]) >>> cs_demean(X) array([[-1., 0., 1.]])
Weighted demeaning:
>>> cs_demean(np.array([[1., 2., 3.]]), weights=np.array([1., 1., 2.])) array([[-1.25, -0.25, 0.75]])
NaN-aware: the missing asset is excluded from the bar’s mean and stays NaN:
>>> cs_demean(np.array([[1., np.nan, 3.]])) array([[-1., nan, 1.]])