Historical California NP15 Day-Ahead Prices

Historical California NP15 Day-Ahead Prices

You need reliable historical CAISO NP15 Day-Ahead power prices in a finance workflow, and you want a paste-and-run path to query, parse, and store them. By the end of this guide you will fetch the California NP15 Day-Ahead series by symbol code CAISO_NP15_DA, understand the response fields, and wire the data into your pricing models with production-ready curl, Python, and JavaScript examples.

What the CAISO NP15 Day-Ahead price represents and how finance teams use it

The California NP15 Day-Ahead series reflects the day-ahead power price level for the NP15 hub in the CAISO market, expressed in USD per MWh. Finance teams use it to value hedges, mark power positions, build implied heat-rate views, and benchmark PPA pricing. The Energy API exposes this series under the symbol code CAISO_NP15_DA with units of USD/MWh, letting you query historical windows or the latest snapshot via a single timeseries endpoint.

Illustration: Historical California NP15 Day-Ahead Prices

In a typical finance integration, you will:

  • Pull a date range of daily values for CAISO_NP15_DA.
  • Normalize units (USD/MWh) and confirm base currency matches the series’ currency.
  • Cache responses for repeatable backtests, and handle non-trading days logically.
  • Aggregate to months/quarters for hedge accounting or budgeting.

Quickstart: fetch NP15 Day-Ahead history with curl

The Energy API uses a GET timeseries endpoint. Authentication is via an api_key query parameter. Use YOUR_API_KEY as the placeholder when testing this guide.

curl -G "https://energy-api.com/api/v1/timeseries" --data-urlencode "start=2026-01-01" --data-urlencode "end=2026-03-31" --data-urlencode "symbols=CAISO_NP15_DA" --data-urlencode "api_key=YOUR_API_KEY"

Notes for finance integrations:

  • Symbol name: California NP15 Day-Ahead (code: CAISO_NP15_DA).
  • Unit: USD/MWh. Store units alongside values for auditability.
  • Auth: api_key query parameter only (use YOUR_API_KEY in examples; do not hardcode credentials in source control).
  • If you later combine series with other assets (for example TTF_GAS or EUA_CO2), do not pass base=USD alongside those; respect the API’s base currency mode guidance.

Response structure and the fields you will actually use

Below are two official response shapes you will encounter. The first block is the official sample from live documentation, and the second block is a real response for the NP15 Day-Ahead symbol that you will parse in your application. Treat the currencies and dates maps as authoritative metadata for downstream calculations.

Official sample response (copy as-is for testing parsers)

{
"success": true,
"date": "2026-10-23",
"base": "EUR",
"rates": {
"OMIE_ES_DA": 110.0906
},
"dates": {
"OMIE_ES_DA": "2026-10-23"
},
"currencies": {
"OMIE_ES_DA": "EUR"
},
"base_filter_note": null
}

What to note in the official sample:

  • success: Boolean request status.
  • date: The API’s reference date for the response.
  • base: The base currency context for the response (EUR in this example).
  • rates: Keyed by symbol; the numeric price value for that symbol.
  • dates: Keyed by symbol; the effective date for the rate provided.
  • currencies: Keyed by symbol; the currency for that symbol’s quote.

Real CAISO NP15 Day-Ahead response example (use these exact values)

{"success":true,"date":"2026-10-21","base":"USD","rates":{"CAISO_NP15_DA":56.6361},"dates":{"CAISO_NP15_DA":"2026-10-21"},"currencies":{"CAISO_NP15_DA":"USD"},"base_filter_note":null}

How to interpret for NP15 Day-Ahead in a finance workflow:

  • rates.CAISO_NP15_DA is the price level for NP15 Day-Ahead for the given date (unit: USD/MWh).
  • dates.CAISO_NP15_DA provides the effective date. Use this date as your primary key in a price table.
  • currencies.CAISO_NP15_DA confirms currency is USD. This should match your valuation currency or be converted outside the API if needed.

Single-day fetch example (identical to the real response above, used to validate your parser)

{"success":true,"date":"2026-10-21","base":"USD","rates":{"CAISO_NP15_DA":56.6361},"dates":{"CAISO_NP15_DA":"2026-10-21"},"currencies":{"CAISO_NP15_DA":"USD"},"base_filter_note":null}

This duplicate example is intentional so you can test idempotent parsing and upsert logic without changing any expected values between runs.

Cross-checking base currency handling (official sample again)

