HKUDS/Vibe-Trading · error · RegistryError

{alpha_id}: output contains +/- inf

Error message

{alpha_id}: output contains +/- inf

What it means

The output matrix is converted to float64 and checked for infinite values; +/- inf (from division by zero producing inf rather than NaN) fails validation because downstream rank/zscore steps cannot handle inf.

Source

Thrown at agent/src/factors/registry.py:393

    @staticmethod
    def _validate_output(
        alpha_id: str,
        result: Any,
        panel: dict[str, pd.DataFrame],
    ) -> pd.DataFrame:
        if not isinstance(result, pd.DataFrame):
            raise RegistryError(
                f"{alpha_id}: compute() returned {type(result).__name__}, expected DataFrame"
            )
        ref = panel.get("close")
        if ref is not None and result.shape != ref.shape:
            raise RegistryError(
                f"{alpha_id}: output shape {result.shape} != close shape {ref.shape}"
            )
        arr = result.to_numpy(dtype=np.float64, na_value=np.nan)
        if np.isinf(arr).any():
            raise RegistryError(f"{alpha_id}: output contains +/- inf")
        nan_ratio = float(np.isnan(arr).mean()) if arr.size > 0 else 1.0
        if nan_ratio > 0.95:
            raise RegistryError(f"{alpha_id}: output >95% NaN (nan_ratio={nan_ratio:.3f})")
        return result

    def export_manifest(self) -> dict[str, Any]:
        """Return a JSON-serialisable snapshot for wiki rendering."""
        from datetime import datetime, timezone

        zoos: dict[str, list[dict[str, Any]]] = {}
        for a in self._alphas.values():
            zoos.setdefault(a.zoo, []).append(
                {
                    "id": a.id,
                    "module_path": a.module_path,
                    "meta": a.meta,
                }
            )

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Guard divisions: `x / denom.replace(0, np.nan)`
  2. Convert at the end: `result = result.replace([np.inf, -np.inf], np.nan)`
  3. Clip if inf is meaningful: `result.clip(lower=-1e12, upper=1e12)`

Example fix

# before
return (close - open) / (high - low)  # high==low -> inf
# after
rng = (high - low).replace(0, np.nan)
return (close - open) / rng
Defensive patterns

Strategy: validation

Validate before calling

arr = result.to_numpy(float)
if np.isinf(arr).any(): result = result.replace([np.inf,-np.inf], np.nan)

Try / catch

try:
    out = registry.compute(aid, panel)
except RegistryError as e:
    if 'contains +/- inf' in str(e): skip(aid)
    else: raise

Prevention

When it happens

Trigger: Factor divides by a zero-containing denominator without NaN semantics (e.g. x / volume where volume==0 on some entries), or uses np.log(0) variants returning -inf via errstate.

Common situations: Zero-volume bars, zero volatility windows producing inf in ratio alphas; integer division vs float division differences; newer numpy defaulting to raise/warn on divide.

Related errors


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