Commit tomorrow's output before noon today.
The client operates a solar plant in western Romania and has to declare its next-day generation before the day-ahead market closes. PowerCast forecasts the plant in fifteen-minute steps, keeps every forecast it has ever issued, and scores each one against metered production.

The problem
The Romanian day-ahead market closes at noon. The producer is held to whatever they declare for the following day, and the difference between that declaration and what the meter later records is settled at imbalance prices the producer does not set.
Solar output is a physics problem with a weather term in it, and that weather term is revised every few hours. A forecast made at five in the morning is already out of date by the time the declaration is due.
What we built
A single platform that transforms weather and satellite data into a scored production forecast.
- Plant forecast. Expected production at fifteen-minute resolution with a calibrated P10–P90 band, re-issued whenever a weather model publishes a new run.
- The scoring ledger. Every stored forecast is scored against live inverter data, grouped by how far ahead it was issued.

A forecast without a scoreboard is just an opinion with decimal places.
Hundreds of revisions get issued for a single delivery day. All of them are scored against what actually happened.
Scoring itself
Any delivery day can be replayed. Every forecast issued for it, from six days out down to the same-day nowcast, is drawn against the live truth curve for that day.
On the day shown below, error runs from 3.8% on the same-day forecast to 15.1% six days out, with the declaration submitted at the gate landing at 5.4%.

Inside the model
Irradiance is not production, and a chain of physics sits between them: solar position, a clear-sky estimate, a split of global irradiance into its beam and diffuse parts, and a transposition onto the plane of the array. That last step gives what the tilted panels actually receive rather than what a flat sensor would.
What sits on top is machine learning over those features plus cloud dynamics, a cell-temperature proxy, the fog signature of temperature closing on dew point, snow burial and aerosol. Quantile heads produce the band, and conformal calibration scales it so the interval covers what it claims to.
Three decisions shaped the result more than the choice of algorithm did:
- Train on the forecast, not on the truth. Historical weather comes from the archive of past forecast runs rather than a reanalysis, so the model never learns from a data source it will not have at issue time.
- Validate chronologically. Expanding windows grouped by date, an issue-time embargo, and preprocessing fitted inside each fold.
- Version everything. Model artifacts are content-addressed and move through an active, shadow and archived lifecycle, so a new candidate can be measured against the one in production before it replaces it.
Details
- Client
- A solar producer in western Romania
- Market
- Romanian day-ahead and imbalance, D−1 12:00 gate
- Resolution
- 15-minute slots · P10 / P50 / P90 · re-issued on every weather update
- Physics
- Solar position · clear-sky model with turbidity climatology · beam/diffuse decomposition · plane-of-array transposition
- Model
- Gradient boosting on physics and weather-dynamics features · monotonic constraints · quantile heads with conformal band calibration · expanding-window validation with an issue-time embargo
- Weather
- Multi-model ensemble · past-forecast archive for training · satellite irradiance for the nowcast · aerosol and ensemble-spread inputs
- Stack
- FastAPI · SQLite · React · TypeScript · ECharts · Vite · content-addressed model registry
Plant identity, grid registration and coordinates have been removed from the screenshots on this page.