Skip to content

Deduplicate rates by tariff_rate_id in tariff_iter_rates_for_dt #52

Open

Description

@alexhyunminlee

What

tariff_iter_rates_for_dt yields the same rate twice when Arcadia inlines a rider rate into the parent tariff. The parent tariff contains both (a) a direct rate entry with populated rate_bands and (b) a separate rider-pointer entry (rider_id set, rate_bands empty) whose resolved rider tariff contains the exact same rate (same tariff_rate_id). The iterator yields both without deduplication, causing the charge to be counted twice in the URDB output.

Why

This produces incorrect URDB tariffs. For example, BGE's Universal Service Charge (tariff_rate_id=18603035, $0.32/month) is yielded once from the inline entry and once from rider 669, producing a total of $0.64/month. The Maryland OPC confirms the actual charge is a single fixed fee (currently ~$0.36/month). The bug affects both fixed charges and consumption-based energy rates for any utility where Arcadia inlines rider rates into the parent tariff.

Known affected tariffs (Maryland):

BGE (masterTariffId=674): Universal Service Charge counted twice → fixed charge overstated by $0.32/month
Pepco (masterTariffId=832): Electric Universal Service surcharge counted twice → fixed charge overstated by ~$0.05/month
DPL (masterTariffId=2639): Renewable Portfolio Credit counted twice → fixed charge understated by ~$0.06/month (credit applied twice)
Hagerstown (masterTariffId=3240941): Universal Service Program Charge counted twice in energy rates

How

Add tariff_rate_id deduplication to tariff_iter_rates_for_dt. Pass a seen set through the recursive rider traversal and skip any rate whose tariff_rate_id has already been yielded:

def tariff_iter_rates_for_dt(tariff, scenario, library, dt, _seen=None):
    if _seen is None:
        _seen = set()
    rates = tariff.get("rates", [])
    for rate in rates:
        if not rate_is_applied_to_scenario(rate, scenario, library):
            continue
        if not rate_is_applied_to_datetime(rate, dt):
            continue
        if rate["rate_bands"]:
            rate_id = rate["tariff_rate_id"]
            if rate_id in _seen:
                continue
            _seen.add(rate_id)
            yield rate
        elif rider_id := rate.get("rider_id"):
            rider_tariff = library.tariffs.get_tariff(rider_id)
            yield from tariff_iter_rates_for_dt(rider_tariff, scenario, library, dt, _seen)

The _seen parameter defaults to None so the public API signature is unchanged.

Deliverables

tariff_iter_rates_for_dt deduplicates by tariff_rate_id so that the same physical rate is never yielded more than once per call.
Test case: BGE (masterTariffId=674) fixed charge resolves to ~$9.97 (not $10.29) with charge_classes={DISTRIBUTION, TRANSMISSION, OTHER} and competitiveBilling=False.

Activity

  1. linear commented on Jul 8, 2026

    @linear
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions