{"record":{"id":"84ebd825383fce7f","repo":"HKUDS/Vibe-Trading","slug":"alpha-id-output-95-nan-nan-ratio-nan-ratio","errorCode":null,"errorMessage":"{alpha_id}: output >95% NaN (nan_ratio={nan_ratio:.3f})","messagePattern":"(.+?): output >95% NaN \\(nan_ratio=(.+?)\\)","errorType":"validation","errorClass":"RegistryError","httpStatus":null,"severity":"error","filePath":"agent/src/factors/registry.py","lineNumber":396,"sourceCode":"        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            )\n        return {\n            \"generated_at\": datetime.now(timezone.utc).isoformat(),\n            \"zoos\": [","sourceCodeStart":378,"sourceCodeEnd":414,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/factors/registry.py#L378-L414","documentation":"_validate_output computes the NaN fraction of the output; above 95% NaN the factor is considered degenerate (effectively all-missing) and rejected. This catches broken formulas, wrong-keyed panels, and long warmup windows exceeding the data length.","triggerScenarios":"A factor whose warmup (rolling window longer than the panel history) leaves >95% NaN, or whose logic produces NaN almost everywhere (e.g. log of negative prices, wrong index alignment).","commonSituations":"Short test panels fed to long-window alphas; misaligned indexes causing all-NaN merges; applying log to negative/zero inputs.","solutions":["Use a longer panel than the alpha's max lookback window","Fix the formula so it produces values on most cells (check input dtypes/signs)","Pick shorter-window alphas for small datasets"],"exampleFix":"# before\npanel = last_30_days()  # 20-day warmup alpha -> mostly NaN\n# after\npanel = last_250_days()  # ample history past warmup","handlingStrategy":"validation","validationCode":"nan_ratio = float(np.isnan(result.to_numpy(float)).mean())\nif nan_ratio > 0.95: skip(aid, nan_ratio)","typeGuard":null,"tryCatchPattern":"try:\n    out = registry.compute(aid, panel)\nexcept RegistryError as e:\n    if '>95% NaN' in str(e): skip(aid)\n    else: raise","preventionTips":["Ensure panel length exceeds the factor's max lookback","Check input signs/dtypes before transform-only ops like log"],"tags":["numerical","nan","validation"],"backgroundTag":"output-mostly-nan","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}