| Title: | Download Australian Energy Market Operator Data |
|---|---|
| Description: | Fetch Australian Energy Market Operator (AEMO) public data from 'NEMweb' <http://nemweb.com.au> and the Market Management System Data Model (MMSDM) historical archive. Provides tidy access to 5-minute and 30-minute wholesale electricity prices, regional demand, dispatch-unit output, interconnector flows, rooftop photovoltaic generation, generator bids, predispatch forecasts, frequency control ancillary services markets, and gas market data across the National Electricity Market (NEM) regions. Data is published by AEMO under its Copyright Permissions Notice <https://www.aemo.com.au/privacy-and-legal-notices/copyright-permissions>. |
| Authors: | Charles Coverdale [aut, cre] |
| Maintainer: | Charles Coverdale <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.4.2 |
| Built: | 2026-05-31 20:11:41 UTC |
| Source: | https://github.com/charlescoverdale/aemo |
Returns BIDDAYOFFER_D (daily bid summary: 10 price bands,
MaxAvail, fixed load, locked at 12:30 D-1), BIDPEROFFER_D
(per-interval availability and rebids), or the two joined on
(duid, settlementdate, bidtype).
aemo_bids( duid, start, end, resolution = c("day", "period", "joined"), allow_large = FALSE )aemo_bids( duid, start, end, resolution = c("day", "period", "joined"), allow_large = FALSE )
duid |
Character vector of DUIDs. Required. |
start, end
|
Window. |
resolution |
One of |
allow_large |
Logical. Default |
Parent / child structure. BIDDAYOFFER_D carries the
price bands (priceband1..priceband10), which are locked
at 12:30 on the day ahead and cannot be rebid.
BIDPEROFFER_D carries the per-interval availability
bands (bandavail1..bandavail10), which can be rebid
intraday. Serious bidding analysis (Goncalves & Menezes 2022
Energy Economics 113 106398; Nelson et al. 2024 AJARE 68(4))
needs both joined.
Size warning. BIDPEROFFER_D monthly archives are
multi-gigabyte. By default aemo_bids() refuses spans longer
than 30 days; pass allow_large = TRUE to override.
Upstream gap. AEMO has a documented gap in
BIDPEROFFER_D between March 2021 and July 2024. Rows in
that range may be missing.
An aemo_tbl.
Other dispatch:
aemo_constraints(),
aemo_dispatch_units(),
aemo_fcas_enablement(),
aemo_gencon(),
aemo_interconnector(),
aemo_market_notices(),
aemo_outages(),
aemo_rooftop_pv(),
aemo_spd_constraints()
op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() # Daily bid summary (price bands) b <- aemo_bids(duid = "BW01", start = now - 86400, end = now) # Joined: price bands + per-interval volumes bj <- aemo_bids(duid = "BW01", start = now - 86400, end = now, resolution = "joined") }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() # Daily bid summary (price bands) b <- aemo_bids(duid = "BW01", start = now - 86400, end = now) # Joined: price bands + per-interval volumes bj <- aemo_bids(duid = "BW01", start = now - 86400, end = now, resolution = "joined") }) options(op)
Inspect the local aemo cache
aemo_cache_info()aemo_cache_info()
A list with dir, n_files, size_bytes, size_human, files.
Other configuration:
aemo_clear_cache(),
aemo_throttle()
op <- options(aemo.cache_dir = tempdir()) aemo_cache_info() options(op)op <- options(aemo.cache_dir = tempdir()) aemo_cache_info() options(op)
Clear the aemo cache
aemo_clear_cache()aemo_clear_cache()
Invisibly returns NULL.
Other configuration:
aemo_cache_info(),
aemo_throttle()
op <- options(aemo.cache_dir = tempdir()) aemo_clear_cache() options(op)op <- options(aemo.cache_dir = tempdir()) aemo_clear_cache() options(op)
Returns the DISPATCHCONSTRAINT table from NEMweb: one row
per binding (or near-binding) constraint per 5-minute dispatch
interval. Each row records the constraint ID, the left-hand
side (LHS) and right-hand side (RHS) values, the marginal
value (shadow price on the constraint in AUD/MWh), and the
violation degree if any.
aemo_constraints( start, end, constraint_id = NULL, intervention = FALSE, min_marginal_value = 0.01 )aemo_constraints( start, end, constraint_id = NULL, intervention = FALSE, min_marginal_value = 0.01 )
start, end
|
Window (inclusive), character or POSIXct. |
constraint_id |
Optional character vector of constraint
IDs (e.g. |
intervention |
Logical. Default |
min_marginal_value |
Numeric. Only return constraints
with marginal value at or above this threshold (AUD/MWh).
|
This is the table that answers the question "why was the RRP so high at 17:35?": the sum of marginal values across binding constraints at the Regional Reference Node equals the regional price component attributable to network limits.
Constraint equations and RHS terms (GENCONDATA,
GENCONSETINVOKE) are published through MMSDM on a separate
cadence and are not exposed directly by this function; use
aemo_nemweb_download() on an MMSDM URL for those.
An aemo_tbl with columns settlementdate,
constraintid, rhs, marginalvalue, violationdegree,
lhs, plus the intervention flag.
AEMO NEMweb DISPATCHIS_Reports, DISPATCHCONSTRAINT table.
Other dispatch:
aemo_bids(),
aemo_dispatch_units(),
aemo_fcas_enablement(),
aemo_gencon(),
aemo_interconnector(),
aemo_market_notices(),
aemo_outages(),
aemo_rooftop_pv(),
aemo_spd_constraints()
op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() c <- aemo_constraints(start = now - 3600, end = now) head(c) }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() c <- aemo_constraints(start = now - 3600, end = now) head(c) }) options(op)
Returns 5-minute regional demand from DISPATCHREGIONSUM.
Three demand measures are supported, aligned with AEMO's
Demand Terms taxonomy:
aemo_demand( region, start, end, measure = c("operational", "operational_less_snsg", "native"), intervention = FALSE )aemo_demand( region, start, end, measure = c("operational", "operational_less_snsg", "native"), intervention = FALSE )
region |
NEM region code. Vector accepted. |
start, end
|
Window (inclusive), character or POSIXct. |
measure |
One of |
intervention |
Logical. Default |
"operational" (default): TOTALDEMAND, the grid-measured
demand met by scheduled and semi-scheduled generation plus
net interchange. This is the quantity AEMO dispatches.
"operational_less_snsg": TOTALDEMAND minus small
non-scheduled generation (SS_SOLAR_UIGF + SS_WIND_UIGF
where present).
"native": TOTALDEMAND plus estimated rooftop PV
generation. Closest to end-use consumption. If the rooftop
PV component is not available in DISPATCHREGIONSUM the
function warns and returns TOTALDEMAND; users should join
with aemo_rooftop_pv() for a full native-demand estimate.
Timestamps are AEST (UTC+10, no DST).
An aemo_tbl with columns settlementdate,
regionid, demand_mw (the requested measure), plus the
underlying DISPATCHREGIONSUM columns used in the derivation.
AEMO NEMweb, AEMO Copyright Permissions Notice.
op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() d <- aemo_demand("VIC1", now - 3600, now) head(d) }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() d <- aemo_demand("VIC1", now - 3600, now) head(d) }) options(op)
Returns 5-minute generator output for one or more DUIDs. Three measures are available:
aemo_dispatch_units( duid = NULL, start, end, measure = c("scada_mw", "target_mw", "both") )aemo_dispatch_units( duid = NULL, start, end, measure = c("scada_mw", "target_mw", "both") )
duid |
Optional character vector of DUIDs. |
start, end
|
Window (inclusive). |
measure |
One of |
"scada_mw" (default): actual metered output from
DISPATCH_UNIT_SCADA (SCADAVALUE).
"target_mw": dispatch target from DISPATCHLOAD
(TOTALCLEARED). This is the MW AEMO asked the unit to
produce at the end of the interval.
"both": returns SCADAVALUE, INITIALMW (SCADA at the
start of the interval) and TOTALCLEARED (target at the
end) in a single row per DUID per interval. Use this for
ramp-trajectory research: the ramp applied during the
interval is the straight line from INITIALMW to
TOTALCLEARED.
Timestamps are AEST (UTC+10, no DST).
An aemo_tbl with columns settlementdate, duid,
and the requested measure(s).
Other dispatch:
aemo_bids(),
aemo_constraints(),
aemo_fcas_enablement(),
aemo_gencon(),
aemo_interconnector(),
aemo_market_notices(),
aemo_outages(),
aemo_rooftop_pv(),
aemo_spd_constraints()
op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() # SCADA actual d <- aemo_dispatch_units(duid = "BW01", start = now - 3600, end = now) # Paired: INITIALMW, TOTALCLEARED, SCADAVALUE (ramp research) d_both <- aemo_dispatch_units(duid = "BW01", start = now - 3600, end = now, measure = "both") }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() # SCADA actual d <- aemo_dispatch_units(duid = "BW01", start = now - 3600, end = now) # Paired: INITIALMW, TOTALCLEARED, SCADAVALUE (ramp research) d_both <- aemo_dispatch_units(duid = "BW01", start = now - 3600, end = now, measure = "both") }) options(op)
Returns the Distribution Loss Factor for NEM connection
points from the MMSDM LOSSFACTORMODEL table. DLFs measure
the average energy loss on the distribution network between
a connection point and the transmission network boundary; a
DLF of 1.02 means the generator must produce 2% more energy
than it delivers to the transmission system.
aemo_dlf(year = NULL, connection_point_id = NULL)aemo_dlf(year = NULL, connection_point_id = NULL)
year |
Financial year(s) as |
connection_point_id |
Optional character vector of connection point IDs. |
DLFs are published annually by AEMO (NER 3.6.3) and combined with MLFs in settlement to give the total loss factor (TLF = MLF x DLF) used in energy payments.
An aemo_tbl with at minimum financial_year,
connectionpointid, and dlf.
AEMO MMSDM archive, LOSSFACTORMODEL table. AEMO Copyright Permissions Notice.
Other reference:
aemo_interconnectors(),
aemo_mlf(),
aemo_participants(),
aemo_price_caps(),
aemo_regions(),
aemo_settlement(),
aemo_snapshot(),
aemo_units()
op <- options(aemo.cache_dir = tempdir()) try({ dlf <- aemo_dlf(year = "2024-25") head(dlf) }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ dlf <- aemo_dlf(year = "2024-25") head(dlf) }) options(op)
Returns regional FCAS market prices across the eight contingency services plus the two regulation services. Ten services are live in the NEM since R1/L1 Very Fast commenced on 9 October 2023.
aemo_fcas(region, start, end, service = NULL, intervention = FALSE)aemo_fcas(region, start, end, service = NULL, intervention = FALSE)
region |
NEM region code. |
start, end
|
Window (inclusive). |
service |
Optional character vector of service names
(e.g. |
intervention |
Logical. See |
Thin wrapper over aemo_price(..., market = "fcas").
An aemo_tbl with one row per interval and columns
for each requested FCAS RRP (AUD/MW).
Other price:
aemo_price()
op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() f <- aemo_fcas("NSW1", now - 3600, now) head(f) }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() f <- aemo_fcas("NSW1", now - 3600, now) head(f) }) options(op)
Returns the MW enabled for each of the ten Frequency Control
Ancillary Services (FCAS) per DUID per 5-minute dispatch
interval from DISPATCHLOAD. This is the quantity side of
the FCAS market: how much each unit was enabled (dispatched)
to provide each service, as distinct from the price returned
by aemo_fcas().
aemo_fcas_enablement( duid = NULL, start, end, service = NULL, intervention = FALSE )aemo_fcas_enablement( duid = NULL, start, end, service = NULL, intervention = FALSE )
duid |
Optional character vector of DUIDs. |
start, end
|
Window (inclusive), character or POSIXct. |
service |
Optional character vector of service names,
e.g. |
intervention |
Logical. Default |
Ten services are active since 9 October 2023 when Very Fast
(RAISE1SEC / LOWER1SEC) commenced. Before that date only
eight services are present; the raise1secmw / lower1secmw
columns will be NA for intervals before that date.
An aemo_tbl with columns settlementdate, duid,
and one column per FCAS service (raise1secmw,
lower1secmw, raise6secmw, lower6secmw,
raise60secmw, lower60secmw, raise5minmw,
lower5minmw, raiseregmw, lowerregmw). Values are
MW; zero means the unit was not enabled for that service.
AEMO NEMweb DISPATCHIS_Reports, DISPATCHLOAD table.
Other dispatch:
aemo_bids(),
aemo_constraints(),
aemo_dispatch_units(),
aemo_gencon(),
aemo_interconnector(),
aemo_market_notices(),
aemo_outages(),
aemo_rooftop_pv(),
aemo_spd_constraints()
op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() e <- aemo_fcas_enablement(start = now - 3600, end = now) head(e) }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() e <- aemo_fcas_enablement(start = now - 3600, end = now) head(e) }) options(op)
Returns Short Term Trading Market (STTM, Adelaide, Brisbane,
Sydney hubs) or Declared Wholesale Gas Market (DWGM,
Victoria) prices and volumes.
aemo_gas(market = c("sttm", "dwgm"), hub = NULL, start, end)aemo_gas(market = c("sttm", "dwgm"), hub = NULL, start, end)
market |
One of |
hub |
Optional STTM hub: |
start, end
|
Window. |
An aemo_tbl.
op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() g <- aemo_gas(market = "sttm", hub = "sydney", start = now - 7 * 86400, end = now) head(g) }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() g <- aemo_gas(market = "sttm", hub = "sydney", start = now - 7 * 86400, end = now) head(g) }) options(op)
Downloads the GENCONDATA table from the most recent MMSDM
monthly archive. GENCONDATA contains the equation
definitions for every generic constraint active in the NEM:
the constraint ID, the type (equality/inequality), a
description of what the constraint models (thermal limit,
voltage stability, system strength, etc.), and the default
RHS value.
aemo_gencon(constraint_id = NULL, type = NULL)aemo_gencon(constraint_id = NULL, type = NULL)
constraint_id |
Optional character vector of constraint
IDs to filter on. |
type |
Optional constraint type filter (e.g.
|
Pair this with aemo_constraints() to go from a binding
dispatch interval to the underlying network equation. The
workflow is: aemo_constraints() tells you which constraint
bound and how hard (marginalvalue = shadow price);
aemo_gencon() tells you what the constraint is (which
elements and why the RHS was set at that level).
An aemo_tbl with columns including genconid
(constraint ID), constrainttype, description,
genericconstraintrhs (default RHS value). Additional
columns from GENCONDATA (effective dates, generic
constraint equation weights) will be present when
available.
AEMO NEMweb MMSDM archive, GENCONDATA table. AEMO Copyright Permissions Notice.
aemo_constraints() for the real-time binding
constraint shadow prices.
Other dispatch:
aemo_bids(),
aemo_constraints(),
aemo_dispatch_units(),
aemo_fcas_enablement(),
aemo_interconnector(),
aemo_market_notices(),
aemo_outages(),
aemo_rooftop_pv(),
aemo_spd_constraints()
op <- options(aemo.cache_dir = tempdir()) try({ # Find equations for the Heywood interconnector thermal limits g <- aemo_gencon(constraint_id = c("V::S_NIL_TBSE", "V::S_NIL_FCSPS")) head(g) }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ # Find equations for the Heywood interconnector thermal limits g <- aemo_gencon(constraint_id = c("V::S_NIL_TBSE", "V::S_NIL_FCSPS")) head(g) }) options(op)
Returns MW flows, losses, and limits for one or more NEM
interconnectors from DISPATCHINTERCONNECTORRES.
aemo_interconnector(flow = NULL, start, end, intervention = FALSE)aemo_interconnector(flow = NULL, start, end, intervention = FALSE)
flow |
Optional character vector of interconnector IDs. |
start, end
|
Window. |
intervention |
Logical. Default |
AEMO's METEREDMWFLOW is positive when power flows from
REGIONFROM to REGIONTO. For per-interconnector direction
conventions see aemo_interconnectors().
An aemo_tbl.
Other dispatch:
aemo_bids(),
aemo_constraints(),
aemo_dispatch_units(),
aemo_fcas_enablement(),
aemo_gencon(),
aemo_market_notices(),
aemo_outages(),
aemo_rooftop_pv(),
aemo_spd_constraints()
op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() i <- aemo_interconnector(flow = "V-SA", start = now - 3600, end = now) head(i) }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() i <- aemo_interconnector(flow = "V-SA", start = now - 3600, end = now) head(i) }) options(op)
Returns a static table of the seven NEM interconnectors. The seventh entry is Project EnergyConnect (PEC), whose Stage 1 was energised on 30 April 2025 with full ~800 MW capability expected mid-2026.
aemo_interconnectors()aemo_interconnectors()
An aemo_tbl with columns interconnector_id,
from_region, to_region, name, energised.
Other reference:
aemo_dlf(),
aemo_mlf(),
aemo_participants(),
aemo_price_caps(),
aemo_regions(),
aemo_settlement(),
aemo_snapshot(),
aemo_units()
aemo_interconnectors()aemo_interconnectors()
Returns the MARKETNOTICEDATA feed from MMSDM. Market
notices are AEMO's free-text log of market-relevant events:
Lack of Reserve (LOR1/2/3) declarations, Reliability and
Emergency Reserve Trader (RERT) activations, market
suspensions, market directions, unit withdrawals, system
security events, administered price declarations, and
operator advisories.
aemo_market_notices(start, end, notice_type = NULL, region = NULL)aemo_market_notices(start, end, notice_type = NULL, region = NULL)
start, end
|
Window (inclusive) applied to |
notice_type |
Optional character vector (e.g. |
region |
Optional NEM region code. |
Pair with aemo_constraints() and aemo_price() to sequence
the causal chain of a price event. Rangarajan, Svec, Foley
and Trück (2025, Energy Economics 141) use
MARKETNOTICEDATA to order the intervention messages that
mark entry to and exit from the June 2022 NEM suspension.
An aemo_tbl with columns from MARKETNOTICEDATA:
noticeid, effectivedate, typeid (notice category),
originator, priority, reason (the notice text),
externalreference, and where present regionid.
AEMO NEMweb MMSDM archive, MARKETNOTICEDATA table. AEMO Copyright Permissions Notice.
Other dispatch:
aemo_bids(),
aemo_constraints(),
aemo_dispatch_units(),
aemo_fcas_enablement(),
aemo_gencon(),
aemo_interconnector(),
aemo_outages(),
aemo_rooftop_pv(),
aemo_spd_constraints()
op <- options(aemo.cache_dir = tempdir()) try({ # LOR declarations during the June 2022 NEM suspension n <- aemo_market_notices( start = "2022-06-13", end = "2022-06-14", notice_type = "LOR" ) head(n) }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ # LOR declarations during the June 2022 NEM suspension n <- aemo_market_notices( start = "2022-06-13", end = "2022-06-14", notice_type = "LOR" ) head(n) }) options(op)
Returns the Marginal Loss Factor applicable to each DUID for the requested financial year(s). MLFs measure the incremental network loss at a connection point relative to the Regional Reference Node (RRN); a DUID with MLF = 0.97 receives 97% of the regional RRP per MWh generated.
aemo_mlf(year = NULL, duid = NULL)aemo_mlf(year = NULL, duid = NULL)
year |
Financial year(s) as |
duid |
Optional character vector of DUIDs to filter on.
|
MLFs are published annually by AEMO under NER 3.6.2 and are
used in settlement calculations and in PPA revenue
reconstruction. The function first attempts to download the
TRANSMISSIONLOSSFACTOR table from the most recent MMSDM monthly
archive; if that fails it returns a bundled static table
covering FY 2020-21 to FY 2025-26 for ~20 well-known DUIDs.
An aemo_tbl with columns financial_year, duid,
connectionpointid, regionid, mlf. From a live MMSDM
download additional columns (participantid,
lastchanged) may also be present.
AEMO MMSDM archive, TRANSMISSIONLOSSFACTOR table. AEMO Copyright Permissions Notice.
aemo_units() for the DUID registry,
aemo_price() for regional RRPs.
Other reference:
aemo_dlf(),
aemo_interconnectors(),
aemo_participants(),
aemo_price_caps(),
aemo_regions(),
aemo_settlement(),
aemo_snapshot(),
aemo_units()
op <- options(aemo.cache_dir = tempdir()) try({ mlf <- aemo_mlf(year = "2024-25") head(mlf) }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ mlf <- aemo_mlf(year = "2024-25") head(mlf) }) options(op)
Thin wrapper over the internal cache-aware downloader.
aemo_nemweb_download(url, cache = TRUE)aemo_nemweb_download(url, cache = TRUE)
url |
A fully-qualified NEMweb URL (zipped CSV). |
cache |
Logical. Reuse cached file if present. |
Path to the cached file.
Other low-level:
aemo_nemweb_ls()
op <- options(aemo.cache_dir = tempdir()) try({ files <- aemo_nemweb_ls("/Reports/Current/DispatchIS_Reports/") if (nrow(files) > 0) { f <- aemo_nemweb_download(files$url[1]) file.exists(f) } }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ files <- aemo_nemweb_ls("/Reports/Current/DispatchIS_Reports/") if (nrow(files) > 0) { f <- aemo_nemweb_download(files$url[1]) file.exists(f) } }) options(op)
Returns a data frame of files in a NEMweb path, parsed from the Apache directory-listing HTML.
aemo_nemweb_ls(path)aemo_nemweb_ls(path)
path |
NEMweb subpath (e.g. |
A data frame with name, modified, size, url.
AEMO NEMweb http://nemweb.com.au, published under the AEMO Copyright Permissions Notice.
Other low-level:
aemo_nemweb_download()
op <- options(aemo.cache_dir = tempdir()) try({ files <- aemo_nemweb_ls("/Reports/Current/DispatchIS_Reports/") head(files) }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ files <- aemo_nemweb_ls("/Reports/Current/DispatchIS_Reports/") head(files) }) options(op)
Returns the NETWORK_OUTAGEDETAIL table from MMSDM, which
records every planned and forced outage on NEM transmission
and distribution network elements. Outages are a primary
driver of binding constraints and price spikes: when a line
or transformer is out of service the network is more
constrained, reducing the thermal limits that appear as RHS
values in DISPATCHCONSTRAINT.
aemo_outages(start, end, element_id = NULL, outage_type = NULL, region = NULL)aemo_outages(start, end, element_id = NULL, outage_type = NULL, region = NULL)
start, end
|
Outage window (inclusive). Filters on
|
element_id |
Optional character vector of network
element IDs. |
outage_type |
Optional character. One of |
region |
Optional NEM region code. Filters on the region column where available. |
Use case. Pair with aemo_constraints() to explain a
price spike: aemo_outages() tells you which elements were
off-service at the time; aemo_constraints() tells you
which constraints bound; together they answer "why was SA
spot price AUD 15,000 at 17:35?".
An aemo_tbl with columns from
NETWORK_OUTAGEDETAIL including outageid, starttime,
endtime, substationid, equipmenttype,
equipmentid, outagetype, regionid, and
restarttimeunknown. Exact column set depends on the
MMSDM version.
AEMO NEMweb MMSDM archive, NETWORK_OUTAGEDETAIL table. AEMO Copyright Permissions Notice.
aemo_constraints() for the binding constraint
shadow prices that these outages drive.
Other dispatch:
aemo_bids(),
aemo_constraints(),
aemo_dispatch_units(),
aemo_fcas_enablement(),
aemo_gencon(),
aemo_interconnector(),
aemo_market_notices(),
aemo_rooftop_pv(),
aemo_spd_constraints()
op <- options(aemo.cache_dir = tempdir()) try({ # Forced outages during a recent high-price period in SA o <- aemo_outages( start = "2024-03-01", end = "2024-03-02", outage_type = "FORCED" ) head(o) }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ # Forced outages during a recent high-price period in SA o <- aemo_outages( start = "2024-03-01", end = "2024-03-02", outage_type = "FORCED" ) head(o) }) options(op)
Returns a mapping of NEM market participants (companies) to
their registered Dispatchable Unit Identifiers (DUIDs), joined
from the MMSDM PARTICIPANT and DUDETAILSUMMARY tables.
Use this for corporate ownership analysis: rolling up generator
output or bids from DUID-level data to the company level.
aemo_participants()aemo_participants()
An aemo_tbl with columns participantid,
participantclassid (e.g. GENERATOR, LOAD, TRADER),
name (company name), duid, stationid, regionid,
dispatchtype, schedule_type. Rows are one per
participant-DUID combination. If MMSDM is unreachable,
returns an empty table with a warning.
AEMO NEMweb MMSDM archive, PARTICIPANT and DUDETAILSUMMARY tables. AEMO Copyright Permissions Notice.
aemo_units() for DUID-level registry without
participant mapping.
Other reference:
aemo_dlf(),
aemo_interconnectors(),
aemo_mlf(),
aemo_price_caps(),
aemo_regions(),
aemo_settlement(),
aemo_snapshot(),
aemo_units()
op <- options(aemo.cache_dir = tempdir()) try({ pt <- aemo_participants() # DUIDs owned by AGL pt[grepl("AGL", pt$name, ignore.case = TRUE), ] }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ pt <- aemo_participants() # DUIDs owned by AGL pt[grepl("AGL", pt$name, ignore.case = TRUE), ] }) options(op)
Returns short-term (STPASA, 1-7 day) or medium-term
(MTPASA, 2-year) system adequacy projections.
aemo_pasa( horizon = c("short", "medium"), region = NULL, start = NULL, end = NULL )aemo_pasa( horizon = c("short", "medium"), region = NULL, start = NULL, end = NULL )
horizon |
One of |
region |
Optional NEM region code. |
start, end
|
Optional window of run-times. Defaults to the last 24 hours. |
An aemo_tbl.
Other forecast:
aemo_predispatch()
op <- options(aemo.cache_dir = tempdir()) try({ p <- aemo_pasa(horizon = "short", region = "NSW1") }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ p <- aemo_pasa(horizon = "short", region = "NSW1") }) options(op)
Returns AEMO's forecast prices and demand for a NEM region. Two horizons:
"p5min": 5-minute-ahead forecast, 12 intervals ahead,
published every 5 minutes.
"predispatch": 40-hour-ahead predispatch at 30-minute
resolution, published every 30 minutes.
aemo_predispatch( region, start, end, horizon = c("predispatch", "p5min"), run_datetime = NULL )aemo_predispatch( region, start, end, horizon = c("predispatch", "p5min"), run_datetime = NULL )
region |
NEM region code. |
start, end
|
Window of forecast run-times. |
horizon |
One of |
run_datetime |
Optional character or |
The 7-day predispatch publication was retired when 5-minute
settlement commenced; for longer horizons use aemo_pasa().
Vintages. PREDISPATCH and P5MIN forecasts are re-issued
every 30 or 5 minutes respectively. Every vintage is archived
by its RUN_DATETIME. By default (run_datetime = NULL) this
function returns all vintages whose file timestamp falls in
[start, end], i.e. all the forecasts issued during the
window. The periodid / datetime columns on the returned
rows give each forecast's target time.
For forecast-error research (comparing a forecast vintage
against the realised dispatch) pass run_datetime to pin a
specific vintage:
# The PREDISPATCH run issued at 15:00 on 1 June 2024 --
# 80 half-hour-ahead rows covering 15:30 out to 31:30 hours.
v <- aemo_predispatch("NSW1", start = "2024-06-01", end = "2024-06-02",
run_datetime = "2024-06-01 15:00")
This is the vintage-aware pattern used in Prakash (2023) NEMSEER (JOSS 8(92) 5883).
An aemo_tbl.
Other forecast:
aemo_pasa()
op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() p <- aemo_predispatch("NSW1", start = now - 3600, end = now) head(p) }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() p <- aemo_predispatch("NSW1", start = now - 3600, end = now) head(p) }) options(op)
Returns 5-minute dispatch prices or 30-minute trading prices for a NEM region over a specified window. Filters intervention runs by default so the returned prices are the market clearing prices used in settlement.
aemo_price( region, start, end, interval = c("5min", "30min"), market = c("energy", "fcas"), intervention = FALSE )aemo_price( region, start, end, interval = c("5min", "30min"), market = c("energy", "fcas"), intervention = FALSE )
region |
One of |
start, end
|
Start and end times (inclusive). Character
(parsed as AEST) or |
interval |
One of |
market |
One of |
intervention |
Logical. |
Timestamps are AEST (UTC+10, no daylight savings) to match AEMO's market clock. See the package-level documentation for the period-ending timestamp convention (a row stamped 00:05 is the 5-minute period ending at 00:05).
Intervention. DISPATCHPRICE contains both market pricing
runs (INTERVENTION = 0) and physical / intervention runs
(INTERVENTION = 1). The default filters to market runs.
Pass intervention = TRUE to get both.
30-minute settlement and the 5MS transition. Before
1 October 2021 the NEM settled on 30-minute trading prices
from TRADINGPRICE (TRADINGIS). On 1 October 2021 five-minute
settlement (5MS) commenced and settlement moved to native
5-minute prices. When interval = "30min":
For the pre-5MS period (start < 2021-10-01): prices are
read from TRADINGIS (TRADINGPRICE).
For the post-5MS period: prices are derived by taking the
arithmetic mean of the six 5-minute dispatch prices within
each 30-minute trading interval, consistent with how AEMO
calculates the TRADINGPRICE column in TradingIS post-5MS.
Data availability. NEMweb Current-directory files retain
the last ~30 days of 5-minute dispatch files. Historical
queries use the Archive daily-rollup files automatically; for
queries older than the Archive window, use
aemo_nemweb_download() with an MMSDM URL directly.
An aemo_tbl. Key columns include settlementdate
(POSIXct AEST), regionid, rrp (AUD/MWh, energy) or the
FCAS service RRPs (AUD/MW), and intervention.
AEMO NEMweb http://nemweb.com.au, AEMO Copyright Permissions Notice.
Other price:
aemo_fcas()
op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() p <- aemo_price("NSW1", now - 3600, now) head(p) }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() p <- aemo_price("NSW1", now - 3600, now) head(p) }) options(op)
Returns a static reference table of the Market Price Cap (MPC), Market Price Floor (MPF), Cumulative Price Threshold (CPT), and Administered Price Cap (APC) that apply in each NEM financial year (1 July to 30 June). These are set by the AEMC under NER 3.9.4 and indexed annually to CPI.
aemo_price_caps()aemo_price_caps()
Use this table to interpret spot-price extremes: any RRP hitting the MPC (typically AUD 15,000 to 17,500 per MWh depending on year) indicates a price cap event; when the rolling-seven-day cumulative price in a region exceeds the CPT (~AUD 1.5 million per MWh-equivalent), AEMO imposes the APC (AUD 300/MWh) until the CPT falls back below the threshold.
The table covers 2015-16 onwards and is updated on each package release. For the authoritative current values see https://www.aemc.gov.au/regulation/energy-rules/national-electricity-rules and the AEMO Reliability Settings publications.
An aemo_tbl with columns year (financial year,
"YYYY-YY"), market_price_cap_aud_per_mwh,
market_price_floor_aud_per_mwh,
cumulative_price_threshold_aud,
administered_price_cap_aud_per_mwh, and source.
Other reference:
aemo_dlf(),
aemo_interconnectors(),
aemo_mlf(),
aemo_participants(),
aemo_regions(),
aemo_settlement(),
aemo_snapshot(),
aemo_units()
caps <- aemo_price_caps() head(caps)caps <- aemo_price_caps() head(caps)
Returns a static table of the five NEM regions with metadata.
The market_timezone column is the AEMO market clock (AEST,
UTC+10, no DST, year-round) that applies to every timestamp
in NEMweb files; wall_timezone is the local civil time zone
consumers experience (observes DST in NSW/VIC/TAS/SA).
aemo_regions()aemo_regions()
An aemo_tbl with columns region, name, state,
wall_timezone, market_timezone, commenced.
Other reference:
aemo_dlf(),
aemo_interconnectors(),
aemo_mlf(),
aemo_participants(),
aemo_price_caps(),
aemo_settlement(),
aemo_snapshot(),
aemo_units()
aemo_regions()aemo_regions()
Returns AEMO's region-level estimate of rooftop PV generation, either actuals or forecasts. Published at 30-minute resolution.
aemo_rooftop_pv(region, start, end, type = c("actual", "forecast"))aemo_rooftop_pv(region, start, end, type = c("actual", "forecast"))
region |
NEM region code. |
start, end
|
Window. |
type |
One of |
The "actual" figure is an AEMO estimate derived from the APVI sampling model and weather data, not metered SCADA output. It is the best available public measure of aggregate rooftop PV generation but is subject to revision.
An aemo_tbl.
Other dispatch:
aemo_bids(),
aemo_constraints(),
aemo_dispatch_units(),
aemo_fcas_enablement(),
aemo_gencon(),
aemo_interconnector(),
aemo_market_notices(),
aemo_outages(),
aemo_spd_constraints()
op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() r <- aemo_rooftop_pv("NSW1", start = now - 3600, end = now) head(r) }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ now <- Sys.time() r <- aemo_rooftop_pv("NSW1", start = now - 3600, end = now) head(r) }) options(op)
Returns settlement reconciliation tables from MMSDM. Three views are exposed, corresponding to the three tables gentailer hedging workflows most commonly need:
aemo_settlement(table = c("cashflow", "fcas_recovery", "residues"), start, end)aemo_settlement(table = c("cashflow", "fcas_recovery", "residues"), start, end)
table |
One of |
start, end
|
Window (inclusive) applied to
|
"cashflow" (default): SETCFM (NEMDE-derived energy
settlement amounts per participant per trading interval).
"fcas_recovery": SETFCASREGIONRECOVERY (the recovery
allocation of FCAS costs to customer load per region per
trading interval).
"residues": SETRESIDUECONTRACTPAYMENT (settlement
residue auction (SRA) contract payments against
interconnector settlement residues).
Access. These tables are in the MMSDM monthly archive (not the NEMweb Current retention). Expect two-month latency between trading date and availability.
An aemo_tbl with the raw MMSDM columns for the
requested table.
AEMO NEMweb MMSDM archive, SETCFM / SETFCASREGIONRECOVERY / SETRESIDUECONTRACTPAYMENT. AEMO Copyright Permissions Notice.
aemo_mlf() for the transmission loss factors that
scale settlement amounts; aemo_interconnector() for the
flow side of the residue calculation.
Other reference:
aemo_dlf(),
aemo_interconnectors(),
aemo_mlf(),
aemo_participants(),
aemo_price_caps(),
aemo_regions(),
aemo_snapshot(),
aemo_units()
op <- options(aemo.cache_dir = tempdir()) try({ s <- aemo_settlement(table = "cashflow", start = "2024-06-01", end = "2024-06-02") head(s) }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ s <- aemo_settlement(table = "cashflow", start = "2024-06-01", end = "2024-06-02") head(s) }) options(op)
Returns a one-row-per-source provenance record for an
aemo_tbl, suitable for inclusion in a paper appendix, a
Zenodo deposit, or a CRAN-style data manifest. The snapshot
captures:
aemo_snapshot(x)aemo_snapshot(x)
x |
An |
title: the human-readable title of the table;
source: the NEMweb / MMSDM URL family the table was drawn
from;
licence: the AEMO Copyright Permissions Notice (always);
retrieved: the POSIXct timestamp at which the table was
constructed;
rows, cols: observed dimensions;
sha256: a SHA-256 digest of the table's printed body,
stable across R versions and platforms.
The sha256 column is what makes the snapshot pinnable: if
the same query returns a different hash, the underlying data
has changed (or the row-order has, which is also worth
knowing). Pair with a git commit of the analysis script to
give a reader a closed reproducibility loop.
A data frame with one row per table.
Other reference:
aemo_dlf(),
aemo_interconnectors(),
aemo_mlf(),
aemo_participants(),
aemo_price_caps(),
aemo_regions(),
aemo_settlement(),
aemo_units()
x <- structure( data.frame(settlementdate = Sys.time(), region = "NSW1", rrp = 80), aemo_title = "Demo", aemo_source = "http://nemweb.com.au", aemo_licence = "AEMO Copyright Permissions Notice", aemo_retrieved = Sys.time(), class = c("aemo_tbl", "data.frame") ) aemo_snapshot(x)x <- structure( data.frame(settlementdate = Sys.time(), region = "NSW1", rrp = 80), aemo_title = "Demo", aemo_source = "http://nemweb.com.au", aemo_licence = "AEMO Copyright Permissions Notice", aemo_retrieved = Sys.time(), class = c("aemo_tbl", "data.frame") ) aemo_snapshot(x)
Returns the SPD (Security and Projected Dispatch) constraint
coefficient tables from MMSDM. Where GENCONDATA gives the
high-level equation definition, the SPD tables give the
per-term coefficients used in the NEMDE dispatch
optimisation:
aemo_spd_constraints( table = c("region", "interconnector", "connection_point"), constraint_id = NULL )aemo_spd_constraints( table = c("region", "interconnector", "connection_point"), constraint_id = NULL )
table |
One of |
constraint_id |
Optional character vector of
|
"region": SPDREGIONCONSTRAINT (regional-demand and
regional-generation terms).
"interconnector": SPDINTERCONNECTORCONSTRAINT
(interconnector-flow terms).
"connection_point": SPDCONNECTIONPOINTCONSTRAINT
(per-DUID connection-point terms).
These tables are required for NEM dispatch replication (the
nempy Python package, Gorman, Bruce & MacGill 2022,
JOSS 7(70) 3596, https://doi.org/10.21105/joss.03596, uses all three
when reproducing NEMDE solves).
An aemo_tbl with columns from the requested SPD
table. GENCONID and FACTOR (the coefficient) are
always present; other columns vary by table.
AEMO NEMweb MMSDM archive, SPDREGIONCONSTRAINT / SPDINTERCONNECTORCONSTRAINT / SPDCONNECTIONPOINTCONSTRAINT.
aemo_gencon() for the equation-level metadata,
aemo_constraints() for the 5-min binding-constraint
feed with shadow prices.
Other dispatch:
aemo_bids(),
aemo_constraints(),
aemo_dispatch_units(),
aemo_fcas_enablement(),
aemo_gencon(),
aemo_interconnector(),
aemo_market_notices(),
aemo_outages(),
aemo_rooftop_pv()
op <- options(aemo.cache_dir = tempdir()) try({ s <- aemo_spd_constraints(table = "interconnector") head(s) }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ s <- aemo_spd_constraints(table = "interconnector") head(s) }) options(op)
Controls the delay between successive NEMweb requests. Defaults to 1 second (half a request per second).
aemo_throttle(delay = 1)aemo_throttle(delay = 1)
delay |
Numeric. Minimum delay between requests in
seconds. Internally this becomes |
Invisibly returns the previous value.
Other configuration:
aemo_cache_info(),
aemo_clear_cache()
old <- aemo_throttle(0.5) # 2 requests per second aemo_throttle(old) # restoreold <- aemo_throttle(0.5) # 2 requests per second aemo_throttle(old) # restore
Downloads the DUDETAILSUMMARY table from the most recent
MMSDM monthly archive and returns one row per registered DUID
(Dispatchable Unit Identifier) with station, region, dispatch
type, classification, and schedule type. Typical output is
500+ DUIDs covering scheduled, semi-scheduled, and
non-scheduled generators, bidirectional storage (BESS), and
loads.
aemo_units(as_of = NULL)aemo_units(as_of = NULL)
as_of |
Optional |
Effective-date filtering. DUDETAILSUMMARY is
effective-dated (START_DATE, END_DATE per row with
multiple VERSIONNO vintages per DUID over time). The
default (as_of = NULL) returns rows whose
[START_DATE, END_DATE] interval covers the date the MMSDM
archive was published: i.e. the current registry. Pass an
as_of date to get the registry as it was on that date
(essential for historical analysis: Liddell's four DUIDs
were retired in April 2023; pre-2023 queries need them).
This matches the as-of-join pattern documented in Gorman et al. (2018) NEMOSIS (APSRC) for correct historical joins.
An aemo_tbl keyed by duid. Columns include (from
DUDETAILSUMMARY): duid, stationid, regionid,
dispatchtype (GENERATOR / LOAD), connectionpointid,
schedule_type (SCHEDULED / SEMI-SCHEDULED /
NON-SCHEDULED), start_date, end_date.
AEMO NEMweb MMSDM archive, DUDETAILSUMMARY table, AEMO Copyright Permissions Notice.
Other reference:
aemo_dlf(),
aemo_interconnectors(),
aemo_mlf(),
aemo_participants(),
aemo_price_caps(),
aemo_regions(),
aemo_settlement(),
aemo_snapshot()
op <- options(aemo.cache_dir = tempdir()) try({ # Current DUID registry u <- aemo_units() # DUIDs as they were on 1 March 2023 (pre-Liddell retirement) u_2023 <- aemo_units(as_of = "2023-03-01") }) options(op)op <- options(aemo.cache_dir = tempdir()) try({ # Current DUID registry u <- aemo_units() # DUIDs as they were on 1 March 2023 (pre-Liddell retirement) u_2023 <- aemo_units(as_of = "2023-03-01") }) options(op)
Print an aemo_tbl
## S3 method for class 'aemo_tbl' print(x, ...)## S3 method for class 'aemo_tbl' print(x, ...)
x |
An |
... |
Passed to the next print method. |
Invisibly returns x.
x <- data.frame(settlementdate = Sys.time(), region = "NSW1", rrp = 80) x <- structure(x, aemo_title = "Demo", aemo_source = "http://nemweb.com.au", aemo_licence = "AEMO Copyright Permissions Notice", aemo_retrieved = Sys.time(), class = c("aemo_tbl", "data.frame")) print(x)x <- data.frame(settlementdate = Sys.time(), region = "NSW1", rrp = 80) x <- structure(x, aemo_title = "Demo", aemo_source = "http://nemweb.com.au", aemo_licence = "AEMO Copyright Permissions Notice", aemo_retrieved = Sys.time(), class = c("aemo_tbl", "data.frame")) print(x)