"Hit the right spot with your energy prices"

This custom integration allows you to fetch day-ahead electricity spot prices from various trustworthy global sources for use in automations, dashboards, and energy monitoring within Home Assistant.
Note: This integration is in early release (v0.0.1). Future updates may include breaking changes as the implementation matures.
- Installation
- Supported Price Sources & Regions
- Features
- Configuration
- Multi-Source API & Fallback System
- Technical Features
- Usage Examples
- Troubleshooting
- For Developers
- Make sure HACS is installed
- Add this repository as a custom repository in HACS
- Click "Add"
- Search for "GE-Spot: Global Electricity Spot Prices"
- Click Install
- Restart Home Assistant
- Copy the
ge_spot
directory from this repository to your Home Assistant'scustom_components
directory - Restart Home Assistant
The integration supports multiple price data sources with automatic fallback capabilities:
- Nordpool - Prices for Nordic and Baltic countries
- Energi Data Service - Prices for Denmark
- Stromligning - Prices for Denmark
- ENTSO-E - European Network of Transmission System Operators for Electricity (requires API key)
- EPEX SPOT - European Power Exchange for Central Europe
- OMIE - Iberian Electricity Market Operator for Spain and Portugal
- WIP: AEMO - Australian Energy Market Operator (partial implementation)
The table below shows which price sources support specific regions:
Region | Description | Nordpool | ENTSO-E | Energi Data | Stromligning | EPEX | OMIE |
---|---|---|---|---|---|---|---|
SE1 | Sweden North | ✓ | ✓ | ||||
SE2 | Sweden North-Central | ✓ | ✓ | ||||
SE3 | Sweden South-Central | ✓ | ✓ | ||||
SE4 | Sweden South | ✓ | ✓ | ||||
DK1 | Denmark West | ✓ | ✓ | ✓ | ✓ | ||
DK2 | Denmark East | ✓ | ✓ | ✓ | ✓ | ||
NO1-5 | Norway Areas | ✓ | ✓ | ||||
FI | Finland | ✓ | ✓ | ||||
EE | Estonia | ✓ | ✓ | ||||
LV | Latvia | ✓ | ✓ | ||||
LT | Lithuania | ✓ | ✓ | ||||
DE | Germany | ✓ | ✓ | ||||
FR | France | ✓ | ✓ | ||||
NL | Netherlands | ✓ | ✓ | ||||
BE | Belgium | ✓ | ✓ | ||||
AT | Austria | ✓ | ✓ | ||||
ES | Spain | ✓ | ✓ | ||||
PT | Portugal | ✓ | ✓ | ||||
Other EU | Various EU countries | ✓ |
For a complete list of supported areas and their currency mappings, see the Const files in the codebase.
- Simple configuration through the Home Assistant UI
- Region-specific setup options
- Source-agnostic sensors that provide consistent entity IDs regardless of data source
- Tomorrow's prices available after 13:00 CET (when published)
- Automatic fallback between data sources for the same region for increased reliability
- Seamless timezone handling to ensure correct hourly price display regardless of API source
- Currency conversion with dynamic exchange rates from the European Central Bank
- Timestamps in ISO format for compatibility with other systems
- Eight sensor types for each configured region:
- Current hour price
- Next hour price
- Day average price
- Peak price (highest of the day)
- Off-peak price (lowest of the day)
- Tomorrow average price
- Tomorrow peak price (highest of tomorrow)
- Tomorrow off-peak price (lowest of tomorrow)
After installation:
- Go to Configuration → Integrations
- Click "Add Integration" and search for "GE-Spot: Global Electricity Spot Prices"
- Select your region/area from the dropdown
- Configure settings:
- Region/Area: Select your electricity price area (e.g., SE4, DK1)
- Source Priority: Order of data sources to try (first = highest priority)
- VAT Rate: Set your applicable VAT percentage (e.g., 25 for 25%)
- Update Interval: How often to refresh data (15, 30, or 60 minutes)
- Display Format: Choose between decimal (e.g., 0.15 EUR/kWh) or subunit (e.g., 15 cents/kWh)
- API Keys: For ENTSO-E, you'll need to register for an API key
- API Key Reuse: The integration will reuse API keys across different regions using the same source
The integration handles VAT correctly based on your configuration:
- Enter VAT as a percentage (e.g., 25 for 25%)
- VAT is applied to the converted price after any currency conversion
- Some sources like Stromligning already include VAT in their prices
The integration implements several mechanisms to ensure reliability:
- Automatic Retries: Failed API requests are retried with exponential backoff
- Source Fallbacks: If the primary source fails, alternative sources are tried automatically
- Data Caching: Successfully fetched data is cached and used if all API sources fail
- Rate Limiting: Minimum update interval of 15 minutes to respect API rate limits
- Special Update Windows: More frequent updates during price publication times (around 13:00 CET)
GE-Spot uses a robust multi-source approach to ensure reliable price data:
flowchart TD
Config[User Configuration] --> Coordinator
subgraph Coordinator["Data Coordinator"]
Priority[Source Priority List]
FetchLoop["Try Each API in Priority Order"]
Cache["Cached Data"]
Priority --> FetchLoop
FetchLoop --> |Success| DataStore["Store Current Data"]
FetchLoop --> |All Failed| Fallback["Use Cached Data"]
Cache --> Fallback
DataStore --> Cache
end
Coordinator --> Sensors
subgraph APIGroup["API Sources"]
Nordpool["Nordpool API"]
ENTSOE["ENTSO-E API"]
EPEX["EPEX API"]
EDS["Energi Data Service API"]
OMIE["OMIE API"]
AEMO["AEMO API"]
end
FetchLoop --> APIGroup
- Source Prioritization: You control the order in which APIs are tried
- Automatic Fallback: If the primary source fails, the system tries alternative sources automatically
- Transparent Attribution: Sensor attributes show which API provided the data
- Data Caching: Previously fetched data serves as a last-resort fallback if all APIs fail
Each region has a defined fallback chain based on data compatibility:
Primary Source | Fallback Sources (in order) |
---|---|
Nordpool | Energi Data Service, ENTSO-E, EPEX |
Energi Data Service | Nordpool, ENTSO-E |
ENTSO-E | Nordpool, EPEX |
EPEX | ENTSO-E, Nordpool |
OMIE | ENTSO-E |
AEMO | (No fallbacks available) |
Stromligning | Energi Data Service, Nordpool |
The integration will automatically adjust the fallback chain based on the region's compatibility with each source.
The integration normalizes timestamps from different APIs to ensure correct hourly prices:
flowchart TD
API["API Response with Timestamps"] --> Parser["Timestamp Parser"]
Parser --> Normalizer["Timezone Normalizer"]
Normalizer --> Converter["Convert to Local Time"]
HAConfig["Home Assistant Timezone"] --> Converter
AreaTZ["Region-specific Timezone"] --> Converter
Converter --> Matcher["Match Price to Current Hour"]
Matcher --> Sensor["Current Price Sensor"]
- Timezone Awareness: Handles UTC, local time, and timezone-naive timestamps correctly
- Region-specific Handling: Applies appropriate timezone for each price area
- Home Assistant Integration: Uses your Home Assistant timezone setting for consistent display
The integration implements a comprehensive price conversion system that ensures accurate pricing across all regions and currencies:
flowchart TD
API[API Response] -->|Raw Data| Process
subgraph Process["Process Data"]
Extract[Extract Raw Price\ne.g. 158.67 EUR/MWh]
Convert[Convert to Target Currency & Unit]
Apply[Apply VAT]
Store[Store in Standardized Format]
Extract --> Convert
Convert --> Apply
Apply --> Store
end
Process --> Sensors[Home Assistant Sensors]
subgraph Exchange["Exchange Rate Service"]
ECB[ECB Exchange Rate API]
Cache[Local Cache File]
Fallback[Fallback Fixed Rates]
ECB --> Cache
Cache --> |If API fails| Fallback
end
Convert <-.->|Get rates| Exchange
Config[User Configuration\nVAT, Currency, Display Unit] --> Apply
RegionMap[Region to Currency Mapping] --> Convert
The price conversion follows this detailed process:
sequenceDiagram
participant API as API Source
participant Processor as Price Processor
participant Converter as Currency Utils
participant Exchange as Exchange Service
participant Cache as Exchange Rate Cache
participant ECB as ECB API
API->>Processor: Raw Price Data (e.g., 158.67 EUR/MWh)
Processor->>Converter: async_convert_energy_price()
Converter->>Exchange: Get exchange rates
Exchange->>Cache: Check for cached rates
alt Cache valid
Cache-->>Exchange: Return cached rates
else Cache invalid or missing
Exchange->>ECB: Fetch current rates
alt ECB API success
ECB-->>Exchange: Current exchange rates
Exchange->>Cache: Save to cache
else ECB API fails
Exchange->>Exchange: Use fallback rates
end
Exchange-->>Converter: Return rates
end
Note over Converter: Step 1: Convert Currency<br>(e.g., EUR → SEK using rate)
Note over Converter: Step 2: Convert Energy Unit<br>(MWh → kWh, divide by 1000)
Note over Converter: Step 3: Apply VAT<br>(if configured)
Note over Converter: Step 4: Convert to Subunit<br>(e.g., SEK → öre, multiply by 100)
Converter-->>Processor: Final Price
Processor-->>Processor: Store price in standardized format
GE-Spot makes currency conversion simple and reliable:
- Automatic Currency Detection: Appropriate currency selected based on region
- Dynamic Exchange Rates: Fresh rates from the European Central Bank
- Smart Caching: Exchange rates are cached for 24 hours to reduce API calls
- Scheduled Updates: Exchange rates are refreshed at 00:00, 06:00, 12:00, and 18:00
- Fallback Rates: Works even during network outages using cached values
- Display Flexibility: Show prices in main units (EUR/kWh) or subunits (cents/kWh, öre/kWh)
For example, converting from 69.16 EUR/MWh to öre/kWh for SE4 (with exchange rate 10.72):
- EUR to SEK: 69.16 × 10.72 = 741.40 SEK/MWh
- MWh to kWh: 741.40 ÷ 1000 = 0.7414 SEK/kWh
- Apply VAT (if any): 0.7414 × (1 + VAT rate)
- SEK to öre (if requested): 0.7414 × 100 = 74.14 öre/kWh
Different data sources will return different prices for the same hour due to what they include:
Source | Price Components | Notes |
---|---|---|
Energi Data Service/ENTSO-E | Raw spot price | Base wholesale electricity market price |
Nordpool | Raw spot price | May differ slightly due to timing/rounding |
Stromligning | Spot price + grid fees + tariffs + taxes | Full consumer electricity price |
Energi Data Service and ENTSO-E typically match as they provide raw spot market prices. Stromligning includes additional cost components as seen in its implementation:
# Components extracted from Stromligning
electricity_price = price_entry["details"]["electricity"]["total"]
grid_price = (
price_entry["details"]["transmission"]["systemTariff"]["total"] +
price_entry["details"]["transmission"]["netTariff"]["total"] +
price_entry["details"]["distribution"]["total"]
)
tax_price = price_entry["details"]["electricityTax"]["total"]
For Danish areas (DK1, DK2), the integration extracts only the electricity component from Stromligning to match other price sources. The full price breakdown with all components is available in the sensor attributes.
To ensure all sources report prices for the same hours despite different source timezones:
- Each API response is processed with explicit timezone awareness
- Timestamps are parsed in their original timezone context
- Hours are normalized to the Home Assistant timezone
- DST transitions are handled automatically
This ensures that, for example, the price for 14:00 is the same regardless of which API provided it.
type: entities
entities:
- entity: sensor.gespot_current_price_se4
name: Current Electricity Price
- entity: sensor.gespot_next_hour_price_se4
name: Next Hour Price
- entity: sensor.gespot_day_average_price_se4
name: Today's Average
- entity: sensor.gespot_tomorrow_average_price_se4
name: Tomorrow's Average
type: custom:apexcharts-card
header:
show: true
title: Electricity Prices
show_states: true
series:
- entity: sensor.gespot_current_price_se4
attribute: today_with_timestamps
type: column
name: Today
group_by:
func: raw
- entity: sensor.gespot_current_price_se4
attribute: tomorrow_with_timestamps
type: column
name: Tomorrow
group_by:
func: raw
automation:
- alias: Turn on water heater when prices are low
trigger:
- platform: state
entity_id: sensor.gespot_current_price_se4
condition:
- condition: template
value_template: "{{ states('sensor.gespot_current_price_se4')|float < states('sensor.gespot_day_average_price_se4')|float * 0.8 }}"
action:
- service: switch.turn_on
entity_id: switch.water_heater
To integrate GE-Spot with the Energy Dashboard, you can create template sensors:
template:
- sensor:
- name: "Energy Cost Sensor"
unit_of_measurement: "SEK/kWh"
state: "{{ states('sensor.gespot_current_price_se4') }}"
Then set this sensor as your energy cost sensor in the Energy Dashboard settings.
If you experience issues:
- No Data/Empty Sensors: Check if your area is correctly supported by your selected source
- API Key Errors: For ENTSO-E, verify your API key is entered correctly
- Timezone Issues: Check if the hourly prices align with your expected hours
- Missing Tomorrow Prices: Tomorrow's prices are typically only available after 13:00 CET
-
Check sensor attributes for detailed information:
data_source
: Which API provided the dataactive_source
: Current active source being usedfallback_sources
: Alternative sources that succeededattempted_sources
: All sources that were triedusing_cached_data
: Whether cached data is being used
-
Check Home Assistant logs for errors related to
ge_spot
-
Verify network connectivity to the API endpoints
-
Try increasing the update interval if you experience frequent timeouts
- Configure multiple sources in your priority list
- Get an ENTSO-E API key for better fallback options
- Use longer update intervals (30 or 60 minutes)
- Check if your internet connection is stable
To add a new price source:
- Create a new API module in
custom_components/ge_spot/api/
- Implement the
fetch_day_ahead_prices
function following the pattern in existing modules - Register the source in
api/__init__.py
and add to theSOURCE_REGION_SUPPORT
mapping - Add region mappings in the
const/areas.py
file - Update the fallback chain in
ApiRegistry.get_fallback_chain()
to include the new source
All API modules should return data in this format:
{
"current_price": float, # Current hour price
"next_hour_price": float, # Next hour price
"day_average_price": float, # Day average
"peak_price": float, # Day maximum
"off_peak_price": float, # Day minimum
"hourly_prices": dict, # Hourly prices "HH:00" -> float
"tomorrow_hourly_prices": dict, # Tomorrow's hourly prices (if available)
"raw_values": dict, # Raw conversion information
"data_source": str, # Source name
"last_updated": str, # ISO timestamp
"currency": str # Target currency
}
The modular architecture allows for easy extension:
- New sensor types can be added in
sensor/electricity.py
- Additional price attributes can be calculated in
price/statistics.py
- Currency conversion logic can be enhanced in
price/conversion.py
- Timezone handling can be adjusted in the
timezone/
package
This integration is licensed under the MIT License.