cross_section
cross_section
Cross-sectional characteristics and relative asset measurements.
Factor calculations compare assets; they do not choose portfolio positions.
Functions
| Name | Description |
|---|---|
| compute_elo | Compute daily cross-sectional Elo ratings within sectors. |
| group_weighted_return | Calculate weighted simple returns for groups of assets. |
| neutralize | Return weighted least-squares residuals after removing exposures. |
| percentile_rank | Return cross-sectional ranks scaled to the interval (0, 1]. |
| rank | Rank assets within a snapshot or each row of a time-by-asset panel. |
| relative_strength | Rank trailing asset returns cross-sectionally for every timestamp. |
| zscore | Standardize values against their cross-sectional mean and deviation. |
compute_elo
cross_section.compute_elo(
data,
daily_vol_window=20,
matches_per_stock=1,
initial_elo=1500,
epsilon=0.001,
rf_data=None,
low_qt=0.2,
high_qt=0.8,
use_excess_returns=True,
)Compute daily cross-sectional Elo ratings within sectors.
Call this function once for a complete long-form universe. It calculates each symbol’s daily return, pairs symbols with nearby Elo ratings inside the same sectorid, and carries ratings forward through time.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| data | pd.DataFrame | Daily observations with required date, symbol, close, and sectorid columns. Missing sector values are grouped into an "UnknownSector" bucket. |
required |
| daily_vol_window | int | Rolling return-volatility window. | 20 |
| matches_per_stock | int | Maximum opponents selected per symbol and date. | 1 |
| initial_elo | int | Starting rating for every symbol. | 1500 |
| epsilon | float | Absolute return difference treated as a draw. | 0.001 |
| rf_data | pd.DataFrame | None | Optional frame with date and decimal daily rate. |
None |
| low_qt | float | Legacy lower K-factor threshold. Its semantics require review; see the cross-section roadmap. | 0.2 |
| high_qt | float | Legacy upper K-factor threshold. Its semantics require review; see the cross-section roadmap. | 0.8 |
| use_excess_returns | bool | Use returns minus rf_data when both are supplied. If no risk-free frame is supplied, use log returns. |
True |
Returns
| Name | Type | Description |
|---|---|---|
| pd.DataFrame | A new DataFrame containing the prepared return columns plus elo, |
|
| pd.DataFrame | daily elo_change, and cumulative matches_played. |
Raises
| Name | Type | Description |
|---|---|---|
| TypeError | If data is not a DataFrame. |
|
| ValueError | If required columns are absent or parameters are invalid. |
Notes
This is a migration of the legacy algorithm. Match scheduling, K-factor thresholds, and missing-price semantics remain under review and are tracked in the q.cross_section roadmap.
group_weighted_return
cross_section.group_weighted_return(
data,
*,
group_field='sectorid',
date_field='date',
symbol_field='symbol',
field=None,
field_type=None,
weighting='equal',
weight_field=None,
weight_lag=1,
volatility_window=20,
min_assets=1,
)Calculate weighted simple returns for groups of assets.
The input must contain one row per symbol and date. When field is not supplied, a return column is used as simple returns if present; otherwise returns are calculated from close. Explicit fields require a field_type of "price", "simple_return", or "log_return".
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| data | pd.DataFrame | Long-form asset observations. | required |
| group_field | str | Column defining groups, such as sectorid. |
'sectorid' |
| date_field | str | Observation date or datetime column. | 'date' |
| symbol_field | str | Asset identifier column. | 'symbol' |
| field | str | None | Optional price or return column. | None |
| field_type | FieldType | None | Interpretation of an explicitly supplied field. |
None |
| weighting | Weighting | Equal, market-cap, volume, inverse-volatility, or custom weighting. | 'equal' |
| weight_field | str | None | Weight column. It defaults to market_cap or volume for those named methods and is required for custom. |
None |
| weight_lag | int | Observations by which non-equal weights are lagged within each symbol. The default prevents look-ahead bias. | 1 |
| volatility_window | int | Trailing window for inverse-volatility weights. | 20 |
| min_assets | int | Minimum valid assets required for a group return. | 1 |
Returns
| Name | Type | Description |
|---|---|---|
| pd.DataFrame | A new DataFrame with the date and group columns, weighted_return, |
|
| pd.DataFrame | contributing asset_count, and raw weight_sum. |
Raises
| Name | Type | Description |
|---|---|---|
| TypeError | If the input or a required numeric column has the wrong type. | |
| ValueError | If columns, observations, or parameters are invalid. |
neutralize
cross_section.neutralize(values, exposures, *, weights=None, add_intercept=True)Return weighted least-squares residuals after removing exposures.
Numeric exposures are used directly. Categorical exposures are expanded into dummy variables, making sector or industry neutralization explicit. Rows containing missing values remain missing in the returned Series.
percentile_rank
cross_section.percentile_rank(
values,
*,
axis='columns',
method='average',
ascending=True,
)Return cross-sectional ranks scaled to the interval (0, 1].
rank
cross_section.rank(
values,
*,
axis='columns',
method='average',
ascending=True,
na_option='keep',
)Rank assets within a snapshot or each row of a time-by-asset panel.
relative_strength
cross_section.relative_strength(prices, *, lookback=21, method='average')Rank trailing asset returns cross-sectionally for every timestamp.
The input must be a time-by-asset price matrix. Output values are percentile ranks in (0, 1]; larger values indicate stronger trailing performance relative to the contemporaneous universe.
zscore
cross_section.zscore(values, *, axis='columns', ddof=0)Standardize values against their cross-sectional mean and deviation.