HKUDS/Vibe-Trading · error · KeyError
granger_test: column(s) not in data: {missing}
Error message
granger_test: column(s) not in data: {missing} What it means
granger_test raises KeyError listing the requested columns missing from the input DataFrame, because statsmodels would fail cryptically when selecting data[[y_col, x_col]] with unknown names.
Source
Thrown at agent/src/quantlib/timeseries.py:414
Raises:
ImportError: If ``statsmodels`` is not installed.
KeyError: If either column is missing from ``data``.
ValueError: If ``max_lag`` is below 1, or if ``x_col`` and ``y_col`` are
the same column. Testing a series against itself hands statsmodels a
duplicated column, where the F-test trivially fails to reject and
every p-value comes back 1.0 -- an answer that looks like a finding.
"""
if x_col == y_col:
raise ValueError(
f"x_col and y_col must differ; both are {x_col!r}. A series cannot "
"Granger-cause itself and the test returns p=1.0 regardless."
)
stattools = _require("statsmodels.tsa.stattools", "statsmodels", "granger_test")
if max_lag < 1:
raise ValueError(f"granger_test needs max_lag >= 1, got {max_lag}")
missing = [c for c in (y_col, x_col) if c not in data.columns]
if missing:
raise KeyError(f"granger_test: column(s) not in data: {missing}")
# statsmodels >= 0.14 dropped the `verbose` kwarg and prints the full test
# table to stdout unconditionally; swallow it so a library call stays quiet.
with contextlib.redirect_stdout(io.StringIO()):
results = stattools.grangercausalitytests(data[[y_col, x_col]].dropna(), maxlag=max_lag)
return {lag: float(results[lag][0]["ssr_ftest"][1]) for lag in range(1, max_lag + 1)}
def fit_garch(returns: pd.Series, horizon: int = 5) -> dict:
"""Fit a GARCH(1,1) model and forecast forward volatility.
Model: ``r_t = μ + ε_t`` with ``σ²_t = ω + α·ε²_{t-1} + β·σ²_{t-1}``.
``α + β`` is volatility persistence (typically 0.95-0.99 in equities).
Args:
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.View on GitHub (pinned to 80ffdda44c)
Solutions
- Print/inspect data.columns and fix the name
- Normalize column names to lowercase/snake_case before calling
- Ensure upstream steps that create derived columns (returns, spreads) executed
Example fix
# before res = granger_test(df, x_col='Close', y_col='Volume') # actual: 'close','volume' # after res = granger_test(df.rename(columns=str.lower), x_col='close', y_col='volume')
Defensive patterns
Strategy: validation
Validate before calling
missing = [c for c in (y_col, x_col) if c not in data.columns]
if missing:
raise KeyError(f'missing columns: {missing}') Type guard
def columns_present(data: pd.DataFrame, *cols: str) -> bool:
return all(c in data.columns for c in cols) Try / catch
try:
granger_test(data, y_col, x_col)
except KeyError as e:
# re-raise with available columns for debugging
raise KeyError(f'{e}; available: {list(data.columns)}') from e Prevention
- Normalize column names (str.lower/strip) at load time
- Assert required columns exist after feature engineering
- Log data.columns when debugging pipeline failures
When it happens
Trigger: Calling granger_test with a column name not in data.columns — typos, differing naming conventions ('Close' vs 'close'), or DataFrame built without the expected columns.
Common situations: Case-mismatched column names, DataFrames from CSVs with renamed headers, or pipelines where the feature-engineering step that creates the column (e.g. returns) never ran.
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 at least 3 aligned observations, got
- find_hedge_ratio needs an x that varies; this one is constan
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/99d1d1ed48b4c076.
Report an issue: GitHub.