Time conventions and resampling

NEM time

All AEMO market timestamps are in NEM time: Australian Eastern Standard Time, a fixed UTC+10 offset with no daylight saving (equivalent to the Australia/Brisbane timezone — never Sydney/Melbourne time).

The public API accepts and returns naive datetimes that are understood to be NEM time. Timezone-aware datetimes are rejected with a TypeError rather than silently converted; convert first if you work in another zone:

import datetime

aware.astimezone(datetime.timezone(datetime.timedelta(hours=10))).replace(tzinfo=None)

Date arguments to the fetch functions may be naive datetime objects, date objects (midnight assumed), or strings in YYYY/MM/DD or YYYY/MM/DD HH:MM:SS form. Ranges are inclusive at both ends.

Interval-ending timestamps

AEMO timestamps mark the end of the interval they describe: the row stamped 00:05 covers 00:00–00:05. This matters when aggregating — pandas’ resample defaults (closed='left', label='left') shift every result by one interval and mix trading periods.

resample() fixes both to 'right', so the 00:30 half-hour bucket aggregates the six 5-minute rows stamped 00:05 through 00:30 — matching how AEMO itself derives 30-minute trading prices from 5-minute dispatch prices:

import nemdatatools as ndt

prices = ndt.fetch("DISPATCHPRICE", "2026/06/01", "2026/06/07", regions=["QLD1"])
half_hourly = ndt.resample(prices[["RRP"]], "30min")

Grouping multi-entity frames

A frame holding several regions, units, or interconnectors must be grouped explicitly with by=, otherwise distinct entities would be averaged together. Ungrouped frames that clearly hold several entities are rejected with a ValueError:

all_regions = ndt.fetch("DISPATCHPRICE", "2026/06/01", "2026/06/07")
daily = ndt.resample(all_regions, "1D", by="REGIONID")

Aggregation functions

agg is a single function name applied to all numeric columns (default "mean"), or a column-to-function mapping — non-mapped columns are dropped:

daily = ndt.resample(scada, "1D", agg={"SCADAVALUE": "sum"}, by="DUID")

The NEM trading day

The NEM trading day runs 04:00 to 04:00, not midnight to midnight. When aggregating to days or coarser, pass trading_day=True to align buckets to the trading day:

daily = ndt.resample(all_regions, "1D", by="REGIONID", trading_day=True)

Each resulting bucket is labelled with its interval-ending timestamp (the 04:00 that closes the trading day).