Core Architecture & Market Taxonomy for Energy Settlements

Energy settlement reconciliation breaks the moment two systems disagree about what a megawatt-hour is worth, when it was delivered, or which node it settled against — and it breaks silently, surfacing weeks later as an unexplained variance on a T+30 statement. This section of the energy settlement automation reference defines the market taxonomy and the deterministic system architecture that keep those disagreements from ever entering the ledger. For energy traders, settlement analysts, utility operations teams, and Python automation engineers, the integrity of P&L attribution, regulatory compliance, and cash-flow forecasting depends on a rigorously typed classification framework paired with an auditable, replayable pipeline. Regional transmission organizations (RTOs) and independent system operators (ISOs) operate under FERC and NERC mandates, emitting heterogeneous, high-frequency data streams that must be normalized, validated, and reconciled across temporal, spatial, and contractual dimensions. Without a standardized taxonomy and resilient data pipelines, settlement variances compound into margin calls, compliance penalties, and month-end close delays.

The diagram below traces the end-to-end data lineage this section governs: from raw source telemetry through normalization and three-way reconciliation to final invoice generation.

End-to-end settlement data lineage Three source feeds — ISO/RTO LMP statements, interval meter data, and ETRM trade capture — converge into an ingestion and schema-validation stage, then flow through normalization, settlement-cycle mapping, and a three-way reconciliation engine. Reconciliation variances route to an exception queue, and resolved and matched records post to the append-only settlement ledger. ISO / RTO feeds LMP statements Meter data 5–15-min intervals Trade capture ETRM positions Ingestion schema validation Normalization unified schema Cycle mapping statement run Reconciliation three-way match Exception queue Settlement ledger invoice generation variance resolved

Everything downstream — the Settlement Calculation & Validation Engines that price and validate obligations, and the Trade Ingestion & Matching Workflows that feed positions in — assumes the taxonomy and architecture described here are already in force. Get the classification wrong at this layer and no amount of downstream vectorization will recover a correct number.

Market & Regulatory Context

Settlement architecture is not a greenfield design problem; it is constrained on every side by tariff law and reliability standards, and the classification decisions made here are effectively dictated by the regulators who audit them.

The Federal Energy Regulatory Commission (FERC) approves the Open Access Transmission Tariff (OATT) and the market rules under which each RTO settles. Tariff schedules define exactly which charge types exist, how Locational Marginal Prices (LMPs) decompose, and what data a market participant is entitled to receive on preliminary versus final runs. FERC Order 2222 further pulls distributed energy resource (DER) aggregations into wholesale settlement, widening the set of resource types a taxonomy must model. Reporting obligations flow through FERC Form 1 and the Electric Quarterly Report (EQR); the authoritative index of these forms and tariff mechanics is the FERC Electric Industry Forms & Tariffs portal.

The North American Electric Reliability Corporation (NERC) governs the reliability and security envelope around the same data. NERC Critical Infrastructure Protection (CIP) standards — CIP-005 for electronic security perimeters, CIP-007 for system security management, and CIP-011 for information protection — dictate how settlement systems that touch Bulk Electric System data must be isolated, logged, and access-controlled. These map directly onto the Security & Access Boundaries enforced across settlement environments.

Regional business practice manuals (BPMs) and NAESB standards translate the tariff into machine-actionable detail: PJM’s Manual 28, CAISO’s Business Practice Manual for Settlements, ERCOT’s Nodal Protocols, and SPP’s Market Protocols each specify settlement charge codes, statement cadence, and dispute windows. State public utility commissions (PUCs) layer on retail reporting mandates. The practical consequence for architecture is that a settlement taxonomy must be versioned against a jurisdiction and an effective date — the same charge code can change meaning across a tariff revision, and a pipeline that hard-codes today’s semantics will mis-settle tomorrow’s intervals.

Core Concepts & Taxonomy

A settlement taxonomy classifies every obligation along three orthogonal axes — product, time, and location — and refuses to let a record enter the reconciliation engine until all three are resolved to canonical identifiers.

Product classification

Wholesale power markets segment obligations by delivery timeframe, pricing mechanism, and contractual structure. Day-Ahead Market (DAM) and Real-Time Market (RTM) positions clear at LMPs; Financial Transmission Rights (FTRs) and Auction Revenue Rights (ARRs) hedge congestion exposure; capacity and ancillary services settle under separate tariff schedules entirely. Each product class maps to FERC-approved charge codes and distinct settlement cadences.

