Get Flexing

A practical guide to understanding and using the Peaky Flexers electricity market model

← Back to the model

Contents

  1. The Big Picture
  2. Understanding the Inputs
    1. Load Duration Curve Blocks
    2. ZVC Availability Profile (Sub-Blocks)
    3. Demand Tiers & Expandable Demand
    4. Supply-Side Technology Costs
  3. How the Optimisation Works
    1. In Plain Language
    2. The Formal Problem
  4. Reading the Outputs
    1. Market Equilibrium Summary
    2. Optimal Capacity Mix
    3. Input Load Duration Curve
    4. Generation Duration Curve
    5. Demand & Supply by Sub-Block (GW)
    6. Energy by Sub-Block (GWh)
    7. Demand Flexibility (GW)
    8. Energy Transfers (GWh)
    9. Storage Activity
    10. Detailed Sub-Block Results
  5. Using the AI Chat Assistant

1. The Big Picture

Peaky Flexers is a welfare-maximising linear program (LP) for an electricity market. It answers a deceptively simple question: if we had to design an electricity system from scratch, what mix of generation and storage capacity would maximise the total value that consumers get from electricity, minus the cost of providing it?

The model works with three types of supply technology—zero-variable-cost renewables (ZVC), gas peakers, and battery storage—and a demand side that can flex: consumers can shift demand to cheaper periods, expand consumption when prices are low, or curtail when the cost of supply exceeds the value of the electricity to them.

The key output is a set of market-clearing prices—one for each time period. These prices emerge naturally from the optimisation: they are the shadow prices on the energy-balance constraints, representing the cost to the system of serving one more megawatt-hour of demand in that period. In a well-functioning market, these are the prices that would prevail.

Why does this matter? Understanding how electricity prices form—and what drives them to differ across time periods—is essential for anyone thinking about energy policy, investment in generation or storage, or the economics of demand flexibility.

2. Understanding the Inputs

The model page has four input sections. Each represents a distinct part of the electricity system. Here is what each one means and why it is structured the way it is.

2.1 Load Duration Curve Blocks

Real electricity demand varies hour by hour across the year. Rather than modelling all 8,760 hours individually, the model uses a Load Duration Curve (LDC)—a standard tool in energy economics that sorts hours by demand level.

The year is divided into three blocks:

BlockWhat it representsDefault hours
Winter PeakThe coldest, darkest hours when demand is highest300
ShoulderA large middle band—spring, autumn, and milder winter days3,000
Low DemandSummer and overnight hours when demand is lowest and (often) renewables are abundant5,460

You only set the hours for each block. The total should sum to 8,760 (one year). The demand levels come from the tier definitions below.

Intuition: These blocks are not calendar months. Think of them as buckets: all hours with similar demand and weather conditions are grouped together. The Winter Peak block might include just 300 hours spread across December and January; Low Demand captures thousands of hours in summer and at night.

2.2 ZVC Availability Profile (Sub-Blocks)

The wind does not blow constantly during winter, nor does the sun always shine in summer. To capture this intermittency, each LDC block is split into two sub-blocks:

For each sub-block you set two parameters:

ParameterMeaning
% HoursWhat fraction of the block's hours fall in this sub-block (must sum to 100%)
% Renewables AvailabilityWhat fraction of installed ZVC capacity is available during these hours

For example, the default Winter Peak is split 10/90: for just 10% of winter peak hours (30 hours), only 15% of installed ZVC capacity is available. For the remaining 90% (270 hours), 80% is available. This creates a large price differential between the two sub-blocks, and it is precisely this differential that makes storage valuable within a block—storage can charge when renewables are plentiful and discharge when they are scarce, even within the same season.

Key insight: Without sub-blocks, the model would see each season as uniform, and storage would only be valuable for shifting energy between seasons. Sub-blocks make storage valuable even within a single season—which is how real batteries operate.

2.3 Demand Tiers & Expandable Demand

Not all electricity demand is equally valuable. A hospital's life-support system has a very different willingness to pay than a dishwasher that could run at 3am instead of 6pm. The model captures this by dividing demand in each block into three tiers:

For each tier you set three parameters:

ParameterMeaning
Quantity (GW)How many gigawatts of this tier's demand are present during the block
VoLL (£/MWh)Value of Lost Load: the maximum price this demand is willing to pay. If the clearing price exceeds VoLL, this demand goes unserved ("curtailed").
Shift Cost (£/MWh)The cost of moving this demand to a later, cheaper block. Demand can only shift downward: Winter Peak → Shoulder → Low Demand. It cannot shift upward.

Expandable demand represents new consumption that would switch on if prices fell low enough—think of energy-intensive industries that would locate near cheap power, or electric heating that becomes attractive when electricity prices drop. You specify a quantity (GW) and an activation value (£/MWh). If the clearing price drops below this value, the expandable demand activates.

