Skip to content

Guides

Climate gaps

Identify the date ranges where GHCNh climate data is missing for a station. Useful for backtest setup — decide whether to interpolate, drop, or fail-loudly. Wired in Python; deferred in TypeScript v1.x behind a typed error.

from mostlyright.discover import climate_gaps
gaps = climate_gaps("KNYC", "2020-01-01", "2025-01-01")
# [{"start": "2020-03-14", "end": "2020-04-01"}, ...]

Returns a sorted list of contiguous gap intervals. Empty list means full coverage in the window.

import { climateGaps } from "@mostlyrightmd/core/discovery";
import { DataAvailabilityError } from "@mostlyrightmd/core";
try {
const gaps = await climateGaps("KNYC", "2020-01-01", "2025-01-01");
} catch (e) {
if (e instanceof DataAvailabilityError && e.reason === "model_unavailable") {
console.warn(e.hint); // operator-actionable
}
}

A subclass of DataAvailabilityError (ClimateGapsNotImplementedError) is raised on every call. The hint points here.

Three architectural constraints make the browser/Node path impractical for v1.x — all three would need to change before a parity port becomes feasible:

  1. GHCNh CSVs are 10+ MB per station-year. A 5-year backfill is 50+ MB per station; multi-station portfolio queries hit hundreds of MB. The payload is too big to ship over a bare browser fetch on every call.

  2. Browser fetch doesn’t slice. GHCNh’s CSV endpoint has no HTTP Range support; the whole file pulls per call. Mobile and low-bandwidth users exit the SDK as bad-citizen behavior. Server-side ingest could pre-slice, but that means we’d be running a hosted service — explicitly out of scope for the local-first SDK in v1.x.

  3. Cache layer doesn’t scale. IndexedDB has per-origin storage quotas (typically ≤2 GB before browser eviction); the working set for a quant backtest commonly exceeds that. The Node FS cache works for bandwidth savings but doesn’t solve the per-call download problem the first time a station-year is touched.

One future option is a hosted climate-gap-precompute API that serves small JSON responses keyed by (station, window). This ships post-v1.x as part of the broader hosted-cache initiative. Until then, climateGaps() raises with a typed exception so consumers can branch on reason === "model_unavailable" instead of string-matching the message.

For a hot backtest path: run the Python SDK ahead-of-time, serialize the gap list to JSON, and ship it alongside your TS bundle.

generate-gaps.py
import json
from mostlyright.discover import climate_gaps
gaps = climate_gaps("KNYC", "2020-01-01", "2025-01-01")
with open("gaps-KNYC.json", "w") as f:
json.dump(gaps, f)
// In your TS app
import gaps from "./gaps-KNYC.json";
console.log(gaps); // [{"start": "...", "end": "..."}, ...]

For exploratory work: use research() directly. If you see cli_high_f === null for a date, that’s a climate gap signal — but it’s per-row, not pre-computed as a range list.