Ask
27

Writing an automation to heat and charge during the cheapest hours — why does "pick the N cheapest hours" perform so badly?

I am on an hourly spot price tariff and I have the prices for tomorrow available in my automation system each afternoon. I want to shift the water tank, the heating and the car charging into the cheap hours.

My first attempt was the obvious thing: sort tomorrow's hours by price, take the cheapest N, run everything during those.

It works in the sense that it runs when prices are low. But the house is cold at the wrong times, the tank sometimes runs out mid-evening, and one day the car did not finish charging because the cheap hours were scattered across the night with gaps.

What is the actual shape of this problem? I get the feeling I am solving it wrong rather than tuning it wrong.

3 answers Share
Report

Answering anonymously — a moderator will review it first.

  • @thermal_mass_theo · 2h ago

    You are solving it wrong, and the reason is a good one to internalise because it applies to all three of your loads differently.

    "Cheapest N hours" optimises price and ignores the constraint. Each of your loads is really a storage problem with its own rules, and the rules are what make the schedule feasible:

    • The car needs a total amount of energy before a deadline. It does not care when, but it usually cannot pause and resume for free — and some cars and chargers handle interrupted sessions badly. So it wants contiguous cheap hours, or at least few segments.
    • The hot water tank is a store that leaks. Heat it at two in the morning and some of it is gone by the evening shower. It also has a hard constraint you must not optimise away: the tank needs to reach a high enough temperature regularly for hygiene reasons, regardless of price.
    • The house is a store with a large capacity and a slow response. You can heat it early and coast, but only within the comfort band, and how far you can coast depends on the outdoor temperature and how leaky the building is.

    So the correct framing is: for each load, what is the minimum energy needed, by when, subject to what constraints — and then place that energy in the cheapest hours that satisfy the constraints. Price is the objective; the constraints come first.

    A concrete shape that works and is not hard to implement:

    1. Define a horizon and a deadline per load. Car: by 07:00. Tank: hot by 18:00. Heating: comfort band maintained continuously.
    2. Estimate the energy each needs. For the car, target minus current state of charge, divided by charge rate, gives hours needed. For the tank, a fixed number of hours from cold is a fine first approximation. For heating, this is the hard one — see below.
    3. Within each load's own window, rank hours by price and allocate. For the car, prefer the cheapest contiguous block long enough to finish, rather than the cheapest scattered hours. That fixes your unfinished-charge problem directly.
    4. Respect minimum run times. A heat pump or a compressor cycled on and off hourly is being damaged and is running inefficiently. If an hour is cheap and the next is not, do not toggle — put a minimum-on constraint in.
    5. Always have a fallback. If prices are unavailable, or the day is uniformly expensive, the system must fall back to "just heat the house" rather than doing nothing. Comfort failures are far more expensive in household goodwill than a few hours at a bad price.

    On the heating specifically, this is where "cheapest hours" fails worst. Preheating works, but only if the building holds it. A well-insulated house with underfloor heating can coast for hours; a leaky one with radiators loses it in forty minutes and you have paid for heat that went outside. Measure your own coast rate before designing around it: heat to the top of the band, turn everything off, and time how long it takes to fall to the bottom. That number is the only thing that tells you how much preheating is worth doing.

    Start with a threshold rather than an optimiser — run when the price is below some percentile of the day — measure for a fortnight, and only then decide whether the extra complexity pays. It frequently does not.

    30
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @bill_watcher · 11h ago

    The trap that quietly ruins these projects: the spot price is not your price.

    What you pay per unit is the spot price plus supplier margin, plus network and distribution charges, plus tax — and several of those components are themselves time-varying, often with a day/night split whose boundaries do not line up with the cheap spot hours at all.

    So an optimiser fed raw spot prices can confidently move consumption from an hour that costs you less into one that costs you more, because it is looking at a component rather than the total.

    Build your price series as the actual delivered cost per unit, with every component included, and optimise on that. It is a bit of work once and it changes the answer materially. If you have a negative or near-zero spot price, this is what tells you whether it is genuinely free or whether the fixed components mean it never really is.

    Same applies in reverse if you export: the value of not-exporting is your export rate, not zero, so self-consumption has an opportunity cost.

    27
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @spot_price_sanna · 2h ago

    On the contiguous-block point for the car, one implementation detail that took me a while.

    Finding the cheapest window of length N in a price series is a sliding window: sum each consecutive run of N hours, keep the cheapest. It is a few lines and it runs instantly on 24 or 48 values. There is no need for anything cleverer at this scale.

    The subtlety is that you usually want the cheapest window that ends before the deadline, not the cheapest window overall, and those differ often enough to matter. Filter the candidate windows by deadline before comparing them.

    Also: use tomorrow's prices as soon as they are published rather than at midnight, so an evening plug-in gets the full night considered rather than only the hours after the automation happens to run.

    22
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report