{"record":{"id":"836efe411647d916","repo":"HKUDS/Vibe-Trading","slug":"delay-requires-n-1-lookahead-ban-836efe","errorCode":null,"errorMessage":"delay requires n >= 1 (lookahead ban)","messagePattern":"delay requires n >= 1 \\(lookahead ban\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"critical","filePath":"agent/src/factors/zoo/alpha101/alpha_024.py","lineNumber":62,"sourceCode":"    'extras_required': [],\n    'requires_sector': False,\n    'universe': ['equity_us', 'equity_in', 'equity_kr'],\n    'frequency': ['1D'],\n    'decay_horizon': 5,\n    'min_warmup_bars': 200,\n    'notes': 'Very long lookback (>= ~100 bars); produces NaN warmup on short panels which may trigger the >95% NaN registry guard.',\n}\n\n\ndef _rolling_sum(df: pd.DataFrame, n: int) -> pd.DataFrame:\n    \"\"\"Rolling window sum; warmup -> NaN.\"\"\"\n    return df.rolling(window=n, min_periods=n).sum()\n\n\ndef _delay(df: pd.DataFrame, n: int) -> pd.DataFrame:\n    \"\"\"Backward shift by n (lookahead-safe; n>=1 required).\"\"\"\n    if n < 1:\n        raise ValueError(\"delay requires n >= 1 (lookahead ban)\")\n    return df.shift(n)\n\n\ndef _where_ternary(cond, a, b):\n    \"\"\"Vectorised ternary `(cond ? a : b)` returning a DataFrame.\n\n    ``cond`` is a boolean DataFrame; ``a`` / ``b`` may be DataFrame or scalar.\n    \"\"\"\n    if isinstance(a, (int, float)):\n        a_arr = np.full_like(cond.to_numpy(dtype=np.float64), float(a))\n    else:\n        a_arr = a.to_numpy(dtype=np.float64, na_value=np.nan)\n    if isinstance(b, (int, float)):\n        b_arr = np.full_like(cond.to_numpy(dtype=np.float64), float(b))\n    else:\n        b_arr = b.to_numpy(dtype=np.float64, na_value=np.nan)\n    cond_arr = cond.to_numpy(dtype=bool, na_value=False) if hasattr(cond, \"to_numpy\") else np.asarray(cond, dtype=bool)\n    out = np.where(cond_arr, a_arr, b_arr)","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/factors/zoo/alpha101/alpha_024.py#L44-L80","documentation":"alpha_024's local _delay enforces the same n>=1 rule to prevent lookahead. The ValueError fires before shift, keeping any future-leaking computation from silently producing results.","triggerScenarios":"Calling alpha_024's compute when its internal delay expression evaluates to 0 or negative (bad constant or edited formula).","commonSituations":"Editing zoo constants (window/delay params) while experimenting; copy-pasting between factor files with changed signs.","solutions":["Restore/verify the delay constant as a positive integer","Bypass _delay for zero-lag semantics"],"exampleFix":"# before\n_DELAY = 0\n// after\n_DELAY = 1","handlingStrategy":"validation","validationCode":"assert delay_n >= 1, 'lookahead ban'","typeGuard":"def valid_delay(n: int) -> bool:\n    return isinstance(n, int) and n >= 1","tryCatchPattern":null,"preventionTips":["Validate edited window/delay constants before running","Use zero-lag as direct frame use, not _delay(df, 0)"],"tags":["lookahead-bias","validation","alpha101"],"backgroundTag":"invalid-argument-value","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}