| Vose Software

Industry: Energy
Product: ModelRisk
Application: Stochastic dispatch optimization for a grid-connected BESS


Dispatching a 100 MW / 400 MWh BESS: Stochastic Co-Optimization in ModelRisk

The 4-hour LFP battery is built. The asset's lifetime NPV is now controlled not by capex but by a single recurring decision made 96 times a day: how to split each 15-minute interval between energy arbitrage, frequency regulation, and reserve capacity, given a price stack that won't be known until clearing. A deterministic dispatch optimiser pointed at next-day forwards generates a "perfect-foresight" schedule whose realised P&L falls 28% short of the optimiser's promised revenue. The shortfall is not modelling laziness — it is the distance between a single forecast price and the actual conditional distribution, and it is visible the moment you run both dispatch policies against the same simulated price stacks:

Daily revenue distribution — perfect-foresight vs stochastic dispatch

The deterministic optimiser promised $11.4k/day; following its instructions into the realised price distribution earns a mean of just $8.2k with a 5th percentile of $1.9k. The stochastic optimiser — which leaves 18% state-of-charge headroom for high-spread real-time events — recovers most of the gap: a realised mean of $10.6k and a 5th percentile of $4.8k. Stochastic dispatch closes most of the foresight-vs-reality shortfall.

Three revenue stacks, one battery, one SoC

Every 15-minute interval the battery can earn from:

  • DA energy arbitrage at the cleared day-ahead LMP.
  • Real-time energy arbitrage at the RT LMP (DA bid + a settlement on RT–DA spread).
  • Frequency regulation (ERCOT FRRS) — a capacity payment ($/MW-hr) plus a small mileage payment; the battery is committed to swing on AGC signal.
  • Spinning reserve — capacity payment with low probability of deployment.

The same MWh of state-of-charge cannot simultaneously back an arbitrage charge and a reg-up bid. The optimiser must co-optimise across products under stochastic prices and stochastic AGC signal.

Where the price uncertainty actually lives

The dispatch engine wraps a forward-looking SoC LP inside a Monte Carlo over conditional price scenarios. Conditional structure matters:

  • DA LMP modelled as the day-ahead forecast + a residual that is AR(1) in hour-of-day, with ϕ = 0.46 and σ scaled by the market's recent volatility (last 14 trading days). A constant-σ assumption underprices the high-vol regime by ~25%.
  • RT–DA basis modelled as a Normal mixture — a tight Normal (μ = 0, σ = $4/MWh) for 96% of intervals and a fat Normal (μ = 0, σ = $42/MWh) for the 4% of intervals when reserves clear scarcity. The mixture is essential; a single Normal smears the regime and tells the optimiser to chase basis arbitrage in the wrong intervals.
  • Reg-up clearing price Beta-distributed on [$3, $80]/MW-hr, with daily seasonality. Reg-up and energy spread are linked by a rank correlation ρ = 0.41 (scarcity drags both upward together).
  • AGC mileage drawn empirically per interval — heavy-tailed, modelled as Generalized Pareto above the 90th-percentile threshold.

Perfect-foresight vs stochastic dispatch

The same battery, same week of forward curves, dispatched two ways — the comparison shown above. The deterministic optimiser claimed a mean daily revenue of $11.4k. The realised mean — feeding the same dispatch instructions into the stochastic price simulator — was $8.2k, with a 5th percentile of $1.9k. The stochastic optimiser, which sizes its reg-up bid to leave 18% SoC headroom for high-spread RT events, posts a realised mean of $10.6k and a 5th percentile of $4.8k. Mean +$2.4k/day (×400 cycling days = +$0.96M/year), tail +$2.8k/day. On a $272M asset this is roughly 180 basis points of additional levered equity return.

What actually moves the revenue

Tornado: drivers of annual dispatch revenue

The RT–DA basis-volatility mixture parameter dominates — the same battery, with the same forecast, earns $1.4M/year more in a high-basis-vol regime than a low one. Reg-up clearing price is second, ahead of DA-spread itself; for a 4-hour battery the regulation product is where the real economic value sits.

Co-optimisation versus single-product

The team ran a sweep on the regulation-share parameter — what fraction of battery power is bid into reg-up versus energy.

Annual revenue by regulation share — Monte Carlo P10/P50/P90

The deterministic optimum sits at 60% reg-up share, where mean revenue maxes at $3.9M. But the P10 revenue maxes at 45% — and that's the share the asset owner picked, trading $0.06M of expected revenue for $0.20M of downside protection. The optimal split is risk-preference-sensitive, and only the distribution makes that visible.

What changed

  • Realised dispatch revenue up 30% year-over-year versus the deterministic forecast-following baseline.
  • Bid-curve template rewritten to leave 18% SoC headroom during DA-bid construction, sized from the joint distribution of RT-spread severity and reserve scarcity.
  • Reg-up share policy band set at 40–50% with quarterly re-fitting of the basis-mixture parameters; previous policy was a fixed 60% inherited from the deterministic model.
  • Cycle-count budget allocated explicitly — the LP now treats each charge–discharge cycle as a $4.20 cost (replacement-cost amortisation), which suppresses low-margin opportunistic cycling that the deterministic model had recommended.

ModelRisk Functionality Used

  • AR(1) DA-LMP residual with volatility scaled by trailing 14-day realised vol — capturing the regime structure that a constant-σ assumption misses by ~25%.
  • Normal-mixture RT–DA basis (96% tight / 4% fat) — single-Normal smearing routed RT-arb to the wrong intervals.
  • Rank correlation between reg-up clearing and DA spread (ρ = 0.41) — propagated through the LP to size the joint bid.
  • Generalized Pareto AGC mileage tail above the 90th-percentile threshold, valued at the marginal mileage payment.
  • Risk-frontier sweep on regulation share that exposed a 45% optimum on P10 versus 60% on mean — the basis for the chosen risk-adjusted policy.
  • Cycle-cost amortisation baked into the LP objective ($4.20/EFC), suppressing the low-margin cycling the deterministic optimiser had been recommending.

A battery does not earn its forecast revenue; it earns the conditional expectation under the realised price stack, which is always lower and almost always more volatile. Monte Carlo dispatch in ModelRisk closes the foresight-vs-reality gap by treating the price stack as a distribution, not a forecast.