Product class Market / instrument Pricing basis Typical settlement cadence
Energy — Day-Ahead DAM LMP (nodal) Preliminary T+1, final T+30
Energy — Real-Time RTM LMP (5-min → hourly integrated) Preliminary T+2, final T+55
Congestion hedge FTR / ARR Auction clearing price Monthly / annual true-up
Capacity Capacity market (e.g. RPM/RA) Auction clearing price Monthly
Ancillary services Regulation, reserves Market clearing price per service Preliminary T+2, final T+55
Losses Marginal loss component Loss factor × energy Follows energy run

Locational taxonomy and LMP decomposition

Location is the axis that most often breaks naive reconciliations. LMP is not a scalar — at any pricing node \(n\) it decomposes into a system-wide energy component, a congestion component, and a marginal loss component:

$$LMP_n = \lambda + \mu_n + \nu_n$$

where \(\lambda\) is the system energy price, \(\mu_n\) the congestion component, and \(\nu_n\) the marginal loss component at node \(n\). A reconciliation that compares a counterparty’s total LMP against your own without verifying that each component agrees will pass records that are wrong in offsetting ways. The canonical location identifiers — pnodes, aggregate nodes, load zones, and hubs — differ in naming across every ISO, which is why ISO/RTO Data Format Standards must resolve every raw node string to an internal node key before pricing.

Temporal taxonomy and cycle windows

Settlement statements arrive in staggered waves, and each wave can restate prior intervals. A standardized Settlement Cycle Mapping framework assigns every interval to the correct statement run so meter acquisition, invoice generation, and variance resolution stay synchronized across jurisdictions.

Statement run Typical window What it establishes
Preliminary / initial T+1 to T+3 First financial estimate, often on estimated meter data
Final T+30 to T+90 Settlement on validated meter data
True-up / resettlement T+4 months to T+24 months Correction of meter, price, or rule errors

Cycle definitions are where daylight-saving-time boundaries, leap seconds, and regional holiday calendars silently corrupt cash positions. A spring-forward day has 23 clock hours and a fall-back day has 25; a pipeline that assumes a fixed 24-interval grid will drop or double-count an hour of settlement every March and November unless timestamps are handled as timezone-aware instants.

Metering taxonomy and data normalization

Reconciliation logic is ultimately governed by metering classification. Interval data — typically 5-minute or 15-minute granularity — must be aggregated and reconciled against hourly or sub-hourly market statements. ANSI C12 standards (notably the C12.20 accuracy classes) define measurement-accuracy tolerances and revenue-grade telemetry requirements, while Meter Data Management (MDM) systems apply Validation, Estimation, and Editing (VEE) rules to flag missing intervals and estimate gaps. Raw telemetry rarely aligns natively with market formats, so normalizing CSV, XML, and proprietary API payloads into one unified schema — with dimensionally consistent LMP components, megawatt-hour volumes, and loss factors — is a precondition for every downstream financial model, and the province of the Schema Validation Frameworks applied at the ingestion boundary.

Architecture & Integration Patterns

The backbone of modern settlement automation is the ETRM System Architecture, which orchestrates trade capture, position management, and financial settlement. Production-grade pipelines decouple ingestion, transformation, and reconciliation into independently deployable layers so that a spike in market volatility or a malformed vendor feed degrades one stage without cascading into a full close failure. Four patterns make that decoupling durable.

Idempotent, replayable stages. Every stage must produce the same output when fed the same input, and reprocessing an interval must never double-post to the ledger. This is enforced with deterministic idempotency keys — typically a hash of (node_id, settlement_interval, product_class, statement_run) — so a resubmitted record updates in place rather than appending. Idempotency is what makes a resettlement run safe: you can replay six months of true-ups without fear of duplicating charges.

Schema enforcement at the boundary. Records are validated against an explicit contract before they touch the reconciliation engine, never after. Malformed timestamps, unknown node strings, negative volumes on unidirectional meters, and out-of-range loss factors are rejected into a dead-letter queue at the edge. The same discipline that Trade Ingestion & Matching Workflows apply to trade capture applies here to market and meter feeds.

Versioned, immutable state. Trade and price states are versioned rather than mutated in place, and the ledger is append-only. A settlement number is never overwritten; a correcting entry supersedes it, preserving a complete audit trail from initial estimate to final true-up. This immutability is what satisfies FERC and SOX auditors who need to reconstruct exactly what was known at the time each statement was issued.

Graceful degradation. When integrating with clearinghouses, ISO market data feeds, or utility MDM platforms, engineers implement fallback routing to keep the pipeline moving during API rate limits, SFTP outages, or feed degradation. Local caching, exponential retry backoff, and manual override queues prevent a single upstream stall from freezing month-end close. High-throughput, multi-ISO ingestion pushes this further into concurrency, drawing on the same Async Batch Processing Pipelines and ETRM API Integration Patterns that govern non-blocking trade retrieval.

Decoupled settlement pipeline layers Four independently deployable layers stacked top to bottom: an ingestion and adapter layer with SFTP, REST, and XML connectors; a normalization layer performing schema validation and node resolution; a reconciliation core running an idempotent three-way match; and an append-only settlement ledger. Records that fail schema enforcement at the ingestion boundary are rejected into a dead-letter queue, and a retry-with-backoff loop guards the same boundary against upstream feed outages. Ingestion & adapter layer SFTP REST XML / API Normalization layer schema validation node resolution Reconciliation core idempotent three-way match Append-only settlement ledger versioned, immutable, auditable Dead-letter queue malformed records rejected at the edge reject retry / backoff

Python Implementation Overview

For Python engineers, production readiness on this layer rests on three habits: vectorized processing for interval math, the decimal module for every financial quantity, and deterministic idempotency keys so runs are replayable. The reconciliation engine performs three-way matching — trade capture versus ISO settlement versus utility meter data — with variance thresholds configurable per product class. Libraries such as pandas or polars handle interval-to-hourly aggregation and numpy handles LMP component decomposition, but the money itself never touches a binary float, where 0.1 + 0.2 fails to equal 0.3 and pennies drift across millions of intervals.

The snippet below normalizes a raw ISO statement into the unified schema, resolves each node, and computes an idempotency key and a decimal-safe settlement amount for every interval.

import hashlib
from decimal import Decimal, ROUND_HALF_EVEN

import pandas as pd

# Money is Decimal end to end; floats are barred from settlement arithmetic.
CENTS = Decimal("0.01")


def normalize_iso_statement(
    lmp_df: pd.DataFrame,
    node_map: dict[str, str],
    statement_run: str,
) -> pd.DataFrame:
    """Normalize a raw ISO LMP statement into the unified settlement schema.

    Expects columns: interval_start (UTC), raw_node, lmp, energy_mwh.
    Returns one row per settlement interval with a decimal amount and an
    idempotency key suitable for an append-only ledger upsert.
    """
    df = lmp_df.copy()

    # 1. Timezone-aware instants only — never a naive 24-interval assumption.
    df["settlement_interval"] = pd.to_datetime(df["interval_start"], utc=True)

    # 2. Resolve every raw node string to a canonical internal node key.
    df["node_id"] = df["raw_node"].map(node_map)
    unresolved = df["node_id"].isna()
    if unresolved.any():
        raise ValueError(
            f"{int(unresolved.sum())} unresolved nodes: "
            f"{sorted(df.loc[unresolved, 'raw_node'].unique())}"
        )

    # 3. Decimal arithmetic for money; banker's rounding to the cent.
    df["settlement_amount"] = [
        (Decimal(str(price)) * Decimal(str(volume))).quantize(
            CENTS, rounding=ROUND_HALF_EVEN
        )
        for price, volume in zip(df["lmp"], df["energy_mwh"])
    ]

    # 4. Deterministic idempotency key -> safe to replay / resettle.
    def _key(row: pd.Series) -> str:
        basis = f"{row.node_id}|{row.settlement_interval.isoformat()}|{statement_run}"
        return hashlib.sha256(basis.encode()).hexdigest()

    df["ledger_key"] = df.apply(_key, axis=1)
    return df[
        ["ledger_key", "node_id", "settlement_interval",
         "settlement_amount", "energy_mwh"]
    ]

The pricing and loss stages that consume this normalized frame live in the Pricing Logic Implementation and Loss Factor Mapping Strategies components, and the deviation math in the Imbalance Allocation Algorithms component — each of which assumes the decimal-typed, node-resolved contract established above. Interval-to-hourly aggregation and feed parsing patterns are covered under Pandas for Trade Data Processing. For production temporal handling, consult the official Python Data Analysis Documentation.

Validation & Compliance Requirements

An architecture is only as trustworthy as the evidence it can produce under audit, so validation and logging are first-class stages, not afterthoughts bolted on before close.

Cryptographic audit trails. Every transformation is logged with a content hash of its inputs and outputs, so an auditor can prove that a given ledger figure was derived from a specific set of meter and price records and was never tampered with. The ledger_key above and a per-run manifest hash together let you replay a statement and confirm bit-for-bit reproducibility across preliminary and final runs.

