HKUDS/Vibe-Trading · error · ValueError

the characteristic has no cross-sectional variation, so a z-

Error message

the characteristic has no cross-sectional variation, so a z-score would divide by zero

What it means

standardise_exposures z-scores by dividing by the cross-sectional standard deviation; if every finite (winsorised) value is identical the spread is zero and the z-score would divide by zero, so the library raises instead of returning inf/NaN exposures.

Source

Thrown at agent/src/quantlib/factormodel.py:302

    if market_caps is None:
        centre = float(clipped.dropna().mean())
    else:
        caps = pd.Series(market_caps, dtype=float)
        missing = series.index.difference(caps.index)
        if len(missing):
            raise ValueError(
                f"market_caps is missing {len(missing)} asset(s) present in values"
            )
        aligned_caps = caps.reindex(clipped.index)
        usable = clipped.notna() & aligned_caps.notna() & (aligned_caps > 0)
        if not usable.any():
            raise ValueError("no asset has both a finite value and a positive market cap")
        weights = aligned_caps[usable]
        centre = float((clipped[usable] * weights).sum() / weights.sum())

    spread = float(clipped.dropna().std(ddof=1))
    if not np.isfinite(spread) or spread <= 0.0:
        raise ValueError(
            "the characteristic has no cross-sectional variation, so a z-score "
            "would divide by zero"
        )
    return (clipped - centre) / spread


def build_style_exposures(
    characteristics: pd.DataFrame,
    market_caps: pd.Series | None = None,
    definitions: Mapping[str, Mapping[str, int]] = STYLE_FACTOR_DEFINITIONS,
    winsorise: float = DEFAULT_WINSORISE,
) -> tuple[pd.DataFrame, dict[str, int]]:
    """Assemble a style exposure matrix from raw characteristics.

    Args:
        characteristics: Raw values, rows indexed by asset, one column per
            characteristic named in ``definitions``. Columns a definition asks
            for but the frame does not carry cause that factor to be skipped,

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Check spread: values.dropna().std(); if 0, the characteristic carries no information for that date.
  2. Fix the upstream column construction; if the column is legitimately constant, exclude that factor for the date rather than standardising it.

Example fix

# before
z = standardise_exposures(df['leverage'])  # all identical
# after
if df['leverage'].dropna().std(ddof=1) > 0:
    z = standardise_exposures(df['leverage'])
else:
    z = pd.Series(0.0, index=df.index)  # neutral placeholder, factor skipped
Defensive patterns

Strategy: validation

Validate before calling

assert pd.Series(values).dropna().std(ddof=1) > 0

Prevention

When it happens

Trigger: A characteristic that is constant across the universe for a date — e.g. 'days since listing' filled with a placeholder, a categorical field encoded as the same number, or a column accidentally broadcast from a scalar.

Common situations: Data pipeline bugs that overwrite a column with one value, placeholder/fillna(0) columns, or genuinely degenerate cross-sections on illiquid dates.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/1edb72157dfee26e. Report an issue: GitHub.