Skip to content

feat(nowcast): observed generation price from EIA-861 sales for resale - #1220

Open
WesIngwersen wants to merge 2 commits into
electricity_price_by_buyerfrom
electricity_generation_price
Open

WesIngwersen wants to merge 2 commits into
electricity_price_by_buyerfrom
electricity_generation_price

Conversation

@WesIngwersen

Copy link
Copy Markdown
Member

Closes #1215. Stacked on #1219. Part of the plan in #902.

Adds generation_price(year): one price per kWh generated, from EIA-861 sales for resale (revenue over MWh, through PUDL). It replaces a price derived from the electricity row's dollar total, which moved with the same bills it divides. buyers_below lists buyers paying less than this price. Nothing in the model reads either yet, so no output changes.

The series

2017 2018 2019 2020 2021 2022 2023 2024
Generation price, ¢/kWh 4.11 4.36 4.22 3.83 5.68 6.29 5.27 5.00
EIA retail price, all sectors, ¢/kWh 10.48 10.53 10.54 10.59 11.10 12.36 12.68 12.94
Generation, at this price x eGRID kWh, $bn 166 182 175 154 234 267 221 215
EIA retail revenue less generation, $bn 224 225 227 240 188 219 271 299
Manufacturing industries priced below it 1 1 0 0 6 4 1 0
Their share of manufacturing kWh 2.3% 2.3% 0 0 16.0% 11.7% 1.0% 0

Revenue less generation shows the size of the delivery margin before losses, on EIA's level. Bills are higher than EIA revenue, so 42ELEC will be larger.

Decision for #902: buyers below the generation price

These industries have a negative margin in 2021-22:

Year Buyers, ¢/kWh delivered
2021 311221 4.88, 331410 5.00, 331110 5.18, 325180 5.24, 331313 5.51, 325110 5.59
2022 311221 5.42, 331410 5.86, 331110 6.02, 325180 6.22

Large industrial contracts don't follow the annual wholesale average, and retail rates lag wholesale. Options, for #902 to decide:

  1. Use the observed price, and hold these buyers' margins at zero by lowering their generation dollars. Simple, but those buyers' generation per kWh then differs.
  2. Use a multi-year average for p_gen. Fewer negatives and steadier margins, but less observed in any one year.
  3. Allow the small negative margins, and name them.

Limits

  • Trading inside the wholesale market: sales for resale counts power traded more than once, and includes marketers. Its volume falls from 3,463 to 2,967 TWh over the span. It's a price measure rather than a measure of generation. Retail marketers' revenue is unusually high in 2021 ($67.5bn against $30-40bn in 2017-20), and I haven't traced why.
  • What the price covers: some sales for resale are bundled with transmission, so this may run slightly above pure generation.
  • Basis: this is per kWh generated. Buyer prices in feat(nowcast): annual electricity price by manufacturing industry from MECS and EIA #1219 are per kWh delivered.

Checks

Unit tests are synthetic and need no data. black, ruff and mypy are clean on these files. The real-data results above came from a local run. The suite is left to CI.

🤖 Generated with Claude Code

#1215)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant