HKUDS/Vibe-Trading · error · ValueError

ts_corr window must be >= 2, got {n}

Error message

ts_corr window must be >= 2, got {n}

What it means

ts_corr requires a window of at least 2 observations because Pearson correlation is undefined for a single point; n < 2 raises immediately. min_periods=n means the first n-1 rows return NaN (warmup), and constant series in the window yield NaN rather than a silent zero.

Source

Thrown at agent/src/factors/base.py:154

    rank_avg = less + 0.5 * (eq + 1)
    with np.errstate(divide="ignore", invalid="ignore"):
        pct = rank_avg / valid_count
    # min_periods=n: any NaN in window → NaN output
    pct[nan_last | (nan_count > 0)] = np.nan

    result = np.full((T, C), np.nan)
    result[n - 1 :] = pct
    return pd.DataFrame(result, index=df.index, columns=df.columns)


def ts_corr(x: pd.DataFrame, y: pd.DataFrame, n: int) -> pd.DataFrame:
    """Rolling Pearson correlation per column, min_periods=n.

    Constant series in the window → NaN (no silent zero). Pairs are inner-joined
    on columns; columns missing from either side become NaN.
    """
    if n < 2:
        raise ValueError(f"ts_corr window must be >= 2, got {n}")
    x = _as_float(x)
    y = _as_float(y)
    cols = x.columns.union(y.columns)
    xa = x.reindex(columns=cols)
    ya = y.reindex(columns=cols)
    corr = xa.rolling(window=n, min_periods=n).corr(ya)
    # corr above can produce +/- inf when one series is constant in some
    # pandas versions; force to NaN.
    return corr.replace([np.inf, -np.inf], np.nan)


def ts_cov(x: pd.DataFrame, y: pd.DataFrame, n: int) -> pd.DataFrame:
    """Rolling sample covariance per column, min_periods=n."""
    if n < 2:
        raise ValueError(f"ts_cov window must be >= 2, got {n}")
    x = _as_float(x)
    y = _as_float(y)
    cols = x.columns.union(y.columns)

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Pass n >= 2
  2. When auto-scaling windows to data length, enforce a floor of 2 and skip/raise on shorter series
  3. Validate factor configs once at startup rather than per call

Example fix

# before
corr = ts_corr(x, y, n=1)

# after
corr = ts_corr(x, y, n=20)
Defensive patterns

Strategy: validation

Validate before calling

if not isinstance(n, int) or n < 2:
    raise ValueError(f'invalid ts_corr window: {n!r}')
corr = ts_corr(x, y, n)

Type guard

def is_valid_ts_corr_window(n) -> bool:
    return isinstance(n, int) and n >= 2

Prevention

When it happens

Trigger: ts_corr(x, y, 1), ts_corr(x, y, 0), or a negative n. Windows are often computed relative to series length and can collapse to 1 on short inputs. Called by compute() and in tests.

Common situations: Short data slices (fewer rows than the intended window) leading to auto-scaled n=1; config typos; reusing a window tuned for ts_mean (min 1) with ts_corr (min 2).

Related errors


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