{"record":{"id":"3abdfcb66ff59465","repo":"microsoft/qlib","slug":"need-more-instruments-to-calculate-precision","errorCode":null,"errorMessage":"Need more instruments to calculate precision","messagePattern":"Need more instruments to calculate precision","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"qlib/contrib/eva/alpha.py","lineNumber":44,"sourceCode":"                2020-12-01 09:30:00 SH600068    0.553634\n                                    SH600195    0.550017\n                                    SH600276    0.540321\n                                    SH600584    0.517297\n                                    SH600715    0.544674\n    label :\n        label\n    date_col :\n        date_col\n\n    Returns\n    -------\n    (pd.Series, pd.Series)\n        long precision and short precision in time level\n    \"\"\"\n    if is_alpha:\n        label = label - label.groupby(level=date_col, group_keys=False).mean()\n    if int(1 / quantile) >= len(label.index.get_level_values(1).unique()):\n        raise ValueError(\"Need more instruments to calculate precision\")\n\n    df = pd.DataFrame({\"pred\": pred, \"label\": label})\n    if dropna:\n        df.dropna(inplace=True)\n\n    group = df.groupby(level=date_col, group_keys=False)\n\n    def N(x):\n        return int(len(x) * quantile)\n\n    # find the top/low quantile of prediction and treat them as long and short target\n    long = group.apply(lambda x: x.nlargest(N(x), columns=\"pred\").label)\n    short = group.apply(lambda x: x.nsmallest(N(x), columns=\"pred\").label)\n\n    groupll = long.groupby(date_col, group_keys=False)\n    l_dom = groupll.apply(lambda x: x > 0)\n    l_c = groupll.count()\n","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/contrib/eva/alpha.py#L26-L62","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Increase the number of instruments in pred/label (at least a few times 1/quantile).","Use a more extreme quantile (e.g. 0.1 or 0.05) so 1/quantile is well below the instrument count.","If you truly have few instruments, use a different metric (e.g. plain IC) instead of quantile-based long/short precision."],"exampleFix":"// before\nprec = calc_long_short_prec(pred, label, quantile=0.5)  # 2 instruments -> raises\n\n// after\nprec = calc_long_short_prec(pred, label, quantile=0.1)  # top/bottom 10% of a larger universe","handlingStrategy":"validation","validationCode":"n_inst = label.index.get_level_values(1).nunique()\nq = 0.1\nassert int(1 / q) < n_inst, f\"need > {int(1/q)} instruments, got {n_inst}\"\ncalc_long_short_prec(pred, label, quantile=q)","typeGuard":"def enough_instruments(label, quantile: float) -> bool:\n    n = label.index.get_level_values(1).nunique()\n    return int(1 / quantile) < n","tryCatchPattern":"try:\n    prec = calc_long_short_prec(pred, label, quantile=q)\nexcept ValueError as e:\n    if \"Need more instruments\" in str(e):\n        logger.warning(\"skipping precision calc: universe too small\")\n    else:\n        raise","preventionTips":["Sanity-check universe size vs 1/quantile before evaluation.","Prefer quantile <= 0.1 for small universes.","Fall back to IC-based metrics for tiny cross-sections."],"tags":["qlib","evaluation","alpha","quantile"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}