microsoft/qlib · error · ValueError

PIT database does not support referring to future period (e.

Error message

PIT database does not support referring to future period (e.g. expressions like `Ref('$$roewa_q', -1)` are not supported

What it means

Raised by the PIT (point-in-time) operator P (qlib/data/pit.py) when the wrapped feature's extended window has a positive end offset — i.e. the expression needs FUTURE data relative to each evaluation timestamp. Financial PIT data must only be read as-of the current date to avoid look-ahead bias, so forward references like Ref('$$roewa_q', -1) inside P(...) are rejected with this ValueError.

Source

Thrown at qlib/data/pit.py:34

import numpy as np
import pandas as pd
from qlib.data.ops import ElemOperator
from qlib.log import get_module_logger
from .data import Cal


class P(ElemOperator):
    def _load_internal(self, instrument, start_index, end_index, freq):
        _calendar = Cal.calendar(freq=freq)
        resample_data = np.empty(end_index - start_index + 1, dtype="float32")

        for cur_index in range(start_index, end_index + 1):
            cur_time = _calendar[cur_index]
            # To load expression accurately, more historical data are required
            start_ws, end_ws = self.feature.get_extended_window_size()
            if end_ws > 0:
                raise ValueError(
                    "PIT database does not support referring to future period (e.g. expressions like `Ref('$$roewa_q', -1)` are not supported"
                )

            # The calculated value will always the last element, so the end_offset is zero.
            try:
                s = self._load_feature(instrument, -start_ws, 0, cur_time)
                resample_data[cur_index - start_index] = s.iloc[-1] if len(s) > 0 else np.nan
            except FileNotFoundError:
                get_module_logger("base").warning(f"WARN: period data not found for {str(self)}")
                return pd.Series(dtype="float32", name=str(self))

        resample_series = pd.Series(
            resample_data, index=pd.RangeIndex(start_index, end_index + 1), dtype="float32", name=str(self)
        )
        return resample_series

    def _load_feature(self, instrument, start_index, end_index, cur_time):
        return self.feature.load(instrument, start_index, end_index, cur_time)

View on GitHub (pinned to 79633dd950)

Solutions

  1. Remove the future-looking reference: use Ref($$roewa_q, N) with N >= 0 for past values inside P(...).
  2. Restructure so P(...) wraps only the raw PIT field and apply any forward shift outside P (and reconsider whether forward shifting is legitimate at all for your backtest).
  3. Inspect feature.get_extended_window_size() of the wrapped expression; it must return end_ws == 0.

Example fix

# before (future reference inside PIT operator — look-ahead, rejected)
expr = "P(Ref($$roewa_q, -1))"

# after (past reference only)
expr = "P(Ref($$roewa_q, 1))"
Defensive patterns

Strategy: validation

Validate before calling

_, end_ws = feature.get_extended_window_size()
if end_ws > 0:
    raise ValueError("P(...) cannot wrap expressions that reference future data")

Type guard

def is_pit_safe(feature) -> bool:
    return feature.get_extended_window_size()[1] <= 0

Prevention

When it happens

Trigger: P(Ref($$roewa_q, -1)) or any P-wrapped expression whose get_extended_window_size() returns end_ws > 0 — negative-count Ref (future reference in qlib's sign convention), or a nested operator that looks ahead, inside P().

Common situations: Building point-in-time fundamental features and naively reusing lag/lead patterns from price features; the sign convention trips people: Ref(x, -N) refers to the future in qlib, Ref(x, N) to the past.

Related errors


AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15). Data as JSON: /api/errors/e3827fe3b77e90c6. Report an issue: GitHub.