{
"success": true,
"date": "2026-10-23",
"base": "EUR",
"rates": {
"OMIE_ES_DA": 110.0906
},
"dates": {
"OMIE_ES_DA": "2026-10-23"
},
"currencies": {
"OMIE_ES_DA": "EUR"
},
"base_filter_note": null
}

If your finance backend uses a single-currency book, ensure your data warehouse keeps both base and per-symbol currencies, then convert in ETL if needed. For NP15 specifically, you will see USD as the symbol’s currency.

Python: query CAISO_NP15_DA and normalize to a price table

This example reads the response and prepares a record suitable for insertion into a warehouse table keyed by trade_date and symbol. It uses the endpoint and fields exactly as described above and respects the currency metadata.

import os
import json
import datetime as dt
from urllib.parse import urlencode
from urllib.request import urlopen, Request

API_URL = "https://energy-api.com/api/v1/timeseries"
API_KEY = os.getenv("ENERGY_API_KEY", "YOUR_API_KEY")

params = {
"start": "2026-01-01",
"end": "2026-03-31",
"symbols": "CAISO_NP15_DA",
"api_key": API_KEY
}

url = f"{API_URL}?{urlencode(params)}"
req = Request(url)
with urlopen(req) as resp:
payload = json.loads(resp.read().decode("utf-8"))

if not payload.get("success"):
raise RuntimeError("API call failed")

# Extract the fields you actually need
symbol = "CAISO_NP15_DA"
price = payload["rates"].get(symbol)
price_date = payload["dates"].get(symbol)
currency = payload["currencies"].get(symbol)
base_currency = payload.get("base")

# Build a normalized record (example)
record = {
"trade_date": price_date, # "YYYY-MM-DD"
"symbol": symbol, # CAISO_NP15_DA
"price": price, # numeric
"unit": "USD/MWh", # documented unit
"symbol_currency": currency, # should be "USD" for NP15 DA
"base_currency": base_currency # may match symbol currency
}

print(json.dumps(record, indent=2))

Production tips for finance code:

  • Upsert by (trade_date, symbol) to keep historical runs idempotent.
  • Store unit and currency with the price to avoid ambiguous joins later.
  • If you aggregate to monthly averages for settlement estimation, compute after loading the daily series to preserve audit trails.

JavaScript: fetch and return a series datum

The following snippet requests the same window and extracts the symbol’s price, effective date, and currency for downstream charting or valuation UIs.

const API_URL = "https://energy-api.com/api/v1/timeseries";
const params = new URLSearchParams({
start: "2026-01-01",
end: "2026-03-31",
symbols: "CAISO_NP15_DA",
api_key: "YOUR_API_KEY"
});

async function fetchNp15() {
const res = await fetch(`${API_URL}?${params.toString()}`, { method: "GET" });
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
if (!data.success) throw new Error("API returned success=false");

const sym = "CAISO_NP15_DA";
return {
trade_date: data.dates[sym],
price: data.rates[sym],
currency: data.currencies[sym],
base: data.base
};
}

fetchNp15()
.then((row) => console.log(row))
.catch((err) => console.error(err));

For UI plotting, you can map the API’s date field directly to your x-axis and the price to y. Persist the response to local storage or an app cache to reduce repeat calls when a user toggles date windows.

Choosing date windows, understanding timezones, and handling gaps

Day-ahead power prices are daily values. When you select a window with start and end, the API returns values keyed by effective dates. Treat dates as plain calendar dates in your warehouse and avoid adding timezone logic to the key fields; use them for scheduling and refresh windows, not for the identity of a price datum.

  • Timezone: The response dates are ISO calendar dates (YYYY-MM-DD). Use them as canonical keys.
  • Non-trading days: Power markets can have days without new quotes due to holidays or scheduling. Align your analytics to a business calendar and use forward/backfill logic with explicit flags if you need continuous series.
  • Backfills: If you rerun a window, upsert on (symbol, trade_date) so late-arriving corrections overwrite prior values deterministically.

Caching, retries, and request budgeting

To keep finance backfills reproducible and cost-controlled, you should:

  • Cache successful responses by URL (start, end, symbols, api_key) for a limited time during ETL runs.
  • Retry transient network errors with exponential backoff; do not retry client errors without code changes.
  • Batch symbols where appropriate, but keep CAISO_NP15_DA isolated if you only need NP15 to avoid unnecessary payloads.
  • Plan usage: Starter $19.99/mo with a 7-day trial / 50 calls is available. Use the trial to finalize your schema and validations before scaling.

Validating units and currency handling

