Methods, sources, and model limits
Power Dispatch Studio archives Philippine market files, calculates a three-grid dispatch, and shows where the calculation agrees with recorded prices. This page separates records, calculations, assumptions, and known limits.
Can supply cover demand?
Recorded demand, scheduled outages, reserve needs, and sourced plant capacity set the starting point.
Can power reach a site?
Recorded link limits and mapped transmission routes show where transfers reach their limits.
How do prices change?
The model recalculates dispatch and compares its hourly prices with WESM records.
Dispatch model
The calculation is a three-zone linear dispatch. It meets demand at the lowest stated generation and transfer cost. A full inter-island link can leave the importing grid with a higher marginal price.
The default calculation groups plants by fuel and cost. The published-offer setting uses the operator's recorded generation offers instead. Hourly replay applies each day's demand, scheduled outages, hydro energy, solar profile, storage, and link limits.
WESM source files report prices in Philippine pesos per megawatt-hour. The interface divides by 1,000 and reports pesos per kilowatt-hour. Power uses MW and energy uses MWh.
IEMOP market records
IEMOP publishes the files below without a login. Its public window rolls
forward, so the repository copies each available day into data/raw/.
Git history keeps older public files after they leave the IEMOP pages.
| Public record | Source | Use in this project |
|---|---|---|
| Real-time and day-ahead constraints | IEMOP RTD constraints and IEMOP DAP constraints | Names equipment and stations that reached a limit. Daily rankings count each equipment item once per day. |
| Regional dispatch summaries | IEMOP regional summaries | Supplies demand, generation, curtailed load, and scheduled reserve by grid and interval. |
| Final load-weighted average prices | IEMOP final LWAP | Supplies the settlement-side price used in the regional price charts and historical replay. |
| Final nodal dispatch and prices | IEMOP final energy results | Supplies per-resource schedules, hydro energy limits, and recorded price differences between grid connection points. |
| Generation offers and self-schedules | IEMOP generation offers | Builds the published-offer replay for each grid and hour. |
| Reserve offers, schedules, and prices | IEMOP reserve files | Compares the last needed reserve offer with the operator's published regional reserve price. |
| HVDC schedules and limits | IEMOP HVDC records | Supplies hourly flow, direction, congestion flags, and transfer limits for the inter-island links. |
| Real-time outage schedules | IEMOP outage schedules | Matches unavailable resource codes to the sourced plant list. |
Fixed model inputs
| Input | Public source | How the model uses it |
|---|---|---|
| Power plants and announced projects | Department of Energy plant and project lists | Sets unit capacity, fuel, grid, and the long-term project list. |
| Inter-island and planned transmission | NGCP monthly reports and Transmission Development Plan | Sets sourced transfer limits and lists planned links. Unpublished line ratings stay labeled assumptions. |
| Fuel and market price rules | Energy Regulatory Commission and WESM rules | Sets cited fuel values and the ₱32/kWh offer cap used as the shortfall penalty. The penalty is not a value-of-lost-load estimate. |
| Transmission geometry | OpenStreetMap under ODbL | Draws mapped routes and supports the reduced nodal loss calculation. The geometry is not an NGCP network model. |
| Named data-center projects | Government, company, and cited news announcements | Places only sourced projects at city or campus precision. |
Replay accuracy
Replay accuracy recalculates every complete market day in the archive. It reports mean absolute error, bias, correlation, and high-price-hour agreement for each island grid. Recorded prices do not set the model inputs.
The cost calculation shows the competitive fuel-cost floor. The published-offer calculation shows the effect of recorded bids. Neither one reproduces every WESM price. The tables in the studio state the remaining difference.
Python and browser tests create the same linear-program text. Saved cases need both solvers to agree within ₱0.02/kWh and 1 MW.
Transmission-loss calculation
The nodal calculation uses OpenStreetMap routes, class reactances, and sourced inter-island limits. It compares calculated marginal-loss ranks with recorded node-price differences. The interface reports a separate result for each grid.
WESM can express inter-island congestion through different regional prices. Price-substitution rules can leave the nodal congestion field at zero even when dispatch records name equipment at a limit. The map calls the node values recorded price deviations. Read the source notes for the longer explanation.
Future-year calculation
pipeline/future_year.py joins four published inputs into the
same two files the engine already reads. The DOE Power Development Plan supplies
peak demand per grid per year. The DOE project lists supply capacity, counted
when the target year falls at or before the target year. NGCP's plan supplies
the link upgrades. The archive supplies the hourly shapes.
Demand uses the plan's growth ratio rather than its absolute level. Every recorded hour is multiplied by the ratio between the base year and the target year, so the archive keeps its own level and shape and the plan supplies only the growth. Each date in the target year borrows a recorded day of its own kind, weekday or weekend, cycling in date order.
Four limits ride with every figure the year produces. The build applies no retirements, because no public Philippine retirement schedule is archived here. It counts committed projects unless someone asks for indicative ones. Storage projects are reported and never dispatched, exactly as the DOE's summaries treat them. And each day solves on its own with a free terminal storage state, so storage resets at midnight and the hydro budget caps one day at a time. Seasonal hydro carry and multi-day storage cycling stay outside this build.
A year built this way is a scenario from published plans. It is not a forecast, and no figure from it may be quoted as one.
Fuel-block minimum-output experiment
Per-unit commitment needs unit-level minimum output, start cost, minimum
run time, and heat-rate inputs. Those inputs are not in this public-data
model. pipeline/uc_probe.py instead tests generic minimum-output
constraints on aggregate fuel blocks. This is a sensitivity check, not unit
commitment and not a Studio capability.
| Recorded series | Linear model | With commitment | Change |
|---|---|---|---|
| Luzon load-weighted average price | 0.297 | 0.128 | -0.169 |
| Visayas load-weighted average price | 0.442 | -0.003 | -0.445 |
| Mindanao load-weighted average price | 0.109 | -0.011 | -0.120 |
| Luzon market clearing price | 0.437 | 0.137 | -0.300 |
| Mindanao market clearing price | 0.113 | -0.006 | -0.119 |
Mean absolute error moves by less than ₱0.03/kWh in every series, so only the correlation falls. The Visayas market clearing price has no paired hours in the window, so five series carry the test.
The minimum-stable levels are generic thermal values, applied per fuel block and labeled generic. No public Philippine unit registry publishes a per-unit floor or heat rate. A fuel-block floor is coarser than a per-unit floor, and that coarseness is a likely reason the experimental run scores worse. The production model remains a linear fuel-block dispatch because the available public inputs do not support per-unit commitment.
Contract-position calculation
The dispatch model answers half of "what does this scenario do to my position". It produces an hourly spot price for each grid. The other half is a contract book, and the book belongs to the reader, so the studio holds an editable one that stays in the browser and never uploads.
One contract is a volume at a strike price over a set of hours. A buy contract fixes what the holder pays, so a spot price above the strike is a gain against buying at spot. A sell contract fixes what the holder receives, so the same move is a loss. The load a reader declares and has not contracted is the open position, and it prices at spot.
The arithmetic is the same in both places. studio/src/studio/contracts.ts
runs it in the browser and src/power_dispatch/contracts.py runs it
on the command line, and both test suites check the same worked numbers, so a
position marked in one re-marks in the other.
What it leaves out: no capacity fee, no wheeling or line-rental charge, no tax, no take-or-pay, and no credit terms. A settlement statement carries more lines than this. It marks energy against modeled spot and nothing else.
Named-unit probe
The model holds one block per fuel per grid, so it cannot say which plant
ran. pipeline/unit_probe.py tests what a per-unit model would
change. It gives every plant in the DOE fleet list its own variable, 141 of
them across the three grids, and scales each grid's per-fuel capacity to match
the block model exactly. The two runs then hold the same MW at the same costs,
cut into different pieces.
Across ten sampled market days the two runs burn the same daily energy of every fuel on every grid, to 0.0 MWh, and no hour's price differs by more than ₱0.004/kWh. The hour an energy-limited fuel lands in does move, by up to 1,408 MW, across hours that cost the same, because the epsilon that makes the optimum unique rides the variable index and the two models number their variables differently.
One score still moves. The Mindanao market clearing price correlation goes from 0.133 to 0.243, and that is a warning about the metric rather than a gain. The cost model clears near flat, and a correlation against a moving recorded series is hypersensitive when the modeled series barely varies. Four tenths of a centavo reorders it.
So a per-unit model buys attribution and not accuracy. Every unit of a fuel carries that fuel's cost here, so splitting a block into units cannot reorder the stack. A per-unit heat rate or a per-unit offer would change that, and no public Philippine source publishes either.
Model limits
- The model does not claim that data centers caused recorded electricity prices.
- Recorded curtailment and reserve shortfalls do not forecast brownouts.
- Future demand, fuel, hydrology, outage, and build cases are scenarios. They are not forecasts.
- The model has three zones and two inter-island links. It omits within-zone security constraints and per-unit commitment.
- OpenStreetMap routes and class line ratings do not replace an NGCP planning model or interconnection study.
- Company and project records come from cited public sources. Specific allegations need separate evidence.
Reproduce the data and checks
make data rebuilds the calculated files from the archive.
make qa checks data values, public wording, and browser model
agreement. The repository keeps the source URL and calculation date beside
each main dataset.
Code uses the MIT license. Calculated data products use CC BY 4.0. Source records stay the property of their publishers.