HKUDS/Vibe-Trading · error · TypeError

index_levels must be a pandas Series of index levels indexed

Error message

index_levels must be a pandas Series of index levels indexed by date, got {type(index_levels).__name__}

What it means

PME functions (ks_pme, pme_plus, direct_alpha) normalize the benchmark via _index_levels_by_date, which requires a pandas.Series indexed by date. Any other type (DataFrame, list, dict, ndarray) is rejected with a TypeError.

Source

Thrown at agent/src/quantlib/fundmath.py:1364

    Args:
        index_levels: Public-market index levels, a ``pandas.Series`` whose
            index is date-like (``DatetimeIndex``, or labels accepted by
            :func:`~src.entities.models.normalize_date`) and whose values are
            the index's level on each date (a price or a total-return index
            value, not a return).

    Returns:
        Mapping from ``datetime.date`` to the index level on that date.

    Raises:
        TypeError: If ``index_levels`` is not a ``pandas.Series``.
        ValueError: If it is empty, a level is not finite and positive, or two
            entries normalize to the same date (an ambiguous lookup, refused
            rather than guessed at by taking the first or last).
    """
    if not isinstance(index_levels, pd.Series):
        raise TypeError(
            "index_levels must be a pandas Series of index levels indexed by "
            f"date, got {type(index_levels).__name__}"
        )
    if index_levels.empty:
        raise ValueError(
            "index_levels is empty; a public market equivalent needs a "
            "benchmark to compare against"
        )
    lookup: dict[_dt.date, float] = {}
    for raw_date, raw_level in index_levels.items():
        day = normalize_date(raw_date, field_name="index_levels date")
        if day in lookup:
            raise ValueError(
                f"index_levels has more than one entry for {day}; resolve the "
                "duplicate before calling, rather than have this function "
                "guess which one is authoritative"
            )
        level = float(raw_level)

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Convert to a Series first: pd.Series(levels, index=pd.to_datetime(dates)) or df['level']
  2. Use pd.read_csv(..., index_col=0, parse_dates=True)['close'] so you get a Series
  3. Check type(index_levels) is pd.Series before the call

Example fix

# before
ks_pme(series, index_levels={d: lvl for d, lvl in rows})

# after
import pandas as pd
levels = pd.Series([lvl for _, lvl in rows], index=pd.to_datetime([d for d, _ in rows]))
ks_pme(series, index_levels=levels)
Defensive patterns

Strategy: type-guard

Validate before calling

assert isinstance(index_levels, pd.Series), type(index_levels)

Type guard

def is_date_indexed_series(x) -> bool:
    return isinstance(x, pd.Series) and isinstance(x.index, pd.DatetimeIndex)

Prevention

When it happens

Trigger: Calling ks_pme(series, index_levels=[[date, level]]) or passing a DataFrame, dict {date: level}, or plain list of levels.

Common situations: Loading a benchmark CSV with pd.read_csv and forgetting to squeeze/select the single column; building levels as a list from an API response; passing a DataFrame column slice which yields a DataFrame on older pandas.

Understand the failure class

Background: "Wrong argument type", "must be a string", "expected Array or Prism::Scope": TypeError and ArgumentError when a library receives a value of the wrong type — this error's family across 28 libraries.

Related errors


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