{"record":{"id":"9993d2ca6cd048dd","repo":"HKUDS/Vibe-Trading","slug":"fit-garch-needs-horizon-1-got-horizon","errorCode":null,"errorMessage":"fit_garch needs horizon >= 1, got {horizon}","messagePattern":"fit_garch needs horizon >= 1, got (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/quantlib/timeseries.py","lineNumber":448,"sourceCode":"        returns: Daily return series as *fractions* (0.01 = 1%). Scaled to\n            percent internally, which is what ``arch`` optimises well on.\n        horizon: Number of days ahead to forecast.\n\n    Returns:\n        Dict with keys ``omega``, ``alpha``, ``beta``, ``persistence``,\n        ``long_run_vol``, ``current_vol`` (all float, volatilities as daily\n        fractions), ``forecast_vol`` (numpy array of length ``horizon``, daily\n        fractions), ``horizon`` (int), ``aic`` and ``bic`` (float).\n        ``long_run_vol`` is ``nan`` when persistence >= 1 (no finite\n        unconditional variance).\n\n    Raises:\n        ImportError: If ``arch`` is not installed.\n        ValueError: If ``horizon`` is below 1.\n    \"\"\"\n    arch_mod = _require(\"arch\", \"arch\", \"fit_garch\")\n    if horizon < 1:\n        raise ValueError(f\"fit_garch needs horizon >= 1, got {horizon}\")\n\n    model = arch_mod.arch_model(\n        pd.Series(returns, dtype=float).dropna() * 100,\n        vol=\"Garch\",\n        p=1,\n        q=1,\n        mean=\"Constant\",\n        dist=\"normal\",\n    )\n    result = model.fit(disp=\"off\")\n\n    omega = float(result.params[\"omega\"])\n    alpha = float(result.params[\"alpha[1]\"])\n    beta = float(result.params[\"beta[1]\"])\n    persistence = alpha + beta\n\n    # `conditional_volatility` is already a standard deviation (in percent);\n    # the skill's markdown took sqrt of it again, which is dimensionally wrong.","sourceCodeStart":430,"sourceCodeEnd":466,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/quantlib/timeseries.py#L430-L466","documentation":"fit_garch requires horizon >= 1; a horizon of 0 or negative asks for zero forecast steps, which the arch library cannot produce.","triggerScenarios":"Calling fit_garch(returns, horizon=0) or a negative value, typically from a computed horizon (e.g. days_to_expiry that underflowed) or a config default of 0.","commonSituations":"Risk pipelines deriving horizon from calendar math that returns 0 on same-day expiry, or misconfigured YAML/JSON parameters.","solutions":["Clamp: horizon = max(1, horizon)","Validate the scheduling/calc math producing the horizon","Default to 1 (next-step volatility forecast) when the computed value is 0"],"exampleFix":"# before\nfc = fit_garch(returns, horizon=days_left)\n# after\nfc = fit_garch(returns, horizon=max(1, days_left))","handlingStrategy":"validation","validationCode":"horizon = max(1, int(horizon))","typeGuard":"def valid_horizon(h: int) -> bool:\n    return isinstance(h, int) and h >= 1","tryCatchPattern":"try:\n    fit_garch(returns, horizon=horizon)\nexcept ValueError as e:\n    if 'horizon >= 1' in str(e):\n        return fit_garch(returns, horizon=1)\n    raise","preventionTips":["Clamp calendar-derived horizons with max(1, value)","Validate config keys for horizon at startup","Unit-test boundary values 0 and 1"],"tags":["python","garch","volatility","parameter-validation"],"backgroundTag":"invalid-argument-range","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}