AI Solar Panel
§1 Section 1 of 6 3,658 words · 17 min

Sizing From Your Own Consumption Data

Ask an installer how many solar panels do I need UK and you will get an answer derived from your roof, not from your electricity use. That is the correct answer to a different question. The roof tells you the ceiling. Your half-hourly consumption tells you the point at which each additional panel stops being worth its marginal cost, and those two numbers are rarely the same.

This page is about closing that gap with data you already have access to. If you have a smart meter that reports in half-hourly mode, you are sitting on somewhere between 17,520 and 35,040 rows of the most valuable input to the whole calculation, and almost nobody uses it. Rules of thumb (“3-bed semi, 10 panels”) are compression artefacts of thousands of houses that are not yours.

The question behind the keyword

There are actually four questions hiding inside “how many panels do I need”:

  1. How many panels physically fit, given ridge and eaves setbacks and panel dimensions?
  2. How many can I connect without a G99 application, or with one?
  3. How many will generate roughly as much as I consume across a year?
  4. How many maximise net present value, given what I pay for import and get for export?

Question 3 is the one people accidentally answer, and it is the least useful of the four. Annual netting is a fiction: your 5 kWp array generates 675 kWh in June against a 330 kWh June load, and 105 kWh in December against a 470 kWh December load. Annual balance conceals a July surplus you sell at 15p and a January deficit you buy at 26p. Question 4 is the one worth your evening, and answering it needs half-hourly resolution on both sides of the equation.

MCS installers work to the Standard Estimation Method in MIS 3002, which produces a kWh/kWp figure from your postcode region, tilt, orientation and a shading factor. That is a generation estimate and a good one. It is not a savings estimate, and the “assumed 50% self-consumption” line that appears on so many quotes is a default, not a measurement. Your own data replaces that default with a number you can defend.

Get the half-hourly data first

Before modelling anything, pull at least 12 months of half-hourly import. Your meter’s internal store holds roughly 13 months, so if you have never pulled it, do that today and worry about the model later.

Three routes, in rough order of effort:

Octopus Energy API. If you are an Octopus customer this is the fastest path. Generate an API key in your account dashboard, find your MPAN and meter serial, then:

curl -u "sk_live_YOURKEY:" \
  "https://api.octopus.energy/v1/electricity-meter-points/1200012345678/meters/21L1234567/consumption/?period_from=2024-09-01T00:00Z&period_to=2025-09-01T00:00Z&page_size=25000&order_by=period"

You get JSON with consumption, interval_start, interval_end. Paginate via the next field. If you already export, your export MPAN has its own endpoint and its own serial, and the two series are what you need for any retrospective analysis.

n3rgy consumer API. Supplier-agnostic, reads straight from the DCC, free for consumers at the time of writing. You register with your MPxN and the postcode on the account, then query by date range. This is the route if you are with a supplier whose API is a web portal and a CSV download button.

Hildebrand Glowmarkt / the Bright app. Bright will show you 13 months of half-hourly data and, with a Glow CAD (about £70), gives you near-real-time consumption over MQTT, which matters later for validation. The Glowmarkt API is documented and stable.

Whatever you use, normalise to a single CSV with timestamp_utc, import_kwh and watch the clock changes. BST transitions produce a 46-period day in March and a 50-period day in October, and if your parser silently drops or duplicates rows you will find a phantom 1% error you cannot trace. Tag each row with is_bst and validate that every day sums 48 periods except the two that should not.

For the full extraction-to-panel-count pipeline, including the parsing scripts and the specific column shapes each API returns, see Turning Smart Meter Data Into a Panel Count.

The five numbers to extract before you open any calculator

Run these on your year of data. They will tell you more about what to buy than any quote will.

Baseload. Take the 5th percentile of all half-hourly readings, or the median of 02:00 to 04:00 periods. A reading of 0.09 kWh per half hour is a 180 W baseload, which is 1,577 kWh a year, which may be a third of your bill. Solar barely touches this: in December your array produces nothing at 3 a.m. Find it, then go and kill it before you spend £9,000 on panels. Common culprits, measured with a Tapo P110 or Shelly Plus PM: a 1990s chest freezer at 95 W average, an always-on gaming PC at 65 W, a hot water circulation pump left on a permanent schedule at 45 W.

Daytime share. Sum consumption in the 09:00 to 16:00 window and divide by the annual total. This is the fraction of your demand that solar can serve without a battery, and it is usually 20% to 30% for a working household, 40% to 50% for a home-worker or a retired couple. In the worked example below it is 24%.

Evening peak shape. Sum 16:00 to 22:00. This is what a battery is for. If that block is 1,900 kWh a year you have a strong battery case; if it is 700 kWh you are buying a battery for tariff arbitrage, which is a different justification and needs a different sum.

Winter-to-summer ratio. January total over July total. A ratio near 1.0 says electric load is weather-independent. A ratio of 1.6 (as below) says lighting and occupancy drive it. A ratio above 2.5 usually means resistive heating or a heat pump, which changes the sizing answer completely because your biggest load is anti-correlated with generation.

Maximum half-hourly reading. Useful for inverter and battery power sizing. A 4.1 kWh half-hour means an 8.2 kW instantaneous draw, and a 3.6 kW battery inverter will not cover it.

Turning your roof into a half-hourly generation series

PVGIS, run by the EU JRC, is the free tool that installers’ paid software sits on top of. You want the hourly series, not the annual summary.

https://re.jrc.ec.europa.eu/api/v5_2/seriescalc?lat=52.6369&lon=-1.1398
  &raddatabase=PVGIS-SARAH3&pvcalculation=1&peakpower=5.28&loss=14
  &angle=35&aspect=0&mountingplace=building&startyear=2016&endyear=2020
  &outputformat=csv

Notes that matter. aspect is 0 for south, 90 for west, -90 for east, which is the opposite sign convention to some other tools. loss=14 is the system loss default covering inverter, cabling, mismatch and soiling; it does not include shading, temperature is handled separately in the model, and 14% is reasonable for a modern string inverter on a clean roof. Five years of hourly data gives you interannual variance, which you want: UK annual yield swings roughly ±7% year to year, and modelling one year gives you false precision.

Use the horizon tool as well. PVGIS will fetch a computed horizon profile from terrain data, but terrain does not include your neighbour’s sycamore. For near shading, measure it: stand at the array position, use a compass app and a clinometer (Theodolite on iOS, or the free Sun Surveyor), and record obstruction elevation every 15° of azimuth. Feed that as userhorizon=0,0,5,12,18,14,6,0,.... A chimney that clips 40 minutes off a December afternoon is worth about 4 kWh a year and is not worth modelling. A conifer that shades the bottom row from 14:00 onwards costs you 250 kWh and changes your string layout.

If you want repeatability, pvlib-python gives you the same physics locally with full control:

import pvlib, pandas as pd

loc = pvlib.location.Location(52.6369, -1.1398, tz='Europe/London', altitude=65)
tmy, _, _, _ = pvlib.iotools.get_pvgis_tmy(52.6369, -1.1398, map_variables=True)

mount  = pvlib.pvsystem.FixedMount(surface_tilt=35, surface_azimuth=180)
array  = pvlib.pvsystem.Array(mount, module_parameters={'pdc0': 440, 'gamma_pdc': -0.0029},
                              modules_per_string=12, strings=1)
system = pvlib.pvsystem.PVSystem(arrays=[array],
                                 inverter_parameters={'pdc0': 5000, 'eta_inv_nom': 0.97})
mc = pvlib.modelchain.ModelChain(system, loc, aoi_model='physical', spectral_model='no_loss')
mc.run_model(tmy)

ac = mc.results.ac.clip(lower=0) / 1000          # kW
hh = ac.resample('30min').interpolate() / 2       # kWh per half hour
print(hh.sum().round(0), 'kWh/yr')

The gamma_pdc of -0.29%/°C is typical for an N-type TOPCon module and is worth carrying because UK summer cell temperatures of 45 to 55°C cost you 6 to 9% at exactly the moment you are generating most.

The matching calculation, in a spreadsheet and in Python

Once you have two aligned half-hourly series, self-consumption without a battery is one line. In Google Sheets or Excel, with consumption in column B and generation in column C:

Self-consumed:  =SUMPRODUCT(MIN(B2:B17521, C2:C17521))     ' array-entered, or:
Self-consumed:  =SUMPRODUCT((B2:B17521<C2:C17521)*B2:B17521 + (B2:B17521>=C2:C17521)*C2:C17521)
Exported:       =SUM(C2:C17521) - <self-consumed>
Imported:       =SUM(B2:B17521) - <self-consumed>

That single SUMPRODUCT replaces the installer’s 50% assumption with your number. Ninety per cent of the value of this whole exercise is in that cell.

The battery needs a loop, because state of charge carries between periods:

def simulate(load, gen, capacity=9.5, usable=0.95, p_max=3.6,
             eta_c=0.96, eta_d=0.96, soc0=0.0):
    soc, imp, exp, sc = soc0, 0.0, 0.0, 0.0
    cap = capacity * usable
    e_max = p_max / 2                       # kWh per half hour
    for l, g in zip(load, gen):
        direct = min(l, g)
        sc += direct
        surplus, deficit = g - direct, l - direct
        if surplus > 0:
            charge = min(surplus, e_max, (cap - soc) / eta_c)
            soc += charge * eta_c
            exp += surplus - charge
        if deficit > 0:
            dis = min(deficit, e_max, soc * eta_d)
            soc -= dis / eta_d
            sc  += dis
            imp += deficit - dis
    return dict(self_consumed=sc, imported=imp, exported=exp)

Round-trip efficiency here is 0.96 × 0.96 = 92%, which is about right for an LFP battery with a hybrid inverter measured at the AC side. Vendors quote 95% or higher at the DC cell level; you pay bills at the meter. Run the loop over capacities from 0 to 20 kWh in 1 kWh steps and you get the marginal-value curve that tells you where to stop. It is steeply diminishing: on the house below, the first 5 kWh delivers 940 kWh a year of shifted energy, the second 5 kWh delivers 520, the third 5 kWh delivers 210.

This is the point where an LLM earns its place in the workflow. Getting pandas to align two differently-timestamped series with a DST-aware index, then sweeping a parameter grid and plotting the result, is 40 minutes of fiddly work you can hand to Claude Code or ChatGPT’s code interpreter and have back in four. What you should not hand over is the assumption set. Write the tariff rates, the efficiencies and the degradation figure into a config dict yourself, because those are the numbers that decide the answer.

Worked example: a 1930s semi in Leicestershire

Measured: 4,850 kWh annual import, 180 W baseload (1,577 kWh), daytime 09:00 to 16:00 share 1,180 kWh (24%), evening 16:00 to 22:00 block 1,610 kWh, January/July ratio 1.58, peak half hour 3.4 kWh.

Roof: rear-facing south at 35°, 8.2 m wide, 3.4 m rafter length. With 440 W modules at 1762 × 1134 mm and 300 mm setbacks, three landscape rows need 3.40 m of rafter plus gaps, so it does not fit. Two rows of four gives eight modules, 3.52 kWp. Four more go on the west-facing garage roof at 30°, 1.76 kWp. Total 5.28 kWp, twelve panels, which is the answer to the headline question for this specific house.

PVGIS gives 940 kWh/kWp for the south array and 745 kWh/kWp for the west. Modelled all-south equivalent, 5.28 kWp at 940, would be 4,963 kWh. Take that as the reference case:

MonthGeneration (kWh)Consumption (kWh)Self-consumed, no batterySelf-consumed, 9.5 kWh battery
Jan12452088110
Feb218460128190
Mar397440170300
Apr566380160345
May665350152330
Jun675330145315
Jul675330145315
Aug591340143320
Sep466360148330
Oct313410140250
Nov16846098150
Dec1054707195
Year4,9634,8501,5883,050

Look at June. Generation 675 kWh against a 330 kWh load: monthly netting says you are 100% covered with 345 kWh to spare. Half-hourly matching says you self-consume 145 kWh of it, 21%. The annual columns nearly balance (4,963 against 4,850) and the balance means nothing.

Without a battery, self-consumption is 32% of generation and covers 33% of demand. With 9.5 kWh of storage it reaches 61% and 63%. Note where the battery gains come from: March to October. In December it adds 24 kWh because there is nothing to store.

Where the money is: the tariff, not the panel count

Price the same physical system on Intelligent Octopus Go: 7 p/kWh from 23:30 to 05:30, 26 p/kWh otherwise, 15 p/kWh export on Outgoing Octopus fixed.

Solar only, no battery. 1,588 kWh self-consumed at 26p is £413. 3,375 kWh exported at 15p is £506. Annual benefit £919.

Solar plus 9.5 kWh battery, solar charging only. 3,050 kWh at 26p is £793. 1,913 kWh exported at 15p is £287. Total £1,080. The battery added £161.

Solar plus battery, also charging from the grid on the cheap rate. November to February the battery can cycle almost fully from the overnight window every night; across the year call it 1,400 kWh imported at 7p (£98) delivering 1,260 kWh at 92% round trip, displacing £328 of day-rate import. Net gain £230. Total annual benefit £1,310.

So the battery is worth £391 a year, of which £230 (59%) has nothing whatever to do with solar. At a marginal installed cost of around £3,500 for a 9.5 kWh unit fitted alongside the array (0% VAT on domestic solar and storage runs to 31 March 2027), that is an 8.9 year simple payback. Price the same battery without grid charging and it is a 22 year payback, which is longer than the warranty.

This is the finding that your own data gives you and a generic calculator never will: for most UK households in 2026, battery economics are a tariff play with a solar bonus, not the reverse. It also means the sizing question for the battery is set by your overnight window length and inverter power, not by your solar surplus. Six hours at 3.6 kW is 21.6 kWh of import capacity, so a 9.5 kWh battery is nowhere near the power-limited ceiling.

One warning on arbitrage maths: export and import net within each half-hour settlement period, so a battery discharging 1 kW while the kettle draws 3 kW shows as 2 kW of import for that period, not as simultaneous import and export. Model at half-hourly granularity and you get this right for free. Model at daily granularity and you will overstate savings by 10 to 15%.

The east/west question, answered with your own numbers

Splitting an array east/west trades kWh for timing. In this example, 8 south plus 4 west generates 4,620 kWh against 4,963 for a notional all-south layout, a 7% loss, but self-consumption rises to about 1,690 kWh because the west array is still producing at 18:00 in June when the cooking load starts.

Price both at 15p export: all-south is £413 + £506 = £919, the split is £439 + £440 = £879. South wins by £40. Now price both on a legacy SEG rate of 4.1p: all-south is £413 + £138 = £551, the split is £439 + £120 = £559. The split wins by £8.

The crossover sits near 11p export in this case. That is the actual decision rule, and it flips depending on which export tariff you are on. Anyone who tells you east/west is always worse, or that it is always better for self-consumption, is reasoning without a price.

Constraints that cap the answer before the arithmetic does

G98/G99. Up to 3.68 kW per phase (16 A at 230 V) you notify your DNO after the fact under G98. Above that you apply under G99 before installation, which takes 45 working days at National Grid Electricity Distribution and sometimes returns a curtailment condition. A 5 kW hybrid inverter on 5.28 kWp of panels needs G99. Some installers export-limit to 3.68 kW to stay under G98, which on this array costs you roughly 80 kWh a year of clipped export (£12), but costs nothing if you have a battery soaking up the midday peak.

DC to AC ratio. 5.28 kWp on a 5.0 kW inverter is a 1.06 ratio, which in the UK is conservative. Ratios of 1.2 to 1.3 are fine here because peak irradiance rarely sustains long enough for clipping to matter: at 1.25 you lose around 0.5% of annual yield and gain better inverter efficiency at part load, which is where a UK inverter spends most of its life. Check the datasheet’s maximum DC input power, not just the AC rating.

