State of Charge Is the Real Constraint: Why Dispatch Is a Schedule, Not a Rule

State of Charge Is the Real Constraint: Why Dispatch Is a Schedule, Not a Rule

September 18, 2026 · Dezzmond Team
Financial Modeling Data Analysis Excel

The two previous posts produced clean rules. Charge when the spread clears the cycle cost. Discharge when the price beats the storage value.

Both assume something that is not true: that the battery is in a position to act.

You cannot discharge energy you did not store, and you cannot store energy without having spent hours charging beforehand at a limited rate. State of charge is the variable that links every hour of the day to every other one, and once it enters, the clean rule becomes a schedule.

This post is about that constraint: why the best hours are not freely selectable, how much charging time a peak actually requires, what the warranty does to the usable range, and why a dispatch model that does not track state of charge produces revenue that cannot be earned.

ℹ️ Note: The price shape here is a two-peak day, chosen because single-peak days conceal most of the scheduling difficulty. Figures are labelled assumptions.

What State of Charge Actually Does

It makes the hours dependent on each other.

Every other input to a dispatch decision is local to the hour: the price is what it is, the degradation cost is constant, the efficiency is fixed. State of charge is different — it is the accumulated consequence of every decision already taken, and it constrains every decision still to come.

SoC(h) = SoC(h−1) + Charge(h) × RTE − Discharge(h)

subject to:   SoC_min  ≤  SoC(h)  ≤  SoC_max
              Charge(h), Discharge(h)  ≤  Power_Rating
              Charge(h) × Discharge(h) = 0        (not both at once)

That recursion is the whole problem. It cannot be solved hour by hour because each hour's feasible set depends on choices made earlier and constrains choices made later.

The Best Hours Are Not Freely Selectable

The most common modelling shortcut is to pick the N highest-priced hours and assume the battery discharges into all of them. It is wrong for two reasons, and the second is the expensive one.

Take a two-peak day:

Hour    00  01  02  03  04  05  06  07  08  09  10  11
Price   22  19  17  16  16  25  55  85  70  40  18  12

Hour    12  13  14  15  16  17  18  19  20  21  22  23
Price   10  12  20  32  50  75  92  85  60  42  30  25

The four highest-priced hours are 18 ($92), 7 ($85), 19 ($85) and 17 ($75).

Reason one: they are split across two peaks. Serving hour 7 and hours 17–19 requires two separate charge–discharge cycles with a recharge in between. That is possible here — the midday trough at hours 11–13 provides it — but it is a scheduling fact, not a price fact, and the top-N selection did not check it.

Reason two: consecutive high hours compete for the same energy. The evening block runs 17, 18, 19, 20 at $75, $92, $85 and $60. A battery cannot discharge into all four unless it has four hours of energy:

Duration Hours served Revenue captured Hours missed
2 hours $92, $85 $177 $75, $60
3 hours $92, $85, $75 $252 $60
4 hours $92, $85, $75, $60 $312

That table is the duration question from earlier in this series, arriving again from the operational side. The declining marginal hour is not an abstraction about price distributions — it is literally the fourth-best hour of a consecutive block, and whether you can reach it depends on having stored enough.

Charging Takes Time, and the Time Must Exist Before the Peak

The constraint that catches morning peaks.

Filling a battery is not instantaneous. At a 1 MW rate with 88% round-trip efficiency, storing E megawatt-hours takes E / 0.88 hours of charging:

Capacity Hours of charging required
2 MWh 2.27
4 MWh 4.55
6 MWh 6.82

Now check the morning peak. Hour 7 is the first high-priced hour of the day, which leaves hours 0 to 6 — seven hours — in which to charge. At 1 MW that stores 7 × 0.88 = 6.16 MWh, so a four-hour battery can be full and a six-hour one is close.

But those charging hours are priced at $22, $19, $17, $16, $16, $25 and $55. They are not the cheapest hours of the day — the midday trough at $10–12 is much cheaper — and the cheap hours come after the morning peak, when they are useless for serving it.

