microsoft/qlib · error · ValueError

No enough data for calculating IC

Error message

No enough data for calculating IC

What it means

ICLoss.forward slices predictions/labels per day (via index boundaries in idx) and skips days with fewer than skip_size samples or zero std. If every day is skipped, the count of usable days (len(diff_point)-1-skip_n) is <= 0 and it raises ValueError. Note: the raise is preceded by __import__('ipdb').set_trace(), a leftover debug breakpoint that will first hang or crash in non-interactive environments where ipdb is not installed.

Source

Thrown at qlib/contrib/meta/data_selection/utils.py:58

            if pred_focus.shape[0] < self.skip_size:
                # skip some days which have very small amount of stock.
                skip_n += 1
                continue
            y_focus = y[start_i:end_i]
            if pred_focus.std() < EPS or y_focus.std() < EPS:
                # These cases often happend at the end of test data.
                # Usually caused by fillna(0.)
                skip_n += 1
                continue

            ic_day = torch.dot(
                (pred_focus - pred_focus.mean()) / np.sqrt(pred_focus.shape[0]) / pred_focus.std(),
                (y_focus - y_focus.mean()) / np.sqrt(y_focus.shape[0]) / y_focus.std(),
            )
            ic_all += ic_day
        if len(diff_point) - 1 - skip_n <= 0:
            __import__("ipdb").set_trace()
            raise ValueError("No enough data for calculating IC")
        if skip_n > 0:
            get_module_logger("ICLoss").info(
                f"{skip_n} days are skipped due to zero std or small scale of valid samples."
            )
        ic_mean = ic_all / (len(diff_point) - 1 - skip_n)
        return -ic_mean  # ic loss


def preds_to_weight_with_clamp(preds, clip_weight=None, clip_method="tanh"):
    """
    Clip the weights.

    Parameters
    ----------
    clip_weight: float
        The clip threshold.
    clip_method: str
        The clip method. Current available: "clamp", "tanh", and "sigmoid".

View on GitHub (pinned to 79633dd950)

Solutions

  1. Ensure the test data passed to ICLoss has >= skip_size (default 50) valid instruments per date.
  2. Trim the tail of the test data where labels were filled with 0.0 (zero std days are skipped).
  3. Lower ICLoss(skip_size=...) if a smaller cross-section is expected.
  4. Install ipdb if you must reproduce interactively; in production, patch out the set_trace() line or pin a qlib version where it is removed — otherwise the debugger hook fires before the ValueError.

Example fix

// before
criterion = ICLoss()  # default skip_size=50; test set has 20 stocks/day -> raises
loss = criterion(pred, y_test, test_idx)

// after
criterion = ICLoss(skip_size=10)
loss = criterion(pred, y_test, test_idx)
Defensive patterns

Strategy: validation

Validate before calling

import collections
day_counts = collections.Counter(idx.get_level_values(0))
usable = [d for d, n in day_counts.items() if n >= skip_size]
assert usable, "no day has >= skip_size instruments; ICLoss would raise"
loss = criterion(pred, y, idx)

Try / catch

try:
    loss = criterion(pred, y_test, test_idx)
except ValueError as e:
    if "No enough data" in str(e):
        continue  # MetaModelDS already catches this per-batch; mirror that pattern
    raise

Prevention

When it happens

Trigger: Calling ICLoss (via MetaModelDS with criterion='ic_loss') on a test set with very few stocks per day (< skip_size=50), or where predictions/labels are constant per day (e.g. after fillna(0.0) at the tail of the data), so all days get skipped.

Common situations: Tiny test universes or single-stock tests; label windows running past data end so trailing rows are zero-filled; running headless (CI, docker, scheduled jobs) where the ipdb.set_trace() itself fails with ImportError or blocks forever.

Related errors


AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15). Data as JSON: /api/errors/386308a9da02d2fb. Report an issue: GitHub.