Independent System Operator Data Automated Request Tool
A modern Python toolkit for downloading and analyzing electricity market data from US Independent System Operators
Quick Start β’ Documentation β’ Examples β’ Contributing
ISO-DART simplifies access to electricity market data across the United States. Whether you're a researcher, energy analyst, or data scientist, ISO-DART provides a unified interface to download pricing, load, generation, and weather data from multiple ISOs.
- π 7 ISO Coverage: CAISO, MISO, NYISO, SPP, BPA, PJM, ISO-NE
- π€οΈ Weather Integration: Historical weather and solar radiation data
- π Modern Python: Type hints, async support, comprehensive error handling
- π― User-Friendly: Interactive CLI or programmatic API
- π Analysis-Ready: CSV output compatible with pandas, Excel, and R
- β‘ Performance: Automatic retry logic, connection pooling, rate limiting
CAISO (California) - Click to expand
- Pricing: LMP (DAM/HASP/RTM/RTPD), Scheduling Point Tie Prices, AS Clearing Prices
- Load: System load forecasts (DAM/RTM/2DA/7DA/RTPD Advisory)
- Generation: Wind & Solar Summary, EIM Transfer, Flexible Ramping
- Ancillary Services: Requirements, Awards, Operating Reserves
- Market Data: MPM Status, Fuel Prices, GHG Allowance Prices, Constraint Shadow Prices
MISO (Midcontinent) - Click to expand
- Pricing: LMP (DA/RT ExAnte/ExPost), MCP (ASM DA/RT)
- Load: Demand (DA/RT Forecast/Actual), Load Forecasts (MTLF)
- Generation: Fuel Mix, Cleared Generation (DA/RT), Fuel Type
- Interchange: Net Scheduled/Actual Interchange
- Constraints: Binding Constraints, Outage Forecasts
NYISO (New York) - Click to expand
- Pricing: LBMP (Zonal/Generator, DAM/RTM), AS Prices
- Load: ISO Forecast, Zonal Bid Load, Weather Forecast, Actual Load
- Generation: Fuel Mix, Interface Flows, Wind Generation, BTM Solar
- Market Data: Bid Data (Generator/Load/Transaction), Outages, Constraints
SPP (Southwest) - Click to expand
- Pricing: LMP (DA/RTBM by Settlement Location/Bus), MCP
- Reserves: Operating Reserves (RTBM)
- Forecasts: Load (STLF/MTLF), Resource/Wind (STRF/MTRF)
- Constraints: Binding Constraints (DA/RTBM), Fuel On Margin
- Clearing: Market Clearing, Virtual Clearing
BPA (Bonneville) - Click to expand
- Load & Generation: Wind Generation, Total Load (5-min resolution)
- Reserves: Operating Reserves Deployed (Regulation Up/Down, Contingency)
- Historical Data: Full calendar year datasets (2000-present)
PJM - Click to expand
- Pricing: LMP (DA Hourly, RT 5-min, RT Hourly)
- Load: Forecasts (5-min, Historical, 7-day), Hourly Load (Estimated/Metered/Prelim)
- Generation: Solar, Wind
- Ancillary Services: Hourly/5-min LMPs, Reserve Market Results
- Grid Data: Outages by Type, Transfer Limits & Flows
ISO-NE (New England) - Click to expand
- Pricing: Hourly LMP (DA/RT), 5-Minute RT LMP
- Ancillary Services: Regulation Clearing Prices, Operating Reserves
- Load: 5-Minute System Demand, DA Hourly Demand
Weather & Solar - Click to expand
- Meteostat: Temperature, humidity, wind, precipitation (hourly)
- NSRDB: Solar irradiance (GHI, DHI, DNI) from NREL
# Clone repository
git clone https://github.com/LLNL/ISO-DART.git
cd ISO-DART
# Create virtual environment (recommended)
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txtInteractive Mode (easiest):
python isodart.pyCommand Line (fastest):
# Download last week's CAISO Day-Ahead LMP
python isodart.py --iso caiso --data-type lmp --market dam \
--start 2024-01-01 --duration 7Python API (most flexible):
from datetime import date
from lib.iso.caiso import CAISOClient, Market
client = CAISOClient()
client.get_lmp(Market.DAM, date(2024, 1, 1), date(2024, 1, 7))
client.cleanup()- Download data:
python isodart.py --iso caiso --data-type lmp --market dam \
--start 2024-01-01 --duration 7- Analyze in Python:
import pandas as pd
import matplotlib.pyplot as plt
# Load data
df = pd.read_csv('data/CAISO/20240101_to_20240107_PRC_LMP_TH_NP15_GEN-APND.csv')
# Quick statistics
print(df['VALUE'].describe())
# Plot prices
df['OPR_DT'] = pd.to_datetime(df['OPR_DATE'])
plt.figure(figsize=(12, 6))
plt.plot(df['OPR_DT'], df['VALUE'])
plt.xlabel('Date')
plt.ylabel('Price ($/MWh)')
plt.title('Day-Ahead LMP - NP15')
plt.xticks(rotation=45)
plt.tight_layout()
plt.savefig('lmp_analysis.png')- Done! You now have data and a visualization.
- Quick Start Guide - Get running in 5 minutes
- Migration Guide - Upgrading from v1.x
- API Reference - Complete function documentation
- Examples Gallery - Jupyter notebooks and scripts
# daily_download.py
from datetime import date, timedelta
from lib.iso.caiso import CAISOClient, Market
def download_yesterday():
yesterday = date.today() - timedelta(days=1)
client = CAISOClient()
try:
success = client.get_lmp(Market.DAM, yesterday, yesterday)
if success:
print(f"β Downloaded {yesterday}")
finally:
client.cleanup()
if __name__ == '__main__':
download_yesterday()Schedule with cron:
0 2 * * * cd /path/to/ISO-DART && /path/to/venv/bin/python daily_download.pyfrom datetime import date
from lib.iso.caiso import CAISOClient, Market as CAISOMarket
from lib.iso.miso import MISOClient, MISOConfig
from lib.iso.nyiso import NYISOClient, NYISOMarket
start = date(2024, 1, 1)
# CAISO
caiso = CAISOClient()
caiso.get_lmp(CAISOMarket.DAM, start, start)
# MISO
miso_config = MISOConfig.from_ini_file()
miso = MISOClient(miso_config)
miso.get_lmp("da_exante", start, 1)
# NYISO
nyiso = NYISOClient()
nyiso.get_lbmp(NYISOMarket.DAM, "zonal", start, 1)
print("β Downloaded data from all three ISOs")import pandas as pd
import matplotlib.pyplot as plt
# Load LMP data
lmp = pd.read_csv('data/CAISO/20240101_to_20240131_PRC_LMP_TH_NP15_GEN-APND.csv')
lmp['datetime'] = pd.to_datetime(lmp['OPR_DATE'])
# Load weather data
weather = pd.read_csv('data/weather/2024-01-01_to_2024-01-31_San_Francisco_CA.csv',
index_col='time', parse_dates=True)
# Resample to daily averages
lmp_daily = lmp.groupby(lmp['datetime'].dt.date)['VALUE'].mean()
temp_daily = weather['temperature'].resample('D').mean()
# Plot correlation
fig, ax1 = plt.subplots(figsize=(14, 6))
ax2 = ax1.twinx()
ax1.plot(lmp_daily.index, lmp_daily.values, 'b-', label='LMP')
ax2.plot(temp_daily.index, temp_daily.values, 'r-', label='Temperature')
ax1.set_xlabel('Date')
ax1.set_ylabel('LMP ($/MWh)', color='b')
ax2.set_ylabel('Temperature (Β°F)', color='r')
plt.title('Electricity Prices vs. Temperature')
plt.tight_layout()
plt.savefig('price_temp_correlation.png')Some ISOs and data sources require API keys:
MISO & PJM: Create user_config.ini:
[miso]
pricing_api_key = your-miso-pricing-key
lgi_api_key = your-miso-lgi-key
[pjm]
api_key = your-pjm-keyGet keys from:
NSRDB (Solar Data): Get free API key at https://developer.nrel.gov/signup/
ISO-NE: Requires ISO Express credentials
[isone]
username = your-username
password = your-passwordOr set environment variables:
export ISONE_USERNAME="your-username"
export ISONE_PASSWORD="your-password"Create config.yaml:
caiso:
max_retries: 5
timeout: 60
step_size: 1
miso:
rate_limit_delay: 0.8
logging:
level: DEBUG
file: logs/isodart.logUse: python isodart.py --config config.yaml
# Install dev dependencies
pip install -r requirements.txt
# Run all tests
pytest tests/ -v
# Run with coverage
pytest tests/ --cov=lib --cov-report=html
# Run specific tests
pytest tests/test_caiso.py -v# Format code
black lib/ tests/
# Lint
flake8 lib/ tests/
# Type check
mypy lib/ISO-DART/
βββ isodart.py # Main entry point
βββ lib/
β βββ iso/ # ISO client modules
β β βββ caiso.py
β β βββ miso.py
β β βββ nyiso.py
β β βββ spp.py
β β βββ bpa.py
β β βββ pjm.py
β β βββ isone.py
β βββ weather/ # Weather client
β β βββ client.py
β βββ interactive.py # Interactive mode
βββ tests/ # Test suite
βββ docs/ # Documentation
βββ examples/ # Example scripts & notebooks
βββ data/ # Downloaded data (created automatically)
We welcome contributions! Here's how you can help:
- π Report bugs - Create an issue with details
- π‘ Suggest features - We'd love to hear your ideas
- π Improve docs - Fix typos, add examples
- π§ Submit code - Fix bugs or add features
- β Star the repo - Show your support!
- Fork the repository
- Create a feature branch:
git checkout -b feature-name - Make your changes
- Add tests for new functionality
- Run tests:
pytest tests/ - Format code:
black lib/ tests/ - Submit a pull request
To add support for a new ISO:
- Create
lib/iso/new_iso.pyfollowing the pattern of existing clients - Add configuration dataclass
- Implement download methods
- Add tests in
tests/test_new_iso.py - Update
lib/interactive.pyfor CLI support - Document in README.md
See Contributing Guide for details.
All data is saved as CSV files with ISO-specific naming:
CAISO:
{start_date}_to_{end_date}_{query_name}_{data_item}.csv
Example: 20240101_to_20240131_PRC_LMP_TH_NP15_GEN-APND.csv
MISO:
miso_{data_type}_{date}.csv
Example: miso_da_exante_lmp_2024-01-01.csv
NYISO:
{start_date}_to_{end_date}_{dataid}_{aggregation}.csv
Example: 20240101_to_20240131_damlbmp_zone.csv
- β
Pandas:
pd.read_csv() - β Excel: Direct import
- β
R:
read.csv() - β Power BI / Tableau: CSV connector
- β
SQL databases:
COPY FROMor bulk insert
No data returned from API
Symptoms: Empty CSV files or "No data" errors
Solutions:
- Verify date range is not in the future
- Check if data exists for that period on ISO website
- Try a smaller date range
- Use
--verboseflag for detailed logs - Check
logs/isodart.logfor API errors
Import errors / ModuleNotFoundError
Symptoms: ModuleNotFoundError: No module named 'lib'
Solutions:
- Ensure you're running from the ISO-DART directory
- Activate virtual environment:
source venv/bin/activate - Reinstall dependencies:
pip install -r requirements.txt
API authentication failures
Symptoms: 401 Unauthorized, "Check API key" messages
Solutions:
- Verify API key is correct in
user_config.ini - Check key hasn't expired
- For MISO/PJM: Ensure you have the right API product subscription
- For ISO-NE: Verify credentials at https://webservices.iso-ne.com/
Slow downloads
Symptoms: Downloads take a long time
Solutions:
- This is normal for large date ranges (ISO APIs can be slow)
- Use smaller
step_sizevalues - Download during off-peak hours (early morning)
- For SPP: FTP is naturally slower than REST APIs
SSL certificate errors
Symptoms: SSLError: Certificate verification failed
Solutions:
pip install --upgrade certifi requestsMIT License - Copyright (c) 2025, Lawrence Livermore National Security, LLC
See LICENSE file for full terms.
If you use ISO-DART in your research, please cite:
@software{isodart2024,
title = {ISO-DART: Independent System Operator Data Automated Request Tool},
author = {Sotorrio, Pedro and Edmunds, Thomas and Musselman, Amelia and Sun, Chih-Che},
year = {2024},
version = {2.0.0},
publisher = {Lawrence Livermore National Laboratory},
doi = {LLNL-CODE-815334},
url = {https://github.com/LLNL/ISO-DART}
}This work was produced under the auspices of the U.S. Department of Energy by Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344.
- CAISO OASIS
- MISO Data Exchange
- NYISO Market Data
- SPP Marketplace
- BPA Operations
- PJM Data Miner
- ISO-NE Web Services
- GridStatus - Real-time grid data
- PyISO - Alternative ISO library
- Open Energy Dashboard - Energy visualization
- π Documentation: Check docs/ directory
- π¬ Discussions: GitHub Discussions
- π Issues: Report bugs
- π§ Email: Contact LLNL support
- ERCOT support
- ISO-NE full coverage
- Async/concurrent downloads
- Data validation & quality checks
- Built-in visualization tools
- PostgreSQL/SQLite export
- Web dashboard (Flask/FastAPI)
- Database integration (PostgreSQL, InfluxDB)
- Parquet output format
- Real-time data streaming
- Machine learning integration
- Docker containerization
If ISO-DART helps your work, please:
- β Star this repository
- π’ Share with colleagues
- π Report bugs you find
- π‘ Suggest improvements
- π Contribute documentation or code
Made with β€οΈ by Lawrence Livermore National Laboratory