Skip to content

Migration

→ v1.14

v1.14 is a purely additive release. Nothing you call today returns different data: dataset()/research() with its default granularity=“daily” is byte-identical to 1.13.0, and obs() output is unchanged except for one new optional column. There is no find-and-replace to do and no deprecation train that advances this release.

The kwarg contract behind all of this lives in Source identity.

  • dataset(granularity="observation") / research(granularity="observation"). Returns the merged per-report observation rows LEFT-joined by LST settlement day to every daily column the call produces (cli_* incl. cli_report_type, obs_*, fcst_* when include_forecast, and sat_*/cwop_* when the covariate flags are on). Row count equals the per-report row count (never fanned out); label-less days keep NaN/null daily columns. The default granularity="daily" is unchanged.
  • obs() per-report rows carry settlement_date (TS: settlementDate) — the ISO LST settlement day for each report, computed with the settlement machinery (not a UTC-date slice). A new optional field; existing columns are untouched.
# opt in to the observation grain
frame = mostlyright.dataset(
"KNYC", "2025-01-06", "2025-01-12",
granularity="observation",
)
# each per-report row now also carries settlement_date + the repeated daily labels

The one behavioral callout: group your CV by settlement_date

Section titled “The one behavioral callout: group your CV by settlement_date”

On an observation-grain frame, the daily labels (cli_high_f/cli_low_f, obs_high_f/obs_low_f, and any covariates) repeat across every report row of the same settlement day. That is by design — it lets a strategy learn from intraday structure while keeping the settlement label attached. But it means a naive row-wise train/test split will put rows from the same settlement day on both sides of the split and leak the label (pseudo-replication).

Use grouped cross-validation keyed on the settlement day:

from sklearn.model_selection import GroupKFold
groups = frame["settlement_date"] # one group per settlement day
cv = GroupKFold(n_splits=5)
for train_idx, test_idx in cv.split(frame, y, groups=groups):
...

Source identity has the full “observation-grain composer and pseudo-replication” writeup and the equivalent example.

TS ships the same dataset({ granularity }) and settlementDate this release. One pre-existing divergence remains from 1.13.0 and is unchanged here: the obs() default grain differs between the SDKs — Python obs() defaults to "daily", TS obs() defaults to "observation". The dataset() default is "daily" in both. If you rely on obs()’s default in cross-SDK code, pass granularity= explicitly.

Surface1.14.0 behavior
dataset() / research() default (granularity="daily")byte-identical to 1.13.0
obs() existing columnsunchanged (adds optional settlement_date/settlementDate)
dataset(granularity="observation")new, opt-in
Deprecationsnone advance this release