Most Nordpool cost savings by comparing sequences of high energy prices to previous sequence when heating house continuosly

Automating heating the house is kind of hard when considering hourly prices

Here I try explaining the concept of heating my one family house with 2 air heat pumps, central water heating system with multiple smart valves added to radiators.
All other concepts have been concentrating on heating only on when energy price is cheap, like heating x most cheap hours a day.

My approach to heating is that I want to live in pleasant environment, have minimal impact on house climate while minimizing energy cost. I do need to heat house all the time especially when temperature outdoors is -25°C.

As most, I used to cut with automation “high” electric prices of the day as it easy to find those hours. But then I started thinking other way around: if I would find the highest difference between X sequential prices and X sequential prices before that, so the sparing the money is the most. Imagine that you look up the chart

and see that on the morning before prices go high, you could warm up the house a bit more and then cut the heating. And do it automatically on every occasion on the sequence width of your choosing.

So I did come up a concept and implemented it on my system on which I could maybe spare more money while finding more those high peak/ highest prices of the day:

  1. find X hours sequence that is most expensive than the previous X hours sequence
  2. use same algorithm to find X hours sequence before and after the most expensive X hours sequence to further maximize sparing money
  3. heat more before the expensive hours sequence, maybe set 1-2 degrees more to heating elements
  4. set the heating off/ minimal on the expensive hours sequence

Concept premises:

  • have a list of today prices of energy, price per hour (24h per day)
  • I’m using norpool which has attribute for “today” prices on list

The basics of the system is the sensors which I use in my automations like one below (the checking if nordpool is available is not necessary, but it is good to output recent value when the cloud value is not available). The /config/configuration.yaml -file has an entry

template: !include_dir_merge_list template/

and the following code of sensors is in the “/config/template/template_sensor.yaml” -file:

