Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
114 commits
Select commit Hold shift + click to select a range
14f5dcf
Add typed historical ZIP readers and DAM disclosure schema variants
kvkenyon Sep 7, 2026
281e6a6
Filter archive listings by date and type more price and load history
kvkenyon Sep 7, 2026
47a422e
Generate typed readers for public archive-only CSV products
kvkenyon Sep 7, 2026
7bcf8ea
Type EIA daily archive cells and historical layouts
kvkenyon Sep 7, 2026
dd20527
Batch typed archive downloads within product limits
kvkenyon Sep 7, 2026
55317b2
Expand typed history and preserve compatible schema evolution
kvkenyon Sep 7, 2026
1f8a2e0
Add typed historical workbook readers with optional files extra
kvkenyon Sep 7, 2026
907b6bd
Add typed renewable generation and demand history
kvkenyon Sep 7, 2026
0c9a031
Add typed price-adder and system-operation history
kvkenyon Sep 7, 2026
20cf653
Add typed historical load forecasts and publication example
kvkenyon Sep 7, 2026
9b8adff
Add typed outage capacity and system adequacy history
kvkenyon Sep 7, 2026
3be0d62
Add typed ancillary-service and pricing-summary history
kvkenyon Sep 7, 2026
b4c40eb
Add typed regional renewable forecast history
kvkenyon Sep 7, 2026
aeacbad
Add typed ancillary-service deployment-factor history
kvkenyon Sep 7, 2026
7532cbb
Add typed ancillary-service demand-curve history
kvkenyon Sep 7, 2026
8a6a39a
Add typed real-time ancillary-service clearing history
kvkenyon Sep 7, 2026
bd327fb
Add typed RUC constraint and RTD price history
kvkenyon Sep 7, 2026
c689d10
Add typed settlement-point and bus-mapping history
kvkenyon Sep 7, 2026
0251313
Add typed correction history with document subtype selection
kvkenyon Sep 7, 2026
65ee781
Add typed SOG price and weather-assumption history
kvkenyon Sep 7, 2026
1d417c4
Add typed aggregated ancillary-service offer history
kvkenyon Sep 7, 2026
ecceddd
Add typed highest-price bid and offer history
kvkenyon Sep 7, 2026
e427c27
Add typed SCED and DAM disclosure curve history
kvkenyon Sep 7, 2026
72efe85
Add typed historical DAM bids and real-time summaries
kvkenyon Sep 7, 2026
be71782
Add typed SCED curves and legacy combined archive tables
kvkenyon Sep 7, 2026
9329697
Add typed DAM ancillary-service disclosure history
kvkenyon Sep 7, 2026
7f258da
Add typed COP snapshot and obligation history
kvkenyon Sep 7, 2026
7436963
Add typed event-trigger and SASM disclosure history
kvkenyon Sep 7, 2026
85eae40
Add typed COP update history with explicit timestamp formats
kvkenyon Sep 7, 2026
e0ac09f
Add typed SCED disclosure history for every query table
kvkenyon Sep 7, 2026
5e3a753
Add typed historical price-adder workbook readers
kvkenyon Sep 7, 2026
001e3f1
Add typed historical capacity and clearing-price workbooks
kvkenyon Sep 7, 2026
ffb3671
Add typed fuel-cost submissions and path-adder history
kvkenyon Sep 7, 2026
d31ee01
Add typed hourly EIA history and record archive availability
kvkenyon Sep 7, 2026
78e8556
Add typed public ESR Integration PDF tables
kvkenyon Sep 7, 2026
fa6a87c
Expose typed rows from monthly historical bundles
kvkenyon Sep 7, 2026
04aadad
Recover rejected bundle downloads through published GET links
kvkenyon Sep 7, 2026
d075e76
Add typed hourly percentage labels from public ESR charts
kvkenyon Sep 7, 2026
baf1913
Document verified archive and bundle publication overlap
kvkenyon Sep 7, 2026
04fc754
Support intermediate SCED and wind historical layouts
kvkenyon Sep 7, 2026
871af92
Preserve legacy wind hour-beginning and combined-region layouts
kvkenyon Sep 7, 2026
2a636d3
Record full-row annual DAM and regional solar archive checks
kvkenyon Sep 7, 2026
ceb2a95
Support legacy controllable-load filenames and solar forecast layout
kvkenyon Sep 7, 2026
8dd3294
Preserve intermediate price-adder workbook capacity fields
kvkenyon Sep 7, 2026
aa6ab9b
Verify annual 15-minute price-adder workbook values
kvkenyon Sep 7, 2026
3dd8eea
Record annual ancillary-service and COP archive coverage
kvkenyon Sep 7, 2026
560d56f
Verify intermediate outage and load-forecast source values
kvkenyon Sep 7, 2026
c4f45b1
Verify fresh-client data workflows and update coverage summary
kvkenyon Sep 7, 2026
43f83b3
Confirm live API inventory and generated parameter coverage
kvkenyon Sep 7, 2026
a02bd90
Identify direct website wind archives beyond the API catalog
kvkenyon Sep 7, 2026
63a9896
Read public wind integration archives as typed daily summaries
kvkenyon Sep 7, 2026
f832274
Read public historical weather-zone load workbooks
kvkenyon Sep 7, 2026
df5d443
Read legacy public hourly loads back to 1995
kvkenyon Sep 7, 2026
c388528
Read historical load outlooks and package source fixtures
kvkenyon Sep 7, 2026
a6f180a
Read historical public fuel mix with typed intervals and totals
kvkenyon Sep 7, 2026
94fade7
Read public historical zonal generation schedules back to 2001
kvkenyon Sep 7, 2026
0be4e84
Read typed public wind and solar planning profiles back to 1980
kvkenyon Sep 8, 2026
4cb08fb
Add typed site keys for historical wind and solar profiles
kvkenyon Sep 8, 2026
5df2dd2
Add typed public load forecast summaries
kvkenyon Sep 8, 2026
4c53f35
Add typed winter reliability load forecasts
kvkenyon Sep 8, 2026
4182a7b
Focus release on market and operational time series
kvkenyon Sep 8, 2026
be4c131
Preserve publication metadata for historical market rows
kvkenyon Sep 8, 2026
3442cb4
Combine bundles and archives in typed historical backfills
kvkenyon Sep 8, 2026
f4e5b76
Add practical market data and forecast vintage examples
kvkenyon Sep 8, 2026
a45bcf3
Continue historical backfills across absent disclosure tables
kvkenyon Sep 8, 2026
c979456
Record final live coverage audit and clarify historical limits
kvkenyon Sep 8, 2026
8735e35
Verify complete retained load backfill and document source gaps
kvkenyon Sep 8, 2026
762b3fc
Recover intact workbooks from stale ZIP directory metadata
kvkenyon Sep 8, 2026
3adbe8d
Cache repeated date parsing within historical reads
kvkenyon Sep 8, 2026
7e7d873
Verify complete retained DAM settlement-price backfill
kvkenyon Sep 8, 2026
64db5e0
Add typed public SCED and ancillary capacity feeds
kvkenyon Sep 8, 2026
094e4dc
Add typed public real-time system conditions
kvkenyon Sep 8, 2026
220f8d1
Expose typed public LMP components and five-minute changes
kvkenyon Sep 8, 2026
f002823
Add typed public indicative prices for every hub and load zone
kvkenyon Sep 8, 2026
f3fec4c
Add typed historical retail load profiles and adjustment factors
kvkenyon Sep 8, 2026
309346c
Add typed historical four-coincident-peak allocations
kvkenyon Sep 8, 2026
bbfa82c
Add typed monthly four-coincident-peak history
kvkenyon Sep 8, 2026
1f8bfa1
Add typed historical profile-assignment counts
kvkenyon Sep 8, 2026
2df87a1
Add typed historical weather-zone observations
kvkenyon Sep 8, 2026
d8c3b32
Add typed historical IDR compliance summaries
kvkenyon Sep 8, 2026
7695f85
Add typed historical settlement loss factors
kvkenyon Sep 8, 2026
126a33d
Add typed CRR calendars and retail territory totals
kvkenyon Sep 8, 2026
66612a9
Add typed retail transaction histories
kvkenyon Sep 8, 2026
d675f5a
Add typed interim indicative ORDC history
kvkenyon Sep 8, 2026
a67d97c
Add typed historical resource-outlook percentiles
kvkenyon Sep 8, 2026
72cf21d
Add typed historical resource-capacity details
kvkenyon Sep 8, 2026
69cfa96
Add typed monthly capacity and supply-balance tables
kvkenyon Sep 8, 2026
5d9c115
Add typed historical capacity changes and project vintages
kvkenyon Sep 8, 2026
5693e61
Extend typed settlement loss histories to all public annual archives
kvkenyon Sep 8, 2026
288767d
Add typed seasonal transmission coefficients and operator load shares
kvkenyon Sep 8, 2026
397353f
Add typed historical distribution-loss coefficients
kvkenyon Sep 8, 2026
48782e9
Add typed daily 4CP source energy and settlement history
kvkenyon Sep 8, 2026
5e4b91d
Add typed historical zonal generation and load energy
kvkenyon Sep 8, 2026
551f2f5
Add typed MORA conditional risk curve points
kvkenyon Sep 8, 2026
e922b11
Focus market data guidance and add typed price-history export
kvkenyon Sep 8, 2026
b488d01
Verify complete intermediate market report samples
kvkenyon Sep 8, 2026
55e9674
Add typed wind and solar planning profiles
kvkenyon Sep 8, 2026
1d02f24
Add typed generation profile site keys and summaries
kvkenyon Sep 8, 2026
3635743
Read independently dated legacy wind profile tables
kvkenyon Sep 8, 2026
8554920
Read older wind profile workbooks with typed site metadata
kvkenyon Sep 8, 2026
7f5cfd7
Stream unbounded backfills before archive pagination
kvkenyon Sep 8, 2026
beadb04
Expose public peak-demand forecast scenarios as typed rows
kvkenyon Sep 8, 2026
41b47ce
Read monthly load forecasts with original dates and declared units
kvkenyon Sep 8, 2026
35ae9ef
Add typed seasonal and weekly weather-zone peaks
kvkenyon Sep 8, 2026
ab38da9
Read public hourly load forecasts with typed regional components
kvkenyon Sep 8, 2026
17844e6
Drop legacy compliance reports from the market-data scope
kvkenyon Sep 8, 2026
f31896e
Read regional hourly load scenarios with original source markers
kvkenyon Sep 8, 2026
552608e
Generate typed ESR queries and historical archive access
kvkenyon Sep 8, 2026
4bc406d
Read typed hourly forecast performance and error summaries
kvkenyon Sep 8, 2026
b46026b
Read monthly forecast and backcast performance with source scales
kvkenyon Sep 8, 2026
2dbd913
Read typed dated public price and load displays
kvkenyon Sep 8, 2026
533fd31
Keep market dashboards usable before day-ahead publication
kvkenyon Sep 8, 2026
bc0dff1
Preserve public LMP prices when five-minute changes are unavailable
kvkenyon Sep 8, 2026
460e3a1
Record complete retained wind history verification
kvkenyon Sep 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 5 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ tools/inputs/operations.json linguist-generated=true
tools/inputs/esr-operations.json linguist-generated=true
tools/inputs/products.json linguist-generated=true
tools/inputs/*-sample.json linguist-generated=true
# Keep captured HTML byte-for-byte, including ERCOT's trailing whitespace.
tools/inputs/*-index.html linguist-generated=true -whitespace
tools/inputs/samples/** linguist-generated=true
tools/inputs/dashboards/** linguist-generated=true
# Hand-maintained mappings, overrides and evidence remain visible.
tools/inputs/generation-profiles/csv-header-samples.json linguist-generated=true
tinyercot/_generated_esr.py linguist-generated=true
tools/inputs/esr/operations.json linguist-generated=true
5 changes: 5 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
Keep the SDK small and fully typed. Product methods and row models are generated;
handwritten code handles shared transport, typed metadata, and public dashboards.

Focus the release on actionable market and operational time series for retailers,
battery operators, and energy traders. Planning studies, profile-key workbooks,
and document-specific summary extraction are outside the release scope.

- `tinyercot/_client.py`: authentication, sync/async retrieval, pagination, metadata, ZIP downloads.
- `tinyercot/_history.py`: shared typed CSV and nested ZIP readers. Verified mappings live in `tools/inputs/history-formats.json`.
- `tinyercot/_generated.py`: generated typed product namespaces; never edit manually.
- `tinyercot/_dashboards.py`: typed public dashboard payloads and retrieval.
- `tools/generate_client.py`: offline generation from `tools/inputs/operations.json`
Expand Down
4 changes: 3 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
include api_response_fields.json
recursive-include tools *.py *.json
recursive-include tools *.py *.md *.json *.csv *.xlsx *.pdf *.zip *.html
recursive-include tests *.py
recursive-include examples *.py *.md
recursive-include docs *.md
130 changes: 80 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,79 +1,109 @@
# tinyercot

A small, fully typed client for ERCOT public data.
A small, fully typed ERCOT data client for retailers, battery operators, and
energy traders. Query recent data, stream historical archives and monthly
bundles, or read public load and generation files. Coverage focuses on data for market
decisions, settlement and resource planning.

**Development status:** all 242 Public Reports endpoints have typed methods and captured-response tests. The separate ESR API is awaiting an enabled subscription key. MIS is not included.
## Install and connect

This development branch contains the API described below. Install from its checkout:

```sh
pip install .
```

Set `ERCOT_USERNAME`, `ERCOT_PASSWORD`, and `ERCOT_SUBSCRIPTION_KEY`, or pass
`username`, `password`, and `subscription_key` to `Client`. Credentials are read
lazily; anonymous public downloads do not need them.

```python
from datetime import date
from tinyercot import Client

with Client() as ercot:
prices = ercot.np4_190_cd.dam_stlmnt_pnt_prices_iter(
deliveryDateFrom=date(2026, 1, 1),
deliveryDateTo=date(2026, 1, 2),
for price in ercot.np4_190_cd.dam_stlmnt_pnt_prices_iter(
deliveryDateFrom=date(2026, 9, 1),
deliveryDateTo=date(2026, 9, 1),
settlementPoint="HB_HOUSTON",
)
for price in prices:
):
print(price.deliveryDate, price.settlementPointPrice)
```

Pass `username`, `password`, and `subscription_key` to `Client`, or set
`ERCOT_USERNAME`, `ERCOT_PASSWORD`, and `ERCOT_SUBSCRIPTION_KEY`.
Authentication is lazy; the client refreshes tokens and retries transient failures.
Methods have named, typed filters and Pydantic row models. A method returns one
`Page[Row]`; `_iter` streams every page. `_async` and `_iter_async` provide async
access. Dates, decimals, missing values, and DST flags retain their source meaning.

Each product exposes generated methods with named, typed filters and Pydantic row
models. A method returns one `Page[Row]`; its `_iter` variant streams all pages.
`_async` and `_iter_async` provide asynchronous access. Date and decimal values
retain their Python types. Nullable source cells are represented by `None`.
## Get the available history

```python
from pathlib import Path
from tinyercot import Client
Use the same method name with `_history`. `backfill()` combines monthly bundles
with individual archives, including older and bundle-only reports:

```python
with Client() as ercot:
products = ercot.products()
history = ercot.archives("np4-190-cd")
document = history.archives[0]
Path("prices.zip").write_bytes(
ercot.download("np4-190-cd", [document.docId])
)

bundles = ercot.bundles("np4-190-cd")
Path("monthly.zip").write_bytes(
ercot.download("np4-190-cd", [bundles.bundles[0].docId], kind="bundle")
)
history = ercot.np4_190_cd.dam_stlmnt_pnt_prices_history
for price in history.backfill(
where=lambda row: row.settlementPoint == "HB_HOUSTON",
batch_size=25,
):
print(price.deliveryDate, price.hourEnding, price.settlementPointPrice)
```

Archive and bundle listings expose typed metadata. Downloads return the original
ZIP bytes. Listing metadata includes the server's total and page counts; `iter_documents()` streams all listing pages.
This requests all retained publications and can take considerable time. The
predicate filters typed rows after download. Original document IDs prevent
fetching the same publication twice; distinct corrections and repeated source
rows remain intact. Output is streamed without sorting.

`posted_from` and `posted_to` select **publication times**, which can differ from
operating dates. Omit them for the widest history, including bundle-only reports.
Use `publications()` to retain each archive's original posting metadata for
forecast backtests. A bundle's timestamp does not establish when its forecasts
were available. `read(zip_bytes)` decodes saved downloads with the same types.

Runnable exports from this repository:

```sh
uv run python -m examples.market_day 2026-09-01 --point HB_HOUSTON --output market-data
uv run python -m examples.price_history dam --point HB_HOUSTON --output dam-history.jsonl
uv run python -m examples.price_history rt --point HB_HOUSTON --output rt-history.jsonl
```

See the [market-data guide](docs/market-data.md) to choose price, load, forecast,
ancillary-service, outage, and disclosure readers, and the
[examples](examples/README.md) for export details and forecast vintages.

## Coverage

The September 7, 2026 inventory check matched **242 Public Reports queries** and
**249 HTTP operations** including shared metadata/download operations. Generated
history readers cover **289 tables across 113 products**. This establishes API
and known-format coverage, not uninterrupted history for every dataset.

Full-source comparisons cover retained DAM settlement prices, DAM ancillary
prices, and weather-zone actual load. Other products have sampled historical
layout checks; see the [coverage evidence](docs/data-coverage.md). Available
history and source gaps differ by product. The separate ESR service adds one
generated query and its history reader through `ESRClient`, using
`ERCOT_ESR_SUBSCRIPTION_KEY` with the same username/password. See the
[ESR workflow](docs/usage.md#energy-storage-four-second-data) for verified retention
and source freshness. MIS remains outside the current scope.

Direct public services include `hourly_load`, `fuel_mix`, `load_profiles`,
`loss_factors`, `load_forecast_performance`, and `dashboards`. Install `tinyercot[files]` for XLS/XLSX/XLSB readers
or `tinyercot[pdf]` for supported PDF tables. Detailed source-specific examples
remain in the [usage reference](docs/usage.md).

## Development

Runtime dependencies are `httpx`, `httpx-retries`, and `pydantic`. The handwritten
core handles authentication, transport, pagination, and metadata. Product methods
and row models are generated from saved ERCOT operation and field definitions.
Product methods and row models are generated from saved ERCOT definitions. The
runtime depends on `httpx`, `httpx-retries`, and `pydantic`; optional file parsers
are loaded when used. Source fixtures support tests and generation and are
excluded from the installed wheel.

```sh
uv sync --group dev
uv run python tools/generate_client.py
uv run mypy tinyercot tests/typing_client.py --strict --follow-untyped-imports
uv run mypy tinyercot tests/typing_client.py examples --strict --follow-untyped-imports
uv run pytest
uv build
```

Generation fails if an endpoint has no field schema. During discovery only,
`--allow-incomplete` emits available endpoints and reports the missing count.
Public dashboards are available through `ercot.dashboards`: fuel mix, grid
conditions, energy storage, generation outages, DC-tie flows, system prices,
supply/demand, combined wind/solar, system demand, ancillary services, weather,
and the current locational price map.

Source-specific corrections live in `tools/inputs/type-overrides.json`,
`row-fields.json`, and `query-defaults.json`. ERCOT declares hour-ending labels
and offer identifiers as numeric on two reports. The ESR-west report includes
two metadata-only columns absent from its rows and has an invalid default sort;
its generated method uses `SCEDTimestamp` by default. Captured responses support
these small corrections. Large forecasts may need a date filter or a longer
client timeout. Specify `sort` when supplying `dir`. Tests use saved public responses and mocked
HTTP; credentials are not part of the test suite.
Loading