Alpiq · Swiss energy producer & trader
Day-Ahead Bidding That Adds €0.9M of Realized Profit on a 900 MW Pumped-Storage Plant
A stochastic + CVaR unit-commitment framework for Alpiq's Nant de Drance asset, validated on 4 months of real cleared day-ahead prices in 2021–2022
Pumped-storage hydropower is a financial instrument as much as a power plant. The operator buys cheap electricity at night to pump water uphill, sells it back at the peak, and has to commit to those decisions hours before market prices clear. Get it right and the asset prints money; get it wrong and the loss is real.
We worked with Alpiq through EPFL to build a stochastic and robust optimization framework that turns probabilistic price forecasts into ready-to-submit bid curves for the 900 MW Nant de Drance plant. A single risk-aversion knob lets traders dial how cautious to be, defensibly.
The challenge
Pumped-storage operators submit hourly offer and bid curves to the day-ahead market hours before prices clear. Volatile spot prices, complex hydraulic constraints, and minimum up/down times turn each daily bid into a high-stakes optimization problem.
Risk-neutral models can lead to catastrophic losses on bad-price days. Pure robust formulations are too conservative and leave money on the table. Alpiq needed a framework that lets traders dial in the right balance.
Our approach
We formulated the price-based unit commitment problem as a stochastic MILP across a fan of price scenarios, with full machine-level constraints (turbines, pumps, startup costs, transition times) and a CVaR-based risk term tunable by a single λ parameter.
Alongside the stochastic engine we built a Bertsimas-Sim robust formulation and a hybrid variant for offer/bid curve construction. We validated everything via a post-optimization pass: generate the bid curves, clear them against the actual day-ahead prices, measure realized profit.
The outcome
Deliverable: a Python / Gurobi codebase implementing four day-ahead bidding formulations (deterministic, stochastic, stochastic + CVaR, hybrid robust), the offer/bid curve construction algorithm, and a side-by-side benchmark report Alpiq's traders can lean on when choosing their risk appetite.
Across 4 months of real cleared day-ahead prices in 2021–2022 (January, April, June, October), the stochastic version adds €897,315 (+3.2%) of realized profit over the deterministic baseline that day-ahead desks typically run today. With the CVaR risk knob enabled at λ = 0.5, the same engine trades roughly 2.5% of expected profit for roughly 70% lower tail risk — a single dial between profit-seeking and risk-aversion that traders can defend in front of a committee.
Technical deep dive
The model behind the result.
The model
At the core sits a deterministic mixed-integer linear program. The objective: maximize short-term profit (energy sold minus energy bought, net of operating costs), plus the value of water left in the reservoir at the end of the horizon, minus a small penalty for moving the reservoir trajectory between iterations.
Deterministic profit objective. Prod is positive (turbining, selling), Cons is negative (pumping, buying), pr_t is the day-ahead price, and the final term values water left in each reservoir.
Reservoir mass balance. Volume next hour = volume now + inflows + spills from upstream − residuals − outflows + turbine and pump throughputs, signed by which side of the asset the reservoir sits on.
Risk-averse stochastic objective. λ = 1 recovers risk-neutral expected-profit maximisation; λ → 0 makes the model maximally averse to tail losses.
Conditional Value at Risk: μ is the VaR at confidence level α (typically 0.9), and v_s catches the shortfall of each scenario below it.
Robust formulation (Bertsimas–Sim). Γ is the uncertainty budget: it caps how many time-steps the dual variable b_t may push the price toward its worst-case bound. Larger Γ = more risk-averse, lower expected profit.
Each formulation produces an hourly schedule of turbine and pump activations. From that schedule we read off the offer (production) and bid (consumption) curves the trader submits to the day-ahead exchange, then validate everything against actual cleared prices in a post-optimization pass.
Benchmark
Realised profit (€) across four test months, post-optimization procedure on Nant de Drance data.
| Approach | January 2022 | April 2022 | June 2022 | October 2021 | Total |
|---|---|---|---|---|---|
| Deterministic perfect foresight | 8 974 588 | 10 652 319 | 5 550 447 | 6 098 301 | 31 275 654 |
| Deterministic baseline | 8 677 245 | 9 356 718 | 4 952 089 | 5 310 318 | 28 296 370 |
| Stochastic (real) | 8 177 853 | 9 646 849 | 5 143 970 | 6 225 013 | 29 193 685 |
| Stochastic CVaR, λ = 0.5 (real) | 7 830 682 | 9 526 104 | 5 110 510 | 5 975 414 | 28 442 709 |
| Hybrid robust (real) | 7 808 784 | 9 577 625 | 4 725 725 | 4 759 019 | 26 871 152 |
All numbers in EUR. Perfect foresight is the unattainable upper bound (deterministic optimization against actually cleared prices). 'Real' rows clear the bid curves against the real day-ahead price and require slack activation when the original commitment is physically infeasible. The stochastic and stochastic-CVaR approaches both beat the deterministic baseline on realized profit, with CVaR sacrificing roughly 2.5% of expected profit for ≈ 70% reduction in tail risk.
From the record



Techniques
- Iterative MILP linearization of head-height-dependent power
- Stochastic mixed-integer programming over price scenarios
- CVaR-augmented risk-averse optimization
- Bertsimas-Sim robust optimization with budget Γ
- Hybrid robust formulation for offer/bid curve construction
- Post-optimization procedure with real cleared prices
Stack
- Python
- Gurobi
- Pyomo
- Pandas
- Alpiq market data
A problem like this?