fix(factors): extend look-ahead rules to session factors and add intraday-factor guidance

- Rule 7 extended: session-based aggregations (London/NY/Asian) must also
  be shifted by 1 trading day before use — same as daily aggregations
- Rule 8 added: prefer pure intraday rolling factors (RSI, Bollinger, VWAP
  deviation, rolling std) that have no look-ahead risk and vary every minute
- predix_full_eval.py: apply _shift_daily_constant_factor_if_needed before IC
- predix_gen_strategies_real_bt.py: improved swing prompt with daily-level
  signal logic guidance for daily-constant factors

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
TPTBusiness
2026-04-24 20:19:07 +02:00
parent 935adde6c5
commit 5c98f48597
2 changed files with 29 additions and 4 deletions
+14 -1
View File
@@ -134,7 +134,20 @@ qlib_factor_strategy: |-
# then map back to minute bars via ffill
```
This rule applies to ALL daily aggregations: returns, OHLC stats, volume, momentum, slopes, etc.
Intraday rolling factors (e.g. 30-min rolling std) do NOT need this shift — only daily aggregations do.
**Session-based aggregations (London, NY, Asian session returns) are also daily aggregations** — the London
session (08:00-16:00 UTC) ends at 16:00, so its return must be shifted by 1 day before use.
Intraday rolling factors (e.g. 30-min rolling std computed at bar t using only bars t-N..t-1) do NOT need this shift.
8. **PREFER pure intraday rolling factors**: Factors that use only a trailing window of recent bars (e.g.
rolling(30).mean() of returns, RSI(14), Bollinger Band z-score) have NO look-ahead risk and vary every
minute. These are the best candidates for short-horizon (96-bar) prediction. Examples:
- Rolling 15-min / 30-min / 60-min return momentum
- Rolling volatility (std of returns over 20-60 bars)
- Distance of close from N-bar moving average (z-score)
- RSI or similar oscillators computed on 1-min bars
- VWAP deviation (requires volume — use $volume column)
Always use `.shift(1)` on the lagged window (e.g. `rolling(N).mean().shift(1)`) to avoid using the
current bar's own price in its own feature value.
qlib_factor_output_format: |-
Your output should be a pandas dataframe similar to the following example information: