HKUDS/Vibe-Trading · error · ValueError
find_hedge_ratio needs at least 3 aligned observations, got
Error message
find_hedge_ratio needs at least 3 aligned observations, got {len(frame)} What it means
After aligning y and x and dropping NaN rows, fewer than 3 complete observations remain — not enough to fit the two-parameter OLS hedge regression. The library enforces a minimum sample size rather than emitting an unstable beta.
Source
Thrown at agent/src/quantlib/timeseries.py:362
``spread_mean`` (float), ``spread_std`` (float, sample ddof=1) and
``half_life`` (float, in observation periods).
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``.View on GitHub (pinned to 80ffdda44c)
Solutions
- Check the aligned, NaN-dropped overlap length before calling
- Extend the shared date range of the two inputs
- Drop or impute NaNs upstream so more complete pairs survive
Example fix
# before
ratio = find_hedge_ratio(y_short, x_short)
# after
frame = pd.concat({'y': y, 'x': x}, axis=1).dropna()
assert len(frame) >= 3, f"only {len(frame)} aligned observations"
ratio = find_hedge_ratio(y, x) Defensive patterns
Strategy: validation
Validate before calling
frame = pd.concat({'y': pd.Series(y, dtype=float), 'x': pd.Series(x, dtype=float)}, axis=1).dropna()
if len(frame) < 3:
raise ValueError(f'insufficient overlap: {len(frame)} rows') Type guard
def has_enough_overlap(y, x, minimum: int = 3) -> bool:
frame = pd.concat({'y': pd.Series(y, dtype=float), 'x': pd.Series(x, dtype=float)}, axis=1)
return len(frame.dropna()) >= minimum Try / catch
try:
find_hedge_ratio(y, x)
except ValueError as e:
if 'at least 3 aligned' in str(e):
# widen date range or fetch more data
raise
raise Prevention
- Check aligned row count before regressing
- Use at least 60+ overlapping observations for stable hedge ratios
- Drop NaNs upstream and assert the resulting length
When it happens
Trigger: Passing very short series (<3 points), series whose overlap after index alignment is under 3 rows, or series with many NaNs that leave <3 complete pairs after dropna.
Common situations: Mismatched date ranges where only 1-2 dates overlap, series with heavy missing data, or unit tests built from tiny hand-made arrays.
Related errors
- label_end_times is empty
- fit_ornstein_uhlenbeck needs a series that varies; this one
- find_hedge_ratio needs y and x sharing one index
- find_hedge_ratio needs an x that varies; this one is constan
- granger_test: column(s) not in data: {missing}
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/817b5769d37affdc.
Report an issue: GitHub.