{"record":{"id":"8fdcf26dff20585d","repo":"HKUDS/Vibe-Trading","slug":"no-cross-section-had-at-least-min-cross-section","errorCode":null,"errorMessage":"No cross-section had at least {min_cross_section} valid asset pairs to compute IC","messagePattern":"No cross-section had at least (.+?) valid asset pairs to compute IC","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/quantlib/factormodel.py","lineNumber":815,"sourceCode":"            continue\n\n        f_vals = f_row.loc[shared].to_numpy(dtype=float)\n        r_vals = r_row.loc[shared].to_numpy(dtype=float)\n\n        if method == \"spearman\":\n            f_vals = rankdata(f_vals)\n            r_vals = rankdata(r_vals)\n\n        f_std = np.std(f_vals, ddof=1)\n        r_std = np.std(r_vals, ddof=1)\n\n        if f_std > 0 and r_std > 0:\n            corr = float(np.corrcoef(f_vals, r_vals)[0, 1])\n            if np.isfinite(corr):\n                ic_records[date] = corr\n\n    if not ic_records:\n        raise ValueError(\n            f\"No cross-section had at least {min_cross_section} valid asset pairs to compute IC\"\n        )\n\n    ic_series = pd.Series(ic_records, dtype=float, name=\"ic\").sort_index()\n    n = len(ic_series)\n    mean_ic = float(ic_series.mean())\n\n    if n > 1:\n        std_ic = float(ic_series.std(ddof=1))\n        ic_ir = mean_ic / std_ic if std_ic > 0 else float(\"nan\")\n        t_stat = ic_ir * np.sqrt(n) if std_ic > 0 else float(\"nan\")\n        p_val = float(2 * student_t.sf(abs(t_stat), df=n - 1)) if np.isfinite(t_stat) else float(\"nan\")\n        sk = float(skew(ic_series.to_numpy(), bias=False)) if n > 2 else 0.0\n        # Non-excess kurtosis (normal == 3.0)\n        kurt = float(kurtosis(ic_series.to_numpy(), fisher=False, bias=False)) if n > 3 else 3.0\n    else:\n        std_ic = float(\"nan\")\n        ic_ir = float(\"nan\")","sourceCodeStart":797,"sourceCodeEnd":833,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/quantlib/factormodel.py#L797-L833","documentation":"After alignment, each date needs at least min_cross_section valid (finite, non-constant) factor/return pairs to compute a meaningful correlation. If no date qualifies, ic_records stays empty and the error is raised.","triggerScenarios":"Panels with only 1-2 assets per date, all-NaN factor columns, or zero-variance factors where f_std == 0 skips every date.","commonSituations":"Testing with a tiny universe; factor column entirely NaN after a join; returns mostly missing so pairs never reach the threshold.","solutions":["Pass a smaller min_cross_section if a tiny universe is intended","Drop all-NaN / zero-variance factor columns before the call","Fix the join so factor and return data cover the same assets"],"exampleFix":"# before\nic = factor_ic_analysis(panel, rets)\n# after\npanel = panel.dropna(axis=1, how='all')\nic = factor_ic_analysis(panel, rets, min_cross_section=3)","handlingStrategy":"fallback","validationCode":"valid = ((panel.notna() & rets.notna()).sum(axis=1) >= min_cross_section).any()\nassert valid, 'no cross-section meets min_cross_section'","typeGuard":null,"tryCatchPattern":"try:\n    ic = factor_ic_analysis(panel, rets)\nexcept ValueError as e:\n    if 'valid asset pairs' in str(e):\n        ic = None  # universe too small; degrade gracefully\n    else:\n        raise","preventionTips":["Drop all-NaN factor columns pre-call","Scale min_cross_section to the actual universe size"],"tags":["quantlib","factormodel","ic-analysis","insufficient-data"],"backgroundTag":"insufficient-data-validation","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}