diff --git a/docs/providers/arcadia/index.md b/docs/providers/arcadia/index.md new file mode 100644 index 0000000..323f595 --- /dev/null +++ b/docs/providers/arcadia/index.md @@ -0,0 +1,35 @@ +# Arcadia — Signal Tariffs API + +Arcadia's Signal Tariffs API (formerly Genability) provides comprehensive US utility tariff data with detailed rate structures, variable rate lookups, and bill calculation capabilities. + +## Overview + +- **Provider**: Arcadia +- **Product**: Signal Tariffs API +- **Energy Types**: Electricity +- **Coverage**: ~3,000+ US utilities, 100,000+ tariffs +- **Features**: Variable rate lookups, bill calculations, historical versions +- **Authentication**: API key required + +## Data Format + +The Signal API uses a custom JSON objects to represent tariffs, with a complex hierarchical structure. + +- **[Short guide to the Tariff JSON](tariff-json-structure.md)** +- [Official API docs on Tariff JSON](https://docs.arcadia.com/v2022-12-21-Signal/reference/tariff) + +## Key Endpoints + +| Endpoint | Purpose | +|----------|---------| +| `GET /tariffs` | Search and retrieve tariffs | +| `GET /tariffs/{tariffId}` | Get a specific tariff with rates | +| `GET /tariffs/{masterTariffId}/history` | Historical versions | +| `GET /properties/{key}/lookups` | Variable rate values | +| `POST /calculate` | Bill calculations | + + +## Pricing + +Arcadia charges based on API usage. See their [pricing page](https://www.arcadia.com/signal) for current rates. + diff --git a/docs/providers/arcadia/tariff-json-structure.md b/docs/providers/arcadia/tariff-json-structure.md new file mode 100644 index 0000000..44df2f0 --- /dev/null +++ b/docs/providers/arcadia/tariff-json-structure.md @@ -0,0 +1,204 @@ +# Understanding Arcadia Tariff JSON + +> ⚠️ **Disclaimer**: This guide was generated by an LLM (Claude Opus 4.5) based on Arcadia API documentation and tariff data. The content looks reasonable but **has not been verified by domain experts**. Please verify any claims before relying on them for production use. + +This page explains the structure of tariff data returned by the Arcadia Signal API. For complete field definitions, see the [Arcadia Tariff API Reference](https://docs.arcadia.com/v2022-12-21-Signal/reference/tariff). + +## Data Hierarchy + +Tariff data follows a three-level hierarchy: + +``` +Tariff (header) +├── properties[] → Input parameters needed for bill calculations +└── rates[] → Array of TariffRate objects (line items) + └── rateBands[] → Array of TariffRateBand objects (tiers/bands) +``` + +- **Tariff** — The top-level object with metadata about the rate plan (name, utility, customer class, effective dates) +- **TariffRate** — Individual charges like "Customer Charge" or "Summer Rate" — think of these as line items on a bill +- **TariffRateBand** — Tiers within a rate (e.g., first 250 kWh at one price, remaining kWh at another) + +## Key Tariff Fields + +| Field | Description | +|-------|-------------| +| `tariffId` | Unique ID for *this version* of the tariff | +| `masterTariffId` | Persistent ID across all revisions of a tariff | +| `tariffCode` | Utility's shortcode (e.g., "EL1", "E-1") | +| `tariffName` | Official tariff name | +| `lseId` | Load Serving Entity (utility) ID | +| `effectiveDate` | When this version became effective | +| `priorTariffId` | Previous version's `tariffId` | +| `customerClass` | Target segment: RESIDENTIAL, COMMERCIAL, INDUSTRIAL, etc. | +| `customerCount` | Approximate customers on this tariff | + +### `tariffId` vs `masterTariffId` + +Tariff data changes periodically — a residential tariff might update several times per year as rates are adjusted. Each revision gets a new `tariffId`, but they all share the same `masterTariffId`. + +- Use **`masterTariffId`** when tracking a tariff over time or fetching historical versions +- Use **`tariffId`** when you need to reference a specific version + +To get historical versions, use the [Tariff History API](https://docs.arcadia.com/v2022-12-21-Signal/reference/tariff-history). + +### Boolean Flags + +These flags tell you what features a tariff has without parsing all the rates: + +| Flag | What It Tells You | +|------|-------------------| +| `hasTimeOfUseRates` | Rates vary by time of day (peak/off-peak) | +| `hasTieredRates` | Some rates have consumption-based tiers | +| `hasContractedRates` | Includes supply charges (for bundled service) | +| `hasNetMetering` | Net metering is available for solar customers | +| `isActive` | Tariff is currently in effect | + +--- + +## Properties + +The `properties` array defines **input parameters** needed to calculate bills. When you call the Calculate API, you provide values for these properties, and the API uses them to determine which rates apply and compute charges. + +### What Properties Tell You + +Before running any calculations, the properties array reveals: + +- **What inputs you need** — `consumption` (kWh), `demand` (kW), time-of-use period, etc. +- **What choices exist** — Territory/zone options, service types, rate schedules +- **Default assumptions** — What values are assumed if you don't specify (e.g., `systemSize: 0` assumes no solar) +- **Tariff complexity** — More properties usually means more rate variations + +### Common Property Types + +| `propertyTypes` | Meaning | +|-----------------|---------| +| `RATE_CRITERIA` | Input that affects which rates apply or how they're calculated | +| `SERVICE_TERMS` | Describes service characteristics (informational, not an input) | + +### Common Properties + +| Property | Description | Typical Use | +|----------|-------------|-------------| +| `consumption` | Energy usage (kWh) | All consumption-based charges | +| `demand` | Peak demand (kW) | Demand charges (commercial tariffs) | +| `territoryId` | Service zone/region | Zone-specific rates | +| `systemSize` | Solar system capacity (kW) | Solar-related charges (CBC, net metering) | +| `connectionType` | Single-phase vs. three-phase | Service charges | +| `chargeClass` | Categories to include | Filtering SUPPLY vs. DISTRIBUTION | + +### Property Structure + +Each property has metadata explaining what it is and how to use it: + +```json +{ + "keyName": "territoryId", + "displayName": "Territory", + "description": "Rate Baseline Region", + "dataType": "CHOICE", + "propertyTypes": "RATE_CRITERIA", + "choices": [ + { "displayValue": "Zone H", "value": "3632" }, + { "displayValue": "Zone I", "value": "3633" }, + { "displayValue": "Zone J", "value": "3634" } + ], + "isDefault": true +} +``` + +- **`keyName`** — The key to use in API calls +- **`dataType`** — DECIMAL, CHOICE, STRING, BOOLEAN, etc. +- **`choices`** — For CHOICE types, the valid options +- **`propertyValue`** / **`isDefault`** — Default value if not specified + +--- + +## Rates + +The `rates` array contains the actual charges. Each `TariffRate` object represents a line item like "Customer Charge" or "Summer Delivery Rate." + +### Key Rate Fields + +| Field | Description | +|-------|-------------| +| `rateName` | Human-readable name | +| `rateGroupName` | Category grouping (e.g., "Delivery Charges") | +| `chargeType` | How it's calculated: FIXED_PRICE, CONSUMPTION_BASED, QUANTITY, MINIMUM | +| `chargeClass` | Category: DISTRIBUTION, SUPPLY, TRANSMISSION, TAX | +| `variableRateKey` | If present, rate value must be looked up via API | +| `territory` | If present, rate is zone-specific | +| `season` | If present, rate is seasonal | +| `rateBands` | Tier structure with actual rate amounts | + +### Charge Types + +| `chargeType` | Meaning | Unit | +|--------------|---------|------| +| `FIXED_PRICE` | Flat monthly fee | $/month | +| `CONSUMPTION_BASED` | Per-kWh charge | $/kWh | +| `QUANTITY` | Based on a property value | Varies ($/kW, %) | +| `DEMAND` | Based on peak demand | $/kW | +| `MINIMUM` | Floor on total bill | $/month | + +### Variable Rates + +Some rates change frequently (monthly supply charges, adjustment factors). These have: + +- `rateAmount: 0.0` — Placeholder value +- `variableRateKey` — Key to use with the [Lookups API](https://docs.arcadia.com/v2022-12-21-Signal/reference/lookups) + +--- + +## Rate Bands + +Each rate has a `rateBands` array containing one or more `TariffRateBand` objects. For simple rates, there's just one band. For tiered rates, there are multiple bands with consumption limits. + +### Key Rate Band Fields + +| Field | Description | +|-------|-------------| +| `rateAmount` | The actual rate value | +| `rateUnit` | COST_PER_UNIT, PERCENTAGE, etc. | +| `consumptionUpperLimit` | For tiered rates, the kWh threshold | +| `rateSequenceNumber` | Order of tiers (1, 2, 3...) | +| `isCredit` | True if this is a credit (negative charge) | + +### Tiered Rate Example + +```json +"rateBands": [ + { + "rateSequenceNumber": 1, + "consumptionUpperLimit": 250.0, + "rateAmount": 0.16107 + }, + { + "rateSequenceNumber": 2, + "rateAmount": 0.18518 + } +] +``` + +This means: First 250 kWh at $0.16107/kWh, remaining kWh at $0.18518/kWh. + +--- + +## Riders + +Riders are modular tariff components that can be attached to multiple base tariffs. They appear in the rates array with special fields: + +- **`riderId`** — Reference to a rider tariff (placeholder, no rate details) +- **`riderTariffId`** — The actual rider implementation (contains rate details) + +For bill calculations, use rates with `riderTariffId` — they have all the charge details already resolved. + +--- + +## Further Reading + +- [Arcadia Tariff API Reference](https://docs.arcadia.com/v2022-12-21-Signal/reference/tariff) — Complete field definitions +- [Lookups API](https://docs.arcadia.com/v2022-12-21-Signal/reference/lookups) — Retrieving variable rate values +- [Calculate API](https://docs.arcadia.com/v2022-12-21-Signal/reference/calculate) — Running bill calculations +- [Tariff History API](https://docs.arcadia.com/v2022-12-21-Signal/reference/tariff-history) — Historical tariff versions + diff --git a/docs/providers/index.md b/docs/providers/index.md new file mode 100644 index 0000000..2948811 --- /dev/null +++ b/docs/providers/index.md @@ -0,0 +1,24 @@ +# Data Providers + +`tariff_fetch` can retrieve tariff data from multiple sources. Each provider has different coverage, data formats, and API conventions. + +## Supported Providers + +| Provider | Product | Energy Types | Coverage | Data Format | +|----------|---------|--------------|----------|-------------| +| [Arcadia](arcadia/index.md) | Signal Tariffs API | Electricity | US utilities, comprehensive | Tariff JSON object | +| [NREL](nrel/index.md) | Utility Rate Database (URDB) | Electricity | US utilities | URDB JSON format | +| [Rate Acuity](rateacuity/index.md) | Web Portal | Electricity, Gas | US utilities | CSV exports | + +## Choosing a Provider + +**NREL Utility Rate Database (URDB)** is free and open but may have less detailed or less frequently updated data. Good for basic rate lookups and open-source projects. + +**Arcadia Signal Tariffs API** is the most comprehensive option for US electricity tariff data. It is paid and includes: + +- Detailed rate structures with tiers, seasons, and TOU periods +- Variable rate lookups via API +- Historical tariff versions + +**Rate Acuity** provides both electricity and gas tariffs through their web portal. It is also paid Useful when you need gas rates or prefer a different data source for validation. + diff --git a/docs/providers/nrel/index.md b/docs/providers/nrel/index.md new file mode 100644 index 0000000..9c4163b --- /dev/null +++ b/docs/providers/nrel/index.md @@ -0,0 +1,43 @@ +# NREL / OpenEI — Utility Rate Database (URDB) + +The Utility Rate Database (URDB) is a free, open dataset of US utility rates maintained by the National Renewable Energy Laboratory (NREL) and hosted on OpenEI. + +## Overview + +- **Provider**: NREL / OpenEI +- **Product**: Utility Rate Database (URDB) +- **Energy Types**: Electricity +- **Coverage**: US utilities (coverage varies) +- **Features**: Free access, open data +- **Authentication**: API key (free registration) + +## Data Format + +URDB outputs data in the an open data standard called URDB JSON. Many NREL tools already accept this standard. + +- **[Short guide to URDB JSON](urdb-json-structure.md)** +- [Official API docs on URDB JSON](https://openei.org/services/doc/rest/util_rates/?version=7) + +## Key Endpoints + +| Endpoint | Purpose | +|----------|---------| +| `GET /utility_rates` | Search and retrieve rates | +| `GET /utility_rates?getpage={label}` | Get a specific rate by ID | +| `GET /utility_rates?ratesforutility={name}` | Get all rates for a utility | +| `GET /utility_rates?lat={lat}&lon={lon}` | Find rates by location | + +## Resources + +- [Browse URDB Rates](https://openei.org/apps/USURDB/) — Interactive rate browser +- [NREL Developer Network](https://developer.nrel.gov/) — API key registration (free) + +## Comparison with Arcadia + +| Aspect | URDB | Arcadia | +|--------|------|---------| +| Cost | Free | Paid | +| Coverage | OK, community-maintained | Comprehensive, professionally maintained | +| Update frequency | Annual | Regular updates | +| Variable rates | Not supported | Lookups API | + diff --git a/docs/providers/nrel/urdb-json-structure.md b/docs/providers/nrel/urdb-json-structure.md new file mode 100644 index 0000000..49e76fa --- /dev/null +++ b/docs/providers/nrel/urdb-json-structure.md @@ -0,0 +1,1097 @@ +# Understanding URDB JSON Structure + +> ⚠️ **Disclaimer**: This guide was generated by an LLM (Claude Opus 4.5) based on URDB API documentation and the model's understanding of rate structures. The content looks reasonable but **has not been verified by domain experts**. Please verify any claims before relying on them for production use. + +This guide walks through the NREL Utility Rate Database (URDB) JSON format using progressively more complex rate structures. By the end, you'll understand how fixed charges, energy charges, and demand charges are represented—and how they combine. + +For the complete API reference, see the [OpenEI URDB API Documentation](https://openei.org/services/doc/rest/util_rates/?version=7). + +--- + +## Core Structure + +Every URDB rate has these common metadata fields: + +```json +{ + "label": "5374efea9bef51471a6965d0", + "utility": "Example Electric Co", + "name": "Residential Standard", + "sector": "Residential", + "description": "Standard residential service", + "source": "https://example.com/tariff.pdf", + "startdate": 1704067200, + "enddate": null +} +``` + +| Field | Description | +|-------|-------------| +| `label` | Unique identifier for this rate | +| `utility` | Utility company name | +| `name` | Rate schedule name | +| `sector` | Customer class: Residential, Commercial, Industrial, Lighting | +| `startdate` / `enddate` | Unix timestamps for when the rate is effective | + +Beyond metadata, a rate can include: + +1. **Fixed charges** — Flat monthly fees regardless of usage +2. **Energy charges** — Per-kWh charges based on consumption +3. **Demand charges** — Per-kW charges based on peak power draw (common for commercial/industrial) +4. **Adjustments** — Fuel cost pass-throughs, distributed generation rules, and other modifiers + +We will walk through each in turn, building intuition via examples. + + +### Rate Tier Properties + +This will make more sense when we get to the examples, but throughout this guide, you'll see tier objects inside rate structures. The available properties depend on the structure type: + +| Property | `energyratestructure` | `flatdemandstructure` | `demandratestructure` | +|----------|:---------------------:|:---------------------:|:---------------------:| +| `rate` | ✓ | ✓ | ✓ | +| `max` | ✓ | ✓ | ✓ | +| `unit` | ✓ | — | — | +| `adj` | ✓ | ✓ | ✓ | +| `sell` | ✓ | — | ✓ | + +- **`rate`** — The rate amount ($/kWh or $/kW) +- **`max`** — Cumulative upper limit for this tier +- **`unit`** — Unit of measurement (energy tiers only; demand uses `flatdemandunit` or `demandrateunit`) +- **`adj`** — Adjustment factor (multiplier applied to rate) +- **`sell`** — Sell-back rate for net metering + +**Example energy tier:** + +```json +{ + "max": 500, + "rate": 0.08, + "unit": "kWh", + "sell": 0.04 +} +``` + +This means: up to 500 kWh at $0.08/kWh, with a sell-back rate of $0.04/kWh for exported solar. + +--- + +## Fixed Charges + +Fixed charges are flat monthly fees that don't depend on how much electricity you use. Typically, they cover the utility's cost of maintaining your connection to the grid. + +### Example: Fixed Charge Only + +The simplest possible rate—just a monthly customer charge with no usage-based fees. + +```json +{ + "label": "fixed_only_example", + "utility": "Simple Electric Co", + "name": "Basic Service", + "sector": "Residential", + + "fixedchargefirstmeter": 15.00, + "fixedchargeunits": "$/month", + + "mincharge": 15.00, + "minchargeunits": "$/month" +} +``` + +| Field | Description | +|-------|-------------| +| `fixedchargefirstmeter` | Monthly fixed charge (customer charge) | +| `fixedchargeunits` | Unit for the fixed charge | +| `mincharge` | Minimum bill amount (floor) | +| `minchargeunits` | Unit for minimum charge | + +#### Bill Calculation + +``` +Fixed charge: $15.00 +────────────────────── +Total: $15.00 +``` + +The `mincharge` field sets a floor on the total bill. If energy + demand charges would result in less than $15, the customer still pays $15. + +--- + +## Energy Charges + +Energy charges are based on how many kilowatt-hours (kWh) you consume. + +> **Note:** "Energy charge" here means "volumetric charge"—it can represent **supply charges** (generation/procurement), **delivery charges** (transmission/distribution), or both bundled together. URDB doesn't distinguish between them; they're all in `energyratestructure`. + +Energy charges can be flat, tiered, seasonal, time-of-use, or any combination. + +### Example 1: Flat Rate + +#### The Concept + +A **flat rate** is the simplest electricity pricing: every kWh costs the same amount, regardless of how much you use or when you use it. This is still quite common across utilities. + +#### URDB JSON + +```json +{ + "label": "flat_example", + "utility": "Simple Electric Co", + "name": "Residential Flat", + "sector": "Residential", + + "fixedchargefirstmeter": 12.00, + "fixedchargeunits": "$/month", + + "energyratestructure": [ + [ + { + "rate": 0.10, + "unit": "kWh" + } + ] + ], + + "energyweekdayschedule": [ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + ], + + "energyweekendschedule": [ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + ] +} +``` + +#### Key Concepts Introduced + +**`energyratestructure`** — The core rate data. It's an array of **periods**, where each period is an array of **tiers** (see [Rate Tier Properties](#rate-tier-properties) for the full list of tier fields): + +``` +energyratestructure[period_index][tier_index] = { rate, unit, max, adj, sell } +``` + +For a flat rate, there's just one period (index 0) with one tier: + +- `rate`: 0.10 ($/kWh) +- `unit`: "kWh" + +**`energyweekdayschedule`** and **`energyweekendschedule`** — These 12×24 arrays map every hour of every month to a period index. Each row is a month (0=January, 11=December), each column is an hour (0=midnight, 23=11pm). + +For a flat rate, every cell is `0`, meaning "use period 0" — the single flat rate. + +#### Bill Calculation + +``` +Monthly bill = $12.00 (fixed) + (500 kWh × $0.10/kWh) = $62.00 +``` + +--- + +### Example 2: Tiered Rate + +#### The Concept + +A **tiered rate** charges different prices based on how much you use. Tiers can be **inclining** (prices increase with usage) or **declining** (prices decrease with usage). Inclining block rates are more common for residential customers—they encourage conservation by making the first kWh cheapest and charging more as usage grows. + +This example shows an inclining tiered rate: + +- First 500 kWh: $0.08/kWh +- Next 500 kWh (501-1000): $0.12/kWh +- Over 1000 kWh: $0.15/kWh + +#### URDB JSON + +```json +{ + "label": "tiered_example", + "utility": "Conservation Electric", + "name": "Residential Tiered", + "sector": "Residential", + + "fixedchargefirstmeter": 15.00, + "fixedchargeunits": "$/month", + + "energyratestructure": [ + [ + { + "max": 500, + "rate": 0.08, + "unit": "kWh" + }, + { + "max": 1000, + "rate": 0.12, + "unit": "kWh" + }, + { + "rate": 0.15, + "unit": "kWh" + } + ] + ], + + "energyweekdayschedule": [ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + ], + + "energyweekendschedule": [ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + ] +} +``` + +#### What Changed + +Recall that `energyratestructure` is an array of periods, where each period is an array of tiers. We still have just **one period** (index 0), but now it contains **three tiers**: + +| Tier | `max` | `rate` | Meaning | +|------|-------|--------|---------| +| 0 | 500 | 0.08 | First 500 kWh at $0.08 | +| 1 | 1000 | 0.12 | Next 500 kWh (501-1000) at $0.12 | +| 2 | _(none)_ | 0.15 | Everything above 1000 kWh at $0.15 | + +The `max` field indicates the **cumulative** upper limit for that tier (see [Rate Tier Properties](#rate-tier-properties)). The final tier has no `max` — it applies to all remaining usage. + +#### Bill Calculation + +For 800 kWh usage: +``` +Tier 1: 500 kWh × $0.08 = $40.00 +Tier 2: 300 kWh × $0.12 = $36.00 +Fixed: $15.00 +───────────────────────────────── +Total: $91.00 +``` + +--- + +### Example 3: Seasonal Rate + +#### The Concept + +A **seasonal rate** has different prices for different times of year. Summer rates are typically higher because peak demand (air conditioning) strains the grid. Winter rates are lower. + +This example has two seasons with flat (non-tiered) rates: + +- **Summer (June-September)**: $0.12/kWh +- **Winter (October-May)**: $0.08/kWh + +#### URDB JSON + +```json +{ + "label": "seasonal_example", + "utility": "Seasonal Electric Co", + "name": "Residential Seasonal", + "sector": "Residential", + + "fixedchargefirstmeter": 15.00, + "fixedchargeunits": "$/month", + + "energyratestructure": [ + [ + { + "rate": 0.08, + "unit": "kWh" + } + ], + [ + { + "rate": 0.12, + "unit": "kWh" + } + ] + ], + + "energyweekdayschedule": [ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + ], + + "energyweekendschedule": [ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + ] +} +``` + +#### What Changed + +Recall that `energyratestructure` is an array of periods, where each period is an array of tiers. We now have **two periods**, each with just **one tier** (no tiering): + +| Period | Season | Rate | +|--------|--------|------| +| 0 | Winter | $0.08/kWh | +| 1 | Summer | $0.12/kWh | + +**The schedules** now vary by month: + +``` +Month index: 0 1 2 3 4 5 6 7 8 9 10 11 +Month: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec +Period: 0 0 0 0 0 1 1 1 1 0 0 0 + ↑───────────↑ + Summer (Jun-Sep) +``` + +Rows 5-8 (June-September) contain all `1`s, pointing to period 1 (Summer rate). The rest contain `0`s for period 0 (Winter rate). + +#### Bill Calculation + +For 700 kWh in July (summer): + +``` +Energy: 700 kWh × $0.12 = $84.00 +Fixed: $15.00 +────────────────────────────────── +Total: $99.00 +``` + +For 700 kWh in January (winter): + +``` +Energy: 700 kWh × $0.08 = $56.00 +Fixed: $15.00 +────────────────────────────────── +Total: $71.00 +``` + +--- + +### Example 4: Time-of-Use Rate + +#### The Concept + +A **time-of-use (TOU)** rate charges different prices depending on the time of day. Peak hours (when demand is highest) cost more than off-peak hours. This incentivizes shifting usage to times when the grid is less stressed. + +This example has two periods year-round (no seasonal variation, no tiers): + +- **Peak**: 2pm-6pm weekdays — $0.20/kWh +- **Off-Peak**: All other times — $0.08/kWh + +#### URDB JSON + +```json +{ + "label": "tou_example", + "utility": "TOU Electric Co", + "name": "Residential TOU", + "sector": "Residential", + + "fixedchargefirstmeter": 15.00, + "fixedchargeunits": "$/month", + + "energyratestructure": [ + [ + { + "rate": 0.08, + "unit": "kWh" + } + ], + [ + { + "rate": 0.20, + "unit": "kWh" + } + ] + ], + + "energyweekdayschedule": [ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0] + ], + + "energyweekendschedule": [ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + ] +} +``` + +#### What Changed + +Recall that `energyratestructure` is an array of periods, where each period is an array of tiers. We have **two periods**, each with **one tier**: + +| Period | TOU | Rate | +|--------|-----|------| +| 0 | Off-Peak | $0.08/kWh | +| 1 | Peak | $0.20/kWh | + +**The schedules** now vary by hour (not month). Every row is identical because there's no seasonal variation: + +``` +Weekday (any month): +Hour: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 +Period: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 + ↑───────────↑ + 2pm-7pm peak (hours 14-18) +``` + +**`energyweekendschedule`** is all `0`s — weekends are always off-peak. + +#### Bill Calculation + +For 700 kWh, with 200 kWh during peak and 500 kWh off-peak: + +``` +Off-Peak: 500 kWh × $0.08 = $40.00 +Peak: 200 kWh × $0.20 = $40.00 +Fixed: $15.00 +────────────────────────────────── +Total: $95.00 +``` + +--- + +### Example 5: Seasonal Tiered Time-of-Use Rate + +#### The Concept + +This final example combines **all three dimensions** we've covered: + +- **Seasons**: Summer vs. Winter (different base rates) +- **Time-of-Use**: Peak vs. Off-Peak (different prices by hour) +- **Tiers**: First 500 kWh vs. over 500 kWh (different prices by consumption) + +| Season | TOU Period | Hours | Tier 1 (≤500) | Tier 2 (>500) | +|--------|------------|-------|---------------|---------------| +| Summer | Peak | 2pm-7pm weekdays | $0.25 | $0.35 | +| Summer | Off-Peak | All other times | $0.10 | $0.15 | +| Winter | Peak | 6am-9am, 5pm-8pm weekdays | $0.15 | $0.20 | +| Winter | Off-Peak | All other times | $0.08 | $0.10 | + +#### URDB JSON + +```json +{ + "label": "seasonal_tiered_tou_example", + "utility": "Modern Electric Co", + "name": "Residential Seasonal TOU", + "sector": "Residential", + + "fixedchargefirstmeter": 20.00, + "fixedchargeunits": "$/month", + + "energyratestructure": [ + [ + { "max": 500, "rate": 0.08, "unit": "kWh" }, + { "rate": 0.10, "unit": "kWh" } + ], + [ + { "max": 500, "rate": 0.15, "unit": "kWh" }, + { "rate": 0.20, "unit": "kWh" } + ], + [ + { "max": 500, "rate": 0.10, "unit": "kWh" }, + { "rate": 0.15, "unit": "kWh" } + ], + [ + { "max": 500, "rate": 0.25, "unit": "kWh" }, + { "rate": 0.35, "unit": "kWh" } + ] + ], + + "energyweekdayschedule": [ + [0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0], + [0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0], + [0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0], + [0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0], + [0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0], + [2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,2,2,2,2,2], + [2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,2,2,2,2,2], + [2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,2,2,2,2,2], + [2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,2,2,2,2,2], + [0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0], + [0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0], + [0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0] + ], + + "energyweekendschedule": [ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2], + [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2], + [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2], + [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + ] +} +``` + +#### What Changed + +This combines everything from the previous examples. Recall that `energyratestructure` is an array of periods, where each period is an array of tiers. We now have **four periods** (2 seasons × 2 TOU periods), each with **two tiers**: + +| Period | Season | TOU | Tier 1 (≤500) | Tier 2 (>500) | +|--------|--------|-----|---------------|---------------| +| 0 | Winter | Off-Peak | $0.08 | $0.10 | +| 1 | Winter | Peak | $0.15 | $0.20 | +| 2 | Summer | Off-Peak | $0.10 | $0.15 | +| 3 | Summer | Peak | $0.25 | $0.35 | + +**`energyweekdayschedule`** varies by both month AND hour: + +``` +Winter weekday (January, row 0): +Hour: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 +Period: 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 + ↑─────↑ ↑─────↑ + 6-9am peak 5-8pm peak + +Summer weekday (July, row 6): +Hour: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 +Period: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 2 2 2 2 2 + ↑───────────↑ + 2-7pm peak (hours 14-18) +``` + +**`energyweekendschedule`** — weekends are always off-peak: + +- Winter weekends: all `0` (Winter Off-Peak) +- Summer weekends: all `2` (Summer Off-Peak) + +#### Reading the Schedule + +To find the rate for a specific hour: + +1. **Is it a weekday or weekend?** → choose weekday or weekend schedule +2. **Determine the month** → row index (0-11) +3. **Determine the hour** → column index (0-23) +4. **Look up the value** → this is the period index +5. **Go to `energyratestructure[period]`** → get the tiers +6. **Apply usage to tiers** → calculate cost + +**Example**: Wednesday, July 15th at 3pm, first 100 kWh of the month: + +1. Wednesday = weekday schedule +2. July = row 6 +3. 3pm = column 15 +4. `energyweekdayschedule[6][15]` = 3 +5. `energyratestructure[3]` = Summer Peak tiers +6. 100 kWh × $0.25 = $25.00 (within tier 1) + +--- + +## Demand Charges + +Demand charges are based on your **peak power draw** (kW), not total consumption (kWh). They're common for commercial and industrial customers because a customer who briefly draws 100 kW requires more grid infrastructure than one who steadily draws 10 kW—even if both use the same total kWh. + +Demand charges use structures parallel to energy charges: + +| Energy Field | Demand Equivalent | Description | +|--------------|-------------------|-------------| +| `energyratestructure` | `flatdemandstructure` | Seasonal/monthly demand tiers | +| `energyratestructure` | `demandratestructure` | TOU demand periods/tiers | +| `energyweekdayschedule` | `demandweekdayschedule` | Maps hours to TOU demand periods | +| `energyweekendschedule` | `demandweekendschedule` | Weekend TOU demand schedule | +| — | `flatdemandmonths` | Maps months to flatdemandstructure periods | + +### Example: Flat Demand Charge + +This example shows a rate with only a fixed charge plus a flat demand charge (no energy charges, no time-of-use variation). This isolates the demand charge structure. + +```json +{ + "label": "flat_demand_example", + "utility": "Commercial Electric Co", + "name": "Demand Only", + "sector": "Commercial", + + "fixedchargefirstmeter": 25.00, + "fixedchargeunits": "$/month", + + "flatdemandunit": "kW", + "flatdemandstructure": [ + [ + { "rate": 8.50 } + ] + ], + + "flatdemandmonths": [0,0,0,0,0,0,0,0,0,0,0,0] +} +``` + +#### Key Fields + +**`flatdemandunit`** — Units for the demand charge: "kW", "hp", "kVA", "kW daily", "hp daily", or "kVA daily". + +**`flatdemandstructure`** — Array of periods containing arrays of [tiers](#rate-tier-properties). Note: tiers here don't have `unit` or `sell`—units come from `flatdemandunit`. + +**`flatdemandmonths`** — Array of 12 integers mapping each month to a period in `flatdemandstructure`. All `0`s means period 0 applies year-round. + +#### Bill Calculation + +For 50 kW peak demand: + +``` +Fixed: $25.00 +Demand: 50 kW × $8.50 = $425.00 +─────────────────────────────── +Total: $450.00 +``` + +--- + +### Example: Time-of-Use Demand Charge + +This example shows demand charges that vary by time of day. Peak demand during expensive hours costs more than peak demand during off-peak hours. No energy charges—just fixed + TOU demand. + +```json +{ + "label": "tou_demand_example", + "utility": "Commercial Electric Co", + "name": "TOU Demand Only", + "sector": "Commercial", + + "fixedchargefirstmeter": 50.00, + "fixedchargeunits": "$/month", + + "demandrateunit": "kW", + "demandratestructure": [ + [{ "rate": 5.00 }], + [{ "rate": 15.00 }] + ], + + "demandweekdayschedule": [ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0] + ], + + "demandweekendschedule": [ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + ] +} +``` + +#### Key Fields + +**`demandrateunit`** — Units for TOU demand: "kW", "hp", "kVA", "kW daily", "hp daily", or "kVA daily". + +**`demandratestructure`** — TOU demand periods (tiers don't have `unit`—it comes from `demandrateunit`): + +| Period | TOU | Rate | +|--------|-----|------| +| 0 | Off-Peak | $5.00/kW | +| 1 | Peak | $15.00/kW | + +**`demandweekdayschedule`** and **`demandweekendschedule`** — Same 12×24 format as energy schedules. Peak demand is measured during hours 14-18 (2pm-6pm) on weekdays. + +#### Bill Calculation + +For 60 kW peak demand during peak hours, 40 kW during off-peak: + +``` +Fixed: $50.00 +Demand (off-peak): 40 kW × $5.00 = $200.00 +Demand (peak): 60 kW × $15.00 = $900.00 +───────────────────────────────────────────── +Total: $1,150.00 +``` + +--- + +### Combining Tiers, Seasons, and TOU with Demand + +Just like energy charges, demand charges can be combined with: + +- **Tiers** — Different $/kW rates based on peak demand level (e.g., first 50 kW at one rate, additional kW at higher rate) +- **Seasons** — Different demand rates for summer vs. winter +- **Time-of-use** — Different demand rates by time of day (as shown above) + +The structure mirrors what we saw in the energy charge examples: + +- `demandratestructure[period][tier]` works like `energyratestructure[period][tier]` +- Use `max` to define tier thresholds (cumulative kW limits) +- Use schedules to map months and hours to periods + +--- + +## Combining Fixed + Energy + Demand + +Rates can combine all three charge types, and the URDB format supports this naturally—you simply include the relevant fields for each: + +| Charge Type | Required Fields | +|-------------|-----------------| +| Fixed | `fixedchargefirstmeter`, `fixedchargeunits` | +| Energy | `energyratestructure`, `energyweekdayschedule`, `energyweekendschedule` | +| Demand (flat/seasonal) | `flatdemandstructure`, `flatdemandmonths` | +| Demand (TOU) | `demandratestructure`, `demandweekdayschedule`, `demandweekendschedule` | + +### Example: Fixed + Energy + Flat Demand + +```json +{ + "label": "combined_example", + "utility": "Commercial Electric Co", + "name": "Small Commercial Standard", + "sector": "Commercial", + + "fixedchargefirstmeter": 25.00, + "fixedchargeunits": "$/month", + + "energyratestructure": [ + [{ "rate": 0.08, "unit": "kWh" }] + ], + + "energyweekdayschedule": [ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + ], + + "energyweekendschedule": [ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + ], + + "flatdemandunit": "kW", + "flatdemandstructure": [ + [{ "rate": 8.50 }] + ], + + "flatdemandmonths": [0,0,0,0,0,0,0,0,0,0,0,0] +} +``` + +#### Bill Calculation + +For 5,000 kWh consumption with 50 kW peak demand: + +``` +Fixed: $25.00 +Energy: 5,000 kWh × $0.08 = $400.00 +Demand: 50 kW × $8.50 = $425.00 +───────────────────────────────────── +Total: $850.00 +``` + +Each charge type uses its own independent set of fields. The bill calculation simply sums them all together. + +--- + +## Adjustments and Riders + +Beyond the core fixed, energy, and demand charges, utility rates often include various adjustments that modify the base charges. + +| Field | Type | Description | +|-------|------|-------------| +| `fueladjustmentsmonthly` | Array of 12 floats | Monthly $/kWh fuel adjustments | +| `dgrules` | String | Distributed generation compensation policy | +| `energyattrs` | Array of objects | Additional energy charge metadata | +| `demandattrs` | Array of objects | Additional demand charge metadata | + +### Fuel Adjustments + +Fuel costs fluctuate with market prices. Rather than constantly revising base rates, utilities apply monthly fuel adjustment charges (or credits) that pass through actual fuel costs. + +```json +{ + "label": "fuel_adj_example", + "utility": "Example Electric Co", + "name": "Residential with Fuel Adjustment", + "sector": "Residential", + + "fixedchargefirstmeter": 12.00, + "fixedchargeunits": "$/month", + + "energyratestructure": [ + [{ "rate": 0.10, "unit": "kWh" }] + ], + + "energyweekdayschedule": [ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + ], + + "energyweekendschedule": [ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + ], + + "fueladjustmentsmonthly": [0.015, 0.012, 0.010, 0.008, 0.005, 0.018, 0.025, 0.028, 0.022, 0.012, 0.010, 0.014] +} +``` + +#### Key Field + +**`fueladjustmentsmonthly`** — Array of 12 values (one per month, January through December) representing $/kWh adjustments added to the base energy rate. + +In this example: + +- January: base rate ($0.10) + fuel adjustment ($0.015) = $0.115/kWh +- August: base rate ($0.10) + fuel adjustment ($0.028) = $0.128/kWh (peak summer fuel costs) + +#### Bill Calculation + +For 600 kWh in August: + +``` +Fixed: $12.00 +Energy: 600 kWh × $0.10 = $60.00 +Fuel adjustment: 600 kWh × $0.028 = $16.80 +────────────────────────────────────────── +Total: $88.80 +``` + +--- + +### Distributed Generation Rules + +For customers with solar panels or other generation, the `dgrules` field specifies how exported energy is compensated. + +| `dgrules` Value | Meaning | +|-----------------|---------| +| `Net Metering` | Exports offset imports 1:1 at retail rate | +| `Net Billing Instantaneous` | Exports credited at sell rate, calculated instantaneously | +| `Net Billing Hourly` | Exports credited at sell rate, calculated hourly | +| `Buy All Sell All` | All generation sold to utility, all consumption purchased | + +When using net billing, the `sell` property in [tier objects](#rate-tier-properties) specifies the export rate: + +```json +{ + "energyratestructure": [ + [ + { + "rate": 0.12, + "unit": "kWh", + "sell": 0.04 + } + ] + ], + "dgrules": "Net Billing" +} +``` + +#### Bill Calculation Examples + +Consider a solar customer who imports 400 kWh from the grid and exports 200 kWh back. Fixed charge is $12/month, retail rate is $0.12/kWh. + +**Net Metering** (`dgrules: "Net Metering"`): + +Exports offset imports 1:1 at the retail rate. You only pay for net consumption. + +``` +Net consumption: 400 kWh imported - 200 kWh exported = 200 kWh +Fixed: $12.00 +Energy: 200 kWh × $0.12 = $24.00 +───────────────────────────────── +Total: $36.00 +``` + +**Net Billing** (`dgrules: "Net Billing Instantaneous"` or `"Net Billing Hourly"`, `sell: 0.04`): + +Imports and exports are tracked separately. Exports earn a credit at the sell rate. + +``` +Fixed: $12.00 +Imports: 400 kWh × $0.12 = $48.00 +Export credit: 200 kWh × $0.04 = -$8.00 +──────────────────────────────────────── +Total: $52.00 +``` + +**Buy All Sell All** (`dgrules: "Buy All Sell All"`): + +All generation is sold to the utility at the sell rate; all consumption is purchased at the retail rate. + +``` +Fixed: $12.00 +Imports: 600 kWh × $0.12 = $72.00 (all consumption) +Export credit: 200 kWh × $0.04 = -$8.00 (all generation) +──────────────────────────────────────────────────────────── +Total: $76.00 +``` + +--- + +### Energy and Demand Attributes + +The `energyattrs` and `demandattrs` fields provide additional metadata about charges: + +```json +{ + "energyattrs": [ + { "label": "Renewable Energy Charge", "value": 0.002 }, + { "label": "Public Benefits Charge", "value": 0.003 } + ], + "demandattrs": [ + { "label": "Facilities Charge", "value": 2.50 } + ] +} +``` + +These are typically informational—they may represent line items that are already baked into the main rate structures, or they may be separate adders. Check the utility's actual tariff document to understand how they apply. + +--- + +--- + +## Comparison with Arcadia + +| Aspect | URDB | Arcadia | +|--------|------|---------| +| **Schedule granularity** | 12×24 arrays (month × hour) | Separate season/TOU objects | +| **Period indexing** | Zero-based integers in schedules | Named periods with date ranges | +| **Tier structure** | `max` is cumulative | `consumptionUpperLimit` is cumulative | +| **Variable rates** | Not supported | `variableRateKey` for lookups | +| **Riders** | Not separated | Explicit `riderId`/`riderTariffId` | + +--- + +## Further Reading + +- [OpenEI URDB API Documentation](https://openei.org/services/doc/rest/util_rates/?version=7) — Complete field reference +- [Browse URDB Rates](https://openei.org/apps/USURDB/) — Interactive rate browser +- [NREL Developer Network](https://developer.nrel.gov/) — API key registration + diff --git a/docs/providers/rateacuity/index.md b/docs/providers/rateacuity/index.md new file mode 100644 index 0000000..a6a8b92 --- /dev/null +++ b/docs/providers/rateacuity/index.md @@ -0,0 +1,37 @@ +# Rate Acuity + +Rate Acuity provides US utility rate data for both electricity and gas through their web portal. + +## Overview + +- **Product**: Web Portal +- **Energy Types**: Electricity, Gas +- **Coverage**: US utilities +- **Data Format**: CSV +- **Authentication**: Account required + +## Data Format + +COMING SOON. + +## Features + +Rate Acuity offers: +- Electricity and gas tariff data (unlike Arcadia/NREL which are electricity-only) +- Web-based interface for browsing rates +- Export functionality for rate data + +## Use Cases + +Rate Acuity is useful when: +- You need gas tariff data (not available in Arcadia or NREL) +- You want a second source to validate electricity rates +- You want a web portal interface for manual lookups + +## Resources + +- [Rate Acuity Website](https://www.rateacuity.com/) + +## Contributing + +If you'd like to help implement Rate Acuity support, see the [contributing guide](../../wiki/index.md#contributing). diff --git a/mkdocs.yml b/mkdocs.yml index f14736e..7639cb8 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -7,6 +7,15 @@ repo_name: switchbox-data/tariff_fetch nav: - Home: index.md - API Reference: modules.md + - Data Providers: + - providers/index.md + - Arcadia (Genability): + - providers/arcadia/index.md + - Tariff JSON Structure: providers/arcadia/tariff-json-structure.md + - NREL / OpenEI: + - providers/nrel/index.md + - URDB JSON Structure: providers/nrel/urdb-json-structure.md + - Rate Acuity: providers/rateacuity/index.md - Tariff Wiki: - wiki/index.md - Utilities: