Trade the Distribution

An end-to-end flow from fundamentals to trades

In this post we simulate tomorrow's day-ahead and real-time prices as a distribution for how the day could unfold. We optimized for risk adjusted returns across those scenarios to create a 1,000 MWh book of virtual bids for January 26, a scarcity day, and settled with $928k P&L. Running the same routine with a deterministic forecast of each market earned $264k. Everything below is 26 January, 2026; next week's post will run the same process for an entire month.

If you want to the trade simulator for yourself head over to our Virtual Trader, and make your own simulations in our OPF Studio ; send an email to info@distill.energy if you're an ERCOT market participant and we can set up a demo and trial.

An end-to-end flow from fundamentals to trades

From market simulations to bidsThe day-ahead and real-time markets are each simulated many times through the Distill Optimal Power Flow API. Of the four outputs a solve returns, the nodal prices are the one carried forward. Those price distributions, with the three trading parameters K, alpha and lambda, feed the Distill Virtual Trader Module, which returns bids.Day-ahead marketNetwork topologyFinancial bid curvesPhysical bid curvesAncillary bid curvesOptimal Power Flow APINodal day-ahead pricesLine flowsAncillary awardsBinding constraintsDay-ahead prices× NReal-time marketNetwork topologyOffer curves at costLoad forecastAncillary bid curvesOptimal Power Flow APINodal real-time pricesLine flowsAncillary awardsBinding constraintsReal-time prices× NBid constructionKαλbreadth · risk · spreadVirtual Trader ModuleBidsnode · hour · side · price · MWEach scenario is a full network solve,not a perturbation of an earlier answer.

As we've discussed in The Future is a Distribution and our Primer on Optimal Power Flow, Distill lets you simulate the power market according to what could happen, with the understanding that the future holds uncertainty. Here, we elaborate further by distinguishing between the day-ahead and the real-time auctions.

The day-ahead auction is a clearing problem: participants submit offer and bid curves, the market operator picks the cheapest feasible combination, and the resulting prices are as much about how people bid as about the physics. Real-time is closer to pure physics: whatever was scheduled meets the grid as it actually is, and price is set by what it costs to serve the next megawatt where it is needed. Feed each market its own inputs, simulate the power flow, and the two answers differ just like they do when ERCOT solves the models.

However, the future is uncertain: load might show up differently than forecast, units might trip, and wind might arrive early. The trading output is better when each market is solve many times over across a spread of plausible conditions, and every solve is a complete network simulation rather than a perturbation of an earlier answer. Then, what you feed into the trading module is a distribution of prices at every node and hour, and, more usefully, a distribution of the gap between the two markets.

That distribution is what the Virtual Trader module works from. It picks the nodes where the DART gap moves most in the simulations, decides which side of each to take, and sizes the position. The sizing also needs the distribution, because a wide spread of outcomes and a narrow one can share the same average but have very different exposure.The trading algorithm accepts three parameters that can help customize how the shape of the distribution impacts trades: K for how many nodes to look at, α for how much of the average return to trade off for protection against a tail event, and λ for how strongly to prefer many small positions over a few large ones. What comes out is a set of bids ready to submit: node, hour, side, price, megawatts.

How it works

Call OPF Studio for day-ahead and real-time simulations, and bring your own forecasts to augment them. We pull that through a robust optimization routine that finds the portfolio with the best risk-adjusted returns based on parameters you set. The more simulations you bring that explore the space of tomorrow’s possibility, the better your portfolio will end up.

1 · Forecast both markets

Two models, one per market. The day-ahead model simulates tomorrow's auction; the real-time model simulates the physical grid actually running. This produces a distribution of how the day could go instead of a single guess.

2 · Pick where to trade

Each hour, the optimizer chooses K nodes. It looks at the gap between the two forecasts measured across all of the scenarios to identify which nodes have the highest volatility for the day.

3 · Size and price the bids

Across those nodes it places offers (sell day-ahead, buy back real-time) and bids (the reverse), choosing volumes and bid prices to maximize

expected profit − α × CVaR − λ × Σ volume²

CVaR is the average loss over the worst 20% of scenarios; α prices protection against it. The last term is a penalty on the megawatts held at any one node-hour, making size progressively expensive, so λ decides how widely the book spreads beneath the hard 30 MW limit.

4 · Settle honestly

The book obeys ERCOT's rules — 0.1 MW increments, bids inside [−$250, $5,000], a 1,000 MWh daily allocation, 30 MW at any one node-hour — and settles against ERCOT's published day-ahead and real-time prices. The forecasts never saw them.

One guess or a distribution?

The only differences between the deterministic and probabilistic outcomes are the nodal prices. Both portfolios use the same optimizer and the same rules. For deterministic forecasts, the risk parameter α has no effect.

