HKUDS/Vibe-Trading · error · ValueError
delay requires n >= 1 (lookahead ban)
Error message
delay requires n >= 1 (lookahead ban)
What it means
Shared helper _delay in alpha_030.py guards against lookahead bias by refusing n < 1: delay of 0 would use the current bar's value, leaking future information into the alpha computation. It raises ValueError before calling df.shift(n). Any caller passing 0 or a negative window triggers it immediately.
Source
Thrown at agent/src/factors/zoo/alpha101/alpha_030.py:62
'extras_required': [],
'requires_sector': False,
'universe': ['equity_us', 'equity_in', 'equity_kr'],
'frequency': ['1D'],
'decay_horizon': 5,
'min_warmup_bars': 20,
'notes': '',
}
def _rolling_sum(df: pd.DataFrame, n: int) -> pd.DataFrame:
"""Rolling window sum; warmup -> NaN."""
return df.rolling(window=n, min_periods=n).sum()
def _delay(df: pd.DataFrame, n: int) -> pd.DataFrame:
"""Backward shift by n (lookahead-safe; n>=1 required)."""
if n < 1:
raise ValueError("delay requires n >= 1 (lookahead ban)")
return df.shift(n)
def compute(panel: dict) -> pd.DataFrame:
"""Compute the alpha on the OHLCV+ panel and return a wide DataFrame."""
close = panel["close"]
volume = panel["volume"]
# Helper aliases (local closures keep the file standalone & purity-safe).
rolling_sum = _rolling_sum
delay = _delay
s = np.sign(close - delay(close, 1)) + np.sign(delay(close, 1) - delay(close, 2)) + np.sign(delay(close, 2) - delay(close, 3))
out = safe_div((1.0 - rank(s)) * rolling_sum(volume, 5), rolling_sum(volume, 20))
return out
View on GitHub (pinned to 80ffdda44c)
Solutions
- Open agent/src/factors/zoo/alpha101/alpha_030.py, find every _delay(...) call site and confirm each literal is >= 1
- If the formula truly wants the current bar, use the operand directly (e.g. `close`) instead of _delay(close, 0)
- If n comes from config, validate/coerce it: n = max(1, int(n)) or reject the config early with a clear message
- Re-run the alpha's test to confirm no other windows in the chain were corrupted
Example fix
// before part = _delay(close, 0) * _decay(rank(close), 5) // after part = close * _decay(rank(close), 5)
Defensive patterns
Strategy: validation
Validate before calling
def safe_delay(df, n):
n = int(n)
if n < 1:
raise ValueError(f"delay window must be >= 1, got {n}")
return df.shift(n)
# or, if 'no lag' is a valid config value:
n = n if n >= 1 else None
out = df if n is None else safe_delay(df, n) Type guard
def is_valid_delay(n: int) -> bool:
return isinstance(n, int) and not isinstance(n, bool) and n >= 1 Prevention
- Never call _delay with 0 — use the operand directly for current-bar access
- Validate config-driven lag parameters (>= 1) before running the alpha zoo
- Pin lag constants in unit tests so refactors can't silently change them
When it happens
Trigger: compute(panel) in alpha_030 ultimately calls _delay(close, n) with n <= 0 — e.g. a parameterized lookahead/delay constant misconfigured as 0, or an expression like _delay(df, n - 1) evaluated with n = 1.
Common situations: Copying the WorldQuant Alpha101 formula (#30 uses a delay/decay chain) and translating 'delay(x, 0)' literally; editing window constants; generating alphas from config where the delay field is optional and defaults to 0.
Related errors
- delay requires n >= 1 (lookahead ban)
- delay requires n >= 1 (lookahead ban)
- delay requires n >= 1 (lookahead ban)
- delay requires n >= 1 (lookahead ban)
- delay requires n >= 1 (lookahead ban)
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/edac9b43118c2d9b.
Report an issue: GitHub.