Point-in-Time Integrity
Ensuring accurate historical analysis without look-ahead bias.
What is Point-in-Time?
Point-in-time (PIT) integrity means historical data reflects exactly what was known at that time, not what we know now after revisions.
PIT Columns
Every product table carries three PIT timestamps. They answer different questions:
| Column | Meaning | Question it answers |
|---|---|---|
str_effective_at | Valid time: the business date the row describes, plus the source's publication lag where one applies | From when was this knowable to anyone? |
str_observed_at | Transaction time: when Snowtrail could first have held this value | From when did we know it? |
str_ingested_at | Decision time: when this row was written | When was this row computed? |
str_effective_at shifts the business date forward by the source's release lag,
so an EIA storage figure describing 2024-03-01 carries an effective date of
2024-03-07, the day it reached the market. For sources with no meaningful lag
(weather model runs, same-day grid data) it equals the business date.
str_observed_at is provenance-derived: it is the MAX(str_ingested_at) of
the raw rows that actually fed the calculation, propagated through every feature,
signal and event layer.
Because it describes the inputs rather than the write, recomputing a row does
not move it, rebuilds are idempotent, and a value's knowability does not drift
every time the pipeline reruns.
str_ingested_at records when the row was
written. A full rebuild rewrites it for every affected row, so it is not a
first-publication date and should not be used to infer when a value became
available. Use str_observed_at for that.
The as_of Query Parameter
The API exposes an as_of parameter on all product endpoints. It bounds both
time axes, and returns a row only if both hold:
str_observed_at <= as_of -- we actually held it by then
str_effective_at <= as_of -- it was publicly knowable by then
Bounding both is deliberate as Either alone leaks: filtering only on knowability would return values we had not yet computed, and filtering only on what we held would return values before their source published them. The latter of the two binds, which makes the guarantee conservative by construction.
Where a key has several stored versions, as_of takes the newest surviving
version per key, ordering first by the MAJOR part of model_version (highest
first), then str_observed_at DESC, then str_ingested_at DESC. A corrected
model's row therefore wins over a superseded model's row even when its
provenance stamp is earlier.
as_of yourselfThe str_ingested_at tiebreaker is not optional. str_observed_at is
provenance-derived and therefore not unique per version, measured across
sig_system_stress, 16.4% of keys had two rows sharing a stamp but disagreeing
on the value. Ordering on str_observed_at alone returns either row
arbitrarily, so the same query can give different answers between calls. If you
reconstruct as_of against the S3 files, apply the same two-column ordering or
your results will diverge from the API. Order on the MAJOR part of
model_version first, as above.
GET /gbsi_eu/system_stress?date_from=2026-07-01&date_to=2026-09-30&as_of=2026-09-28
The query above returns GBSI-EU signals between July and September 2026, but only includes records that Snowtrail held and that had become knowable on or before 28 September 2026. Any data point whose source had not yet published by that date is excluded, even if its business date falls within the range. Each product has its own effective as_of start (see below); for GBSI-US an as_of before 2026-09-24 returns no composite, signal or event rows, and for GBSI-EU an as_of before 2026-09-24 returns earlier-model rows.
Backtest-Safe Queries
The as_of parameter is essential for backtesting. Without it, you risk look-ahead bias using data that was not yet available at the time your strategy would have made a decision.
from snowtrail import Snowtrail
client = Snowtrail(api_key="your-api-key")
# Simulate what was known on 2026-09-28
df = client.gbsi_eu.system_stress(
date_from="2026-07-01",
date_to="2026-09-30",
as_of="2026-09-28"
)
Walk-Forward Example
To simulate a walk-forward backtest, iterate over decision dates and query with as_of set to each date:
from snowtrail import Snowtrail
from datetime import date, timedelta
client = Snowtrail(api_key="your-api-key")
# Start after the product's effective as_of start (WSSI-US forecast datasets: 2026-02-23)
decision_dates = [date(2026, 3, 2) + timedelta(days=7 * i) for i in range(30)]
for decision_date in decision_dates:
df = client.wssi_us.demand_shock(
date_from=str(decision_date - timedelta(days=90)),
date_to=str(decision_date),
region_id="CONUS",
as_of=str(decision_date)
)
# Each iteration sees only what was known at that decision date
What as_of Does and Does Not Do
as_of protects you from the most common source of look-ahead bias: using data
before it was available. Publication lags mean a value describing a given
business date may not reach the market for days or weeks, and a derived signal
may not be computable until later still. Bounding both axes removes exactly that,
across every product and every delivery channel.
It does reconstruct superseded values
Snowtrail's derived layers are bitemporal. When a source revises a figure, the
recomputed row is appended as a new version rather than overwriting the old one,
and each version carries its own str_observed_at. An as_of query returns the
version we held at that instant.
So if a source published 100 and later restated it to 105, an as_of preceding
the restatement returns 100: the value you would have acted on, while a
current query returns 105.
Only genuine changes are stored. A recomputation that reproduces the same value adds no version, so the history records revisions rather than pipeline runs.