K nodes/hourDeterministicforecastsProbabilisticforecastsProbabilisticadvantage
1−$5,422$679k$685k
3$119k$982k$863k
5$264k$928k$664k
10$406k$941k$535k
20$790k$1.00M$210k

At the default K=5, the probabilistic book settles $928k against $264k for the deterministic book.

A grid of user-defined parameters

There are five parameters to set

  • The total size of the portfolio, here set to 1,000MWh
  • The maximum volume per node-hour, defaulted to 30MW.
  • The maximum number of nodes the book will trade each hour, K.
  • Control over the average return the optimizer will trade away for protection against the bad tail, called α.
  • The willingness to spread the book instead of putting large volumes on one node, call λ.

With these, here’s the settled P&L for all 100 combinations:

1 / 4
λ = 0.0median 34 node-hours held, 1000 MWh deployed — holds the best cell
K \ αα = 0.0α = 0.5α = 1.0α = 2.0α = 5.0
K = 1$604k$604k$1.13M$1.13M$1.18M
K = 3$868k$868k$930k$926k$926k
K = 5$831k$922k$926k$937k$948k
K = 10$693k$714k$776k$977k$1.24M
K = 20$1.03M$1.01M$1.00M$1.03M$1.01M

Breadth pays: more nodes each hour puts more of the allocation to work. Risk aversion pays too, at nearly every setting, because α is guarding against real shifts in DA caught by the simulations. λ buys diversification by moving the median portfolio from 34 node-hours to 85. Best cell K=10, α=5.0, λ=0.0 at $1.24M

The day's forecasts against actuals

These figures show that our day-ahead simulations were more accurate than the real-time, but the uncertainty in the real-time was geographically correct. On scarcity days in particular, the stack is so sensitive that it is impossible to get a forecast right, but by modeling a distribution you don’t have to. Importantly, Distill’s nodal model got the geographic spread very close, which made a big difference in creating a diverse portfolio.

Day-ahead

Distill forecast
ERCOT settled
$349$843$/MWh

Real-time

Distill forecast
ERCOT settled
$88$498$/MWh

Forecast − settled

Day-ahead
Real-time
−$331$331$/MWh

Uncertainty

Day-ahead
$70$78± $/MWh
Real-time
$7$96± $/MWh

Performance

The headline is the difference between probabilistic and deterministic outcomes. As seen above, the forecasts weren’t perfect, but by accounting for uncertainty we were able to put on a portfolio that cleared volume where it mattered in the morning ramp, and left most of the later day alone. Knowing when to trade, and how much, becomes a function of how certain you are that there is edge; instead of gut feel, you get clarity with numbers to back it.

Probabilistic$928ksettled P&L, $1,499 per cleared MWh
Deterministic$264ksettled P&L on the same rules
Volume619 MWhcleared of 996 submitted
Fill rate62%42 of 63 virtuals

Probabilistic forecast

hour gained hour lost
$703k$0−$100kHE1HE3HE5HE7HE9HE11HE13HE15HE19HE21HE23
MW bid MW cleared
136 MW0HE1HE3HE5HE7HE9HE11HE13HE15HE19HE21HE23

Hour ending, market local time.

The book, in full

Note that even though the day was a short, the portfolio still put on (and made money on!) bids where it could across the grid.

