Skip to content

Guides

dataset()

dataset() is the SDK’s primary composer. One call joins multi-source observations, NWS CLI climate, optional forecasts, and optional covariates into one settlement-ready row per day. Same signature in Python and TypeScript. research() is a fully working alias bound to the same callable.

import mostlyright
df = mostlyright.dataset("KNYC", "2025-01-06", "2025-01-12")
print(df.head())

Output is one row per LST settlement date in [from_date, to_date], fused across AWC + IEM + GHCNh observations + NWS CLI climate.

dataset() sits on top of the raw, source-identified domain tables. Reach for the domain tables when you want the ingredients directly; reach for dataset() when you want the SDK to own the leakage-prone day alignment for you.

LayerSurfaceReturns
Composerdataset() / research()one leakage-safe training row per LST settlement day
Domain table — observationsobs()daily extremes or per-report METAR/SPECI rows
Domain table — climateclimate()NWS CLI daily settlement labels
Domain table — forecastsforecasts() / forecast_nwp()per settlement-day forecast envelope

The full contract for source= / delivery= / grain across every table lives in Source identity.

As of v1.15 dataset() has an explicit label axis: the label= kwarg routes which settlement target (“label”) columns the composed frame carries. The core is a venue-free alignment engine — the label you pick is what makes it settlement-ready.

label=Label columnsSettles forNotes
"cli"cli_high_f, cli_low_f, cli_report_typeKalshi NHIGH/NLOW (NWS CLI)Today’s bytes — the byte-identical legacy climate join. The implicit default.
"daily_extremes"daily_extremes_tmax_c, daily_extremes_tmin_c, daily_extremes_tmean_c, daily_extremes_n_obs, daily_extremes_source_tmax, daily_extremes_source_tminPolymarket (WU / NOAA-WRH extremes)Whole-°C precision, station-local calendar; WR-05 low-coverage nulling (rows preserved). Works for international stations.
None(none — features only)nothing (pure feature table)Works for any catalog station worldwide, no market required. The 2.0 default.
(a DataFrame)your own columnsyour own targetBring-your-own — the SDK enforces the leakage discipline for you (see below).
import mostlyright
# Kalshi / NWS CLI settlement columns (today's default output).
cli = mostlyright.dataset("KNYC", "2025-01-06", "2025-01-12", label="cli")
# What Polymarket settles on — WU/NOAA-WRH daily extremes, in °C.
poly = mostlyright.dataset("KNYC", "2025-01-06", "2025-01-12", label="daily_extremes")
# Pure features — no label columns; works for any catalog station worldwide.
feats = mostlyright.dataset("EGLL", "2025-01-06", "2025-01-12", label=None)

Pass a DataFrame instead of a recipe name and the SDK becomes your aligner — you own the label values, it owns the leakage discipline. It buckets your rows to the station’s LST settlement calendar, LEFT-joins them (rows are preserved, missing days NaN), and guards against collisions with the reserved obs_ / cli_ / wu_ / noaa_wrh_ prefixes and registered feature namespaces. A misaligned frame raises the typed LabelAlignmentError (with a stable reason enum), never silently.

import pandas as pd
# Minimum contract: a `date` column (or a datetime/date-named index).
my_labels = pd.DataFrame({
"date": ["2025-01-06", "2025-01-07"],
"my_target": [1, 0],
})
df = mostlyright.dataset("KNYC", "2025-01-06", "2025-01-12", label=my_labels)
# `my_target` is LEFT-joined by settlement day; label-less days are NaN.

Two sharp edges worth internalizing (both enforced, never silent):

  • As-of / publication discipline. By default labels_as_known="settled" treats each label as final. Pass labels_as_known="publication_lag" with a published_at column and the aligner holds a day’s label out until it would have been published by that day’s market close — no published_at column raises rather than silently treating everything as settled.
  • tz-aware vs tz-naive dates. A tz-aware timestamp buckets by the station settlement calendar (a 02:00Z label rolls into the prior LST day); a tz-naive date / plain ISO string is treated as an already-LST calendar date. Be explicit about which you mean.

For multi-station panels (dataset(stations=[...])) and registering your own feature columns, see Extending dataset().

dataset(station, from_date, to_date, ...) accepts these composable kwargs (parity surface across both SDKs unless noted):

KwargDefaultDescription
label(implicit "cli")The settlement target — "cli" | "daily_extremes" | None | a BYO DataFrame. See Choosing the label. Omitting it on dataset() warns (D-22).
labels_as_known"settled"BYO publication discipline — "settled" or "publication_lag" (needs a published_at column).
stationsNoneMulti-station panel (long-format). Mutex with station / city / contract / contracts. See Extending dataset().
featuresNoneExplicit feature list — ["forecasts", "satellite", "cwop", "trades"] + registered contributors. Replaces the include_* flags.
include_forecastFalseDeprecated alias of features=["forecasts"]. Attach fcst_* columns. IEM MOS wired both SDKs; per-NWP-model Python only.
forecast_modelNoneSingle forecast model name (e.g. "gfs"). Requires include_forecast=True / features=["forecasts"].
forecast_modelsNoneMulti-model forecast fan-out. Requires forecasts. Mutex with forecast_model.
include_satelliteFalseDeprecated alias of features=["satellite"]. LEFT-join labels-only sat_* columns. Needs the [satellite] extra. Python.
include_cwopFalseDeprecated alias of features=["cwop"]. LEFT-join labels-only cwop_* columns. Needs the [cwop] extra. Python.
qcFalseRun QC passes, surface QC flags.
tz_overrideNoneIANA tz override for stations not in the canonical registry.
sourcesNoneMulti-source subset. Mutex with source.
sourceNoneSingle-source pin (provenance). Mutex with sources.
backend"pandas"Python: "pandas" or "polars". TS: accepted but "polars" raises (DataAvailabilityError).
return_type"dataframe""dataframe" | "list" | "wrapper". (TS canonical "dataframe"; "frame" is a back-compat alias.)

