Backtesting Renewable Hedging Strategies: Using Energy API to Simulate Spread, Curtailment, and Volatility Scenarios
Renewables are surging onto grids worldwide, and with them comes a new hedging problem set: volatile intraday prices when clouds roll in, curtailment risks when negative prices bite at peak solar, and cross-commodity spreads that can make or break margin for corporate buyers and utilities. Building a robust backtesting stack to simulate these realities has historically been a tangle of CSV scrapers, off-by-one calendars, and inconsistent symbol taxonomies from multiple market portals.
In this post, we’ll build a developer-first path to backtesting renewable hedging strategies—spreads, curtailment exposure, and volatility stress tests—using a single normalized REST surface. We’ll use the Energy API to source historical and intraday electricity curves, gas and oil benchmarks, EU ETS carbon allowances, and grid carbon intensity. Along the way, we’ll highlight repeatable patterns that let you model PPA risk, shape hedges with day-ahead auctions, and quantify carbon-aware dispatch outcomes without days of bespoke ETL.
Whether you ship P&L dashboards for traders, risk engines for corporates, or ESG telemetry for sustainability products, the techniques below will help you move from idea to production quickly. Our focus is practical: which endpoints to call, how to interpret JSON fields, how to link cross-commodity time series, and how to design a backtest that survives the messy reality of energy-market calendars.
Why Energy API
When you backtest spreads or simulate curtailment, consistency matters more than anything. Renewable hedging lives at the edge where intraday electricity curves, gas benchmarks, and carbon prices collide—each published by different operators, on different schedules, and in different formats. The friction comes from misaligned calendars, missing hours, currency mismatches, and subtle differences in symbol naming. Energy API removes that friction so you can focus on strategy logic instead of plumbing.
- One normalized REST surface across electricity, gas, oil, coal, carbon, and carbon intensity: Instead of piecing together OMIE, ENTSO-E, ESIOS, EIA/FRED, and Ember payloads, you call one JSON schema. Your parser doesn’t change when you switch from OMIE day-ahead to EUA CO2 allowances.
- Ship in hours, not weeks: The same parameter model—start, end, symbols—works across commodities. Developers can prototype curtailment detection with /electricity/hourly and then drop the result into a volatility stress framework with /ohlc and /fluctuation, without rewriting data pipelines.
- Intraday curves where they exist: You can fetch granular day-ahead and intraday electricity curves (e.g., 15-minute or hourly) to measure ramp, tail risk, and negative-price windows that drive renewable curtailment logic and PPA settlement variability.
- Cross-commodity joins in a single call: Request BRENT_CRUDE, TTF_GAS, and EUA_CO2 next to OMIE_ES_DA to quantify spark/dark spreads, fuel switching thresholds, and carbon-aware dispatch behaviors—without juggling four different providers’ formats.
The payoffs for hedging analytics are immediate: less time normalizing calendars and more time simulating hedges, stress-testing basis risk, and publishing results into your applications.
Quick Start
The base URL is:
https://energy-api.com/api/v1
Each request contains an api_key query parameter. Here’s a first call to fetch the most recent prices for a cross-commodity bundle—Brent crude, TTF gas, and EU ETS allowances—to initialize a spread calculator or sanity check your backtest inputs.
curl -G https://energy-api.com/api/v1/latest \
--data-urlencode "symbols=BRENT_CRUDE,TTF_GAS,EUA_CO2" \
--data-urlencode "api_key=YOUR_API_KEY"
Example response:
{
"success": true,
"date": "2026-06-11",
"base": "MIXED",
"rates": {
"BRENT_CRUDE": 74.82,
"TTF_GAS": 38.15,
"EUA_CO2": 67.40
},
"dates": {
"BRENT_CRUDE": "2026-06-11",
"TTF_GAS": "2026-06-11",
"EUA_CO2": "2026-06-11"
},
"currencies": {
"BRENT_CRUDE": "USD",
"TTF_GAS": "EUR",
"EUA_CO2": "EUR"
}
}
What to note:
- base: "MIXED" means you requested symbols priced in multiple currencies. Hedge backtests often keep native currencies for realism; you can also rebalance to a common base in post-processing.
- rates: Contains the most recent values per symbol. Use these as spot anchors when seeding Monte Carlo paths or computing end-of-day P&L diffs.
- dates: Publish dates per symbol. Some commodities publish on different calendars; during backtests, match by date before spreading to avoid introducing look-ahead bias.
- currencies: Keep this mapping attached to your time series for transparent FX handling.
Core Endpoints for Hedging Backtests
To simulate renewable hedging, you need four building blocks:
- Historical series: backfill spread regimes and volatility clusters.
- Intraday curves: detect curtailment and negative-price windows.
- Auction results and forecasts: wire in the next day’s day-ahead curve deterministically.
- Volatility summaries and candles: create quick regimes for stress testing.
1) GET /timeseries — Historical series for spreads and long-horizon backtests
Path: /timeseries
Key params:
- start (YYYY-MM-DD, required)
- end (YYYY-MM-DD, required)
- symbols (comma-separated, required) — e.g., OMIE_ES_DA, TTF_GAS, EUA_CO2
- base (optional)
Use this to compute long-run statistics: e.g., the distribution of (OMIE_ES_DA − TTF_GAS × heat_rate − EUA_CO2 × emissions_factor). You’ll often use electricity day-ahead prices with gas and carbon to emulate spark spreads under renewable supply shocks.
curl -G https://energy-api.com/api/v1/timeseries \
--data-urlencode "start=2025-01-01" \
--data-urlencode "end=2025-03-31" \
--data-urlencode "symbols=OMIE_ES_DA,TTF_GAS,EUA_CO2" \
--data-urlencode "api_key=YOUR_API_KEY"
Example response:
{
"success": true,
"base": "MIXED",
"start_date": "2025-01-01",
"end_date": "2025-03-31",
"rates": {
"OMIE_ES_DA": {
"2025-01-01": 64.12,
"2025-01-02": 59.80,
"2025-01-03": 57.45
},
"TTF_GAS": {
"2025-01-01": 46.80,
"2025-01-02": 46.10,
"2025-01-03": 47.10
},
"EUA_CO2": {
"2025-01-01": 71.20,
"2025-01-02": 70.85,
"2025-01-03": 72.10
}
},
"frequencies": {
"OMIE_ES_DA": "daily",
"TTF_GAS": "daily",
"EUA_CO2": "daily"
},
"currencies": {
"OMIE_ES_DA": "EUR",
"TTF_GAS": "EUR",
"EUA_CO2": "EUR"
}
}
How to use it:
- rates: Per-symbol date-keyed values—ideal for joins in pandas/Polars. If your renewable backtest needs cohorts (e.g., winter vs. summer), group by calendar features after merge.
- frequencies: Confirms cadence—primarily daily for these examples. If you mix daily commodities with intraday electricity, align at daily for spread stats, intraday for curtailment windows.
- currencies: Keeps FX context explicit. If you compute spreads in EUR, confirm mixed USD legs (e.g., oil benchmarks) are converted consistently.
2) GET /electricity/hourly — Intraday curves for curtailment simulation
Path: /electricity/hourly
Key params:
- symbol (required) — e.g., OMIE_ES_DA, EPEX_DE_DA, AEMO_NSW1
- date (YYYY-MM-DD, required)
Curtailment analysis depends on hourly or 15-minute prices—especially where negative-price windows incentivize turning down renewable assets. Use this endpoint to pull the full curve for a given date, then compute PPA settlement impacts or negative-period durations.
curl -G https://energy-api.com/api/v1/electricity/hourly \
--data-urlencode "symbol=OMIE_ES_DA" \
--data-urlencode "date=2025-09-15" \
--data-urlencode "api_key=YOUR_API_KEY"
Example response:
{
"success": true,
"symbol": "OMIE_ES_DA",
"date": "2025-09-15",
"granularity": "hourly",
"currency": "EUR",
"curve": [
{ "time": "2025-09-15T00:00:00+02:00", "price": 52.10 },
{ "time": "2025-09-15T01:00:00+02:00", "price": 49.80 },
{ "time": "2025-09-15T02:00:00+02:00", "price": 45.70 },
{ "time": "2025-09-15T03:00:00+02:00", "price": 44.20 },
{ "time": "2025-09-15T04:00:00+02:00", "price": 42.90 },
{ "time": "2025-09-15T05:00:00+02:00", "price": 41.75 },
{ "time": "2025-09-15T06:00:00+02:00", "price": 43.30 },
{ "time": "2025-09-15T07:00:00+02:00", "price": 48.40 },
{ "time": "2025-09-15T08:00:00+02:00", "price": 55.20 },
{ "time": "2025-09-15T09:00:00+02:00", "price": 60.10 },
{ "time": "2025-09-15T10:00:00+02:00", "price": 58.50 },
{ "time": "2025-09-15T11:00:00+02:00", "price": 56.80 },
{ "time": "2025-09-15T12:00:00+02:00", "price": 51.60 },
{ "time": "2025-09-15T13:00:00+02:00", "price": 42.10 },
{ "time": "2025-09-15T14:00:00+02:00", "price": 38.40 },
{ "time": "2025-09-15T15:00:00+02:00", "price": 35.60 },
{ "time": "2025-09-15T16:00:00+02:00", "price": 29.90 },
{ "time": "2025-09-15T17:00:00+02:00", "price": 33.10 },
{ "time": "2025-09-15T18:00:00+02:00", "price": 46.30 },
{ "time": "2025-09-15T19:00:00+02:00", "price": 59.40 },
{ "time": "2025-09-15T20:00:00+02:00", "price": 65.80 },
{ "time": "2025-09-15T21:00:00+02:00", "price": 61.20 },
{ "time": "2025-09-15T22:00:00+02:00", "price": 57.00 },
{ "time": "2025-09-15T23:00:00+02:00", "price": 54.40 }
]
}
How to use it:
- curve: Time-stamped prices that reflect the auction-published day-ahead schedule. Compute the number of hours below zero (if present), or below your PPA strike, to quantify curtailment and settlement variance.
- granularity: Can be hourly or 15-minute depending on the market. Be explicit when resampling so your volumetric allocations match.
- time: Always treat timestamps with timezone awareness. Daylight saving transitions can produce 23 or 25 hours; your backtest engine should handle these edge cases cleanly.
3) GET /ohlc — Candles to summarize volatility regimes
Path: /ohlc
Key params:
- symbols (required)
- period (weekly|monthly|quarterly, default monthly)
- start, end (optional)
- base (optional)
When creating volatility scenarios or stress buckets (e.g., “monthly drawdown,” “weekly spike”), OHLC candles help compress thousands of points into a handful of risk-relevant metrics. Pair them with intraday electricity curves to build realistic tail profiles around key market regimes.
curl -G https://energy-api.com/api/v1/ohlc \
--data-urlencode "symbols=TTF_GAS,EUA_CO2" \
--data-urlencode "period=monthly" \
--data-urlencode "start=2024-01-01" \
--data-urlencode "end=2024-12-31" \
--data-urlencode "api_key=YOUR_API_KEY"
Example response:
{
"success": true,
"period": "monthly",
"data": {
"TTF_GAS": [
{ "period": "2024-01", "open": 36.80, "high": 42.10, "low": 34.50, "close": 39.20, "data_points": 23 },
{ "period": "2024-02", "open": 39.25, "high": 41.50, "low": 35.10, "close": 36.00, "data_points": 21 }
],
"EUA_CO2": [
{ "period": "2024-01", "open": 85.40, "high": 89.30, "low": 80.00, "close": 82.10, "data_points": 20 },
{ "period": "2024-02", "open": 82.15, "high": 84.20, "low": 75.80, "close": 76.90, "data_points": 19 }
]
},
"currencies": {
"TTF_GAS": "EUR",
"EUA_CO2": "EUR"
}
}
How to use it:
- open, high, low, close: Classic candle elements for scenario construction. For a simple stress set, sample from “high” or “low” regimes and stitch with your intraday shape.
- data_points: Number of observations contributing to the candle; helps sanity-check months with holidays or publishing gaps.
- period format: "YYYY-MM" or "YYYY-Wxx" depending on aggregation. Bind your backtester’s windowing logic to this key.
4) GET /fluctuation — Start/end and percentage change windows for spread windows
Path: /fluctuation
Key params:
- start (YYYY-MM-DD, required)
- end (YYYY-MM-DD, required)
- symbols (required)
- base (optional)
Fluctuation provides start_value, end_value, absolute change, and percentage change. Use this to rank periods of stress, select backtest windows, or quantify hedge slippage from start-of-month to end-of-month.
curl -G https://energy-api.com/api/v1/fluctuation \
--data-urlencode "start=2025-10-01" \
--data-urlencode "end=2025-12-31" \
--data-urlencode "symbols=OMIE_ES_DA,TTF_GAS,EUA_CO2" \
--data-urlencode "api_key=YOUR_API_KEY"
Example response:
{
"success": true,
"start_date": "2025-10-01",
"end_date": "2025-12-31",
"results": {
"OMIE_ES_DA": { "start_value": 68.20, "end_value": 72.10, "change": 3.90, "change_pct": 5.72 },
"TTF_GAS": { "start_value": 41.50, "end_value": 36.80, "change": -4.70, "change_pct": -11.33 },
"EUA_CO2": { "start_value": 69.40, "end_value": 71.25, "change": 1.85, "change_pct": 2.67 }
},
"currencies": {
"OMIE_ES_DA": "EUR",
"TTF_GAS": "EUR",
"EUA_CO2": "EUR"
}
}
How to use it:
- change_pct: Great for filtering volatile quarters and training your scenario generator on high-stress intervals.
- Pair with /ohlc: Derive realistic bounds and then drill down into intraday detail for your curtailment logic with /electricity/hourly.
5) GET /forecast — Next published day-ahead lookup for auction symbols
Path: /forecast
Key params:
- symbol (required) — returns 404 for non-auction symbols.
For deterministic backtests that mimic operations, you often need “the next published day-ahead price.” This endpoint surfaces the latest published auction result for supported electricity markets so your simulated dispatch doesn’t peek into the future.
curl -G https://energy-api.com/api/v1/forecast \
--data-urlencode "symbol=OMIE_ES_DA" \
--data-urlencode "api_key=YOUR_API_KEY"
Example response:
{
"success": true,
"symbol": "OMIE_ES_DA",
"target_date": "2026-06-12",
"currency": "EUR",
"type": "day_ahead_published",
"value": 63.40
}
How to use it:
- target_date: The delivery day of the day-ahead schedule. In backtests, advance your state machine only when new auction results become available.
- value: Single-day average from the published curve. If you need the full curve, pair with /electricity/hourly by date once the auction result is live.
Reference Endpoints You’ll Use Along the Way
GET /symbols — Discoverability with metadata
Before wiring a region or commodity into your model, list available symbols and metadata.
curl -G https://energy-api.com/api/v1/symbols \
--data-urlencode "category=electricity" \
--data-urlencode "api_key=YOUR_API_KEY"
Example response:
{
"success": true,
"count": 3,
"symbols": [
{
"symbol": "OMIE_ES_DA",
"name": "OMIE Spain Day-Ahead",
"category": "electricity",
"country_code": "ES",
"currency_code": "EUR",
"frequency": "daily",
"description": "OMIE day-ahead price published by OMIE."
},
{
"symbol": "EPEX_DE_DA",
"name": "EPEX Germany Day-Ahead",
"category": "electricity",
"country_code": "DE",
"currency_code": "EUR",
"frequency": "daily",
"description": "EPEX Germany day-ahead price."
},
{
"symbol": "AEMO_NSW1",
"name": "AEMO NSW Region Price",
"category": "electricity",
"country_code": "AU",
"currency_code": "AUD",
"frequency": "hourly",
"description": "AEMO New South Wales price."
}
]
}
Use cases:
- Filter by category and country_code to discover targets for a regional hedging backtest.
- frequency hints at granularity: daily vs. hourly. Choose matching aggregation rules.
GET /latest — Real-time anchor points in one call
Bundle several commodities in one call to initialize a simulation or recalibrate spread weights at runtime.
curl -G https://energy-api.com/api/v1/latest \
--data-urlencode "symbols=EPEX_DE_DA,TTF_GAS,EUA_CO2,BRENT_CRUDE" \
--data-urlencode "api_key=YOUR_API_KEY"
Interpretation tips:
- Use dates to avoid look-ahead bias; treat missing publication days with forward-fill only when necessary and documented in your methodology.
- Store currencies for explicit FX treatment when combining EUR and USD legs.
GET /electricity/latest — Monitor all electricity symbols at once
Scan the latest electricity prices to quickly flag negative-price environments or unusually high peaks that might alter curtailment assumptions across your portfolio.
curl -G https://energy-api.com/api/v1/electricity/latest \
--data-urlencode "country=ES" \
--data-urlencode "api_key=YOUR_API_KEY"
Practical tip:
- Use this as a health check in your backtest harness to ensure coverage for your target regions before generating a daily report.
GET /gas/latest, GET /emissions/latest, GET /coal/latest — Cross-commodity pairing
Spark and dark spreads require gas, coal, and carbon allowance benchmarks. Pull them as needed and align with day-ahead electricity.
curl -G https://energy-api.com/api/v1/gas/latest \
--data-urlencode "api_key=YOUR_API_KEY"
curl -G https://energy-api.com/api/v1/emissions/latest \
--data-urlencode "api_key=YOUR_API_KEY"
curl -G https://energy-api.com/api/v1/coal/latest \
--data-urlencode "api_key=YOUR_API_KEY"
Implementation note:
- Convert fuels to electricity basis via assumed heat rates and emissions factors; then compute spreads relative to day-ahead electricity to see where renewables likely displace thermal units or where hedges need rebalancing.
GET /carbon-intensity — Carbon-aware hedging overlays
If your strategy values carbon-aware dispatch or ESG-adjusted P&L, use grid intensity to weight hours by emissions avoided.
curl -G https://energy-api.com/api/v1/carbon-intensity \
--data-urlencode "country=DE" \
--data-urlencode "api_key=YOUR_API_KEY"
Use the result to quantify avoided emissions under curtailment: when price turns negative and you curtail, the emissions avoided per MWh is tied to marginal intensity assumptions. This informs carbon-adjusted hedging outcomes.
POST /cost-estimate — Translate wholesale conditions into monthly bill proxies
While not a hedging engine by itself, /cost-estimate is a handy tool to communicate backtest impacts to non-technical stakeholders: “If this hedge held during a volatile month, here’s the rough effect on a consumer-scale load.”
curl -X POST https://energy-api.com/api/v1/cost-estimate \
-H "Content-Type: application/json" \
-d '{
"symbol": "OMIE_ES_DA",
"kwh_per_month": 12500
}' \
--data-urlencode "api_key=YOUR_API_KEY"
Note: This is a simple wholesale proxy (latest price × kWh/month). For production-grade hedging, pair with hourly usage profiles and intraday curves from /electricity/hourly.
GET /status — Provider health for backtest audits
Operational reliability matters. Use /status to surface last-fetch timestamps and quickly flag upstream interruptions before a scheduled batch backtest.
curl -G https://energy-api.com/api/v1/status \
--data-urlencode "api_key=YOUR_API_KEY"
If your batch encounters missing data, first inspect this endpoint to differentiate source downtime from integration bugs.
Real-World Use Cases
1) Renewable PPA Hedge Backtest with Curtailment Windows
A utility or corporate buyer backtests a solar PPA against regional day-ahead curves to quantify negative-price exposure and settlement variability. The workflow pulls /electricity/hourly for OMIE_ES_DA, calculates hours below a negotiated floor, and then adjusts economics using spark spread proxies from /timeseries for TTF_GAS and EUA_CO2 to measure competitive pressure in peak and off-peak windows. Endpoints used: /electricity/hourly, /timeseries, /fluctuation.
2) Cross-Commodity Spread Monitor for Intraday Rebalancing
A trading desk monitors daily anchors with /latest for BRENT_CRUDE, TTF_GAS, and EUA_CO2 while scanning /electricity/latest across DE and ES. When thresholds trip (e.g., spark spread deteriorates), the engine schedules targeted intraday pulls via /electricity/hourly to recalculate dispatch/hedge deltas. Endpoints used: /latest, /electricity/latest, /electricity/hourly, /ohlc.
3) ESG Dashboard with Carbon-Aware Dispatch Scenarios
A sustainability product quantifies avoided emissions from curtailed vs. dispatched hours using /carbon-intensity for the grid region and /electricity/hourly for price-driven dispatch signals. It overlays EU ETS prices from /emissions/latest to estimate implicit carbon costs within P&L. Endpoints used: /carbon-intensity, /electricity/hourly, /emissions/latest, /timeseries.
Implementation Walkthrough: From Data Pulls to Backtest Results
Let’s wire up a compact but practical backtest kernel using Python and JavaScript examples. We’ll:
- Pull daily series for a cross-commodity spread (electricity vs. gas + carbon).
- Fetch intraday electricity curves for curtailment detection.
- Summarize volatility regimes with OHLC.
- Tag carbon intensity to create ESG-adjusted results.
Python example: Build a daily spread and intraday curtailment overlay
import requests
import pandas as pd
from datetime import datetime
BASE = "https://energy-api.com/api/v1"
API_KEY = "YOUR_API_KEY"
def get_timeseries(symbols, start, end):
r = requests.get(f"{BASE}/timeseries", params={
"symbols": ",".join(symbols),
"start": start,
"end": end,
"api_key": API_KEY
}, timeout=30)
r.raise_for_status()
return r.json()
def get_intraday(symbol, date):
r = requests.get(f"{BASE}/electricity/hourly", params={
"symbol": symbol,
"date": date,
"api_key": API_KEY
}, timeout=30)
r.raise_for_status()
return r.json()
# 1) Daily spread: OMIE_ES_DA - (TTF_GAS * heat_rate) - (EUA_CO2 * emissions_factor)
symbols = ["OMIE_ES_DA", "TTF_GAS", "EUA_CO2"]
js = get_timeseries(symbols, "2025-01-01", "2025-03-31")
df_elec = pd.Series(js["rates"]["OMIE_ES_DA"], name="elec").astype(float)
df_gas = pd.Series(js["rates"]["TTF_GAS"], name="gas").astype(float)
df_co2 = pd.Series(js["rates"]["EUA_CO2"], name="co2").astype(float)
df = pd.concat([df_elec, df_gas, df_co2], axis=1).sort_index()
heat_rate = 7.5 # example MWh_th per MWh_el
emissions_factor = 0.35 # example tCO2 per MWh_el for gas
df["spread"] = df["elec"] - (df["gas"] * heat_rate / 100.0) - (df["co2"] * emissions_factor / 100.0)
# 2) Intraday curtailment: fetch a specific day and count hours below zero
intraday = get_intraday("OMIE_ES_DA", "2025-02-15")
curve = pd.DataFrame(intraday["curve"])
curve["time"] = pd.to_datetime(curve["time"])
neg_hours = (curve["price"] < 0).sum()
print("Daily spread head:")
print(df.head())
print(f"Negative-price hours on 2025-02-15: {neg_hours}")
Notes:
- We used made-up heat_rate and emissions_factor for demonstration; replace with plant- or policy-specific values for realistic spreads.
- If mixing USD and EUR legs, convert consistently before computing spreads.
- Time zone awareness is crucial when mapping intraday curves to PPA settlement schedules.
JavaScript example: Volatility buckets and alerting
import fetch from "node-fetch";
const BASE = "https://energy-api.com/api/v1";
const API_KEY = "YOUR_API_KEY";
async function getOHLC(symbols, start, end, period = "monthly") {
const url = new URL(`${BASE}/ohlc`);
url.searchParams.set("symbols", symbols.join(","));
url.searchParams.set("period", period);
url.searchParams.set("start", start);
url.searchParams.set("end", end);
url.searchParams.set("api_key", API_KEY);
const r = await fetch(url, { method: "GET" });
if (!r.ok) {
const msg = await r.text();
throw new Error(`OHLC fetch failed: ${r.status} ${msg}`);
}
return r.json();
}
(async () => {
const data = await getOHLC(["TTF_GAS", "EUA_CO2"], "2024-01-01", "2024-12-31");
const ttfCandles = data.data["TTF_GAS"] || [];
// Simple alert: flag months where TTF monthly high exceeds 45 EUR/MWh
const alerts = ttfCandles
.filter(c => c.high > 45)
.map(c => `TTF high > 45 in ${c.period}: ${c.high}`);
console.log(alerts);
})();
Best practices:
- Implement retries on transient failures and handle 404s for symbols that don’t publish a forecast (e.g., non-auction instruments on /forecast).
- Use /status in pre-flight checks for batch jobs; fail gracefully with an audit trail if a provider is delayed.
Error Handling and Troubleshooting
Building robust backtests means planning for real-world data issues. Reference error codes help you handle failures cleanly:
- 401 — Missing or invalid api_key. Confirm the parameter is included in all requests.
- 404 — No data for the given symbols or date. This is common on non-publishing days or for unsupported symbol/forecast queries. Implement date roll-back or conditional branching.
- 422 — Validation error. Inspect the message when query params are missing or malformed.
- 429 — Rate limit exceeded. Implement exponential backoff, batch your symbol requests when possible, and cache frequently used series in your data layer.
Error response shape:
{
"success": false,
"error": "Human-readable message."
}
Troubleshooting checklist:
- Calendar alignment: When you join electricity, gas, and carbon, inspect the dates dictionary from /latest or the keys in /timeseries to ensure alignment. Avoid automatic forward-fill unless explicitly part of your methodology.
- Time zone sanity: Intraday curves include explicit time zones; handle DST transitions safely. When summarizing daily averages from intraday points, account for 23- and 25-hour days.
- Currency coherence: Keep currencies at the edge of your model and convert once, in a controlled layer, if you need a single-currency P&L.
- Granularity mismatch: Daily aggregates with intraday shapes must be merged carefully; state which dimension is the “truth source” for each decision in your backtest.
Designing Backtests for Renewable Hedging: Patterns and Tips
Beyond individual endpoints, renewable hedging backtests benefit from several architectural patterns:
- Deterministic data clocks: Use /forecast to reflect when new day-ahead information becomes available. Move your backtest state machine forward only when the corresponding auction data exists.
- Scenario bundling: Use /ohlc to create monthly or weekly volatility buckets. Sample from these to generate stress paths, then inject intraday shapes via /electricity/hourly to add curtailment realism.
- Cross-commodity joins in one step: With /timeseries and /latest supporting multiple symbols, load all legs of a spread in one call. This removes drift and reduces partial-fetch failure modes.
- ESG-aware overlays: Pair /carbon-intensity with intraday electricity to attribute emissions avoidance or cost to operational decisions under curtailment scenarios.
For PPA hedging specifically, include instrumentation around:
- Negative-price hour counters and distributions per season.
- Strike-floor/ceiling breaches per month with mark-to-market effect.
- Spread decomposition: electricity, fuel, and carbon legs, each with sensitivity toggles.
- Liquidity proxies: roll your stress windows with /fluctuation, then re-run PPA cashflows under each regime.
End-to-End Example: Spread Backtest With Curtailment and Carbon Overlay
To illustrate end-to-end flow, here’s a concise sequence with key responses and how to interpret them.
Step 1: Discover symbols for your region
curl -G https://energy-api.com/api/v1/symbols \
--data-urlencode "category=electricity" \
--data-urlencode "api_key=YOUR_API_KEY"
Confirm OMIE_ES_DA for Spain, EPEX_DE_DA for Germany, or AEMO_NSW1 for NSW (AU). Store country_code and currency_code for reporting.
Step 2: Pull historical daily series for spread components
curl -G https://energy-api.com/api/v1/timeseries \
--data-urlencode "start=2025-01-01" \
--data-urlencode "end=2025-12-31" \
--data-urlencode "symbols=OMIE_ES_DA,TTF_GAS,EUA_CO2" \
--data-urlencode "api_key=YOUR_API_KEY"
Join daily series by date, compute your spread function, and build distributions for each quarter.
Step 3: Sample volatility regimes with OHLC
curl -G https://energy-api.com/api/v1/ohlc \
--data-urlencode "symbols=TTF_GAS" \
--data-urlencode "period=monthly" \
--data-urlencode "start=2024-01-01" \
--data-urlencode "end=2025-12-31" \
--data-urlencode "api_key=YOUR_API_KEY"
Identify high-volatility months. Use these as anchors to stress-test your spread with intraday curves.
Step 4: Fetch intraday curves for curtailment days
curl -G https://energy-api.com/api/v1/electricity/hourly \
--data-urlencode "symbol=OMIE_ES_DA" \
--data-urlencode "date=2025-08-22" \
--data-urlencode "api_key=YOUR_API_KEY"
Compute negative-price hour frequency, PPA settlement impacts, and overlay carbon intensity for emissions-aware KPIs.
Step 5: Tag carbon intensity to add ESG-adjusted P&L
curl -G https://energy-api.com/api/v1/carbon-intensity \
--data-urlencode "country=ES" \
--data-urlencode "api_key=YOUR_API_KEY"
Use the latest intensity as a baseline; if you maintain a historical intensity series, normalize against your dispatch window for more precise avoided emissions metrics.
Endpoint-by-Endpoint Notes for Backtesting Fidelity
/historical — Point-in-time price lookup
When simulating decisions tied to specific dates (e.g., “What was the price known on 2025-09-15?”), /historical lets you query exact days. If the date falls on a non-publishing day, you receive the most recent value prior to it. This prevents gaps in your backtest ledger when markets are closed.
curl -G https://energy-api.com/api/v1/historical \
--data-urlencode "date=2025-09-15" \
--data-urlencode "symbols=BRENT_CRUDE,TTF_GAS" \
--data-urlencode "api_key=YOUR_API_KEY"
Response fields mirror /latest, keyed to the requested date. Use this to re-create daily snapshots without accidentally incorporating later revisions.
/electricity/pvpc — Retail reference for Spain (hourly)
PVPC gives a retail reference hourly series in Spain. While wholesale hedging focuses on day-ahead RO markets, PVPC is useful for bridging wholesale-to-retail narratives and testing pass-through effects to end users. This can contextualize the economic impact of curtailment or hedge outcomes on retail-exposed loads.
curl -G https://energy-api.com/api/v1/electricity/pvpc \
--data-urlencode "date=2025-09-15" \
--data-urlencode "api_key=YOUR_API_KEY"
Interpret alongside OMIE_ES_DA to quantify differential exposure between wholesale hedges and retail-linked consumption.
Performance and Reliability Practices for Production Backtests
To keep your backtests fast, auditable, and robust:
- Batch symbols in /latest and /timeseries calls to reduce round-trips. Query BRENT_CRUDE, TTF_GAS, EUA_CO2, and your electricity symbols together when initializing backtests.
- Cache stable historical segments. For long-running tests over fixed past windows, snapshot responses to your object store with explicit provenance.
- Implement retries with exponential backoff on transient failures, and short-circuit if /status reports provider delays; annotate results accordingly.
- Use typed schemas in your application (e.g., typescript or pydantic) to guarantee consistent parsing across all commodities. Energy API’s normalized JSON schema makes this straightforward.
- Log the “currencies” mapping for each request to your audit trail; this prevents silent FX drift when comparing runs.
FAQ
How often does the TTF gas price update?
TTF_GAS updates follow the underlying provider’s publishing schedule and appear in /latest and /timeseries once available. Always read the dates object in responses to confirm the publication date you are using in your backtest and avoid look-ahead bias.
Can I get historical energy prices going back 5 years?
Use /timeseries with start and end parameters for the symbols you need. Availability windows vary by symbol and provider; your response will include all available data within the requested range, with consistent JSON formatting across commodities.
Does the API support multiple commodities in a single request?
Yes. Endpoints like /latest and /timeseries accept comma-separated symbols across electricity, gas, oil, coal, carbon, and carbon intensity. This is ideal for building spreads and cross-commodity hedges without multiple parsing paths.
Can I fetch hourly or 15-minute electricity curves for curtailment modeling?
Yes. Use /electricity/hourly for supported symbols and dates. The response includes a time-stamped curve with a granularity field indicating hourly or 15-minute cadence based on the source market.
How should I handle missing data or non-publishing days?
For /historical and /timeseries, dates on non-publishing days return the most recent prior value (or a gap depending on the symbol). When joining commodities, always align on actual publish dates and document any forward-filling explicitly in your methodology.
Conclusion + CTA
Backtesting renewable hedging strategies doesn’t have to be an exercise in ETL pain. With one normalized REST surface for electricity, gas, oil, coal, carbon allowances, and grid carbon intensity, you can focus on modeling spreads, curtailment windows, and volatility regimes—not wrestling mismatched CSVs and calendars. The endpoints we covered—/timeseries for long-run histories, /electricity/hourly for intraday realism, /ohlc and /fluctuation for volatility and stress selection, and /forecast for deterministic day-ahead transitions—form a practical, production-ready toolkit.
Whether you’re building a PPA hedge engine, cross-commodity trading monitor, or ESG-aware dispatch dashboard, the same JSON schema and multi-commodity calls let you move from prototype to production quickly and auditably. Start with a few curl requests, wire responses into your dataframes, and iterate on strategy logic instead of data plumbing.
Ready to build? Explore the endpoints and examples on Energy API, and kick off your next hedging backtest today. Try Energy API for free.
Ready to get started?
Get your API key and start querying energy commodity prices in minutes.
Get API KeyRelated posts
Discover how to leverage Energy API for portfolio stress testing. Create shock scenarios and automated P&L rep...
Read more →
Unlock the potential of Renewable Energy Certificates with our guide on using Energy API for efficient trackin...
Read more →
Discover how utilities can leverage Energy API to build a robust green energy portfolio and stay competitive i...
Read more →
Discover how to leverage Energy API for effective renewable portfolio management. Unlock strategies that empow...
Read more →
Discover how to leverage Energy API for effective renewable portfolio management. Unlock strategies that empow...
Read more →