{"record":{"id":"1c243388b1651770","repo":"HKUDS/Vibe-Trading","slug":"alpha-id-ic-series-empty-insufficient-overlap","errorCode":null,"errorMessage":"{alpha_id}: IC series empty — insufficient overlap between factor and returns","messagePattern":"(.+?): IC series empty — insufficient overlap between factor and returns","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"agent/src/tools/alpha_bench_tool.py","lineNumber":693,"sourceCode":"        raise ValueError(\"panel missing 'close' — cannot derive forward returns\")\n    # Next-period return aligned to current row (use t+1 close, shift back).\n    fwd = close.pct_change(fill_method=None).shift(-1)\n    return fwd\n\n\ndef _bench_one_alpha(\n    registry: Any,\n    alpha_id: str,\n    panel: dict[str, pd.DataFrame],\n    return_df: pd.DataFrame,\n) -> dict[str, Any]:\n    \"\"\"Compute IC stats for one alpha. Returns a dict, may raise SkipAlpha / RegistryError.\"\"\"\n    from src.factors.factor_analysis_core import compute_ic_series  # local import\n\n    factor_df = registry.compute(alpha_id, panel)\n    ic_series = compute_ic_series(factor_df, return_df)\n    if ic_series.empty:\n        raise RuntimeError(\n            f\"{alpha_id}: IC series empty — insufficient overlap between factor and returns\"\n        )\n    ic_mean = float(ic_series.mean())\n    ic_std = float(ic_series.std())\n    ir = ic_mean / ic_std if ic_std > 0 else 0.0\n    ic_pos = float((ic_series > 0).mean())\n    alpha = registry.get(alpha_id)\n    meta = alpha.meta or {}\n    return {\n        \"id\": alpha_id,\n        \"zoo\": alpha.zoo,\n        \"theme\": meta.get(\"theme\", []),\n        \"formula_latex\": meta.get(\"formula_latex\", \"\"),\n        \"ic_mean\": round(ic_mean, 6),\n        \"ic_std\": round(ic_std, 6),\n        \"ir\": round(ir, 4),\n        \"ic_positive_ratio\": round(ic_pos, 4),\n        \"ic_count\": int(len(ic_series)),","sourceCodeStart":675,"sourceCodeEnd":711,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/tools/alpha_bench_tool.py#L675-L711","documentation":"After computing the IC series for an alpha, _bench_one_alpha requires a non-empty result. Empty means the factor DataFrame and the forward-return DataFrame share no overlapping timestamps (or symbols), so no rank correlation can be computed.","triggerScenarios":"Factor timestamps that don't align with return timestamps (different calendars/timezones); a factor computed only on dates after the returns window ends; all-NaN factor columns causing row-wise drops in compute_ic_series.","commonSituations":"Factors built on a different trading calendar (e.g. crypto 24/7 vs A-share calendar); timezone misalignment between factor and close panels; too-short windows where next-bar shifting removes all overlap.","solutions":["Reindex/align factor_df and return_df to a common trading calendar before benching","Extend the period so factor and return dates overlap by at least a few bars","Verify the alpha's compute() output is not empty or all-NaN for the requested panel"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"common = factor_df.index.intersection(return_df.index)\nassert len(common) >= 5, f'only {len(common)} overlapping dates'","typeGuard":"def has_overlap(factor_df, return_df, min_bars: int = 5) -> bool:\n    return len(factor_df.index.intersection(return_df.index)) >= min_bars","tryCatchPattern":"try:\n    _bench_one_alpha(...)\nexcept RuntimeError as e:\n    if 'IC series empty' in str(e):\n        reindex_factor_to_calendar(); retry or skip alpha","preventionTips":["Align factor and price data to one calendar before benching","Timezone-normalize all index timestamps at load time"],"tags":["data-alignment","ic-computation","alpha-bench"],"backgroundTag":"empty-overlap-in-time-series-join","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}