Roof structure and setbacks. MCS requires a structural assessment. Twelve modules at around 22 kg each is 264 kg spread over 23 m², which is trivial, but wind uplift is not, and rafter spacing plus purlin condition on a 1930s roof occasionally rules out the row you planned.

String layout under shading. Module-level optimisers or microinverters recover most shading losses, at roughly £60 to £90 per module. Worth it when one module in a string is shaded for a meaningful part of the day, and a waste of money on a clean roof. Your horizon measurement is what decides this.

Backtesting the model and keeping it honest

Before you commit money, backtest. Take your PVGIS or pvlib hourly series for a historic year, take your measured import for the same year, and check that the model reproduces things you can verify independently. If a neighbour has a system on a similar orientation and will share their monitoring export, compare kWh/kWp month by month. Discrepancies above 8% in summer usually mean shading you have not modelled or a wrong azimuth.

After installation, validate against reality. Most hybrid inverters expose local data: GivEnergy and Solis over Modbus TCP, SolarEdge via its local API, Sunsynk through the Solarman cloud or a direct RS485 read. Home Assistant with the relevant integration plus the Energy dashboard gives you generation, consumption, battery flow and grid flow at 10-second to 5-minute resolution. Emoncms is the alternative if you prefer something purpose-built for energy accounting rather than general home automation.

Then compare your first 12 months to the model. A 5% shortfall is weather. A 15% shortfall in July is a fault, usually soiling, a tripped optimiser, or a string that has been running at half output since commissioning because a connector was not seated. Set an automation that alerts when daily generation falls below 60% of the Solcast or forecast.solar prediction for that day: Solcast’s hobbyist tier gives you rooftop-specific forecasts and forecast.solar has a free endpoint that takes lat, lon, declination, azimuth and kWp directly in the URL.

Battery dispatch is where operational tooling pays back. Predbat, running in Home Assistant, plans charge and discharge against Agile or Go rate structures and a solar forecast, and will typically extract 10 to 20% more value than a fixed overnight charge window. EMHASS solves a similar problem with a formal optimiser if you want to define your own objective function.

Mistakes that cost the most accuracy

  • Modelling one year of weather. UK annual irradiance varies about ±7%. Use five years and report a range, not a point.
  • Ignoring degradation in a 20-year figure. At 0.45%/year, year 20 output is 91.4% of year 1, and the undiscounted 20-year total is about 5% below 20 × year_1.
  • Forgetting the inverter dies. Budget £900 to £1,300 around year 12. It changes a 20-year IRR by roughly half a percentage point.
  • Using average daily profiles instead of the real series. Averaging 365 days into one typical day destroys exactly the variance that determines battery cycling, and typically overstates self-consumption by 8 to 12%.
  • Assuming your consumption stays put. An EV adds 2,500 to 4,000 kWh a year, almost all of it shiftable to the cheap overnight window, which raises the battery case and barely moves the panel case. A heat pump adds 2,500 to 4,500 kWh concentrated in the months your array generates least. Model the house you will have in three years.
  • Treating standing charge as part of the saving. It is not. Around 58 p/day, £212 a year, is unavoidable unless you disconnect.

Re-running it on a schedule

Keep the pipeline, not just the answer. A config.yaml holding your tariff rates, array parameters, battery spec and efficiencies, plus a script that pulls the last 12 months of half-hourly data and re-runs the simulation, is maybe 200 lines. Run it every time your tariff changes, which for anyone on Octopus’s product churn is two or three times a year.

The interesting output on a re-run is not the payback figure. It is the marginal-value curve: the answer to “what would the next 5 kWh of battery, or the next four panels, be worth to me now?” Export rates move, the cheap-window rate moves, your consumption moves when a child moves out or an EV arrives. A system that was correctly sized in 2024 at a 4.1p SEG rate is frequently undersized at 15p export, because export at 15p against a 26p import means every additional panel earns 58% of what a self-consumed one does instead of 16%.

Start the data pull tonight, because the meter is quietly forgetting last September while you read this.

In this section

The supporting pages under this subject.