This is a finance integration, so unit and currency consistency can make or break reconciliation:

  • Unit: CAISO_NP15_DA is in USD/MWh. If you must compare to $/kWh, convert by dividing by 1000 (1 MWh = 1000 kWh) and document the conversion explicitly in your ETL.
  • Currency: Check currencies.CAISO_NP15_DA. It will be USD for NP15 Day-Ahead. Store both symbol currency and base in your warehouse row for verifiability.
  • Base currency: The top-level base may appear in the payload. Keep it for audit fields but rely on currencies[<symbol>] for the authoritative per-symbol currency.
  • Multi-asset note: Do not pass base=USD when you also need TTF_GAS or EUA_CO2 in the same request, as per the catalog facts. Keep NP15 requests simple and single-currency unless you have a specific need.

Practical parsing patterns that save time

Finance code benefits from consistent parsing conventions. Adopt these patterns early:

  • Field access: Always read price via rates[<symbol>], date via dates[<symbol>], and currency via currencies[<symbol>]. Avoid inferring currency from base.
  • Schema: Use (trade_date, symbol) as a unique key; add price, unit, symbol_currency, base_currency, ingestion_ts.
  • Validation: Assert unit == "USD/MWh" for CAISO_NP15_DA in your loader and fail fast if unexpected units or currencies appear.
  • Audit: Persist the raw JSON payload alongside parsed fields for replay and investigative work.

Finance-ready aggregations: monthlies and rolling windows

Once you have daily NP15 prices stored, you can compute:

  • Monthly averages for settlement estimation or budgeting.
  • Rolling 30-day means for volatility dampening in marks.
  • Quarterly averages for hedge effectiveness testing.

Do these computations inside your analytics layer (SQL or a data frame) using the daily series you ingest with the endpoint covered above. Because the API provides clear dates and currencies, you can easily group by YYYY-MM and average price fields for period marks.

End-to-end example: ETL steps with validation

Below is a concise outline you can implement in your pipeline tooling. It uses the documented endpoint, the CAISO_NP15_DA symbol, and enforces metadata checks:

  1. Fetch: Call GET /api/v1/timeseries with start, end, symbols=CAISO_NP15_DA, api_key=YOUR_API_KEY.
  2. Validate: Assert success==true, currencies.CAISO_NP15_DA=="USD", unit recorded as "USD/MWh".
  3. Normalize: For each date in the window, create a record (trade_date, symbol, price, unit, currency, base, source_payload_hash).
  4. Upsert: Insert or update into your price table keyed by (trade_date, symbol).
  5. Aggregate: Create materialized monthly averages keyed by (YYYY-MM, symbol) for finance reporting.

Additional JSON example for parser tests (real NP15 payload)

{"success":true,"date":"2026-10-21","base":"USD","rates":{"CAISO_NP15_DA":56.6361},"dates":{"CAISO_NP15_DA":"2026-10-21"},"currencies":{"CAISO_NP15_DA":"USD"},"base_filter_note":null}

Use this repeated real payload to validate that your loader is idempotent and safe to re-run without creating duplicates, and that it consistently respects symbol-level currency and date fields.

Common errors and how to avoid them

  • Mixing symbols and currencies: Always use currencies[<symbol>] to confirm the per-symbol currency rather than assuming it equals base.
  • Schema drift: If you later add new symbols, keep the same schema fields and do not overload unit or currency columns.
  • Over-requesting: For backfills, segment by quarter or year as needed, but avoid unnecessary additional symbols in the same call.

FAQ

How do I authenticate?
Use the api_key query parameter. In examples, use YOUR_API_KEY. Do not embed real keys in code samples checked into source control.

Which symbol code should I use for NP15 Day-Ahead?
Use CAISO_NP15_DA. The unit is USD/MWh.

How do I get a historical window of prices?
Call GET /api/v1/timeseries with start, end, symbols=CAISO_NP15_DA, and api_key. Parse rates.CAISO_NP15_DA and dates.CAISO_NP15_DA.

What currency should I store?
Store currencies.CAISO_NP15_DA and also the top-level base for auditability. For NP15, expect USD for the symbol currency.

Should I pass base=USD?
Do not pass base=USD when you also need TTF_GAS or EUA_CO2 in the same request. For NP15-only workflows, you generally do not need to set base explicitly.

Register and build your integration

Create your API key and start testing the exact calls shown above. The trial includes 7 days / 50 calls, which is usually enough to finalize your schema and ETL checks. Register here: Register. When you are ready to extend or double-check parameters and fields, refer to the docs: Documentation.

Ready to get started?

Get your API key and start querying energy commodity prices in minutes.

Get API Key