{"record":{"id":"bd3a6c8c53f688e1","repo":"HKUDS/Vibe-Trading","slug":"alpha-id-output-contains-inf","errorCode":null,"errorMessage":"{alpha_id}: output contains +/- inf","messagePattern":"(.+?): output contains \\+/- inf","errorType":"validation","errorClass":"RegistryError","httpStatus":null,"severity":"error","filePath":"agent/src/factors/registry.py","lineNumber":393,"sourceCode":"\n    @staticmethod\n    def _validate_output(\n        alpha_id: str,\n        result: Any,\n        panel: dict[str, pd.DataFrame],\n    ) -> pd.DataFrame:\n        if not isinstance(result, pd.DataFrame):\n            raise RegistryError(\n                f\"{alpha_id}: compute() returned {type(result).__name__}, expected DataFrame\"\n            )\n        ref = panel.get(\"close\")\n        if ref is not None and result.shape != ref.shape:\n            raise RegistryError(\n                f\"{alpha_id}: output shape {result.shape} != close shape {ref.shape}\"\n            )\n        arr = result.to_numpy(dtype=np.float64, na_value=np.nan)\n        if np.isinf(arr).any():\n            raise RegistryError(f\"{alpha_id}: output contains +/- inf\")\n        nan_ratio = float(np.isnan(arr).mean()) if arr.size > 0 else 1.0\n        if nan_ratio > 0.95:\n            raise RegistryError(f\"{alpha_id}: output >95% NaN (nan_ratio={nan_ratio:.3f})\")\n        return result\n\n    def export_manifest(self) -> dict[str, Any]:\n        \"\"\"Return a JSON-serialisable snapshot for wiki rendering.\"\"\"\n        from datetime import datetime, timezone\n\n        zoos: dict[str, list[dict[str, Any]]] = {}\n        for a in self._alphas.values():\n            zoos.setdefault(a.zoo, []).append(\n                {\n                    \"id\": a.id,\n                    \"module_path\": a.module_path,\n                    \"meta\": a.meta,\n                }\n            )","sourceCodeStart":375,"sourceCodeEnd":411,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/factors/registry.py#L375-L411","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Guard divisions: `x / denom.replace(0, np.nan)`","Convert at the end: `result = result.replace([np.inf, -np.inf], np.nan)`","Clip if inf is meaningful: `result.clip(lower=-1e12, upper=1e12)`"],"exampleFix":"# before\nreturn (close - open) / (high - low)  # high==low -> inf\n# after\nrng = (high - low).replace(0, np.nan)\nreturn (close - open) / rng","handlingStrategy":"validation","validationCode":"arr = result.to_numpy(float)\nif np.isinf(arr).any(): result = result.replace([np.inf,-np.inf], np.nan)","typeGuard":null,"tryCatchPattern":"try:\n    out = registry.compute(aid, panel)\nexcept RegistryError as e:\n    if 'contains +/- inf' in str(e): skip(aid)\n    else: raise","preventionTips":["Guard denominators with replace(0, np.nan)","Replace inf with NaN at the end of compute"],"tags":["numerical","pandas","infinity"],"backgroundTag":"division-produced-infinity","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}