That is the ordering problem in one example. A rule that charges in the cheapest hours will be empty at hour 7. A rule that serves hour 7 must charge at prices roughly double the daily minimum. Which is right depends on whether the morning spread justifies the more expensive energy, and the top-N approach cannot ask that question because it has no concept of sequence.

The Usable Range Is Narrower Than the Nameplate

A second constraint on state of charge, and it comes from the warranty rather than from physics.

Batteries are not operated between 0% and 100%. Deep discharge and full charge both accelerate degradation, so operating bounds are set inside the nameplate — and research on threshold optimisation finds that the minimum should be set higher and the maximum lower to achieve shallower charge and discharge states, reducing degradation cost while maintaining technical performance.

Nameplate capacity                                   400 MWh
Operating range, say 10%–95%                         340 MWh usable
Effective duration at 100 MW                        3.4 hours

So a "four-hour" battery is frequently a 3.4-hour battery in operation, and the difference is a deliberate trade: narrower bounds cost usable energy and buy asset life.

Two consequences.

The duration in the specification is not the duration in the dispatch model. Using nameplate rather than usable energy overstates every arbitrage calculation in this series by the width of the reserved bands.

The bounds interact with the degradation cost from the charge-threshold post. Tighter bounds lower the per-cycle degradation, which lowers the minimum viable spread — so the operating range and the operating threshold should be set together rather than by different teams.

Why This Makes It a Scheduling Problem

Put the pieces together and the character of the problem changes.

The charge rule needs a view of later prices. The discharge rule needs a storage value that depends on remaining time and current state of charge. And the state of charge at any hour is determined by every prior decision, while constraining every subsequent one.

That is not a rule that can be evaluated hour by hour. It is an optimisation over a horizon, and it is why practical dispatch models solve a window rather than a moment — with perfect foresight within each window and real-world calibration applied afterwards.

The practical form is a linear program: maximise revenue over the horizon, subject to the state-of-charge recursion, the power limits, the cycle budget and the no-simultaneous-charge-and-discharge condition. That is a standard formulation and entirely tractable — and it is genuinely different in kind from the threshold rules that preceded it.

What the threshold rules retain is their value as diagnostics. The minimum viable spread tells you whether a market is worth being in. The storage value tells you what a megawatt-hour is worth right now. They just cannot, on their own, produce a schedule.

An Ancillary Award Is a Floor on State of Charge

The constraint that catches operators running more than one product, and it is stricter than the opportunity cost described earlier in this series.

Holding a reserve or frequency response award is not merely a commitment of capacity. It is a commitment to be able to deliver — which means holding enough stored energy to meet the award for its maximum delivery period, at any moment during the commitment.

SoC_min(h) = SoC_floor  +  AS_Award_MW × Max_Delivery_Hours

A 20 MW reserve award with a one-hour maximum delivery period imposes a 20 MWh floor on state of charge for every hour of the commitment. That energy is not available for arbitrage — it is collateral.

Three consequences that a model treating ancillary revenue as a simple per-megawatt payment will miss.

The usable range narrows further. On a 400 MWh battery already restricted to 340 MWh by operating bounds, a 20 MWh ancillary floor leaves 320 MWh for energy arbitrage. The asset is now a 3.2-hour battery for trading purposes.

A downward-regulation award works in reverse. An award to absorb energy requires headroom rather than energy — a ceiling on state of charge rather than a floor. Holding both simultaneously squeezes the usable band from both ends.

The floor binds hardest exactly when arbitrage is most valuable. Scarcity conditions raise both energy prices and the likelihood of a reserve being called, so the hours where the battery most wants to discharge are the hours where its ancillary commitment most restricts it.

This is the mechanical form of the point the Series C battery post made about revenue stacking. Energy and ancillary revenues cannot be added because they compete for the same megawatt-hours — and the competition is not abstract, it is a floor in the state-of-charge recursion.

Why "No Simultaneous Charge and Discharge" Is in the Formulation

A constraint that looks like stating the obvious and is doing real work.

For a standalone battery in a single market, it is almost never binding. Round-trip efficiency below 100% means charging and discharging at the same price in the same hour is a guaranteed loss, so a revenue-maximising optimiser would not choose it anyway.

