HKUDS/Vibe-Trading · error · RuntimeError

csi300: no symbol survived corporate-action adjustment — pro

Error message

csi300: no symbol survived corporate-action adjustment — pro.adj_factor returned nothing usable for any of the {len(codes)} names, which usually means the Tushare token lacks adj_factor permission. Benching on unadjusted prices is not an alternative: an ex-date injects a fabricated cross-sectional return, measured at -47.2% on 300750.SZ 2023-04-26.

What it means

Every csi300 name whose pro.adj_factor call yielded nothing usable is dropped rather than benched on raw prices (an ex-date would inject a fabricated cross-sectional return, measured at -47.2% on 300750.SZ 2023-04-26). If NO symbol survives, this RuntimeError names the most common cause: the Tushare token lacks adj_factor permission.

Source

Thrown at agent/src/tools/alpha_bench_tool.py:410

        return code, _apply_qfq(df, factor)

    fetched: dict[str, pd.DataFrame] = {}
    with ThreadPoolExecutor(max_workers=_CSI300_FETCH_WORKERS) as pool:
        futures = [pool.submit(_fetch_one, code) for code in codes]
        for fut in as_completed(futures):
            try:
                code, frame = fut.result()
            except Exception as exc:  # noqa: BLE001 — _retry already logged
                logger.warning("csi300 fetch worker raised: %s", exc)
                continue
            if frame is not None and not frame.empty:
                fetched[code] = frame

    # A name with no usable adjustment factors is dropped rather than benched on
    # raw prices, so the drop has to be visible or it becomes its own silent bias.
    dropped = sorted(set(codes) - set(fetched))
    if not fetched:
        raise RuntimeError(
            "csi300: no symbol survived corporate-action adjustment — "
            "pro.adj_factor returned nothing usable for any of the "
            f"{len(codes)} names, which usually means the Tushare token lacks "
            "adj_factor permission. Benching on unadjusted prices is not an "
            "alternative: an ex-date injects a fabricated cross-sectional "
            "return, measured at -47.2% on 300750.SZ 2023-04-26."
        )
    if dropped:
        logger.warning(
            "csi300: dropped %d/%d name(s) with no usable adjustment factors: %s",
            len(dropped),
            len(codes),
            ", ".join(dropped[:10]) + ("..." if len(dropped) > 10 else ""),
        )

    panel = _wide_from_fetched(fetched, include_amount=True)
    # CN equity vwap: Tushare ``amount`` is in 千元, ``volume`` in 手. True VWAP
    # = (amount * 1000 CNY) / (volume * 100 shares). Matches

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Upgrade the Tushare account/points so adj_factor is permitted, then retry
  2. If failures are rate-limit related, add backoff between per-symbol calls or reduce the universe window and retry
  3. Check dropped symbols logging — partial drops are visible; only total loss raises
  4. Never work around by benching unadjusted prices; the bias is documented and large
Defensive patterns

Strategy: fallback

Validate before calling

# preflight: token can fetch adj_factor for one symbol
probe = pro.adj_factor(ts_code='000001.SZ', start_date=sd, end_date=ed)
assert probe is not None and not probe.empty

Try / catch

try:
    panel = _load_csi300_panel(s, e)
except RuntimeError as e:
    if 'adj_factor permission' in str(e):
        notify_user_to_upgrade_tushare_points()

Prevention

When it happens

Trigger: Calling csi300 loading with a token tier that cannot call pro.adj_factor; a network condition where all per-symbol adj_factor fetches fail; API quota exhausted across all requests.

Common situations: Free/low-point Tushare accounts without adj_factor access; rate-limit exhaustion (Tushare points-based limits); intermittent network dropping every fetch.

Related errors


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