Add EPMC residual allocation and make allocation method explicit#384
Open
Add EPMC residual allocation and make allocation method explicit#384
Conversation
- Add equi-proportional marginal cost (EPMC) residual allocation to CAIRO via monkey-patches in utils/mid/patches.py. EPMC allocates residual costs in proportion to each customer's economic burden (R_i = R * EB_i / sum(EB_j * w_j)), equivalent to scaling all MC-based rates by K = TRR / MC_Revenue. - Disable broken peak residual allocation to free up compute. - Make build_master_bat.py detect available BAT metrics at runtime instead of hardcoding — gracefully handles missing metrics (logs and skips). - Refactor compute_subclass_rr to compute both per-customer and EPMC subclass RRs in a single pass. Revenue requirement YAML now uses nested format keyed by allocation method (percustomer, epmc). - Add required residual_allocation field to scenario YAML for subclass runs. Parser raises ValueError if field is missing or allocation method not found in the YAML. No defaults — every subclass run must be explicit. - Wire RI runs 17-18 to use EPMC allocation; runs 5-14 explicitly tagged as percustomer. NY runs 5-14 also tagged percustomer. - Migrate all *_hp_vs_nonhp.yaml files (RI + NY) to nested format. Made-with: Cursor
- create_scenario_yamls.py: read run_includes_subclasses directly from the Google Sheet column instead of re-deriving from tariff key count. Add residual_allocation column handling (optional-if-non-empty pattern). - Tests updated: fixture adds run_includes_subclasses column, derivation test replaced with sheet-read test, new test for residual_allocation. Made-with: Cursor
Makes the disabled peak allocator visible in the code for future reference. Made-with: Cursor
…epmc The Justfile recipe and its callers explicitly passed "BAT_percustomer", overriding the Python function's default. This caused the RR YAML to only contain the percustomer block, making run 17 crash with "epmc not found". Made-with: Cursor
The Python CLI default (BAT_percustomer,BAT_epmc) always computes both allocation methods. No reason for the Justfile layer to pass or override it. Made-with: Cursor
- identify_heating_type.py: add postprocess_group.heating_type_v2 with five categories (heat_pump, electrical_resistance, natgas, delivered_fuels, other) alongside the existing heating_type column. - run_scenario.py: include heating_type_v2 in metadata columns so it flows through to CAIRO's customer_metadata.csv. - compute_subclass_rr: compute an informational 5-way breakdown by heating_type_v2 and write it under heating_type_breakdown in the RR YAML. Gracefully skips if the column doesn't exist in metadata. Made-with: Cursor
…tchbox-data/rate-design-platform into add-epmc-residual-allocation
Runs build-master-bills-with-lmi + build-master-bat for all 10 run pairs (1+2 through 19+20) in one command. Usage: just s ri build-all-master <batch> Made-with: Cursor
Runs build-master-bills-with-lmi + build-master-bat for all 8 NY run pairs (1+2 through 15+16) in one command. Usage: just s ny build-all-master <batch> Made-with: Cursor
The run 1/run 2 subtraction architecture produces incorrect supply RRs when EPMC is used, because EB weights differ between runs (HP = 2.67% in delivery-only run vs 4.83% in delivery+supply). This created a phantom $15.9M "supply EPMC residual" that inflated HP total RR by $16M. Fix: restructure the YAML into independent delivery and supply blocks. Each run picks one delivery method and one supply method independently. Delivery methods: passthrough, percustomer, epmc, volumetric Supply methods: passthrough, percustomer, volumetric (Supply EPMC omitted — broken by subtraction; volumetric gives same answer) Supply passthrough = actual supply bills (no BAT adjustment) = same supply rate as default. This is correct for delivery-only rate designs (seasonal, flat HP) where supply shouldn't change. Supply percustomer/volumetric = BAT-adjusted supply (clean subtraction, weights are constant). Correct for TOU runs that address supply cross-sub. Made-with: Cursor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
build_master_bat.pydetect available BAT metrics at runtimeheating_type_v2column (heat_pump, electrical_resistance, natgas, delivered_fuels, other) with informational breakdown in the RR YAMLcreate_scenario_yamls.pyreadsrun_includes_subclasses,residual_allocation_delivery, andresidual_allocation_supplyfrom the Google SheetThe supply subtraction bug (fixed in this PR)
When EPMC was used for both delivery and supply, the supply RR was derived as
total_RR(run 2 EPMC) - delivery_RR(run 1 EPMC). But EPMC weights differ between runs (HP = 2.67% of delivery EB vs 4.83% of combined EB). The subtraction produced a phantom $15.9M supply residual for HP instead of the correct ~$6.4M. The fix: separate delivery and supply into independent YAML blocks with their own allocation methods.New YAML structure
Each scenario run picks independently:
Verification steps after running RI batch
Prerequisites
Update Google Sheet (Runs & Charts):
residual_allocationcolumn withresidual_allocation_deliveryandresidual_allocation_supplypercustomer, supply=passthroughpercustomer, supply=percustomerepmc, supply=passthroughOn server:
git pull, thenjust s ri compute-rev-requirementsVerify YAML structure:
delivery:andsupply:blocksdelivery.epmc.hpshould be ~$14.5Msupply.passthrough.hpshould be ~$21.1M (NOT $31.6M)Delete old run 17-20 S3 outputs, re-run 17-20, rebuild master bills+bat
Verification checks
Expected bill delta chart behavior
The HP flat rate bar should be mostly green (HP flat delivery is a big discount from default). It should be slightly less green than the old per-customer batch because EPMC delivery RR is ~$3M higher. Supply should be neutral (same rate as default).