It becomes binding in two situations, and both matter.

Where charge and discharge face different prices. A co-located battery charging from a solar array at effectively zero marginal cost while exporting to the grid is doing exactly this, and it is the correct behaviour rather than an artefact. The hybrid post later in this series takes that case properly.

Where multiple markets are settled separately. An asset charging in one market and discharging in another within the same interval can show a net position that nets to nothing physically while producing revenue on both legs. Whether that is legitimate or a modelling error depends on the market rules, and models should not be free to do it accidentally.

The formulation consequence is significant. Enforcing "not both" requires a binary variable per interval, which turns a linear program into a mixed-integer one — computationally harder, and the reason some dispatch models relax the constraint and check afterwards rather than imposing it throughout.

For a spreadsheet model, the practical version is a check rather than a constraint: flag any interval where both charge and discharge are non-zero, and confirm each instance is deliberate. Silent simultaneous operation is a strong signal that the model has found revenue that the asset cannot physically deliver.

The Cost of Getting the Starting Point Wrong

A practical consequence of the recursion that is easy to overlook: the schedule depends on where the battery starts.

A model beginning each day at zero state of charge will systematically understate revenue, because a real battery carries energy across the midnight boundary. One beginning each day full will overstate it, because it has been given free energy.

Day-boundary treatment              Effect on modelled revenue
Start empty each day                Understates — misses overnight carry
Start full each day                 Overstates — free energy every day
Carry SoC across the boundary       Correct

The error is largest for long-duration assets, which is exactly where the horizon post established that multi-day optimisation matters. A ten-hour battery physically cannot complete a cycle inside a day, so a model that resets it at midnight has prevented it from doing the thing it was built for.

The fix is trivial in a spreadsheet — carry the closing balance forward as the opening balance — and it is omitted surprisingly often, usually because the model was built one day at a time and then replicated.

There is a related question at the end of the horizon. A schedule optimised to the last hour will empty the battery, because energy has no value beyond the modelled window. That produces an artefact: the final day of any modelled period shows unusually high revenue and leaves the asset empty. Either terminate the analysis before the boundary or attach a terminal value to the remaining state of charge.

How Do You Model State of Charge in Excel?

As a running balance with hard feasibility checks, before any revenue is recognised.

The recursion

SoC(0)   = Starting_SoC
SoC(h)   = SoC(h−1) + Charge(h) × RTE − Discharge(h)

Feasibility tests, every hour:
   SoC(h) ≥ SoC_min
   SoC(h) ≤ SoC_max
   Charge(h) ≤ Power_MW
   Discharge(h) ≤ MIN(Power_MW, SoC(h−1) − SoC_min)
   Charge(h) × Discharge(h) = 0

The fourth line is the one that matters most and is most often omitted: you cannot discharge more than you are holding.

The check that catches the common error

PF_InfeasibleHours = COUNT of hours where a scheduled discharge
                     exceeds available state of charge

If PF_InfeasibleHours > 0, the revenue in this model cannot be earned.

A model built by selecting the best hours and summing their prices will frequently fail this test, and the failure is silent unless the check exists.

The usable energy correction

Usable_MWh  = Nameplate_MWh × (SoC_max − SoC_min)
            = 400 × (0.95 − 0.10)                    = 340 MWh
Effective_Duration = 340 / 100                       = 3.4 hours

Run every duration calculation on usable energy, not nameplate.

The outputs to publish

PF_UsableDuration               3.4 hours, not 4.0
PF_InfeasibleHours              must be zero
PF_EndOfDaySoC                  does the schedule leave the asset positioned?
PF_ChargingHoursRequired        E / RTE, checked against hours available before each peak

The third is worth reporting for a reason that is easy to miss: a schedule that empties the battery at midnight has optimised the day and may have left the asset unable to serve an early peak tomorrow.

ℹ️ Note: Never compute storage revenue by selecting the highest-priced hours. The selection is a price calculation and the answer is a scheduling problem — and the gap between them is revenue that cannot be delivered.

To build the state-of-charge recursion, the feasibility checks and the usable-duration correction, prompt Dezzmond with your price series, power rating and operating bounds.