Mutually-exclusive kwargs raise TypeError before any HTTP or cache I/O:

# All three raise TypeError immediately
mostlyright.dataset("KNYC", "...", "...", sources=["awc"], source="iem") # mutex
mostlyright.dataset("KNYC", "...", "...", forecast_model="gfs", forecast_models=["gfs"]) # mutex
mostlyright.dataset("KNYC", "...", "...", forecast_model="gfs") # missing include_forecast
// Same shape in TypeScript — TypeError, not Error
await dataset("KNYC", "...", "...", {
sources: ["awc"],
source: "iem", // mutex with sources
});
// → TypeError("dataset(): sources= and source= are mutually exclusive …")

Unknown options also raise TypeError:

await dataset("KNYC", "...", "...", { inclide_forecast: true }); // typo
// → TypeError("dataset(): unknown option key 'inclide_forecast' …")

Passing a source the vertical does not recognize also raises a loud typed error immediately, before any network call — never a silent fallback to a different provider.

Fused (default)source=None means best available: a deterministic client-side dedup tiebreak runs in your process — AWC > IEM > GHCNh — so output rows carry the rawest source per (station, observed_at). This is the right choice for reproducing a historical settlement. The fused observation frame carries the distinct frame tag merged.live_v1.

df = mostlyright.dataset("KNYC", "2025-01-06", "2025-01-12")
# obs_high_f / obs_low_f come from the AWC > IEM > GHCNh fused merge

Source-pinned (source=) — pin the provenance to one authority. source= always means WHO produced the row — never delivery, transport, or freshness. Pinning is what keeps a feature backtesting the same way it trades; the validator raises SourceMismatchError if training data and inference data disagree on source.

df = mostlyright.dataset("KNYC", "2025-01-06", "2025-01-12", source="iem")
# Every observation row carries source = "iem"
df = mostlyright.dataset(
"KNYC", "2026-05-01", "2026-05-07",
include_forecast=True,
)
print(df[["date", "obs_high_f", "fcst_high_f", "fcst_model"]])

fcst_* columns ship populated from IEM MOS (the default). For per-model NWP fan-out (Python only):

df = mostlyright.dataset(
"KNYC", "2026-05-01", "2026-05-07",
include_forecast=True,
forecast_models=["hrrr", "gfs"],
)
# Adds fcst_high_f_nwp_hrrr, fcst_high_f_nwp_gfs alongside fcst_high_f (MOS)

See Forecasts.

include_satellite= / include_cwop= LEFT-join per-settlement-day covariate columns onto the composed frame. The label columns are byte-identical whether the flags are on or offobs_*, cli_*, date, station never change, row count and order are unchanged, and missing covariate days are NaN (rows are never dropped or added). Defaults are off, so parity fixtures are untouched.

df = mostlyright.dataset(
"KNYC", "2025-01-06", "2025-01-12",
include_satellite=True, # adds sat_* columns; needs the [satellite] extra
include_cwop=True, # adds cwop_* columns; needs the [cwop] extra
)

A missing [satellite] / [cwop] extra fails loud (typed error), never a silent empty column. Covariates require a DataFrame return path — combining a covariate flag with return_type="list" raises ValueError. Adding a covariate to a trained model is itself a retrain event.

backend and return_type are accepted in TS for surface-equivalence with Python:

// Accepted — no-op (TS arrays don't need a wrapper)
await dataset("KNYC", "...", "...", { return_type: "wrapper" });
// REJECTED at runtime — no Polars in browser/Node
await dataset("KNYC", "...", "...", { backend: "polars" });
// → DataAvailabilityError(reason="model_unavailable", hint="polars backend not available in TypeScript SDK …")

This means a cross-language wrapper can pass the same options dict to either SDK; only Python actually routes to Polars.

Default fused output (without include_forecast):

ColumnTypeNotes
datestrSettlement date in station LST
stationstrNWS code (e.g. "NYC") — not the ICAO
cli_high_ffloatClimate (CLI) max temp °F
cli_low_ffloatClimate (CLI) min temp °F
cli_report_typestr"PRELIM" or "FINAL"
obs_high_fintObservation max temp °F (integer-precision)
obs_low_fintObservation min temp °F (integer-precision)
obs_high_atstrISO-8601 UTC timestamp of the obs_high
obs_low_atstrISO-8601 UTC timestamp of the obs_low
obs_mean_ffloatDaily mean temp °F
obs_max_wind_ktfloatMax sustained wind (kt)
obs_max_gust_ktfloatMax gust (kt)
obs_total_precip_infloatDaily precip total (in)
obs_countintNumber of underlying observations for the day
market_close_utcstrUTC timestamp of the next Kalshi market close

Adding include_forecast=True appends fcst_high_f, fcst_low_f, fcst_model, fcst_issued_at, fcst_pop_6hr_pct, fcst_qpf_6hr_in. Covariate flags append sat_* / cwop_* columns.

dataset(station, from_date, to_date) (and its research() alias) is byte-equivalent to mostlyright==0.14.1’s client.pairs() on the canonical parity fixtures. Default-path changes go through a hard gate before each release. See Source identity and the Parity table.