Make a home battery trade the half-hourly power market, then sell the setup
Octopus Agile changes price every half hour, from negative at 3am to 50p at teatime, and most UK home batteries ignore it on factory defaults. Build a planner, a 12-month backtester and a Home Assistant autopilot that charge at the right times. The software is free, but a battery typically costs £5,500 to £7,500 fitted, so the business sells to people who already own one.
- The payback maths for new and existing batteries, and the service built on it
- A business kit: pricing, installer partner message, backtest-led outreach, site checklist, 30-day plan, scoreboard
- Python 3.9 or newer for the planner and backtest. New to the terminal? Terminal survival kit
- For the autopilot: a home battery with an inverter Home Assistant can control locally (the course uses GivEnergy), an Octopus smart meter account, and a Home Assistant box (Home Assistant Green, list price €179, or a mini PC or Raspberry Pi 5)
- Comfort editing YAML. You never touch wiring: batteries are fitted by an MCS-certified installer
Pull tomorrow's Agile prices and plan a battery around them
See the half-hourly price curve for your region and the optimal plan for a battery, from real published prices.
How Agile worksOn Agile Octopus ↗ every half hour has its own price, set from the wholesale market. Tomorrow's 48 prices are published every afternoon (usually around 4pm). The shape repeats most days: cheap overnight, often cheap again in sunny or windy middays, sometimes negative (you're paid to use power), and expensive from 4pm to 7pm. Agile Outgoing does the same for power you export. A battery earns in two ways: it replaces expensive peak imports with cheap overnight energy, and it can sell energy back when export prices are high.
Get the plannerDownload agile_plan.py. It uses only Python's standard library. Octopus publishes tariff prices on a public API, so there's no key and no account. Run it with your region letter (it's at the end of your tariff code and on your bill;
Cis London):Windows (PowerShell)python agile_plan.py --region CMac/Linuxpython3 agile_plan.py --region CIt fetches Agile import (
AGILE-24-10-01) and Agile Outgoing prices for every half hour available, then runs a small dynamic programme: for each half hour it tries charging, holding and discharging at every battery level, and keeps the cheapest path through the whole period. It respects the battery's size, its charge rate, round-trip losses and your house's typical use. Run the evening the next day's prices came out:OutputAgile AGILE-24-10-01 region C: 58 half hours, Sat 10 Oct 18:00 to Sun 23:00 import min 15.41p avg 28.12p max 51.46p per kWh (inc VAT) export min 10.20p avg 16.28p max 27.56p per kWh cheapest half hours: 22:30 15.76p, 00:30 16.01p, 01:00 15.41p, 02:00 15.97p, 02:30 17.29p, 03:00 17.60p Battery: 9.5 kWh usable, 3.6 kW, 90% round trip, house load 0.35 kWh per half hour, start 2.0 kWh, reserve 1.0 kWh time import p export p action battery kWh Sat 22:30 15.76 10.37 charge 1.8 kWh 2.8 Sun 00:30 16.01 10.49 charge 1.8 kWh 4.3 Sun 01:00 15.41 10.20 charge 1.8 kWh 6.1 Sun 02:00 15.97 10.47 charge 1.8 kWh 7.9 Sun 02:30 17.29 11.10 charge 1.6 kWh 9.5 ... Sun 16:00 44.43 24.22 discharge 0.4 kWh 5.6 Sun 16:30 49.41 26.59 discharge 0.4 kWh 5.2 Sun 17:00 49.68 26.71 discharge 0.4 kWh 4.8 Sun 17:30 51.12 27.40 discharge 0.4 kWh 4.4 Sun 18:00 51.38 27.52 discharge 0.4 kWh 4.0 Sun 18:30 51.46 27.56 discharge 0.4 kWh 3.6 ... Value of the battery over these 29 hours: 186p (about 154p a day at these prices)Read the plan: fill up overnight at 15 to 17p, then cover the house through the day and the 44 to 51p peak. Notice it never exports here: tonight's export peak (27.56p) is worth less than the import it replaces (51p), so using the energy yourself wins. On a day with very cheap or negative overnight prices, the plan changes on its own.

Run at 1am, so only the rest of Monday's prices were out. Even on a flat day with no cheap overnight dip, the plan charges at about 25p and covers the 48p peak. Make it yoursThe defaults describe a common setup (GivEnergy 9.5kWh battery, 3.6kW inverter). Set your own:
Your battery, your housepython agile_plan.py --region M --capacity 13.5 --rate 5 --load 0.4 --soc 3 --csv plan.csv--capacityusable kWh,--ratemax charge/discharge kW,--efficiencyround trip (default 0.90)--loadyour average use per half hour in kWh (annual kWh divided by 17,520 is a fair start)--sochow full it is now,--reservethe floor it never goes below--no-exportif you aren't on an export tariff