Intuition: Demand tiers create a downward-sloping demand curve for each block. High-value demand bids high and is served first. Low-value demand may get curtailed if supply is expensive. The shift cost determines when it is worthwhile for demand to move to a cheaper time period rather than be served (or curtailed) in its original block.

2.4 Supply-Side Technology Costs

The model does not pre-set any generation capacities. Instead, it decides how much of each technology to build, balancing capital costs against the value of the electricity they produce. There are three technologies:

Zero-Variable-Cost (ZVC) Generation

Renewables (wind, solar) and nuclear. Once built, they produce electricity at zero fuel cost, but their output depends on weather conditions (captured by the availability profile above). The only input is the annualised capital cost (£/kW/year).

Gas Peaker

A flexible thermal plant that can run whenever needed but burns gas. You set:

Battery Storage

Storage has two capacity dimensions:

The energy cost is amortised over the number of cycles per year you specify (default 365), since a battery that cycles daily spreads its capital cost over many more MWh than one that cycles once a year.

Round-trip efficiency (default 95%) means that for every MWh charged, only 0.95 MWh is available to discharge. The 5% is lost as heat. This creates an implicit cost: the storage must buy cheap and sell dear enough to cover not just capital costs but also this energy loss.

No fuel cost for storage: Unlike gas, storage has no direct fuel cost. Its "cost" comes from efficiency losses and capital amortisation. The model works this out endogenously—the implied cycling cost is an output, not an input.

3. How the Optimisation Works

3.1 In Plain Language

The model asks: what system design and operating pattern makes society best off?

It simultaneously decides:

  1. How much capacity to build for each technology (ZVC, gas, storage power, storage energy)
  2. How to dispatch each technology in every sub-block (6 sub-blocks total)
  3. How much demand to serve, shift, or curtail in each tier and sub-block
  4. How to operate storage—when to charge, when to discharge, and how much energy to hold

The objective is to maximise net welfare: the total value that consumers place on the electricity they receive, minus the total cost of providing it (both capital and operating costs).

Think of it as a social planner trying to make the best possible use of available resources. The planner values each MWh of served demand at its VoLL, credits shifted demand at VoLL minus the shift cost, and charges for gas generation at its variable cost and all technologies at their capital cost.

The optimisation is subject to physical and economic constraints:

The market-clearing prices are not directly chosen. They emerge as shadow prices on the energy-balance constraints—they tell you the marginal value to society of one additional MWh of supply in each sub-block. In an efficient market, these would be the wholesale electricity prices.

3.2 The Formal Problem

For those who want the mathematics, here is the LP formulation. The model maximises:

max   ∑b,i hb,i · [ ∑t VoLLb,t · servedb,i,t + vbexp · expandb,i − cgasvar · gasb,i ]   +   ∑shifts hsrc · (VoLLt − shiftcostt) · shift_outsrc,t,dest   −   Czvc · Kzvc − Cgas · Kgas − Csto_pw · Ksto_pw − (Csto_en / cycles) · Ksto_en

Where b indexes blocks, i indexes sub-blocks within each block, t indexes demand tiers, h are hours, K are capacity variables, and C are capital costs. The variable cost of gas includes any carbon adder: cgasvar = variable_cost + carbon_price × emission_factor.

Subject to (for all sub-blocks b,i):

Shadow prices on the energy-balance constraints, divided by the sub-block's hours, give clearing prices in £/MWh.

4. Reading the Outputs

After you click Optimise the System, the results page shows several sections. Here is what each one tells you.

4.1 Market Equilibrium Summary

A row of metric cards showing the headline results at a glance:

What to look for: If prices are very high in one sub-block, the system is capacity-constrained there. If prices are very similar everywhere, there may be excess capacity or very effective storage/shifting smoothing prices across periods.

4.2 Optimal Capacity Mix

Two charts side by side:

Together, these tell you how the system spends its investment budget. A system dominated by ZVC will have high ZVC capital cost but zero variable cost. A system with more gas will have lower capital cost but higher variable cost.

4.3 Input Load Duration Curve

This shows the raw demand profile before any optimisation. Sub-blocks are sorted from highest to lowest GW, and the three demand tiers are stacked within each sub-block (low-value at the bottom, high-value at the top). This is what the demand side "looks like" before the model decides what to do with it.

Use this chart as a reference point. After you look at the optimised results, come back here to see how much has changed—how much demand was shifted, curtailed, or served by different sources.

4.4 Generation Duration Curve

This is the post-optimisation counterpart of the input LDC. It shows total generation in each sub-block, broken down by source (ZVC in green, gas in red, storage discharge in blue). Sub-blocks are sorted by total generation from left to right.

Each sub-block is labelled with its clearing price. Hatched areas indicate curtailed demand.

How to read it: The shape of this curve tells you about the system's economics. If ZVC fills most of the curve and gas only appears on the left (high-demand periods), renewables are dominant. If there is a lot of blue (storage discharge) in the high-demand blocks, storage is playing an important peaking role.

