Home Assistant integration that provides current Czech electricity and gas spot prices based on OTE.
If this integration saves (or earns) you some money, you can buy me a coffee ☕.
- Provides real-time Czech electricity and gas spot prices from OTE.
- Supports both 60-minute and 15-minute electricity spot intervals (15-minute prices are available since OTE introduced them).
- Supports multiple currencies (EUR, CZK) and energy units (kWh, MWh).
- Configurable templates for buy/sell prices, including VAT and distribution fees.
- Includes sensors for monitoring current, cheapest, and most expensive electricity prices.
- Configurable binary sensors for the cheapest consecutive hour blocks in a day (e.g. cheapest 2, 4 or 8 hours in a row).
- Persists last downloaded prices across Home Assistant restarts so sensors are available immediately on startup.
- Compatible with Home Assistant automations for energy optimization.
You can add the integration multiple times to combine commodities and intervals, for example:
- one instance for 60-minute electricity spot prices,
- another instance for 15-minute electricity spot prices,
- another instance for gas spot prices.
Each instance is configured separately (currency, unit, buy/sell template, cheapest blocks).
OTE (Czech market operator) uses hourly prices indexed from 1, where:
1(first hour of the day) corresponds to00:00 - 01:00.- It does not mean
01:00 - 02:00, as one might expect.
Keep this in mind when comparing prices reported by this integration with other sources (e.g., OTE, your electricity provider/distributor).
See Displaying a chart for details.
The integration shows just spot prices by default. If you want to also use actual prices for buying and selling (so including distribution fees, VAT, etc), you need to configure it. Use the "Configure" button in integration details and set templates for buying/selling.
Variables for electricity templates:
value— base spot price for the given interval (hourly or 15min, depending on configuration).hour— datetime of the interval being computed. The value is in UTC; if you need the local time (e.g. for tariff windows), useas_local(hour).
Variables for gas templates (gas has only daily prices):
value— base spot price for the day.day— date of the price (in UTC).
If you do not enter a template, the corresponding buy/sell sensors are not created.
Electricity cost when buying
{% set tax_kWh = 28.30 / 1000.0 %}
{% set system_services_kWh = 164.24 / 1000.0 %}
{% set oze_kWh = 0 / 1000.0 %}
{% set low_distrib_kWh = 116.5 / 1000.0 %}
{% set high_distrib_kWh = 754.77 / 1000.0 %}
{% set operator_cost_kWh = 250.0 / 1000.0 %}
{% set vat_percent = 21 %}
{% set distrib_kWh = low_distrib_kWh %}
{% if as_local(hour).hour in [8, 12, 15, 19] %}
{% set distrib_kWh = high_distrib_kWh %}
{% endif %}
{{ (value + distrib_kWh + tax_kWh + oze_kWh + system_services_kWh + operator_cost_kWh) * ( 100.0 + vat_percent ) / 100.0 }}Electricity cost when selling
{% set operator_cost_kWh = 0.25 %}
{{ value - operator_cost_kWh }}Gas cost when buying
{% set distrib_kWh = 130.0 / 1000.0 %}
{% set tax_kWh = 30.60 / 1000.0 %}
{% set operator_cost_kWh = 250.0 / 1000.0 %}
{% set vat_percent = 21 %}
{{ (value + distrib_kWh + tax_kWh + operator_cost_kWh) * (100.0 + vat_percent) / 100.0 }}You can install the integration using HACS (preferred) or manually.
- Open HACS in your Home Assistant instance.
- Search for "Czech Energy Spot Prices" and install it.
- Restart Home Assistant.
- Download the
custom_components/cz_energy_spot_pricesdirectory. - Copy it into the
custom_componentsfolder in your Home Assistant configuration directory. - Restart Home Assistant.
- Go to Settings -> Devices & Services -> Add integration.
- Search for "Czech Energy Spot Prices" and select it.
- Pick the commodity (electricity or gas), currency and energy unit. For electricity you will also be asked to choose the interval (60 minutes or 15 minutes).
- (Optional) Use the "Configure" button to set templates for buy/sell prices (see above) and the list of cheapest consecutive hour blocks (see Cheapest consecutive hour blocks).
- (Optional) Repeat the steps to add another instance for a different commodity or interval (see Multiple instances).
The integration provides several sensors to monitor electricity/gas prices and related data. Below is a list of available sensors and their attributes.
When the 15-minute interval is selected, the same sensors are also created with the _15min suffix in their entity id (e.g. sensor.current_spot_electricity_price_15min).
| Sensor | value | attributes |
|---|---|---|
| Current Spot Electricity Price | electricity price for current interval (hour or 15 minutes) | dictionary with timestamps as keys and spot price for given interval as values |
| Spot Cheapest Electricity Today | price of the cheapest electricity today | At Hour |
| Spot Most Expensive Electricity Today | price of the most expensive electricity today | At Hour |
| Spot Cheapest Electricity Tomorrow | price of the cheapest electricity tomorrow | At Hour |
| Spot Most Expensive Electricity Tomorrow | price of the most expensive electricity tomorrow | At Hour |
| Current Spot Electricity Hour Order | order of current interval when we sort intervals by their price (1=cheapest, N=most expensive; N=24 for hourly, 96 for 15min) | dictionary with timestamps as keys and [order, price] as values |
| Tomorrow Spot Electricity Hour Order | no value | dictionary with timestamps as keys and [order, price] as values |
| Spot Electricity Has Tomorrow Data | On when data for tomorrow are loaded, Off otherwise (created only once for all electricity instances) |
|
| Spot Electricity Is Cheapest | On when current interval has the cheapest price of the day, Off otherwise |
Start Start hour End End hour Min Max Mean |
Spot Electricity Is Cheapest X Hours Block |
On when current time falls inside the cheapest consecutive X hour block of the day, Off otherwise (one sensor per X configured in Cheapest consecutive hour blocks) |
Start Start hour End End hour Min Max Mean |
If you configure templates for buy and sell prices, there will also be similar Buy * and Sell * sensors with the same structure.
Gas prices are published once per day, so gas sensors are simpler than the electricity ones.
| Sensor | value | attributes |
|---|---|---|
| Current Spot Gas Price | gas spot price for today | |
| Tomorrow Spot Gas Price | gas spot price for tomorrow (when available) | |
| Spot Gas Has Tomorrow Data | On when tomorrow's gas price is loaded, Off otherwise (created only once for all gas instances) |
If you configure a buy template for gas, there will also be Current Buy Gas Price and Tomorrow Buy Gas Price sensors. Selling is not supported for gas.
timestamp when the cheapest hour starts
hour with the cheapest electricity (2 means that cheapest electricity is from 2:00 till 3:00 in timezone you've configured in Home Assistant)
timestamp when consecutive block of cheapest hours starts, only available when the block is in the future
hour when consecutive block of cheapest hours starts, only available when the block is in the future
timestamp when consecutive block of cheapest hours ends, only available when the block is in the future
hour when consecutive block of cheapest hours ends, only available when the block is in the future
minimal price in the block, only available when the block is in the future
maximal price in the block, only available when the block is in the future
average (mean) price in the block, only available when the block is in the future
In addition to the always-present Spot Electricity Is Cheapest binary sensor (which marks the single cheapest interval of the day), you can ask the integration to create binary sensors for the cheapest consecutive hour blocks of the day.
Open Configure on the integration card and fill the Cheapest consecutive hour blocks field with a comma-separated list of hour lengths, for example:
2, 4, 8
This creates three additional binary sensors:
binary_sensor.spot_electricity_is_cheapest_2_hours_blockbinary_sensor.spot_electricity_is_cheapest_4_hours_blockbinary_sensor.spot_electricity_is_cheapest_8_hours_block
Each sensor turns On while the current time falls inside the cheapest contiguous window of the given length within today's prices. Equivalent buy_* and sell_* sensors are created when the corresponding templates are configured. Each block is computed within a single day (it does not span midnight).
If you want to display a chart with current day (or two days if it's after noon), you can install apexcharts-card card for Home Assistant and then use following config for it:
type: custom:apexcharts-card
header:
show: true
show_states: true
colorize_states: true
title: Nákupní cena (15 min)
graph_span: 1d
span:
start: day
now:
show: true
label: Nyní
color: "#ff0000"
series:
- entity: sensor.current_buy_electricity_price_15min
name: Cena
float_precision: 2
type: line
curve: stepline
stroke_width: 2
show:
in_header: raw
color_threshold:
- value: -10
color: "#00cc00"
- value: 0
color: "#ffaa00"
- value: 4
color: "#ff0000"
data_generator: |
return Object.entries(entity.attributes)
.filter(([key, _]) => !isNaN(Date.parse(key)))
.map(([date, value]) => {
return [new Date(date).getTime(), value];
});This is useful for example if you want to turn on your water heater in the afternoon and then again during the night.
- Define intervals as tuples
(start_hour, end_hour)(end hour is excluded). - The sensor will return
Trueif the current hour is the cheapest in any of the defined intervals. - Alternatively, replace the last line with
{{ min.cheapest_hours }}to display the cheapest hours.
{# Define your intervals here as tuples (hour starting the interval, hour ending the interval (excluded)) #}
{% set intervals = [
(0, 8),
(8, 16),
(16, 24),
] %}
{# We need to use namespace so we can write into it in inner cycle #}
{% set min = namespace(price=None, dt=None, cheapest_hours=[]) %}
{% set cheapest_hours = [] %}
{% for interval in intervals %}
{# Reset min price from previous runs #}
{% set min.price = None %}
{# Go through all the hours in the interval (end excluded) and find the hour with lowest price #}
{% for i in range(interval[0], interval[1]) %}
{# Get datetime of current hour in current interval #}
{% set hour_dt = now().replace(hour=i, minute=0, second=0, microsecond=0) %}
{# Get value for that hour #}
{% set value = states.sensor.current_spot_electricity_hour_order.attributes.get(hour_dt.isoformat()) %}
{# Skip if not found #}
{% if value is not defined %}
{% break %}
{% endif %}
{# value is tuple (order, price), we'll use the price #}
{% set price = value[1] %}
{# Min price is not set or is higher than price of current hour => store the min price and hour #}
{% if min.price is none or price < min.price %}
{% set min.price = price %}
{% set min.dt = hour_dt %}
{% endif %}
{% endfor %}
{# Store cheapest hour in current interval #}
{% set min.cheapest_hours = min.cheapest_hours + [min.dt.hour] %}
{% endfor %}
{# use this to get the cheapest hours #}
{# {{ min.cheapest_hours }} #}
{# return True if current hour is in the cheapest hour of any interval #}
{{ now().hour in min.cheapest_hours }}This automation turns on a device (e.g., a heater) during the cheapest X hours of the day. Replace X with the desired number of hours and specify the entity to control.
alias: Turn on for cheapest X hours
trigger:
- platform: state
entity_id:
- sensor.current_spot_electricity_hour_order
condition: []
action:
- if:
- condition: numeric_state
entity_id: sensor.current_spot_electricity_hour_order
below: X # Replace with amount of hours you want to have it on
then:
- type: turn_on
entity_id: # Add entity you want to turn on
else:
- type: turn_off
entity_id: # Turn off the entity when cheapest interval ends
enabled: true
mode: singleThis integration is under Apache 2.0 License, the same license as Home Assistant itself.
