{"record":{"id":"f7d837d1e26a95bc","repo":"HKUDS/Vibe-Trading","slug":"fit-ornstein-uhlenbeck-needs-a-series-that-varies","errorCode":null,"errorMessage":"fit_ornstein_uhlenbeck needs a series that varies; this one is constant","messagePattern":"fit_ornstein_uhlenbeck needs a series that varies; this one is constant","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/quantlib/timeseries.py","lineNumber":286,"sourceCode":"\n    Raises:\n        ImportError: If ``statsmodels`` is not installed.\n        ValueError: If ``dt <= 0``, fewer than 3 valid lag pairs remain, or series is constant.\n    \"\"\"\n    if dt <= 0:\n        raise ValueError(f\"dt must be strictly positive, got {dt}\")\n\n    sm = _require(\"statsmodels.api\", \"statsmodels\", \"fit_ornstein_uhlenbeck\")\n    s = pd.Series(series, dtype=float).dropna()\n    if not np.isfinite(s.values).all():\n        raise ValueError(\"series contains non-finite values\")\n\n    lagged = s.shift(1)\n    frame = pd.concat({\"curr\": s, \"lag\": lagged}, axis=1).dropna()\n    if len(frame) < 3:\n        raise ValueError(f\"fit_ornstein_uhlenbeck needs at least 3 lag pairs, got {len(frame)}\")\n    if frame[\"lag\"].std(ddof=0) == 0:\n        raise ValueError(\"fit_ornstein_uhlenbeck needs a series that varies; this one is constant\")\n\n    exog = sm.add_constant(frame[[\"lag\"]])\n    params = _ols_params(frame[\"curr\"], exog)\n    a = float(params[0])\n    b = float(params[1])\n\n    residuals = frame[\"curr\"] - (a + b * frame[\"lag\"])\n    n = len(frame)\n    dof = max(1, n - 2)\n    sigma_eps_sq = float(np.sum(residuals**2) / dof)\n    sigma_eps = float(np.sqrt(sigma_eps_sq))\n\n    if 0.0 < b < 1.0:\n        theta = float(-np.log(b) / dt)\n        mu = float(a / (1.0 - b))\n        half_life = float(np.log(2.0) / theta)\n        one_minus_b2 = float(1.0 - b**2)\n        stat_var = float(sigma_eps_sq / one_minus_b2)","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/quantlib/timeseries.py#L268-L304","documentation":"fit_ornstein_uhlenbeck rejects input series whose lagged values have zero (ddof=0) standard deviation, i.e. a constant series. Mean-reversion estimation via OLS on lag pairs is degenerate when the regressor never varies, so the library raises instead of returning meaningless parameters.","triggerScenarios":"Calling fit_ornstein_uhlenbeck with a series of identical values (e.g. np.full(100, 42.0)), or data that becomes constant after dropna of the lag frame (first N-1 values equal).","commonSituations":"Feeding prices from illiquid assets pinned at a fix, dummy/placeholder data in tests, or a mis-scaled series that rounds to a single value.","solutions":["Check the series varies before calling: s.std(ddof=0) > 0","Inspect upstream data ingestion for a stuck feed or repeated fill-forward values","If constant data is legitimate, skip the OU fit or handle it as zero-volatility case"],"exampleFix":"# before\nres = fit_ornstein_uhlenbeck(pd.Series([5.0] * 100))\n# after\nif s.std(ddof=0) == 0:\n    raise ValueError(\"series is constant; cannot fit OU\")\nres = fit_ornstein_uhlenbeck(s)","handlingStrategy":"validation","validationCode":"s = pd.Series(data, dtype=float).dropna()\nif len(s) < 4 or s.shift(1).std(ddof=0) == 0:\n    raise ValueError('series must vary and have >= 3 lag pairs')","typeGuard":"def is_fittable_ou(s: pd.Series) -> bool:\n    s = s.dropna()\n    return len(s) >= 4 and s.shift(1).dropna().std(ddof=0) > 0","tryCatchPattern":"try:\n    fit_ornstein_uhlenbeck(s)\nexcept ValueError as e:\n    if 'series that varies' in str(e):\n        logger.warning('constant series; skipping OU fit: %s', e)\n    else:\n        raise","preventionTips":["Validate std(ddof=0) > 0 on the series and its lag before calling","Log series statistics before fitting in batch pipelines","Never feed fill-forward or placeholder data to mean-reversion estimators"],"tags":["python","pandas","validation","constant-series","mean-reversion"],"backgroundTag":"degenerate-input-validation","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}