HKUDS/Vibe-Trading · error · ValueError

fit_garch needs horizon >= 1, got {horizon}

Error message

fit_garch needs horizon >= 1, got {horizon}

What it means

fit_garch requires horizon >= 1; a horizon of 0 or negative asks for zero forecast steps, which the arch library cannot produce.

Source

Thrown at agent/src/quantlib/timeseries.py:448

        returns: Daily return series as *fractions* (0.01 = 1%). Scaled to
            percent internally, which is what ``arch`` optimises well on.
        horizon: Number of days ahead to forecast.

    Returns:
        Dict with keys ``omega``, ``alpha``, ``beta``, ``persistence``,
        ``long_run_vol``, ``current_vol`` (all float, volatilities as daily
        fractions), ``forecast_vol`` (numpy array of length ``horizon``, daily
        fractions), ``horizon`` (int), ``aic`` and ``bic`` (float).
        ``long_run_vol`` is ``nan`` when persistence >= 1 (no finite
        unconditional variance).

    Raises:
        ImportError: If ``arch`` is not installed.
        ValueError: If ``horizon`` is below 1.
    """
    arch_mod = _require("arch", "arch", "fit_garch")
    if horizon < 1:
        raise ValueError(f"fit_garch needs horizon >= 1, got {horizon}")

    model = arch_mod.arch_model(
        pd.Series(returns, dtype=float).dropna() * 100,
        vol="Garch",
        p=1,
        q=1,
        mean="Constant",
        dist="normal",
    )
    result = model.fit(disp="off")

    omega = float(result.params["omega"])
    alpha = float(result.params["alpha[1]"])
    beta = float(result.params["beta[1]"])
    persistence = alpha + beta

    # `conditional_volatility` is already a standard deviation (in percent);
    # the skill's markdown took sqrt of it again, which is dimensionally wrong.

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Clamp: horizon = max(1, horizon)
  2. Validate the scheduling/calc math producing the horizon
  3. Default to 1 (next-step volatility forecast) when the computed value is 0

Example fix

# before
fc = fit_garch(returns, horizon=days_left)
# after
fc = fit_garch(returns, horizon=max(1, days_left))
Defensive patterns

Strategy: validation

Validate before calling

horizon = max(1, int(horizon))

Type guard

def valid_horizon(h: int) -> bool:
    return isinstance(h, int) and h >= 1

Try / catch

try:
    fit_garch(returns, horizon=horizon)
except ValueError as e:
    if 'horizon >= 1' in str(e):
        return fit_garch(returns, horizon=1)
    raise

Prevention

When it happens

Trigger: 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.

Common situations: Risk pipelines deriving horizon from calendar math that returns 0 on same-day expiry, or misconfigured YAML/JSON parameters.

Related errors


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