HKUDS/Vibe-Trading · error · ValueError

n_groups must be >= 1, got {n_groups}

Error message

n_groups must be >= 1, got {n_groups}

What it means

compute_group_equity builds N quantile group NAV curves using qcut/cut, which reject non-positive bin counts; range(n_groups) would also be empty. n_groups < 1 is therefore rejected up front with ValueError.

Source

Thrown at agent/src/factors/factor_analysis_core.py:65

    return ic.astype(float)


def compute_group_equity(
    factor_df: pd.DataFrame, return_df: pd.DataFrame, n_groups: int
) -> pd.DataFrame:
    """Layered backtest: rank by factor value daily, hold equal-weight, compute cumulative NAV.

    Args:
        factor_df: Factor values; index=date, columns=codes.
        return_df: Returns; index=date, columns=codes.
        n_groups: Number of quantile groups.

    Returns:
        DataFrame with index=date and columns Group_1 ... Group_N holding cumulative NAV.
    """
    if n_groups < 1:
        # qcut/cut reject non-positive bins; range(n_groups) is also empty for <=0
        raise ValueError(f"n_groups must be >= 1, got {n_groups}")

    common_dates = sorted(factor_df.index.intersection(return_df.index))
    common_codes = factor_df.columns.intersection(return_df.columns)
    if len(common_dates) == 0 or len(common_codes) == 0:
        return pd.DataFrame()

    factor_df = factor_df.loc[common_dates, common_codes]
    return_df = return_df.loc[common_dates, common_codes]

    group_returns: dict[str, list[float]] = {f"Group_{i+1}": [] for i in range(n_groups)}
    valid_dates = []

    for date in common_dates:
        f = factor_df.loc[date].dropna()
        r = return_df.loc[date].dropna()
        shared = f.index.intersection(r.index)
        if len(shared) < n_groups:
            continue

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Use n_groups >= 1 (typical values 5 or 10)
  2. If 'no grouping' is desired, skip group equity computation entirely rather than passing 0
  3. Validate the config value before running analysis

Example fix

# before
compute_group_equity(f, r, n_groups=0)
# after
compute_group_equity(f, r, n_groups=5)
Defensive patterns

Strategy: validation

Validate before calling

if not isinstance(n_groups, int) or n_groups < 1: raise ValueError(f'n_groups must be >= 1, got {n_groups!r}')

Type guard

def is_valid_n_groups(v: object) -> bool:
    return isinstance(v, int) and not isinstance(v, bool) and v >= 1

Prevention

When it happens

Trigger: Calling compute_group_equity(factor, ret, n_groups=0) or a negative value, or run_factor_analysis with a bad groups config.

Common situations: Config with groups: 0 meaning 'no grouping', computed group counts that hit 0, or a UI slider defaulting to 0 before the user sets it.

Related errors


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