microsoft/qlib · error · ValueError

Need more instruments to calculate precision

Error message

Need more instruments to calculate precision

What it means

Raised by qlib.contrib.eva.alpha.calc_long_short_prec when the quantile is so coarse that the top/bottom bucket would cover every instrument. The check int(1/quantile) >= number of unique instruments (level 1 of the index) means each quantile bucket needs multiple instruments to be meaningful for long/short precision.

Source

Thrown at qlib/contrib/eva/alpha.py:44

                2020-12-01 09:30:00 SH600068    0.553634
                                    SH600195    0.550017
                                    SH600276    0.540321
                                    SH600584    0.517297
                                    SH600715    0.544674
    label :
        label
    date_col :
        date_col

    Returns
    -------
    (pd.Series, pd.Series)
        long precision and short precision in time level
    """
    if is_alpha:
        label = label - label.groupby(level=date_col, group_keys=False).mean()
    if int(1 / quantile) >= len(label.index.get_level_values(1).unique()):
        raise ValueError("Need more instruments to calculate precision")

    df = pd.DataFrame({"pred": pred, "label": label})
    if dropna:
        df.dropna(inplace=True)

    group = df.groupby(level=date_col, group_keys=False)

    def N(x):
        return int(len(x) * quantile)

    # find the top/low quantile of prediction and treat them as long and short target
    long = group.apply(lambda x: x.nlargest(N(x), columns="pred").label)
    short = group.apply(lambda x: x.nsmallest(N(x), columns="pred").label)

    groupll = long.groupby(date_col, group_keys=False)
    l_dom = groupll.apply(lambda x: x > 0)
    l_c = groupll.count()

View on GitHub (pinned to 79633dd950)

Solutions

  1. Increase the number of instruments in pred/label (at least a few times 1/quantile).
  2. Use a more extreme quantile (e.g. 0.1 or 0.05) so 1/quantile is well below the instrument count.
  3. If you truly have few instruments, use a different metric (e.g. plain IC) instead of quantile-based long/short precision.

Example fix

// before
prec = calc_long_short_prec(pred, label, quantile=0.5)  # 2 instruments -> raises

// after
prec = calc_long_short_prec(pred, label, quantile=0.1)  # top/bottom 10% of a larger universe
Defensive patterns

Strategy: validation

Validate before calling

n_inst = label.index.get_level_values(1).nunique()
q = 0.1
assert int(1 / q) < n_inst, f"need > {int(1/q)} instruments, got {n_inst}"
calc_long_short_prec(pred, label, quantile=q)

Type guard

def enough_instruments(label, quantile: float) -> bool:
    n = label.index.get_level_values(1).nunique()
    return int(1 / quantile) < n

Try / catch

try:
    prec = calc_long_short_prec(pred, label, quantile=q)
except ValueError as e:
    if "Need more instruments" in str(e):
        logger.warning("skipping precision calc: universe too small")
    else:
        raise

Prevention

When it happens

Trigger: Calling calc_long_short_prec(pred, label, quantile=q) where 1/q rounded down is at least the number of unique instruments in the label's datetime level, e.g. quantile=0.5 with 2 instruments, or quantile=0.2 with 5 instruments.

Common situations: Evaluating predictions on a tiny universe (a handful of stocks) or a single day slice; using quantile=0.5 (long/short split) with small instrument pools; forgetting that the check counts unique instruments per level, not total rows.

Related errors


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