Exception routing thresholds. Variance between the three matched sources is compared against per-product tolerance bands; breaches route to an exception queue rather than halting the pipeline, and the band configuration itself is versioned. Tuning those bands so they catch real errors without drowning analysts in false positives is the job of Threshold Tuning & Alerts. Structured alerts carry the ledger_key, the disagreeing sources, and the signed variance so an analyst can triage without re-deriving the number.

Edge-case coverage. Production pipelines carry explicit unit tests for the cases that quietly corrupt settlement: negative LMPs (legitimate during oversupply), zero-megawatt intervals, DST spring-forward and fall-back boundaries, leap-year and holiday calendar offsets, and schema drift after a tariff revision. Continuous integration runs these on every change so a market-rule update cannot regress a prior close.

Access segregation. FERC and SOX readiness require role-based access control, encryption at rest and in transit, and immutable logging across production, UAT, and development tiers. Settlement analysts and traders get read-only access to finalized statements; automation engineers get isolated staging environments; nobody overwrites a finalized ledger. These controls are specified in full under Security & Access Boundaries.

Cross-Market Reconciliation at Scale

As portfolios expand across balancing authorities, reconciliation complexity scales non-linearly. A multi-ISO reconciliation layer delivers unified variance tracking, consolidated cash positioning, and standardized exception handling across PJM, CAISO, ERCOT, and SPP simultaneously. Achieving that requires harmonizing disparate node-naming conventions, loss-factor methodologies, and settlement-calendar offsets into one analytical model, and accounting for inter-tie scheduling, wheeling charges, and regional ancillary-service allocations when computing net cash positions. The taxonomy defined earlier — product, time, location, each resolved to a canonical key with a jurisdiction and effective date — is precisely what makes a single reconciliation engine able to span four markets without a bespoke code path per ISO.

Explore This Section

Each component below owns a distinct slice of the architecture and taxonomy described above:

  • Settlement Cycle Mapping — assigning every interval to the correct preliminary, final, and true-up statement run across jurisdictions and DST boundaries.
  • ISO/RTO Data Format Standards — parsing and normalizing CSV, XML, and API payloads and resolving raw node strings into one unified schema.
  • ETRM System Architecture — orchestrating trade capture, position management, and financial settlement with decoupled, replayable stages.
  • Security & Access Boundaries — RBAC, encryption, immutable logging, and tier segregation for FERC, NERC CIP, and SOX readiness.
  • Metering Data Integration — ingesting MDM interval usage through Validation, Estimation, and Editing into a settlement-interval-aligned, gap-flagged frame.
  • Reference Data Management — versioning pricing nodes, calendars, and tariff revisions so every historical run resolves the data that was in force.

Frequently Asked Questions

Why doesn’t my LMP decomposition sum to the nodal price?

Because at least one component is missing or mis-signed. A nodal LMP equals the system energy price plus the congestion component plus the marginal loss component (\(LMP_n = \lambda + \mu_n + \nu_n\)). If your total disagrees, verify you are reading the loss component (which is negative at export-constrained nodes and positive at import-constrained ones) and that you have not silently dropped congestion. Reconcile each component independently, not just the total, or offsetting errors will pass validation.

What is the difference between preliminary, final, and true-up settlement runs?

They are the same intervals settled at increasing levels of data maturity. The preliminary run (T+1 to T+3) is an early estimate often computed on estimated meter data; the final run (T+30 to T+90) settles on validated meter data; true-up or resettlement runs (months later) correct meter, price, or market-rule errors. An append-only, versioned ledger lets each run supersede the prior one without losing the audit history.

Why must settlement arithmetic use Python’s decimal module instead of float?

Binary floating point cannot represent most decimal fractions exactly, so 0.1 + 0.2 != 0.3, and those sub-cent errors accumulate across millions of intervals into material ledger drift that fails audit. The decimal module represents monetary values exactly and supports explicit banker’s rounding (ROUND_HALF_EVEN), producing reproducible, penny-accurate settlements.

How do daylight-saving-time boundaries corrupt settlement cycles?

A spring-forward day has 23 clock hours and a fall-back day has 25, so a pipeline that assumes a fixed 24-interval grid drops an hour every March and double-counts one every November. Handling all timestamps as timezone-aware UTC instants and mapping to local settlement periods explicitly — never inferring the count from a date — prevents the gap-and-overlap errors that otherwise surface as unexplained variances.

Explore this section