HKUDS/Vibe-Trading · error · ValueError

find_hedge_ratio needs an x that varies; this one is constan

Error message

find_hedge_ratio needs an x that varies; this one is constant

What it means

find_hedge_ratio requires the regressor x to have nonzero standard deviation; a constant x makes the OLS design matrix rank-deficient (the constant column and x collapse), so the beta lookup would fail with a bare IndexError. The library raises a descriptive error instead.

Source

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

    Raises:
        ImportError: If ``statsmodels`` is not installed.
        ValueError: If the series differ in length, carry different indices,
            fewer than 3 aligned non-NaN observations remain, or ``x`` is
            constant. A flat hedging leg is refused rather than fitted:
            ``sm.add_constant`` leaves an already-constant column alone, so the
            design would silently collapse to one column and the β lookup would
            be a bare ``IndexError``.
    """
    sm = _require("statsmodels.api", "statsmodels", "find_hedge_ratio")
    frame = pd.concat({"y": pd.Series(y, dtype=float), "x": pd.Series(x, dtype=float)}, axis=1)
    if len(frame) != len(pd.Series(y)) or len(frame) != len(pd.Series(x)):
        raise ValueError("find_hedge_ratio needs y and x sharing one index")
    frame = frame.dropna()
    if len(frame) < 3:
        raise ValueError(f"find_hedge_ratio needs at least 3 aligned observations, got {len(frame)}")
    if frame["x"].std(ddof=0) == 0:
        raise ValueError("find_hedge_ratio needs an x that varies; this one is constant")

    params = _ols_params(frame["y"], sm.add_constant(frame[["x"]]))
    intercept, beta = float(params[0]), float(params[1])
    spread = frame["y"] - beta * frame["x"]

    return {
        "hedge_ratio": beta,
        "intercept": intercept,
        "spread_mean": float(spread.mean()),
        "spread_std": float(spread.std()),
        "half_life": compute_half_life(spread),
    }


def granger_test(data: pd.DataFrame, x_col: str, y_col: str, max_lag: int = 5) -> dict:
    """Test whether ``x`` Granger-causes ``y``.

    Granger causality is predictive, not structural: it asks only whether past

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Verify x.std(ddof=0) > 0 before the call
  2. Check data ingestion for stuck/flat feeds
  3. If x is genuinely constant, hedging is undefined — handle as a special case rather than regressing

Example fix

# before
ratio = find_hedge_ratio(y, pd.Series([100.0] * 50))
# after
if x.std(ddof=0) == 0:
    raise ValueError("x is constant; hedge ratio undefined")
ratio = find_hedge_ratio(y, x)
Defensive patterns

Strategy: validation

Validate before calling

x = pd.Series(x, dtype=float)
if x.std(ddof=0) == 0:
    raise ValueError('x is constant; hedge ratio undefined')

Type guard

def regressor_varies(x) -> bool:
    return pd.Series(x, dtype=float).std(ddof=0) > 0

Try / catch

try:
    find_hedge_ratio(y, x)
except ValueError as e:
    if 'x that varies' in str(e):
        # constant x: hedging undefined, handle specially
        return None
    raise

Prevention

When it happens

Trigger: Passing an x series of identical values, or one that becomes constant after alignment and dropna (e.g. only 3 points all equal).

Common situations: Placeholder/fill-forward data, a pegged currency or pinned price feed, or accidentally passing a repeated scalar as x.

Related errors


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