Skip to content

feat(nowcast): split electricity bills into generation and a delivery margin by buyer - #1221

Open
WesIngwersen wants to merge 2 commits into
electricity_generation_pricefrom
electricity_delivery_split
Open

WesIngwersen wants to merge 2 commits into
electricity_generation_pricefrom
electricity_delivery_split

Conversation

@WesIngwersen

Copy link
Copy Markdown
Member

Implements the split in #902, which stays open as the plan. Stacked on #1220.

Adds bedrock/transform/eeio/electricity_delivery.py, which splits each buyer's electricity bill into generation and a delivery margin. It also changes generation_price from #1220 to a three-year trailing average. Nothing in the model reads the split yet, so no output changes. The older G/T/D allocator is untouched, because released configs use it. #1217 wires this in.

The method

kWh_i      = bill_i / price_i, scaled so each class's kWh equals EIA's sales
gen_i      = kWh_i x p_gen, and never more than the bill
delivery_i = bill_i - gen_i
  • Generation price: EIA-861 sales for resale, pooled over three years ending in that year.
  • Floor: a buyer still below it has generation held at its bill and no delivery margin, and is flagged floored.
  • Classes: only rail and transit stay in EIA's transportation class. Trucking, warehousing and the rest of NAICS 48-49 move to commercial, because the older mapping put $14bn of bills on 7 TWh.
  • Exports: take EIA Table 2.14 kWh.
  • Electric power's own purchases: aren't end use, so they stay in generation.
  • Line losses: generation less end use and exports, returned separately for Split electric power into 221100 generation and 42ELEC delivery, with emissions and margins #1217 to enter as an input to 42ELEC. Buyer kWh are on EIA's delivered basis, no longer scaled to eGRID.

Why three years, trailing

Manufacturing industries priced below each candidate, on #1219's prices before bills are applied:

2017 2018 2019 2020 2021 2022 2023 2024
Annual 1 1 0 0 6 4 1 0
3-year trailing (used) 2 1 0 0 0 0 2 1
3-year centered 1 1 0 0 3 1 1 not available
5-year trailing 4 3 1 0 0 0 0 0

Centered needs 2025 revenue, which the source doesn't have yet. Trailing also matches why the spike doesn't reach these buyers at once: retail rates lag wholesale.

Results on the real bills, MUT v1.0.0_b17908f

$bn unless stated 2017 2018 2019 2020 2021 2022 2023 2024
Generation price, ¢/kWh 4.59 4.28 4.23 4.14 4.56 5.24 5.76 5.55
Bills 457 476 471 461 497 566 569 589
Generation sold to buyers 171 166 162 154 174 207 224 221
Delivery (42ELEC sales) 275 298 298 296 307 343 332 355
Own purchases 11 12 12 11 16 17 13 12
Line losses, TWh 165 151 166 151 162 157 160 183
Line losses 7.6 6.5 7.0 6.3 7.4 8.3 9.2 10.1
Buyers floored 2 0 0 2 0 0 0 0
  • Floor: only rail and transit, in 2017 and 2020, at most $0.07bn. No manufacturer is floored in any year, because bills run above EIA.
  • Delivered kWh: class kWh match EIA's sales by construction.

By class, 2024:

Bill, ¢/kWh EIA, ¢/kWh Margin, ¢/kWh Delivery, share of bill
Residential 16.70 16.48 11.15 67%
Commercial 15.43 12.75 9.88 64%
Industrial 10.02 8.13 4.48 45%

Inside manufacturing, 2024: margins run from 0.89 ¢/kWh (wet corn milling) and 1.59 (steel) to 8.38 (beverages) and 11.54 (asphalt paving), with a median of 6.27.

Estimated effect on N, 2024

An estimate rather than a built model: generation emissions follow generation dollars, and losses and the non-fuel chain follow delivery dollars, applied through today's L. #1217 replaces it.

Median change, all sectors +4.6%
Median by class industrial +6.9%, commercial +0.5%, rail and transit +1.3%
Sectors above 10% / 20% 41 / 2
Largest moves 331200 steel products +22%, 331410 nonferrous smelting +22%, S00102 -7%
Emissions moved households -79 Mt, commercial -33 Mt, industrial +109 Mt
N of 42ELEC 0.28 kg per dollar
N of generation 6.45 kg per dollar

Limits

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

… margin by buyer (#902)

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