HKUDS/Vibe-Trading · error · ValueError

No cross-section had at least {min_cross_section} valid asse

Error message

No cross-section had at least {min_cross_section} valid asset pairs to compute IC

What it means

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.

Source

Thrown at agent/src/quantlib/factormodel.py:815

            continue

        f_vals = f_row.loc[shared].to_numpy(dtype=float)
        r_vals = r_row.loc[shared].to_numpy(dtype=float)

        if method == "spearman":
            f_vals = rankdata(f_vals)
            r_vals = rankdata(r_vals)

        f_std = np.std(f_vals, ddof=1)
        r_std = np.std(r_vals, ddof=1)

        if f_std > 0 and r_std > 0:
            corr = float(np.corrcoef(f_vals, r_vals)[0, 1])
            if np.isfinite(corr):
                ic_records[date] = corr

    if not ic_records:
        raise ValueError(
            f"No cross-section had at least {min_cross_section} valid asset pairs to compute IC"
        )

    ic_series = pd.Series(ic_records, dtype=float, name="ic").sort_index()
    n = len(ic_series)
    mean_ic = float(ic_series.mean())

    if n > 1:
        std_ic = float(ic_series.std(ddof=1))
        ic_ir = mean_ic / std_ic if std_ic > 0 else float("nan")
        t_stat = ic_ir * np.sqrt(n) if std_ic > 0 else float("nan")
        p_val = float(2 * student_t.sf(abs(t_stat), df=n - 1)) if np.isfinite(t_stat) else float("nan")
        sk = float(skew(ic_series.to_numpy(), bias=False)) if n > 2 else 0.0
        # Non-excess kurtosis (normal == 3.0)
        kurt = float(kurtosis(ic_series.to_numpy(), fisher=False, bias=False)) if n > 3 else 3.0
    else:
        std_ic = float("nan")
        ic_ir = float("nan")

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Pass a smaller min_cross_section if a tiny universe is intended
  2. Drop all-NaN / zero-variance factor columns before the call
  3. Fix the join so factor and return data cover the same assets

Example fix

# before
ic = factor_ic_analysis(panel, rets)
# after
panel = panel.dropna(axis=1, how='all')
ic = factor_ic_analysis(panel, rets, min_cross_section=3)
Defensive patterns

Strategy: fallback

Validate before calling

valid = ((panel.notna() & rets.notna()).sum(axis=1) >= min_cross_section).any()
assert valid, 'no cross-section meets min_cross_section'

Try / catch

try:
    ic = factor_ic_analysis(panel, rets)
except ValueError as e:
    if 'valid asset pairs' in str(e):
        ic = None  # universe too small; degrade gracefully
    else:
        raise

Prevention

When it happens

Trigger: Panels with only 1-2 assets per date, all-NaN factor columns, or zero-variance factors where f_std == 0 skips every date.

Common situations: Testing with a tiny universe; factor column entirely NaN after a join; returns mostly missing so pairs never reach the threshold.

Related errors


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