Metadata-Version: 2.4
Name: power-dispatch-studio
Version: 0.2.0
Summary: Replay recorded Philippine WESM days, test demand and supply scenarios, and export hourly results from Python or the command line.
Project-URL: Homepage, https://power-dispatch-studio.vercel.app
Project-URL: Source, https://github.com/xmpuspus/power-dispatch-studio
Author: Xavier Puspus
License: MIT License
        
        Copyright (c) 2026 Xavier Puspus
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
        ---
        
        Scope note (not part of the MIT text above):
        
        - The MIT license applies to the code in this repository (pipeline/, web/*.html,
          web/serve.py, scripts/, tests/, Makefile).
        - The generated data files (web/data/*.json, web/data/*.geojson) are additionally
          offered under CC-BY-4.0 (https://creativecommons.org/licenses/by/4.0/).
          Attribution: power-dispatch-studio (2026), IEMOP public market data archive,
          https://github.com/xmpuspus/power-dispatch-studio
        - The mirrored upstream market files under data/raw/ belong to their publishers
          (IEMOP). They are republished as-is for research with attribution, and any
          takedown request from the publisher will be honored.
License-File: LICENSE
Keywords: IEMOP,WESM,dispatch,electricity,energy-market,linear-programming,philippines
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.11
Requires-Dist: highspy==1.15.1
Description-Content-Type: text/markdown

# power-dispatch-studio

The PH WESM dispatch engine behind [Power Dispatch
Studio](https://power-dispatch-studio.vercel.app), as an importable, citable
Python module and CLI.

The studio runs the same linear optimization and lowest-cost-first dispatch
(merit order) in the browser with HiGHS compiled to WebAssembly. This package is
the Python reference code for replaying one recorded day. It builds a
supply stack for each island grid from a calculated snapshot of public IEMOP data,
applies scenario changes, and clears the three connected grids with inter-grid
limits, storage, reserves, and a daily hydro-energy limit. The same calculation
and numbers can run in a notebook.

## Install

```bash
pip install power-dispatch-studio
```

The only runtime dependency is [`highspy`](https://pypi.org/project/highspy/)
(the HiGHS solver). A dated snapshot of the public data archive ships in the
wheel, so it runs with no network access.

## CLI

```bash
power-dispatch days                              # recorded days available
power-dispatch run --date 2026-06-15             # hourly CSV to stdout
power-dispatch run --date 2026-06-15 --offer-mode # replay the market's own bids
power-dispatch run --date 2026-06-15 --demand luzon=1500 -o out.csv
power-dispatch run --scenario scenario.json -o out.csv
```

## Python

```python
import power_dispatch as pd

pd.list_days()[:3]
# ['2026-05-01', '2026-05-02', '2026-05-03']

result = pd.run_scenario({
    "date": "2026-06-15",
    "opts": {"demand_delta": {"luzon": 1500}},  # +1.5 GW data-center load
})
result["summary"]["mean_price"]["luzon"]   # PhP/kWh
```

## The scenario override map

A scenario is `{"date": "YYYY-MM-DD", "opts": {...}}`. The engine accepts
the following override keys.

| key | type | meaning |
| --- | --- | --- |
| `demand_delta` | `{grid: MW}` or `{grid: [24 MW]}` | load added or removed, flat or with an hourly shape |
| `fuel_cost` | `{fuel: PhP/kWh}` | marginal-cost override |
| `fuel_avail_delta` | `{grid: {fuel: MW}}` | availability edit |
| `solar_delta_mw` | `{grid: MW}` | installed solar edit |
| `hydrology` | `float` | water multiplier (1.0 = observed) |
| `caps` | `{leyte\|mvip: MW or [24]}` | link limits |
| `storage` | `[{grid, power_mw, energy_mwh}]` | added BESS |
| `reserve_deduction` | `bool` | withhold scheduled reserve |
| `offer_mode` | `bool` | replay the recorded offer book. False uses the cost calculation |
| `gas_budget` | `{grid: MWh}` | daily gas-energy limit, for a lower-supply case |

`grid` is one of `luzon`, `visayas`, `mindanao`.

## The scenario file

A scenario carries a schema stamp, so a file written in one place runs in
another. The studio writes it, this package reads it, and `validate` says what is
wrong before the solver ever sees it.

```bash
power-dispatch validate myscenario.json
power-dispatch validate --keys myscenario.json   # every option, with its meaning
power-dispatch run --scenario myscenario.json -o out.csv
```

```python
import power_dispatch as pd

pd.validate_scenario(scenario)      # a list of messages, and never raises
pd.load_scenario("myscenario.json") # raises ValueError carrying all of them
```

### Your contract position

A scenario file can carry a contract book, and the engine never reads it.
`settle` marks the book against the modeled spot price, and `compare_position`
reports what a scenario does to it.

```python
pos = pd.compare_position(base, scenario, book, load_mw={"luzon": 400})
pos["net_change_php"]     # the contract gain less the open position's extra cost
```

It marks energy against modeled spot and stops there. No capacity fee, no
wheeling charge, no tax, and no credit terms.

The full key table is in the
[scenario schema](https://github.com/xmpuspus/power-dispatch-studio/blob/main/docs/scenario-schema.md).

## The data snapshot

The bundled data is a dated snapshot of the public archive at build time (see
`power_dispatch/data/meta.json`). To run against newer calculated data, point the
engine at a copy of the deployed `web/data/`.

```bash
power-dispatch run --date 2026-07-01 --data-dir /path/to/web/data
# or: export POWER_DISPATCH_DATA=/path/to/web/data
```

That same flag runs your own system. The directory needs `dispatch.json` and
`profiles.json`, and nothing in it has to be Philippine. The
[data contract](https://github.com/xmpuspus/power-dispatch-studio/blob/main/docs/data-contract.md)
lists every key, with a 30-line system that runs. A test in the repository
builds that system, solves it, and fails when the document stops matching the
engine.

## What this is and is not

This replays recorded days with scenario what-ifs on a documented calculation. It is
not a price forecast, and offer mode replays the market's published bids rather
than simulating bidding strategy. Recorded market inputs trace to the Independent
Electricity Market Operator of the Philippines (IEMOP). Fleet and cost inputs cite
their own sources. Caller inputs and model assumptions have separate labels. The
Historical replay view and method page report the calculation error. Read the
[full method](https://power-dispatch-studio.vercel.app/methodology.html).

The engine dispatches fuel blocks per island grid, so it holds no named units and
no unit commitment. That is a measured choice. Committing each thermal block with
a generic minimum-stable floor lowered the price correlation in all five scored
series, from 0.442 to -0.003 in Visayas. `pipeline/uc_probe.py` in the repository
carries the test.

MIT licensed.
