Concepts
Temporal safety
Temporal safety answers one question: what data was available when the decision was made? Mostly Right keeps event time, knowledge time, and the decision cutoff separate so you can filter and check historical inputs.
Three times, three questions
Section titled “Three times, three questions”| Time | Question |
|---|---|
| Event time | When did the measured or forecast event happen? |
| Knowledge time | When could a user first know this input? |
| Decision time | When would the model have acted? |
An economic observation can describe March, be released in April, and be revised in May. Those are different facts. Treating the March period as the knowledge time leaks April or May into a March decision.
Source-level tools
Section titled “Source-level tools”The temporal toolkit operates on rows that carry knowledge_time:
from datetime import datefrom mostlyright import economyfrom mostlyright.core import KnowledgeView, TimePoint
series = economy.series( "cpi", date(2024, 1, 1), date(2025, 6, 1), vintages="all",)
view = KnowledgeView( series, TimePoint("2025-04-01T00:00:00Z"),)
knowable = view.dataframe()KnowledgeView validates that knowledge_time exists and is timezone-aware UTC, then returns a defensive copy of rows where knowledge_time <= as_of.
Use assert_no_leakage or LeakageDetector when you want an invalid frame to raise instead of being filtered:
from mostlyright.core.temporal import LeakageDetector, assert_no_leakageThese tools check the timestamp carried by each row. They cannot prove that an upstream timestamp is correct or detect leakage added later in feature engineering.
Source timing
Section titled “Source timing”Not every source knows its exact publication time:
| Source timing | What it supports |
|---|---|
| Exact | Filter and audit against the cutoff |
| Derived or bounded | A conservative approximation |
| Reconstructed | Historical rows without a strict point-in-time guarantee |
| Latest-only or unknown | Not suitable for strict as-of research by default |
Check a source’s timing before making a strong claim about a result.
Custom joins
Section titled “Custom joins”mostlyright.experimental.align() joins sources against a decision cutoff:
from mostlyright import weatherfrom mostlyright.experimental import align
target = weather.label.cli("KNYC", "2025-01-01", "2025-01-31")reports = weather.observations("KNYC")
frame = align(target, reports)align() is experimental and semver-exempt. Depending on the join and source contract, it filters rows to the cutoff or raises LeakageError. Reconstructed source timestamps cannot support the same point-in-time audit.
Training-table example
Section titled “Training-table example”weather.training_table() is a compact example built on one predefined recipe:
from mostlyright import weather
example = weather.training_table( "KNYC", "2025-01-06", "2025-01-12",)Each row exposes:
decision_time_utc: the simulated decision cutofflabel_available_time_utc: when the settlement label was availableknowable_at_utc: the latest required input time, meaning the earliest instant the complete row could have existed
Use the helper when its target and feature recipe match your research. Its timing guarantee still depends on the quality of the underlying source timestamps.
Walk-forward evaluation
Section titled “Walk-forward evaluation”SDK timing checks are necessary but not sufficient:
- Split by time, never randomly.
- Recompute rolling and expanding features inside each fold.
- Fit preprocessing only on the training portion of each fold.
- Group cross-station evaluation by station when claiming geographic generalization.
- Filter to the
knowable_at_utccutoff that matches the simulated live decision.
The SDK’s old transform helpers were removed in 2.0. Use pandas or Polars, and fit each transform only on the training rows inside each walk-forward fold.
Common mistakes
Section titled “Common mistakes”- Bucketing observations by raw UTC date instead of
local_standard_date - Selecting the final revised economy value instead of the first vintage
- Using a forecast run issued after the simulated decision
- Computing a rolling feature once over the full dataset before splitting
- Treating label availability as though it were feature availability
See also
Section titled “See also”- Build a point-in-time research table: stable and experimental composition
- Economy: revisions as first-class rows
- Sources & provenance: source identity across train/live
- Daily windows: local-standard-date bucketing