{"record":{"id":"4732b928c552817a","repo":"HKUDS/Vibe-Trading","slug":"delay-requires-n-1-lookahead-ban-4732b9","errorCode":null,"errorMessage":"delay requires n >= 1 (lookahead ban)","messagePattern":"delay requires n >= 1 \\(lookahead ban\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/factors/zoo/alpha101/alpha_036.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 compute(panel: dict) -> pd.DataFrame:\n    \"\"\"Compute the alpha on the OHLCV+ panel and return a wide DataFrame.\"\"\"\n    close = panel[\"close\"]\n    open_ = panel[\"open\"]\n    volume = panel[\"volume\"]\n    vwap = panel[\"vwap\"]\n    adv20 = ts_mean(volume, 20)\n    returns = close.pct_change(fill_method=None)\n    # Helper aliases (local closures keep the file standalone & purity-safe).\n    rolling_sum = _rolling_sum\n    delay = _delay\n    t1 = 2.21 * rank(ts_corr((close - open_), delay(volume, 1), 15))\n    t2 = 0.7 * rank(open_ - close)\n    t3 = 0.73 * rank(ts_rank(delay(-1.0 * returns, 6), 5))\n    t4 = rank(ts_corr(vwap, adv20, 6).abs())","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/factors/zoo/alpha101/alpha_036.py#L44-L80","documentation":"In alpha_036.py the _delay helper rejects n < 1 to keep the factor lookahead-safe; delay 0 would leak the current bar into a signal meant to use only past data. The ValueError fires before df.shift(n) is ever called.","triggerScenarios":"Any _delay(df, n) invocation inside compute() for alpha #36 with n == 0 or negative — e.g. a window constant typo or a dynamic expression evaluating to 0 on edge inputs.","commonSituations":"Literal translation of the published alpha formula that includes delay(x, 0); global search-replace renaming variables and dropping a '1' to '0'; config files where delay defaults to 0 when unset.","solutions":["Grep _delay( in alpha_036.py and verify every literal argument >= 1","Substitute the raw frame where delay 0 was intended","Validate externally supplied windows before compute(): `assert all(n >= 1 for n in windows)`","Re-run the zoo test suite for alpha_036"],"exampleFix":"// before\nr = _delay(rank(volume), 0) * -1\n// after\nr = rank(volume) * -1","handlingStrategy":"validation","validationCode":"n = int(n)\nif n < 1:\n    raise ValueError(f\"delay window must be >= 1, got {n}\")\nresult = _delay(close, n)","typeGuard":"def is_valid_delay(n: int) -> bool:\n    return isinstance(n, int) and not isinstance(n, bool) and n >= 1","tryCatchPattern":null,"preventionTips":["Use the unshifted frame when 'today' is intended","Reject parameter sweeps containing lag 0 before compute","Add fixture-panel smoke tests per alpha"],"tags":["pandas","alpha101","lookahead-bias","input-validation"],"backgroundTag":"invalid-window-argument","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}