HENodeSideBidMWDA settledRT settledP&L
1FOXTROT_ALLOFF, not filled$607.1926.8$217.79$163.87$0
1FREC_2_CCUBID, filled$1,420.747.0$1,347.19$330.73−$7,115
1HOLCOMB_RN1OFF, not filled$792.034.8$728.95$447.25$0
1OUTP_SLR_RNOFF, not filled$688.1614.7$567.37$265.93$0
1PALACIOS_RNBID, filled$1,551.4624.1$1,203.28$1,286.08$1,995
2DC_LOFF, filled$422.4018.4$494.11$168.08$5,999
2FREC_2_CCUBID, filled$1,602.6827.4$1,024.25$377.27−$17.7k
2OUTP_SLR_RNOFF, filled$436.5912.6$498.01$227.41$3,410
2PALACIOS_RNBID, filled$1,530.5329.9$961.74$1,748.53$23.5k
3FREC_2_CCUBID, filled$1,417.1726.9$1,209.63$387.11−$22.1k
3OUTP_SLR_RNOFF, filled$587.1715.5$687.66$56.42$9,784
3PALACIOS_RNBID, filled$1,359.7829.9$1,198.44$1,880.77$20.4k
3STP_STP_G1OFF, filled$588.4623.7$703.89$191.28$12.1k
4FOXTROT_ALLOFF, not filled$476.8426.5$139.42$215.12$0
4FREC_2_CCUBID, filled$1,474.2712.3$1,207.29$365.32−$10.4k
4OUTP_SLR_RNOFF, not filled$563.0515.3$528.87$79.34$0
4PALACIOS_RNBID, filled$1,425.9729.9$1,243.26$1,863.41$18.5k
5CITYVICT_ALLOFF, not filled$758.4029.9$695.01$281.55$0
5FREC_2_CCUBID, filled$1,543.044.4$1,345.84$542.75−$3,534
5OUTP_SLR_RNOFF, not filled$927.7825.6$667.19$109.15$0
5PALACIOS_RNBID, not filled$1,933.9529.9$3,682.42$1,741.85$0
6DC_LOFF, not filled$1,286.5729.9$1,242.67−$1.55$0
6HOLCOMB_RN1OFF, filled$1,384.7429.4$1,398.88$507.03$26.2k
6OUTP_SLR_RNOFF, not filled$1,288.3929.9$1,231.75$70.85$0
6PALACIOS_RNBID, not filled$2,276.3329.9$6,706.73$1,664.28$0
7BOARDCRK_ALLOFF, filled$1,445.9629.9$1,605.88$297.49$39.1k
7CITYVICT_ALLOFF, filled$277.786.0$956.94$229.29$4,366
7FREC_2_CCUOFF, filled$1,600.1319.6$1,613.36$374.68$24.3k
7OUTP_SLR_RNOFF, not filled$1,024.5729.9$742.10$76.69$0
7PALACIOS_RNBID, not filled$1,755.3329.9$22,618.19$1,847.47$0
8CITYVICT_ALLOFF, filled$218.886.9$1,062.64$161.80$6,216
8DECKER_GTOFF, filled$1,761.2529.9$2,102.16$566.74$45.9k
8FREC_2_CCUOFF, filled$1,568.2129.9$1,735.50$180.19$46.5k
8OUTP_SLR_RNOFF, not filled$1,079.2229.9$903.89$67.03$0
9CFLAT_ES_RNOFF, filled$810.1225.6$977.95$204.24$19.8k
9CITYVICT_ALLOFF, filled$401.6220.5$1,415.54$110.01$26.8k
9NRTN_SLR_RNOFF, filled$1,232.9529.9$1,681.46$75.30$48k
9PALACIOS_RNOFF, filled$1,110.3729.9$18,015.25$269.85$531k
9SANDHSYD1_2OFF, filled$1,378.9129.9$1,699.36$223.30$44.1k
10BUDA_RNOFF, filled$539.7510.2$754.97$109.90$6,580
10ERSL_RNOFF, filled$236.060.2$423.29$46.15$75
10MDANP_CT3_4OFF, filled$316.600.1$466.75$123.51$34
11CFLAT_ES_RNBID, filled$144.362.4$133.26$10.43−$295
12CFLAT_ES_RNBID, not filled$116.534.1$120.77$1.40$0
13CFLAT_ES_RNBID, not filled$110.984.8$119.86$4.77$0
14CFLAT_ES_RNBID, not filled$79.603.6$104.51$0.11$0
15CFLAT_ES_RNBID, not filled$52.462.1$79.68−$0.66$0
16CFLAT_ES_RNBID, not filled$61.271.2$88.99−$1.71$0
19JUNCTION_RNOFF, filled$651.919.5$746.27$177.27$5,406
19SANDHSYD1_2OFF, not filled$496.022.2$481.93$169.91$0
20SANDHSYD1_2OFF, filled$475.801.5$480.75$154.72$489
217RNCHSLR_ALLOFF, filled$395.651.7$401.56$167.55$398
21HART_WND_RNOFF, filled$269.704.5$318.68−$45.40$1,638
21SANDHSYD1_2OFF, not filled$543.256.3$531.13$163.14$0
22BOARDCRK_ALLOFF, filled$343.870.2$441.91$157.51$57
22HART_WND_RNOFF, filled$302.866.1$388.87−$35.36$2,588
22JUNCTION_RNOFF, filled$520.347.6$681.54$179.90$3,812
22SANDHSYD1_2OFF, filled$512.636.0$591.87$170.28$2,530
23FAGUSSLR_RNOFF, filled$273.197.4$464.65$75.53$2,879
23RUSSEKST_RNOFF, filled$371.254.1$523.42$128.49$1,619
23SANDHSYD1_2OFF, filled$384.084.2$558.94$119.14$1,847
23X443ESRNOFF, filled$330.493.1$517.07$122.71$1,223
24BUZI_SLR_RNOFF, filled$216.950.8$268.06$101.11$134
63 rows996.2$928k

Uncertainty to decisions

We show here how account for uncertainty can make a huge difference, even when the the forecast is good! Don’t forget you can test out our Virtual Trader (no paywall!) and run your own simulations in our OPF Studio. For the whole system end-to-end send an email to info@distill.energy if you're an ERCOT market participant and we can set up a demo and trial.

Distill is an interconnected platform. Click a node to explore. Drag to rearrange.