What Do Operators and Lenders Actually Check?

  • Does the model track state of charge hour by hour, with the discharge limited by it?
  • Is the count of infeasible hours reported, and is it zero?
  • Is duration computed on usable energy or on nameplate?
  • What operating bounds are assumed, and do they match the warranty?
  • Are the best hours consecutive? If so, duration determines how many are reachable.
  • Is there enough charging time before each peak, at the power rating?
  • Is state of charge carried across the day boundary, and is there a terminal value at the end of the horizon?

Frequently Asked Questions

Why can't you just pick the highest-priced hours?

Because the selection ignores sequence. The best hours may be split across separate peaks requiring a recharge in between, or consecutive and competing for the same stored energy — and a battery cannot discharge into more consecutive hours than it has hours of duration.

How long does it take to charge a battery?

Capacity divided by round-trip efficiency, at the power rating. A 4 MWh battery at 1 MW and 88% efficiency needs 4.55 hours — and those hours must fall before the peak it is charging for, which is what makes morning peaks awkward.

Why is the usable capacity less than the nameplate?

Because operating bounds are set inside the nameplate to limit degradation — research on threshold optimisation supports a higher minimum and a lower maximum. A 400 MWh battery operated between 10% and 95% has 340 MWh usable, so a "four-hour" asset is 3.4 hours in practice.

Does state of charge make threshold rules useless?

No, it makes them insufficient. The minimum viable spread and the storage value remain the right diagnostics for whether a market and a moment are worth acting on. They just cannot produce a feasible schedule on their own.

Does an ancillary award restrict state of charge?

Yes — it imposes a floor, because the award must be deliverable at any moment. A 20 MW reserve with a one-hour delivery period reserves 20 MWh that cannot be arbitraged, narrowing the usable range further and binding hardest in exactly the scarcity hours when arbitrage is most valuable.

Why does the model forbid charging and discharging at once?

Because where the two legs face different prices — a co-located battery charging from its host array, or an asset settling in two markets — an optimiser will do it to collect on both sides. Enforcing the ban requires a binary variable, which makes the problem mixed-integer rather than linear.

What does a dispatch optimiser actually solve?

Revenue maximisation over a horizon subject to the state-of-charge recursion, power limits, a cycle budget and no simultaneous charge and discharge. Practical models use perfect foresight within each window and calibrate to reality afterwards.

Closing: The Constraint That Turns Rules Into Schedules

Each of the last two posts produced something clean. A minimum spread that tells you whether a cycle is worth running. A storage value that tells you what the energy in the battery is worth right now. Both are correct and both are useful.

Neither can run a battery, because both assume a freedom the asset does not have. The energy has to be there. Putting it there takes hours at a limited rate, in a window that has to occur before the price you are targeting. And every megawatt-hour spent now is one not available for the next opportunity.

That is what makes storage different from generation as a modelling problem. A solar plant's output in one hour tells you nothing about its output in the next; the hours are independent. A battery's hours are chained, and the chain is the state of charge.

It is worth noticing how much of this series has converged on that single variable. Duration is the length of the chain. The cycle budget is how many times it may be traversed. The warranty sets how much of it is usable. An ancillary award reserves a portion of it. And the storage value from the previous post is precisely the marginal worth of one link. Five apparently separate decisions, all expressed in the same state variable — which is the clearest sign available that it belongs at the centre of any storage model rather than as a constraint bolted on at the end.

The practical consequence for anyone reading a storage revenue forecast is a single question: does the model track state of charge, and does it check that every scheduled discharge was actually available? A forecast built by summing the best hours of the year is not conservative or aggressive — it is describing an asset with infinite energy and instantaneous charging, and the gap between that and a real battery is not small.

The last post in this series takes the remaining gap: between a schedule optimised against known prices and a revenue forecast a lender will lend against.

Sources: Modo Energy — Battery Dispatch Model · ScienceDirect — SoC Threshold Optimization for Battery Storage in Frequency Regulation · ResearchGate — Optimal Battery Energy Storage Dispatch for the Day-Ahead Electricity Market · Flex Power — Battery Storage Optimization: Value Stacking Explained