{"record":{"id":"2d44ac3ad823745e","repo":"HKUDS/Vibe-Trading","slug":"ts-corr-window-must-be-2-got-n","errorCode":null,"errorMessage":"ts_corr window must be >= 2, got {n}","messagePattern":"ts_corr window must be >= 2, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/factors/base.py","lineNumber":154,"sourceCode":"    rank_avg = less + 0.5 * (eq + 1)\n    with np.errstate(divide=\"ignore\", invalid=\"ignore\"):\n        pct = rank_avg / valid_count\n    # min_periods=n: any NaN in window → NaN output\n    pct[nan_last | (nan_count > 0)] = np.nan\n\n    result = np.full((T, C), np.nan)\n    result[n - 1 :] = pct\n    return pd.DataFrame(result, index=df.index, columns=df.columns)\n\n\ndef ts_corr(x: pd.DataFrame, y: pd.DataFrame, n: int) -> pd.DataFrame:\n    \"\"\"Rolling Pearson correlation per column, min_periods=n.\n\n    Constant series in the window → NaN (no silent zero). Pairs are inner-joined\n    on columns; columns missing from either side become NaN.\n    \"\"\"\n    if n < 2:\n        raise ValueError(f\"ts_corr window must be >= 2, got {n}\")\n    x = _as_float(x)\n    y = _as_float(y)\n    cols = x.columns.union(y.columns)\n    xa = x.reindex(columns=cols)\n    ya = y.reindex(columns=cols)\n    corr = xa.rolling(window=n, min_periods=n).corr(ya)\n    # corr above can produce +/- inf when one series is constant in some\n    # pandas versions; force to NaN.\n    return corr.replace([np.inf, -np.inf], np.nan)\n\n\ndef ts_cov(x: pd.DataFrame, y: pd.DataFrame, n: int) -> pd.DataFrame:\n    \"\"\"Rolling sample covariance per column, min_periods=n.\"\"\"\n    if n < 2:\n        raise ValueError(f\"ts_cov window must be >= 2, got {n}\")\n    x = _as_float(x)\n    y = _as_float(y)\n    cols = x.columns.union(y.columns)","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/factors/base.py#L136-L172","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Pass n >= 2","When auto-scaling windows to data length, enforce a floor of 2 and skip/raise on shorter series","Validate factor configs once at startup rather than per call"],"exampleFix":"# before\ncorr = ts_corr(x, y, n=1)\n\n# after\ncorr = ts_corr(x, y, n=20)","handlingStrategy":"validation","validationCode":"if not isinstance(n, int) or n < 2:\n    raise ValueError(f'invalid ts_corr window: {n!r}')\ncorr = ts_corr(x, y, n)","typeGuard":"def is_valid_ts_corr_window(n) -> bool:\n    return isinstance(n, int) and n >= 2","tryCatchPattern":null,"preventionTips":["Remember correlation needs n>=2, stricter than mean/rank operators","Skip windows larger than len(df)-1 rather than shrinking below 2","Validate per-operator minimums in config"],"tags":["python","factors","rolling-window","correlation","parameter-validation"],"backgroundTag":"rolling-window-invalid","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}