NEMDataTools
An MIT-licensed Python package for accessing and preprocessing Australian Energy Market Operator (AEMO) data for the National Electricity Market (NEM).
How it works
AEMO publishes the same market data at three ages, and NEMDataTools models that system directly instead of hard-coding one source per table:
| Tier | Location | Granularity | Retention |
|---|---|---|---|
| Reports CURRENT | nemweb.com.au/Reports/Current/ |
one file per event | rolling days (varies per package) |
| Reports ARCHIVE | nemweb.com.au/Reports/Archive/ |
daily bundles | ~13 months |
| MMSDM Data Archive | nemweb.com.au/Data_Archive/ |
monthly snapshots | 2009 → ~6 weeks ago |
One fetch() call stitches whichever tiers a date range needs. Remote files
are discovered by reading directory listings and pattern-matching — never by
constructing filenames — so AEMO's filename-format changes (such as the
August 2024 PUBLIC_DVD_* → PUBLIC_ARCHIVE#* switch) and multi-part
archives are handled transparently, including all FILEnn parts of large
tables. Known holes in a table's history (for example the bid tables removed
at the 2021 five-minute-settlement transition) raise a clear error naming
the substitute table instead of returning silently partial data.
Installation
pip install nemdatatools
Requires Python 3.11+. Dependencies: pandas, pyarrow, requests, beautifulsoup4.
Quick start
import nemdatatools as ndt
# One call, any range — tiers are stitched automatically. Start small:
# a week is a quick download; multi-year ranges (e.g. 2020 -> today)
# work the same way but fetch months of archive files on first run.
prices = ndt.fetch(
"DISPATCHPRICE",
"2026/06/01",
"2026/06/07",
regions=["QLD1"],
)
# Interval-ending-aware resampling: the 00:30 bucket aggregates the six
# 5-minute rows stamped 00:05..00:30, matching AEMO's own convention.
half_hourly = ndt.resample(prices[["RRP"]], "30min")
# Frames holding several regions/units must be grouped explicitly:
all_regions = ndt.fetch("DISPATCHPRICE", "2026/06/01", "2026/06/07")
daily = ndt.resample(all_regions, "1D", by="REGIONID", trading_day=True)
# Aggregated price+demand CSVs (aemo.com.au visualisation service):
pd_data = ndt.fetch_price_and_demand("2024/01/01", "2024/12/31", ["NSW1"])
# Discovery:
ndt.tables() # curated table names
ndt.availability("BIDPEROFFER_D") # tier locations + known gaps
# Escape hatch: any of the ~236 MMSDM tables, era-aware, all parts:
gencon = ndt.fetch_mmsdm_table("GENCONDATA", "2026/05/01", "2026/05/31")
All datetimes are naive NEM time (fixed UTC+10, no daylight saving); timezone-aware datetimes are rejected rather than silently converted. AEMO timestamps mark the end of the interval they describe.
Curated tables
fetch() accepts curated tables spanning four families; each is wired to
its locations in every tier and era:
- Prices & demand —
DISPATCHPRICE,TRADINGPRICE,DISPATCHREGIONSUM,TRADINGINTERCONNECT,DISPATCHINTERCONNECTORRES - Generation & SCADA —
DISPATCH_UNIT_SCADA,DISPATCHLOAD,ROOFTOP_PV_ACTUAL - Forecasts —
P5MIN_REGIONSOLUTION,P5MIN_INTERCONNECTORSOLN,PREDISPATCHPRICE,PREDISPATCHREGIONSUM,PREDISPATCHLOAD - Bids & offers —
BIDDAYOFFER_D,BIDPEROFFER_D,BIDDAYOFFER,BIDPEROFFER(plus pre-2021TRADINGREGIONSUMfor history)
Every other MMSDM table is reachable through fetch_mmsdm_table().
Caching
Downloads land under ~/.nemdatatools/ (override with
ndt.Cache("path") passed as cache=):
raw/mirrors nemweb paths — full provenance, a parser fix never forces a re-download;parquet/stores parsed per-table frames, so repeat reads skip zip extraction and CSV parsing entirely.
Data attribution
Data is © AEMO and provided under AEMO's terms; this package downloads publicly available files and does not redistribute data.
License
MIT — see LICENSE.
Metadata
Release files for nemdatatools 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nemdatatools-0.2.0.tar.gz | 138.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nemdatatools-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 170.3 kB
Release files / nemdatatools-0.2.0.tar.gz
| Download URL | nemdatatools-0.2.0.tar.gz |
|---|---|
| Size | 138.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
64e31ca083fe715ccf185d44f6350ccb0c887dc5959461fac32a10fbf7e7f6f7
|
|
BLAKE2b-256 checksum How to use checksums |
7cfb4c5480c9585596d134688096277fa622c7edb24248ca03ffbe1e4de6d0f3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 11, 2026.
Transparency logRelease files / nemdatatools-0.2.0-py3-none-any.whl
| Download URL | nemdatatools-0.2.0-py3-none-any.whl |
|---|---|
| Size | 31.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5060c8144ad651f1ccdf8fe916bc07d025b5648a1aa7ea32bd5f001e6b88b966
|
|
BLAKE2b-256 checksum How to use checksums |
8c64a3a2e803ab8da3ade599b8d564167f0f2472d0b6fef53c35d0fcb3aee493
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 11, 2026.
Transparency log