4.5 Demand & Supply by Sub-Block (GW)

A 2×3 grid of stacked bar charts (one per sub-block). Each chart has two bars:

All six charts share the same Y-axis so you can visually compare the scale of demand and supply across sub-blocks. The title of each chart shows the clearing price.

Storage charging appears as demand (it consumes electricity) while storage discharging appears as supply (it provides electricity). This is physically correct—charging is a load on the system.

4.6 Energy by Sub-Block (GWh)

The same structure as the GW charts, but multiplied by hours to show energy (GWh). Each sub-block has its own Y-axis scale because the blocks have very different durations (300 hours vs 5,460 hours), which would make the shorter blocks invisible if they shared an axis.

These charts are important for understanding the total energy balance. A sub-block might have low GW but high GWh if it lasts many hours. Storage is particularly visible here: you can see how much energy in GWh is being moved around the system.

4.7 Demand Flexibility (GW)

Per-block Sankey diagrams showing what happens to demand in each block. Left-side nodes are demand sources (tiers + shifted-in demand + storage charging). Right-side nodes are destinations:

The width of each flow band is proportional to the GW. This chart only appears when there is flexibility activity (shifting, curtailment, or storage) in the system.

4.8 Energy Transfers (GWh)

A system-level Sankey diagram showing energy transfers between sub-blocks. This is fundamentally different from the flexibility Sankeys above: while those show what happens within a block, this shows what moves between blocks.

Left nodes are energy exporters (sub-blocks that charge storage or shed demand). Right nodes are energy importers (sub-blocks that discharge storage or receive shifted demand), plus efficiency losses.

The diagram visually distinguishes two types of flows:

This is perhaps the most informative single chart. It reveals the full pattern of energy arbitrage: where is energy coming from, where is it going, and how much is lost to efficiency?

4.9 Storage Activity

Two charts plus summary metrics:

The implied cycling cost is the effective cost per MWh of using storage, calculated from the prices at which it charges and discharges and the efficiency loss. If the average charge price is £65/MWh and discharge price is £120/MWh with 95% efficiency, the implied cost is 65/0.95 − 120 ≈ −£52/MWh (a profit, not a cost). This number tells you whether the price spread is enough to justify the capital investment.

4.10 Detailed Sub-Block Results

The final section gives you the full numerical detail for each of the 6 sub-blocks: every demand tier (available, served, lost, shifted out), every supply technology (dispatched vs available), expandable demand activation, storage level, and the clearing price.

This is where you go to verify specific numbers or understand exactly what is happening in a particular sub-block. If a Sankey diagram shows an unexpected flow, the detail tables will tell you exactly which tiers and technologies are involved.

5. Using the AI Chat Assistant

Peaky Flexers includes a built-in AI assistant powered by Anthropic's Claude. Click the AI Chat button in the top-right corner to open the chat panel.

What can you ask?

The AI has access to the complete model source code, your current input values, and your latest optimisation results. This means it can reason about your specific scenario—not just generic electricity economics. Good questions include:

Here is an example of the kind of conversation you might have:

Why are Winter Peak prices at £441/MWh? That seems very high.

The price of £441/MWh in Winter Peak Low Renewables reflects extreme scarcity. During these 30 hours, only 15% of installed ZVC capacity is available. The marginal consumer willing to pay up to their VoLL sets the price.

Looking at the results: all 10 GW of High-value demand (VoLL £15,000/MWh) is served, all 20 GW of Mid-value demand (VoLL £800/MWh) is served, but some Low-value demand (VoLL £100/MWh) is being curtailed. The clearing price settles between the VoLL of the last tier being served and the marginal cost of the next unit of supply.

Storage is discharging at full power here, and gas peakers are running flat out. The high price is what is needed to justify the capital investment in gas peakers that only run for a few hundred hours per year.

Getting an API key

To use the AI chat, you need an Anthropic API key. The model defaults to Claude Opus 4.6, which provides excellent analysis of the model's economics. To get a key:

  1. Visit console.anthropic.com
  2. Create an account (or sign in)
  3. Navigate to API Keys in the dashboard
  4. Click Create Key, give it a name, and copy the key
  5. Paste it into the API key field in the chat panel

Your API key is stored in your browser's local storage and is only sent to the Peaky Flexers server to proxy requests to Anthropic. It is never stored on the server.

A note of caution: Claude Opus 4.6 is remarkably good at interpreting the model's results and explaining electricity market economics. However, like all AI models, it can occasionally make mistakes—particularly with complex numerical reasoning or edge cases in the LP formulation. Treat its answers as a knowledgeable colleague's interpretation, not as gospel. If something seems wrong, check the detailed sub-block results tables, or ask the AI to show its working.

The Clear Chat button resets the conversation history, which is useful when you change input parameters and run a new optimisation—the old context will no longer match the new results.

← Back to the model — get flexing!