{"record":{"id":"4aeb60a88dc9ef72","repo":"HKUDS/Vibe-Trading","slug":"n-regimes-must-be-at-least-2-got-n-regimes","errorCode":null,"errorMessage":"n_regimes must be at least 2, got {n_regimes}","messagePattern":"n_regimes must be at least 2, got (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/quantlib/timeseries.py","lineNumber":546,"sourceCode":"        ``expected_durations`` (numpy array, ``1 / (1 - p_ii)`` in periods),\n        ``smoothed_probabilities`` (DataFrame on the input index, one column per\n        regime), ``current_regime`` (int) and ``current_regime_probability``\n        (float) for the last observation, ``converged`` (bool), and ``llf``,\n        ``aic``, ``bic`` (float).\n\n    Raises:\n        ImportError: If ``statsmodels`` is not installed.\n        ValueError: If ``n_regimes`` is below 2, or fewer than 50 finite\n            observations survive -- an EM fit on a shorter series produces\n            regimes that are numerically fine and substantively meaningless.\n    \"\"\"\n    markov = _require(\n        \"statsmodels.tsa.regime_switching.markov_regression\",\n        \"statsmodels\",\n        \"fit_markov_regime\",\n    )\n    if n_regimes < 2:\n        raise ValueError(f\"n_regimes must be at least 2, got {n_regimes}\")\n\n    series = pd.Series(returns, dtype=float).dropna()\n    if series.size < 50:\n        raise ValueError(\n            f\"fit_markov_regime needs at least 50 finite observations, got {series.size}\"\n        )\n\n    # Passed as a Series, not an array: statsmodels only names the fitted\n    # parameters (``const[k]``, ``sigma2[k]``) when the input is pandas, and\n    # positional unpacking of that vector would silently break if the package\n    # ever reorders it.\n    model = markov.MarkovRegression(\n        series * 100,\n        k_regimes=n_regimes,\n        trend=\"c\",\n        switching_variance=switching_variance,\n    )\n    with contextlib.redirect_stdout(io.StringIO()), contextlib.redirect_stderr(io.StringIO()):","sourceCodeStart":528,"sourceCodeEnd":564,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/quantlib/timeseries.py#L528-L564","documentation":"fit_markov_regime requires n_regimes >= 2; a Markov-switching model with one regime is just a constant-variance model and statsmodels' MarkovRegression cannot fit it, so the library rejects it early.","triggerScenarios":"Calling fit_markov_regime(returns, n_regimes=1) or 0, often from a loop over [1,2,3] regime counts or a config value of 1.","commonSituations":"Model-selection loops that start at 1 regime, config typos, or BIC-driven selection that picks 1 before the guard.","solutions":["Use n_regimes >= 2 (2 or 3 is typical for calm/turbulent markets)","Start model-selection loops at 2","Validate config: assert n_regimes >= 2"],"exampleFix":"# before\nfor k in range(1, 5):\n    res = fit_markov_regime(returns, n_regimes=k)\n# after\nfor k in range(2, 5):\n    res = fit_markov_regime(returns, n_regimes=k)","handlingStrategy":"validation","validationCode":"assert n_regimes >= 2, 'Markov regime models need at least 2 regimes'","typeGuard":"def valid_regime_count(k: int) -> bool:\n    return isinstance(k, int) and k >= 2","tryCatchPattern":"try:\n    fit_markov_regime(returns, n_regimes=k)\nexcept ValueError as e:\n    if 'at least 2' in str(e):\n        continue  # skip k=1 in selection loops\n    raise","preventionTips":["Start regime-selection loops at 2","Validate model config before fitting","Remember k=1 is just a constant-variance model — use simpler tools"],"tags":["python","markov-switching","regime-models","parameter-validation"],"backgroundTag":"invalid-argument-range","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}