- sensor:
    - name: "nordpool_price_most_savings_sequential_hours_energy_today"
      unique_id: nordpool_price_most_savings_sequential_hours_energy_today
      state: >
        {% if (states('sensor.nordpool_kwh_fi') | lower == "unavailable" or states('sensor.nordpool_kwh_fi') | lower == "unknown" )%}
            {% if (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unavailable" or states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unknown" )%}
                 {{(-1) | float (-1)}}
            {% else %}
                {{states('sensor.nordpool_price_most_savings_sequential_hours_energy_today')}}
            {% endif %}                
        {% else %}    
    
    
            {% set numberOfSequentialHours = states('input_number.nordpool_price_savings_sequential_hours') | int (4) %}
            {% set firstHour = (0+numberOfSequentialHours) %}
            {% set lastHour = 23 %}
            
            {% set ns = namespace(max_diff=-1000000000, max_index=-1, enough_percentage_difference=false) %}
            
            
            {% for i in range(firstHour, lastHour - numberOfSequentialHours + 1) %}
              {% set current_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i:i + numberOfSequentialHours] | list | sum %}
              {% set previous_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i - numberOfSequentialHours:i] | list | sum %}
              
              {% set diff = current_sum - previous_sum %}
               
              {% if diff > ns.max_diff %}
                {% set ns.max_diff = diff %}
                 {% set ns.max_index = i %}
                 {% set ns.enough_percentage_difference = (previous_sum *(states('input_number.nordpool_price_savings_minimum_price_multiplier') | float (1))/current_sum<1) %}
              {% endif %}
            {% endfor %}
            {{ns.max_index | float (0)}}    
        {% endif %}
      attributes:
        total_diff_price: >
            {% if (states('sensor.nordpool_kwh_fi') | lower == "unavailable" or states('sensor.nordpool_kwh_fi') | lower == "unknown" )%}
                {% if (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unavailable" or states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unknown" )%}
                     {{(-1) | float (-1)}}
                {% else %}
                    {{state_attr('sensor.nordpool_price_most_savings_sequential_hours_energy_today','total_diff_price')}}
                {% endif %}                
            {% else %}           
                {% set numberOfSequentialHours = states('input_number.nordpool_price_savings_sequential_hours') | int (4) %}
                {% set firstHour = (0+numberOfSequentialHours) %}
                {% set lastHour = 23 %}
                
                {% set ns = namespace(max_diff=-1000000000, max_index=-1, enough_percentage_difference=false) %}
                
                
                {% for i in range(firstHour, lastHour - numberOfSequentialHours + 1) %}
                  {% set current_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i:i + numberOfSequentialHours] | list | sum %}
                  {% set previous_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i - numberOfSequentialHours:i] | list | sum %}
                  
                  {% set diff = current_sum - previous_sum %}
                   
                  {% if diff > ns.max_diff %}
                    {% set ns.max_diff = diff %}
                     {% set ns.max_index = i %}
                     {% set ns.enough_percentage_difference = (previous_sum *(states('input_number.nordpool_price_savings_minimum_price_multiplier') | float (1))/current_sum<1) %}
                  {% endif %}
                {% endfor %}
                {{ns.max_diff | float (0)}}    
            {% endif %}
        enough_percentage_difference: >
            {% if (states('sensor.nordpool_kwh_fi') | lower == "unavailable" or states('sensor.nordpool_kwh_fi') | lower == "unknown" )%}
                {% if (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unavailable" or states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unknown" )%}
                     {{(-1) | float (-1)}}
                {% else %}
                    {{state_attr('sensor.nordpool_price_most_savings_sequential_hours_energy_today','total_diff_price')}}
                {% endif %}                
            {% else %}           
                {% set numberOfSequentialHours = states('input_number.nordpool_price_savings_sequential_hours') | int (4) %}
                {% set firstHour = (0+numberOfSequentialHours) %}
                {% set lastHour = 23 %}
                
                {% set ns = namespace(max_diff=-1000000000, max_index=-1, enough_percentage_difference=false) %}
                
                
                {% for i in range(firstHour, lastHour - numberOfSequentialHours + 1) %}
                  {% set current_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i:i + numberOfSequentialHours] | list | sum %}
                  {% set previous_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i - numberOfSequentialHours:i] | list | sum %}
                  
                  {% set diff = current_sum - previous_sum %}
                   
                  {% if diff > ns.max_diff %}
                    {% set ns.max_diff = diff %}
                     {% set ns.max_index = i %}
                     {% set ns.enough_percentage_difference = (previous_sum *(states('input_number.nordpool_price_savings_minimum_price_multiplier') | float (1))/current_sum<1) %}
                  {% endif %}
                {% endfor %}
                {{ns.enough_percentage_difference}}    
  
            {% endif %}
            
    - name: "nordpool_price_most_savings_sequential_hours_energy_today_datetime"
      unique_id: nordpool_price_most_savings_sequential_hours_energy_today_datetime
      state: >

        {% if (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today')|float(-1) < 0) %}
            {{today_at("00:00") + timedelta( hours = (0 - 480000))}}
        {% else %}   
            {% if (state_attr('sensor.nordpool_price_most_savings_sequential_hours_energy_today','total_diff_price')|float(-1) < 0 )%}
                  {{state_attr('schedule.valtakunnanverkon_energiansaasto_aikataulu_lammitys_pois_paalta','next_event')}}
            {% else %}
                  {% if (state_attr('sensor.nordpool_price_most_savings_sequential_hours_energy_today','total_diff_price') | float (-1) > states('input_number.nordpool_price_savings_minimum_price_difference') | int (6) ) and (state_attr('sensor.nordpool_price_most_savings_sequential_hours_energy_today','enough_percentage_difference'))%}
                      {{ today_at("00:00") + timedelta(hours = states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | float (0))}}
                  {% else %}
                      {{  today_at('00:00') + timedelta( hours = (0 - 480000)) }} 
                  {% endif %}              
            {% endif %}
        {% endif %}


    - name: "nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours"
      unique_id: nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours
      state: >
        {% if (states('sensor.nordpool_kwh_fi') | lower == "unavailable" or states('sensor.nordpool_kwh_fi') | lower == "unknown" )%}
            {% if (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unavailable" or states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unknown" )%}
                 {{(-1) | float (-1)}}
            {% else %}
                {{states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours')}}
            {% endif %}                
        {% else %}    
    
    
            {% set numberOfSequentialHours = states('input_number.nordpool_price_savings_sequential_hours') | int (4) %}
            {% set firstHour = (0+numberOfSequentialHours) %}
            {% set lastHour = (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | int (4) - numberOfSequentialHours) %}
            
            {% set ns = namespace(max_diff=-1000000000, max_index=-1, enough_percentage_difference=false) %}
            
            
            {% for i in range(firstHour, lastHour - numberOfSequentialHours + 1) %}
              {% set current_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i:i + numberOfSequentialHours] | list | sum %}
              {% set previous_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i - numberOfSequentialHours:i] | list | sum %}
              
              {% set diff = current_sum - previous_sum %}
               
              {% if diff > ns.max_diff %}
                {% set ns.max_diff = diff %}
                 {% set ns.max_index = i %}
                 {% set ns.enough_percentage_difference = (previous_sum *(states('input_number.nordpool_price_savings_minimum_price_multiplier') | float (1))/current_sum<1) %}
              {% endif %}
            {% endfor %}
            {{ns.max_index | float (0)}}    
        {% endif %}
      attributes:
        total_diff_price: >
            {% if (states('sensor.nordpool_kwh_fi') | lower == "unavailable" or states('sensor.nordpool_kwh_fi') | lower == "unknown" )%}
                {% if (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unavailable" or states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unknown" )%}
                     {{(-1) | float (-1)}}
                {% else %}
                    {{state_attr('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours','total_diff_price')}}
                {% endif %}                
            {% else %}           
                {% set numberOfSequentialHours = states('input_number.nordpool_price_savings_sequential_hours') | int (4) %}
                {% set firstHour = (0+numberOfSequentialHours) %}
                {% set lastHour = (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | int (4)  - numberOfSequentialHours) %}
                
                {% set ns = namespace(max_diff=-1000000000, max_index=-1, enough_percentage_difference=false) %}
                
                
                {% for i in range(firstHour, lastHour - numberOfSequentialHours + 1) %}
                  {% set current_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i:i + numberOfSequentialHours] | list | sum %}
                  {% set previous_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i - numberOfSequentialHours:i] | list | sum %}
                  
                  {% set diff = current_sum - previous_sum %}
                   
                  {% if diff > ns.max_diff %}
                    {% set ns.max_diff = diff %}
                     {% set ns.max_index = i %}
                     {% set ns.enough_percentage_difference = (previous_sum *(states('input_number.nordpool_price_savings_minimum_price_multiplier') | float (1))/current_sum<1) %}
                  {% endif %}
                {% endfor %}
                {{ns.max_diff | float (0)}}    
            {% endif %}
        enough_percentage_difference: >
            {% if (states('sensor.nordpool_kwh_fi') | lower == "unavailable" or states('sensor.nordpool_kwh_fi') | lower == "unknown" )%}
                {% if (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unavailable" or states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unknown" )%}
                     {{(-1) | float (-1)}}
                {% else %}
                    {{state_attr('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours','total_diff_price')}}
                {% endif %}                
            {% else %}           
                {% set numberOfSequentialHours = states('input_number.nordpool_price_savings_sequential_hours') | int (4) %}
                {% set firstHour = (0+numberOfSequentialHours) %}
                {% set lastHour = (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | int (4)  - numberOfSequentialHours) %}
                
                {% set ns = namespace(max_diff=-1000000000, max_index=-1, enough_percentage_difference=false) %}
                
                
                {% for i in range(firstHour, lastHour - numberOfSequentialHours + 1) %}
                  {% set current_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i:i + numberOfSequentialHours] | list | sum %}
                  {% set previous_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i - numberOfSequentialHours:i] | list | sum %}
                  
                  {% set diff = current_sum - previous_sum %}
                   
                  {% if diff > ns.max_diff %}
                    {% set ns.max_diff = diff %}
                     {% set ns.max_index = i %}
                     {% set ns.enough_percentage_difference = (previous_sum *(states('input_number.nordpool_price_savings_minimum_price_multiplier') | float (1))/current_sum<1) %}
                  {% endif %}
                {% endfor %}
                {{ns.enough_percentage_difference}}    

            {% endif %}
            
    - name: "nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours_datetime"
      unique_id: nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours_datetime
      state: >

        {% if (states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours')|float(-1) < 0) %}
            {{today_at("00:00") + timedelta( hours = (0 - 480000))}}
        {% else %}   
              {% if (state_attr('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours','total_diff_price') | float (-1) > states('input_number.nordpool_price_savings_minimum_price_difference') | int (6) ) and (state_attr('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours','enough_percentage_difference'))%}
                  {{ today_at("00:00") + timedelta(hours = states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours') | float (0))}}
              {% else %}
                  {{  today_at('00:00') + timedelta( hours = (0 - 480000)) }} 
              {% endif %}              
        {% endif %}



    - name: "nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours"
      unique_id: nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours
      state: >
        {% if (states('sensor.nordpool_kwh_fi') | lower == "unavailable" or states('sensor.nordpool_kwh_fi') | lower == "unknown" )%}
            {% if (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unavailable" or states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unknown" )%}
                 {{(-1) | float (-1)}}
            {% else %}
                {{states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours')}}
            {% endif %}                
        {% else %}    
    
    
            {% set numberOfSequentialHours = states('input_number.nordpool_price_savings_sequential_hours') | int (4) %}
            {% set firstHour = (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | int (4) + numberOfSequentialHours) %}
            {% set lastHour = 24 %}
            
            {% set ns = namespace(max_diff=-1000000000, max_index=-1, enough_percentage_difference=false) %}
            
            
            {% for i in range(firstHour, lastHour - numberOfSequentialHours + 1) %}
              {% set current_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i:i + numberOfSequentialHours] | list | sum %}
              {% set previous_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i - numberOfSequentialHours:i] | list | sum %}
              
              {% set diff = current_sum - previous_sum %}
               
              {% if diff > ns.max_diff %}
                {% set ns.max_diff = diff %}
                 {% set ns.max_index = i %}
                 {% set ns.enough_percentage_difference = (previous_sum *(states('input_number.nordpool_price_savings_minimum_price_multiplier') | float (1))/current_sum<1) %}
              {% endif %}
            {% endfor %}
            {{ns.max_index | float (0)}}    
        {% endif %}
      attributes:
        total_diff_price: >
            {% if (states('sensor.nordpool_kwh_fi') | lower == "unavailable" or states('sensor.nordpool_kwh_fi') | lower == "unknown" )%}
                {% if (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unavailable" or states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unknown" )%}
                     {{(-1) | float (-1)}}
                {% else %}
                    {{state_attr('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours','total_diff_price')}}
                {% endif %}                
            {% else %}           
                {% set numberOfSequentialHours = states('input_number.nordpool_price_savings_sequential_hours') | int (4) %}
                {% set firstHour = (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | int (4) + numberOfSequentialHours) %}
                {% set lastHour = 24 %}
                
                {% set ns = namespace(max_diff=-1000000000, max_index=-1, enough_percentage_difference=false) %}
                
                
                {% for i in range(firstHour, lastHour - numberOfSequentialHours + 1) %}
                  {% set current_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i:i + numberOfSequentialHours] | list | sum %}
                  {% set previous_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i - numberOfSequentialHours:i] | list | sum %}
                  
                  {% set diff = current_sum - previous_sum %}
                   
                  {% if diff > ns.max_diff %}
                    {% set ns.max_diff = diff %}
                     {% set ns.max_index = i %}
                     {% set ns.enough_percentage_difference = (previous_sum *(states('input_number.nordpool_price_savings_minimum_price_multiplier') | float (1))/current_sum<1) %}
                  {% endif %}
                {% endfor %}
                {{ns.max_diff | float (0)}}    
            {% endif %}
        enough_percentage_difference: >
            {% if (states('sensor.nordpool_kwh_fi') | lower == "unavailable" or states('sensor.nordpool_kwh_fi') | lower == "unknown" )%}
                {% if (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unavailable" or states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unknown" )%}
                     {{(-1) | float (-1)}}
                {% else %}
                    {{state_attr('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours','total_diff_price')}}
                {% endif %}                
            {% else %}           
                {% set numberOfSequentialHours = states('input_number.nordpool_price_savings_sequential_hours') | int (4) %}
                {% set firstHour = (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | int (4) + numberOfSequentialHours) %}
                {% set lastHour = 24 %}
                
                {% set ns = namespace(max_diff=-1000000000, max_index=-1, enough_percentage_difference=false) %}
                
                
                {% for i in range(firstHour, lastHour - numberOfSequentialHours + 1) %}
                  {% set current_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i:i + numberOfSequentialHours] | list | sum %}
                  {% set previous_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i - numberOfSequentialHours:i] | list | sum %}
                  
                  {% set diff = current_sum - previous_sum %}
                   
                  {% if diff > ns.max_diff %}
                    {% set ns.max_diff = diff %}
                     {% set ns.max_index = i %}
                     {% set ns.enough_percentage_difference = (previous_sum *(states('input_number.nordpool_price_savings_minimum_price_multiplier') | float (1))/current_sum<1) %}
                  {% endif %}
                {% endfor %}
                {{ns.enough_percentage_difference}}    
   
            {% endif %}
        
    - name: "nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours_datetime"
      unique_id: nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours_datetime
      state: >

        {% if (states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours')|float(-1) < 0) %}
            {{today_at("00:00") + timedelta( hours = (0 - 480000))}}
        {% else %}   
              {% if (state_attr('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours','total_diff_price') | float (-1) > states('input_number.nordpool_price_savings_minimum_price_difference') | int (6) ) and (state_attr('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours','enough_percentage_difference'))%}
                  {{ today_at("00:00") + timedelta(hours = states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours') | float (0))}}
              {% else %}
                  {{  today_at('00:00') + timedelta( hours = (0 - 480000)) }} 
              {% endif %}              
        {% endif %}

continuing…

5 Likes

continuing…

Automations

  1. Main HVAC automation is checking outside and inside temperatures, weather forecast and does changes to heating/ cooling by those sensors.

  2. Automation check if it is time to put on energy savings:

trigger:
  - platform: template
    value_template: >-
      {{
      (as_datetime(states('sensor.nordpool_price_most_savings_sequential_hours_energy_today_datetime'))
      -
      timedelta(hours=(states('input_number.nordpool_price_savings_sequential_hours')
      | int (4) - 1) , minutes = 59)) < now() <
      (as_datetime(states('sensor.nordpool_price_most_savings_sequential_hours_energy_today_datetime')))}}
  - platform: template
    value_template: >-
      {{(as_datetime(states('sensor.nordpool_price_most_savings_sequential_hours_energy_today_datetime')))
      < now() <
      (as_datetime(states('sensor.nordpool_price_most_savings_sequential_hours_energy_today_datetime')) 
      + timedelta( minutes = 1))}}
  - platform: template
    value_template: >-
      {{(as_datetime(states('sensor.nordpool_price_most_savings_sequential_hours_energy_today_datetime')) 
      + timedelta(
      hours=states('input_number.nordpool_price_savings_sequential_hours') | int
      (4) )) < now() <
      (as_datetime(states('sensor.nordpool_price_most_savings_sequential_hours_energy_today_datetime')) 
      + timedelta( hours=4, minutes = 1))}}
  - platform: template
    value_template: >-
      {{
      (as_datetime(states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours_datetime')) 
      -
      timedelta(hours=(states('input_number.nordpool_price_savings_sequential_hours')
      | int (4) - 1), minutes = 59)) < now() <
      (as_datetime(states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours_datetime')))}}
  - platform: template
    value_template: >-
      {{(as_datetime(states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours_datetime')))
      < now () <
      (as_datetime(states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours_datetime')) 
      + timedelta( minutes = 1))}}
  - platform: template
    value_template: >-
      {{(as_datetime(states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours_datetime'))
      + timedelta(
      hours=states('input_number.nordpool_price_savings_sequential_hours') | int
      (4) )) < now () <
      (as_datetime(states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours_datetime'))
      + timedelta(
      hours=states('input_number.nordpool_price_savings_sequential_hours') | int
      (4), minutes = 1) )}}
  - platform: template
    value_template: >-
      {{
      (as_datetime(states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours_datetime')) 
      -
      timedelta(hours=(states('input_number.nordpool_price_savings_sequential_hours')
      | int (4) - 1), minutes = 59)) < now() <
      (as_datetime(states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours_datetime')))}}
  - platform: template
    value_template: >-
      {{(as_datetime(states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours_datetime')))
      < now () <
      (as_datetime(states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours_datetime')) 
      + timedelta( minutes = 1))}}
  - platform: template
    value_template: >-
      {{(as_datetime(states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours_datetime'))
      + timedelta(
      hours=states('input_number.nordpool_price_savings_sequential_hours') | int
      (4) )) < now () <
      (as_datetime(states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours_datetime'))
      + timedelta(
      hours=states('input_number.nordpool_price_savings_sequential_hours') | int
      (4), minutes = 1) )}}      
  - platform: time_pattern
    minutes: /15


action:
  - choose:
      - conditions:
          - condition: numeric_state
            entity_id: sensor.weather_combined_temperature
            below: "12"
          - condition: state
            entity_id: input_boolean.hvac_lammitys_valtakunnanverkon_energiansaasto
            state: "off"
          - condition: state
            entity_id: input_boolean.hvac_lammitys_valtakunnanverkon_energiansaasto_pois
            state: "off"
          - condition: or
            conditions:
              - condition: template
                value_template: >-
                  {{( 
                  (as_datetime(states('sensor.nordpool_price_most_savings_sequential_hours_energy_today_datetime')) 
                  -
                  timedelta(hours=states('input_number.nordpool_price_savings_sequential_hours')
                  | int (4), minutes=5)) < now() <
                  (as_datetime(states('sensor.nordpool_price_most_savings_sequential_hours_energy_today_datetime'))
                  ))}}
              - condition: template
                value_template: >-
                  {{( 
                  (as_datetime(states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours_datetime')) 
                  -
                  timedelta(hours=states('input_number.nordpool_price_savings_sequential_hours')
                  | int (4), minutes=5)) < now() <
                  (as_datetime(states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours_datetime'))
                  ))}}
              - condition: template
                value_template: >-
                  {{( 
                  (as_datetime(states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours_datetime')) 
                  -
                  timedelta(hours=states('input_number.nordpool_price_savings_sequential_hours')
                  | int (4), minutes=5)) < now() <
                  (as_datetime(states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours_datetime'))
                  ))}}
        sequence:
          - if:
              - condition: state
                entity_id: >-
                  binary_sensor.nordpool_now_price_really_cheap_compared_to_average_whole_day_longterm_mean
                state: "off"
            then:
              - service: input_boolean.turn_on
                data: {}
                target:
                  entity_id:
                    - >-
                      input_boolean.hvac_lammitys_valtakunnanverkon_energiansaasto
                    - >-
                      input_boolean.hvac_lammitys_valtakunnanverkon_energiansaasto_lisalampo
              - service: input_boolean.turn_off
                data: {}
                target:
                  entity_id: >-
                    input_boolean.hvac_lammitys_valtakunnanverkon_energiansaasto_lammitys_pois
            else: []
  1. Main energy savings HVAC automation is checking if it is time to preheat/ precool house more if the “high price” event is about fire up. After the event is on, it will cut the heat on the house by setting built in + or - to predetermined setting corresponging to outside temperature. That is, if the ouside temperature is +20 and over I set cooling +3 and if the outside temperature is +10 and under I set heating -3.

Main energy savings HVAC automation of mine below as an example. Sorry about the mixed use of Finnish language and the English, historical reasons. I think it is more helpful to see the automation still than not seeing it.

alias: Heating - energy savings
description: ""
trigger:
  - platform: state
    entity_id:
      - input_boolean.hvac_lammitys_valtakunnanverkon_energiansaasto
    for:
      hours: 0
      minutes: 0
      seconds: 30
  - platform: state
    entity_id:
      - input_boolean.hvac_lammitys_valtakunnanverkon_energiansaasto_lisalampo
    for:
      hours: 0
      minutes: 0
      seconds: 30
  - platform: state
    entity_id:
      - >-
        input_boolean.hvac_lammitys_valtakunnanverkon_energiansaasto_lammitys_pois
    for:
      hours: 0
      minutes: 0
      seconds: 30
condition:
action:
  - choose:
      - conditions:
          - condition: state
            entity_id: >-
              input_boolean.hvac_lammitys_valtakunnanverkon_energiansaasto_lisalampo
            state: "on"
          - condition: state
            entity_id: input_boolean.hvac_lammitys_valtakunnanverkon_energiansaasto
            state: "on"
        sequence:
          - if:
              - condition: numeric_state
                entity_id: sensor.weather_combined_temperature
                below: 17
            then:
              - data:
                  hvac_mode: heat
                  temperature: >-
                    {{
                    states('input_number.hvac_asetusarvo_alakerta_lampotila_03_keskiraja')
                    | float (20) +
                    (states('input_number.hvac_asetusarvo_alakerta_lisalampo_lisakylma')
                    | float (0)) + 1}}
                service: climate.set_temperature
                target:
                  entity_id: climate.alakerta_hvac
              - data:
                  fan_mode: mid
                entity_id: climate.alakerta_hvac
                service: climate.set_fan_mode
              - data:
                  hvac_mode: heat
                  temperature: >-
                    {{
                    states('input_number.hvac_asetusarvo_ylakerta_lampotila_03_keskiraja')
                    | float (20) +
                    (states('input_number.hvac_asetusarvo_ylakerta_lisalampo_lisakylma')
                    | float (0)) + 1 }}
                service: climate.set_temperature
                target:
                  entity_id: climate.ylakerta_hvac
              - data:
                  fan_mode: mid
                entity_id: climate.ylakerta_hvac
                service: climate.set_fan_mode
              - data:
                  hvac_mode: heat
                  temperature: >-
                    {{
                    states('input_number.hvac_asetusarvo_alakerta_lampotila_03_keskiraja')
                    | float (20) +
                    (states('input_number.hvac_asetusarvo_alakerta_lisalampo_lisakylma')
                    | float (0)) + 1 +
                    states('input_number.hvac_asetusarvo_alakerta_radiator_thermostats_offset')
                    | float (0)}}
                service: climate.set_temperature
                target:
                  entity_id:
                    - group.alakerta_radiator_thermostats
              - data:
                  hvac_mode: heat
                  temperature: >-
                    {{
                    states('input_number.hvac_asetusarvo_vilpola_03_keskiraja')
                    | float (15) + 1}}
                service: climate.set_temperature
                target:
                  entity_id:
                    - climate.vilpola_radiator_thermostat_thermostat
              - data:
                  hvac_mode: heat
                  temperature: >-
                    {{
                    states('input_number.hvac_asetusarvo_ylakerta_lampotila_03_keskiraja')
                    | float (20) +
                    (states('input_number.hvac_asetusarvo_ylakerta_lisalampo_lisakylma')
                    | float (0)) + 1 +
                    states('input_number.hvac_asetusarvo_ylakerta_radiator_thermostats_offset')
                    | float (0)}}
                service: climate.set_temperature
                target:
                  entity_id:
                    - group.ylakerta_radiator_thermostats
              - service: switch.turn_on
                data: {}
                target:
                  entity_id:
                    - switch.vilpola_pistorasia1
                    - switch.vaatehuone_pistorasia1
            else:
              - data:
                  hvac_mode: cool
                  temperature: >-
                    {{
                    states('input_number.hvac_asetusarvo_alakerta_lampotila_04_lamminraja')
                    | float (25) +
                    (states('input_number.hvac_asetusarvo_alakerta_lisalampo_lisakylma')
                    | float (0)) - 1}}
                service: climate.set_temperature
                target:
                  entity_id: climate.alakerta_hvac
              - data:
                  fan_mode: mid
                entity_id: climate.alakerta_hvac
                service: climate.set_fan_mode
              - data:
                  hvac_mode: cool
                  temperature: >-
                    {{
                    states('input_number.hvac_asetusarvo_ylakerta_lampotila_04_lamminraja')
                    | float (24) +
                    (states('input_number.hvac_asetusarvo_ylakerta_lisalampo_lisakylma')
                    | float (0)) - 1 }}
                service: climate.set_temperature
                target:
                  entity_id: climate.ylakerta_hvac
              - data:
                  fan_mode: mid
                entity_id: climate.ylakerta_hvac
                service: climate.set_fan_mode
              - data:
                  hvac_mode: heat
                  temperature: >-
                    {{
                    states('input_number.hvac_asetusarvo_alakerta_lampotila_01_alaraja')
                    | float (15) +
                    states('input_number.hvac_asetusarvo_alakerta_radiator_thermostats_offset')
                    | float (0)}}
                service: climate.set_temperature
                target:
                  entity_id:
                    - group.alakerta_radiator_thermostats
              - data:
                  hvac_mode: heat
                  temperature: >-
                    {{ states('input_number.hvac_asetusarvo_vilpola_01_alaraja')
                    | float (12)}}
                service: climate.set_temperature
                target:
                  entity_id:
                    - climate.vilpola_radiator_thermostat_thermostat
              - data:
                  hvac_mode: heat
                  temperature: >-
                    {{
                    states('input_number.hvac_asetusarvo_ylakerta_lampotila_01_alaraja')
                    | float (20) +
                    states('input_number.hvac_asetusarvo_ylakerta_radiator_thermostats_offset')
                    | float (0)}}
                service: climate.set_temperature
                target:
                  entity_id:
                    - group.ylakerta_radiator_thermostats
              - service: switch.turn_on
                data: {}
                target:
                  entity_id:
                    - switch.vilpola_pistorasia1
                    - switch.vaatehuone_pistorasia1

                  
      - conditions:
          - condition: state
            entity_id: >-
              input_boolean.hvac_lammitys_valtakunnanverkon_energiansaasto_lammitys_pois
            state: "on"
          - condition: state
            entity_id: input_boolean.hvac_lammitys_valtakunnanverkon_energiansaasto
            state: "on"
        sequence:
          - if:
              - condition: or
                conditions:
                  - condition: numeric_state
                    entity_id: sensor.weather_combined_temperature
                    above: 17
                  - condition: numeric_state
                    entity_id: sensor.24h_forecast_max_temp
                    above: 17
            then:
              - data:
                  hvac_mode: cool
                  temperature: >-
                    {{
                    (states('input_number.hvac_asetusarvo_alakerta_lampotila_05_ylaraja')
                    | float (29)) - 1   }}
                service: climate.set_temperature
                target:
                  entity_id: climate.alakerta_hvac
              - data:
                  fan_mode: mid
                entity_id: climate.alakerta_hvac
                service: climate.set_fan_mode
              - data:
                  hvac_mode: cool
                  temperature: >-
                    {{
                    (states('input_number.hvac_asetusarvo_ylakerta_lampotila_05_ylaraja')
                    | float (29)) - 1 }}
                service: climate.set_temperature
                target:
                  entity_id: climate.ylakerta_hvac
              - data:
                  fan_mode: mid
                entity_id: climate.ylakerta_hvac
                service: climate.set_fan_mode
              - data:
                  hvac_mode: heat
                  temperature: >-
                    {{
                    states('input_number.hvac_asetusarvo_alakerta_lampotila_01_alaraja')
                    | float (15) }}
                service: climate.set_temperature
                target:
                  entity_id:
                    - group.alakerta_radiator_thermostats
              - data:
                  hvac_mode: heat
                  temperature: >-
                    {{ states('input_number.hvac_asetusarvo_vilpola_01_alaraja')
                    | float (12)}}
                service: climate.set_temperature
                target:
                  entity_id:
                    - climate.vilpola_radiator_thermostat_thermostat
              - data:
                  hvac_mode: heat
                  temperature: >-
                    {{
                    states('input_number.hvac_asetusarvo_ylakerta_lampotila_01_alaraja')
                    | float (15)}}
                service: climate.set_temperature
                target:
                  entity_id:
                    - group.ylakerta_radiator_thermostats
              - service: switch.turn_off
                data: {}
                target:
                  entity_id:
                    - switch.vilpola_pistorasia1
                    - switch.vaatehuone_pistorasia1
            else:
              - data:
                  hvac_mode: heat
                  temperature: >-
                    {{
                    (states('input_number.hvac_asetusarvo_alakerta_lampotila_01_alaraja')
                    | float (15)) + 1   }}
                service: climate.set_temperature
                target:
                  entity_id: climate.alakerta_hvac
              - data:
                  fan_mode: mid
                entity_id: climate.alakerta_hvac
                service: climate.set_fan_mode
              - data:
                  hvac_mode: heat
                  temperature: >-
                    {{
                    (states('input_number.hvac_asetusarvo_ylakerta_lampotila_01_alaraja')
                    | float (15)) + 1 }}
                service: climate.set_temperature
                target:
                  entity_id: climate.ylakerta_hvac
              - data:
                  fan_mode: mid
                entity_id: climate.ylakerta_hvac
                service: climate.set_fan_mode
              - data:
                  hvac_mode: heat
                  temperature: >-
                    {{
                    states('input_number.hvac_asetusarvo_alakerta_lampotila_01_alaraja')
                    | float (15) }}
                service: climate.set_temperature
                target:
                  entity_id:
                    - group.alakerta_radiator_thermostats
              - data:
                  hvac_mode: heat
                  temperature: >-
                    {{ states('input_number.hvac_asetusarvo_vilpola_01_alaraja')
                    | float (12)}}
                service: climate.set_temperature
                target:
                  entity_id:
                    - climate.vilpola_radiator_thermostat_thermostat
              - data:
                  hvac_mode: heat
                  temperature: >-
                    {{
                    states('input_number.hvac_asetusarvo_ylakerta_lampotila_01_alaraja')
                    | float (15)}}
                service: climate.set_temperature
                target:
                  entity_id:
                    - group.ylakerta_radiator_thermostats
              - service: switch.turn_off
                data: {}
                target:
                  entity_id:
                    - switch.vilpola_pistorasia1
                    - switch.vaatehuone_pistorasia1
 
      - conditions:
          - condition: state
            entity_id: >-
              input_boolean.hvac_lammitys_valtakunnanverkon_energiansaasto_lammitys_pois
            state: "off"
        sequence:
          - service: automation.trigger
            data:
              skip_condition: false
            target:
              entity_id:
                - >-
                  automation.ylakerta_climavair_automaattiohjaus_ulkolampotilan_ja_sisalampotilan_avulla
                - >-
                  automation.alakerta_climavair_automaattiohjaus_ulkolampotilan_ja_sisalampotilan_avulla
                - >-
                  automation.lammitys_vilpola_automaattiohjaus_ulkolampotilan_ja_sisalampotilan_avulla
                - >-
                  automation.lammitys_kellari_sahkolammitys_automaattiohjaus_ulkolampotilan_ja_sisalampotilan_avulla

    default:

  - delay:
      hours: 0
      minutes: 0
      seconds: 15
      milliseconds: 0
mode: single

4 Likes

Had a stupid error in the template-sensor, did not check if fhe most valuable savings hour is too near the start of the day

{% set firstHour = (0+numberOfSequentialHours) %}
{% set lastHour = (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | int (4) - (2*numberOfSequentialHours)) %}

{% if firstHour < (lastHour-numberOfSequentialHours) %}

or end of the day .

{% set firstHour = (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | int (4) + (2*numberOfSequentialHours)) %}
{% set lastHour = 24 %}
            
{% if firstHour > (lastHour-numberOfSequentialHours) %}

New full template-code:

    - name: "nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours"
      unique_id: nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours
      state: >
        {% if (states('sensor.nordpool_kwh_fi') | lower == "unavailable" or states('sensor.nordpool_kwh_fi') | lower == "unknown" )%}
            {% if (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unavailable" or states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unknown" )%}
                 {{(-1) | float (-1)}}
            {% else %}
                {{states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours')}}
            {% endif %}                
        {% else %}    
            {% set numberOfSequentialHours = states('input_number.nordpool_price_savings_sequential_hours') | int (4) %}
            {% set firstHour = (0+numberOfSequentialHours) %}
            {% set lastHour = (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | int (4) - (2*numberOfSequentialHours)) %}

            {% if firstHour < (lastHour-numberOfSequentialHours) %}
                {{(-1) | float (-1)}}
            {% else %}
                {% set ns = namespace(max_diff=-1000000000, max_index=-1, enough_percentage_difference=false) %}
                
                
                {% for i in range(firstHour, lastHour - numberOfSequentialHours + 1) %}
                  {% set current_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i:i + numberOfSequentialHours] | list | sum %}
                  {% set previous_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i - numberOfSequentialHours:i] | list | sum %}
                  
                  {% set diff = current_sum - previous_sum %}
                   
                  {% if diff > ns.max_diff %}
                    {% set ns.max_diff = diff %}
                     {% set ns.max_index = i %}
                     {% set ns.enough_percentage_difference = (previous_sum *(states('input_number.nordpool_price_savings_minimum_price_multiplier') | float (1))/current_sum<1) %}
                  {% endif %}
                {% endfor %}
                {{ns.max_index | float (0)}}    
            {% endif %}
        {% endif %}
      attributes:
        total_diff_price: >
            {% if (states('sensor.nordpool_kwh_fi') | lower == "unavailable" or states('sensor.nordpool_kwh_fi') | lower == "unknown" )%}
                {% if (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unavailable" or states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unknown" )%}
                     {{(-1) | float (-1)}}
                {% else %}
                    {{state_attr('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours','total_diff_price')}}
                {% endif %}                
            {% else %}           
                {% set numberOfSequentialHours = states('input_number.nordpool_price_savings_sequential_hours') | int (4) %}
                {% set firstHour = (0+numberOfSequentialHours) %}
                {% set lastHour = (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | int (4)  - (2*numberOfSequentialHours)) %}

                {% if firstHour < (lastHour-numberOfSequentialHours) %}
                    {{(-1) | float (-1)}}
                {% else %}                
                    {% set ns = namespace(max_diff=-1000000000, max_index=-1, enough_percentage_difference=false) %}
                    
                    
                    {% for i in range(firstHour, lastHour - numberOfSequentialHours + 1) %}
                      {% set current_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i:i + numberOfSequentialHours] | list | sum %}
                      {% set previous_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i - numberOfSequentialHours:i] | list | sum %}
                      
                      {% set diff = current_sum - previous_sum %}
                       
                      {% if diff > ns.max_diff %}
                        {% set ns.max_diff = diff %}
                         {% set ns.max_index = i %}
                         {% set ns.enough_percentage_difference = (previous_sum *(states('input_number.nordpool_price_savings_minimum_price_multiplier') | float (1))/current_sum<1) %}
                      {% endif %}
                    {% endfor %}
                    {{ns.max_diff | float (0)}}    
                {% endif %}
            {% endif %}
        enough_percentage_difference: >
            {% if (states('sensor.nordpool_kwh_fi') | lower == "unavailable" or states('sensor.nordpool_kwh_fi') | lower == "unknown" )%}
                {% if (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unavailable" or states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unknown" )%}
                     {{(-1) | float (-1)}}
                {% else %}
                    {{state_attr('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours','total_diff_price')}}
                {% endif %}                
            {% else %}           
                {% set numberOfSequentialHours = states('input_number.nordpool_price_savings_sequential_hours') | int (4) %}
                {% set firstHour = (0+numberOfSequentialHours) %}
                {% set lastHour = (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | int (4)  - (2*numberOfSequentialHours)) %}

                {% if firstHour < (lastHour-numberOfSequentialHours) %}
                    {{(-1) | float (-1)}}
                {% else %}                
                    {% set ns = namespace(max_diff=-1000000000, max_index=-1, enough_percentage_difference=false) %}
                    
                    
                    {% for i in range(firstHour, lastHour - numberOfSequentialHours + 1) %}
                      {% set current_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i:i + numberOfSequentialHours] | list | sum %}
                      {% set previous_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i - numberOfSequentialHours:i] | list | sum %}
                      
                      {% set diff = current_sum - previous_sum %}
                       
                      {% if diff > ns.max_diff %}
                        {% set ns.max_diff = diff %}
                         {% set ns.max_index = i %}
                         {% set ns.enough_percentage_difference = (previous_sum *(states('input_number.nordpool_price_savings_minimum_price_multiplier') | float (1))/current_sum<1) %}
                      {% endif %}
                    {% endfor %}
                    {{ns.enough_percentage_difference}}    
                {% endif %}
            {% endif %}
            
    - name: "nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours_datetime"
      unique_id: nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours_datetime
      state: >

        {% if (states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours')|float(-1) < 0) %}
            {{today_at("00:00") + timedelta( hours = (0 - 480000))}}
        {% else %}   
              {% if (state_attr('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours','total_diff_price') | float (-1) > states('input_number.nordpool_price_savings_minimum_price_difference') | int (6) ) and (state_attr('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours','enough_percentage_difference'))%}
                  {{ today_at("00:00") + timedelta(hours = states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_before_most_savings_sequential_hours') | float (0))}}
              {% else %}
                  {{  today_at('00:00') + timedelta( hours = (0 - 480000)) }} 
              {% endif %}              
        {% endif %}



    - name: "nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours"
      unique_id: nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours
      state: >
        {% if (states('sensor.nordpool_kwh_fi') | lower == "unavailable" or states('sensor.nordpool_kwh_fi') | lower == "unknown" )%}
            {% if (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unavailable" or states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unknown" )%}
                 {{(-1) | float (-1)}}
            {% else %}
                {{states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours')}}
            {% endif %}                
        {% else %}    
    
    
            {% set numberOfSequentialHours = states('input_number.nordpool_price_savings_sequential_hours') | int (4) %}
            {% set firstHour = (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | int (4) + (2*numberOfSequentialHours)) %}
            {% set lastHour = 24 %}
            
            {% if firstHour > (lastHour-numberOfSequentialHours) %}
                {{(-1) | float (-1)}}
            {% else %}
                {% set ns = namespace(max_diff=-1000000000, max_index=-1, enough_percentage_difference=false) %}
                
                
                {% for i in range(firstHour, lastHour - numberOfSequentialHours + 1) %}
                  {% set current_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i:i + numberOfSequentialHours] | list | sum %}
                  {% set previous_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i - numberOfSequentialHours:i] | list | sum %}
                  
                  {% set diff = current_sum - previous_sum %}
                   
                  {% if diff > ns.max_diff %}
                    {% set ns.max_diff = diff %}
                     {% set ns.max_index = i %}
                     {% set ns.enough_percentage_difference = (previous_sum *(states('input_number.nordpool_price_savings_minimum_price_multiplier') | float (1))/current_sum<1) %}
                  {% endif %}
                {% endfor %}
                {{ns.max_index | float (0)}}    
            {% endif %}
        {% endif %}
      attributes:
        total_diff_price: >
            {% if (states('sensor.nordpool_kwh_fi') | lower == "unavailable" or states('sensor.nordpool_kwh_fi') | lower == "unknown" )%}
                {% if (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unavailable" or states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unknown" )%}
                     {{(-1) | float (-1)}}
                {% else %}
                    {{state_attr('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours','total_diff_price')}}
                {% endif %}                
            {% else %}           
                {% set numberOfSequentialHours = states('input_number.nordpool_price_savings_sequential_hours') | int (4) %}
                {% set firstHour = (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | int (4) + (2*numberOfSequentialHours)) %}
                {% set lastHour = 24 %}

                {% if firstHour > (lastHour-numberOfSequentialHours) %}
                    {{(-1) | float (-1)}}
                {% else %}
                    {% set ns = namespace(max_diff=-1000000000, max_index=-1, enough_percentage_difference=false) %}
    
                    {% for i in range(firstHour, lastHour - numberOfSequentialHours + 1) %}
                      {% set current_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i:i + numberOfSequentialHours] | list | sum %}
                      {% set previous_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i - numberOfSequentialHours:i] | list | sum %}
                      
                      {% set diff = current_sum - previous_sum %}
                       
                      {% if diff > ns.max_diff %}
                        {% set ns.max_diff = diff %}
                         {% set ns.max_index = i %}
                         {% set ns.enough_percentage_difference = (previous_sum *(states('input_number.nordpool_price_savings_minimum_price_multiplier') | float (1))/current_sum<1) %}
                      {% endif %}
                    {% endfor %}
                    {{ns.max_diff | float (0)}}    
                {% endif %}
            {% endif %}
        enough_percentage_difference: >
            {% if (states('sensor.nordpool_kwh_fi') | lower == "unavailable" or states('sensor.nordpool_kwh_fi') | lower == "unknown" )%}
                {% if (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unavailable" or states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | lower == "unknown" )%}
                     {{(-1) | float (-1)}}
                {% else %}
                    {{state_attr('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours','total_diff_price')}}
                {% endif %}                
            {% else %}           
                {% set numberOfSequentialHours = states('input_number.nordpool_price_savings_sequential_hours') | int (4) %}
                {% set firstHour = (states('sensor.nordpool_price_most_savings_sequential_hours_energy_today') | int (4) + (2*numberOfSequentialHours)) %}
                {% set lastHour = 24 %}
                
                {% if firstHour > (lastHour-numberOfSequentialHours) %}
                    {{(-1) | float (-1)}}
                {% else %}
                    {% set ns = namespace(max_diff=-1000000000, max_index=-1, enough_percentage_difference=false) %}

                    {% for i in range(firstHour, lastHour - numberOfSequentialHours + 1) %}
                      {% set current_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i:i + numberOfSequentialHours] | list | sum %}
                      {% set previous_sum = state_attr('sensor.nordpool_kwh_fi', 'today')[i - numberOfSequentialHours:i] | list | sum %}
                      
                      {% set diff = current_sum - previous_sum %}
                       
                      {% if diff > ns.max_diff %}
                        {% set ns.max_diff = diff %}
                         {% set ns.max_index = i %}
                         {% set ns.enough_percentage_difference = (previous_sum *(states('input_number.nordpool_price_savings_minimum_price_multiplier') | float (1))/current_sum<1) %}
                      {% endif %}
                    {% endfor %}
                    {{ns.enough_percentage_difference}}    
                {% endif %}
            {% endif %}
        
    - name: "nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours_datetime"
      unique_id: nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours_datetime
      state: >

        {% if (states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours')|float(-1) < 0) %}
            {{today_at("00:00") + timedelta( hours = (0 - 480000))}}
        {% else %}   
              {% if (state_attr('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours','total_diff_price') | float (-1) > states('input_number.nordpool_price_savings_minimum_price_difference') | int (6) ) and (state_attr('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours','enough_percentage_difference'))%}
                  {{ today_at("00:00") + timedelta(hours = states('sensor.nordpool_price_2nd_most_savings_sequential_hours_energy_today_after_most_savings_sequential_hours') | float (0))}}
              {% else %}
                  {{  today_at('00:00') + timedelta( hours = (0 - 480000)) }} 
              {% endif %}              
        {% endif %}

This is great. Thanks for sharing!

1 Like

Thanks! FYI, I’ve edited my heating/ cooling automations a bit more simpler 2 automations: one for cooling and one for heating. Much easier to manage the automation code. The checks if the house needs to be cooled or heated are determined in the sensor:

- binary_sensor:
    - name: "Heating ON"
      unique_id: "heating_ON"
      state: >
        {{  (states('sensor.weather_combined_temperature') | float < states('input_number.hvac_asetusarvo_ulkolampotila_03_keskiraja') | float) 
              or
            (states('sensor.weather_combined_24h_forecast_min_temp') | float < states('input_number.hvac_asetusarvo_ulkolampotila_03_keskiraja') | float)
        }}