lookahead-free
中文说明
lookahead-free 用于检查量化数据流程是否使用了当时尚未公开的数据,
适合 A 股回测中的行情、财务和公司行为数据流程。你用带时间标记的流程描述
输入数据何时可用,lf check 再检查决策是否只读取了当时已知的信息。对于
依赖数据值才决定发布时间的复杂操作,它只报告边界,不声称可以完全证明没有
未来数据,因此不能替代数据供应商和研究流程的人工核验。
Verifiable look-ahead-freedom for the value-independent fragment of data
pipelines. Declare your pipeline as a temporally annotated DAG —reads
with release times, windows with ends, PIT reads with cutoffs, decisions
with decision times —and lf check proves, in linear time, that no
decision consumes data that was not knowable yet. Python 3.11+, zero
dependencies, Windows / Linux / macOS.
Status: v0.1.1 alpha, published on PyPI. The model follows Fonseca (2026); expect the op kinds and CLI to grow.
Why this exists
Look-ahead bias is the quiet killer of backtests: a pipeline that computes today's signal from data that only becomes available at 16:00, then "decides" at 15:00, looks great and lies. The usual defenses are heuristics —reviewers eyeballing code, linters matching patterns. This tool is different: it checks a declarative description of the pipeline and gives an exact verdict on the fragment where exactness is possible.
Where it fits. lookahead-free checks the code —whether a pipeline's
data-flow timing is verifiably clean (a static scan of a declarative
pipeline description). It does not constrain the researcher's behavior;
that is the job of falsification-ledger,
which pre-registers claims and keeps tamper-evident receipts (a process
constraint). The two are complementary, not overlapping: one proves the
pipeline did not peek; the other proves the researcher did not revise
expectations after seeing the results.
Grounding. Fonseca (2026), "Look-Ahead-Freedom as Temporal Non-Interference" (arXiv:2607.04958, submitted to ACM TOSEM) proves that look-ahead-freedom is undecidable in general (Pi-0-1-hard when availability depends on data values), but admits a linear-time decidable type-effect system on the value-independent fragment —windowing, resampling, joins, point-in-time and vintage reads. This tool implements exactly that system:
- every op carries a temporal bound (release / window end / PIT cutoff / decision time),
- output availability is derived exactly (monotone: no op can produce a fact earlier than the facts it consumes),
- decision availability is checked exactly: every input of a decision must be available at or before the decision time.
Honest boundary (stated, not hidden). Operations declared
value_dependent: true are flagged at the heuristic boundary (P1):
their temporal structure is still checked exactly, but for the operation
itself no verifiable claim exists —Fonseca's undecidability result is
precisely about value-dependent availability. The tool says so, in the
report, every time.
Quick start
# install the published package from PyPI
pip install lookahead-free
# or run without installing anything:
# PYTHONPATH=src python -m lookahead_free --help
python examples/demo.py # clean pipeline passes, leaky one fails
lf check --pipeline examples/factor-pipeline.json
lf check --pipeline pipeline.json --json # machine-readable verdict
Value-dependent research code is outside the verifiable fragment. For that code there is a heuristic companion — an AST scan of suspicious timing idioms (future subscript/slice) and untimestamped fetch calls. It is explicitly not a proof; hard findings fail, review findings are listed:
lf scan --source my_calculator.py
lf scan --source my_calculator.py --json
Exit codes: 0 = no look-ahead in the value-independent fragment,
1 = at least one P0 temporal violation (or unresolvable DAG),
2 = usage error. Wire it into CI as a hard gate on every pipeline
definition. lf scan exits 1 only on hard heuristic findings (H001/H002);
review findings (H003) are advisory.
Pipeline format
A JSON object with a name and an operations list. Each op:
| Field | Meaning |
|---|---|
op_id |
unique node id |
kind |
read / window / resample / join / pit_read / vintage_read / transform / decision / write |
inputs |
references to other ops —by op_id or by output name (dataflow semantics; ambiguous output names are rejected) |
outputs |
data names this op produces |
release |
(read) when the data becomes knowable |
window_end |
(window/resample, required) end of the lookback window |
read_cutoff |
(pit_read/vintage_read, required) the PIT cutoff |
decision_time |
(decision, required) when the decision is made |
value_dependent |
optional; marks ops in the undecidable fragment (agentic retrieval, value-conditional availability) |
note |
free-form |
Availability of an op's output = its explicit bound, or the maximum availability of its inputs. See examples/factor-pipeline.json for a complete factor pipeline (quotes -> windows -> PIT fundamentals -> join -> agentic retrieval -> decision).
The checks
| Check | Severity | What it proves |
|---|---|---|
dag |
P0 | inputs resolve (op_id or output name), no duplicate ids, no cycles |
monotonicity |
P0 | no op's bound is earlier than an input's availability (impossible availability) |
decision_availability |
P0 | every input of a decision is available at or before the decision time —the core look-ahead check |
window_boundary |
P0 | window/resample ops declare their window end |
pit_reads |
P0 | PIT/vintage reads declare their cutoff |
heuristic_boundary |
P1 | value-dependent ops present -> structural checks exact, op semantics heuristic (per Fonseca's undecidability) |
pipeline_shape |
P2 | informational |
Philosophy
Prices must be knowable; decisions must be honest; undecidability must be stated.
The reproducibility crisis in computational research is structural, and in
quantitative finance it shows up first as leakage: point-in-time data
discipline (Kelly et al., NBER w35247;
Look-Ahead-Bench, arXiv:2601.13770)
is now an industry-wide principle because look-ahead silently inflates
alpha (Daniel, Sornette & Wohrmann 2008).
What has been missing is a machine-checkable statement of compliance.
lookahead-free makes the claim "this pipeline does not peek" a CI gate
instead of an audit ritual —and where the theory says no proof exists, it
says so instead of pretending.
Development
python -m pip install -e . pytest
python -m pytest
CI runs the full test suite on Ubuntu, Windows and macOS with Python 3.11 and 3.12. Issues are handled on weekends; pull requests are welcome.
Related work
- Fonseca (2026), Look-Ahead-Freedom as Temporal Non-Interference (arXiv:2607.04958) —the formal property and its decidability boundary
- Daniel, Sornette & Wohrmann (2008), Look-Ahead Benchmark Bias (SSRN 1289222) —the bias, quantified
- Kelly et al., Scaling Point-in-Time Language Models (NBER w35247) —PIT as an industry principle
- Look-Ahead-Bench (arXiv:2601.13770) —measuring look-ahead in PIT systems
- Temporal Leakage in LLM Backtesting (arXiv:2608.02985) —why passive scores cannot separate skill from leakage
Project family
Part of Holdout — a toolchain against self-deception in quantitative research:
- pit-adjuster — PIT back-adjustment with static forward-adjustment drift detection
- falsification-ledger — pre-registration and falsification ledger
- factor-qc — fail-closed backtest quality gate
- lesson-book — tuition memory for traders
- lookahead-free — verifiable look-ahead-freedom checks
- ashare-data-immunity — data immunity for A-share daily bars
Sister org: Metabolism Tools — workspace-metabolism, policy-driven file lifecycle management for agentic workspaces.
License
MIT
Metadata
Release files for lookahead-free 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| lookahead_free-0.1.2.tar.gz | 20.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lookahead_free-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 36.4 kB
Release files / lookahead_free-0.1.2.tar.gz
| Download URL | lookahead_free-0.1.2.tar.gz |
|---|---|
| Size | 20.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
60516dd57580dfd70529e281746653917e0963744058f798ee1ad775fa1da2ca
|
|
BLAKE2b-256 checksum How to use checksums |
88e85da2186f66071eb28317c6a5f710f6a1fbc10ad6275282d40ab86f44d22f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.15
|
Release files / lookahead_free-0.1.2-py3-none-any.whl
| Download URL | lookahead_free-0.1.2-py3-none-any.whl |
|---|---|
| Size | 15.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
030e7b97ea9a93c7b3b9d368ed13836e0ac8eefeaf395557c18011d72a6dd69c
|
|
BLAKE2b-256 checksum How to use checksums |
ec79a33d8973c755ddfb12e96e65c1e6de09cbdd83b377ecd07aeaef78af3299
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.15
|