HomeGuidesAPI ReferenceChangelog
Log In
Guides

Contracted Rates

Learn how to work with contracted rates in deregulated electricity markets where customers can choose their energy supplier separately from transmission and distribution services.

What are Contracted Rates?

Contracted rates are useful when customers are located in deregulated markets that have separate rate structures for energy supply versus transmission and delivery services. The term "contracted rate" refers to any situation where a customer's electricity bill is divided between two providers: one for the energy itself (the "supply rate") and another for the right to use the transmission and distribution system to deliver that energy to their premises (the "transmission and distribution" or "T&D" rate).

Typically, customers in these markets can choose from many different providers for their energy supply, but they have no choice for delivery services. The Arcadia Signal calculation APIs support this situation. The rates for energy supply can be passed into the calculator as separate rate inputs and will be used to replace some or all of the tariff's energy supply components.

Identifying Tariffs with Contracted Rates

How do you know if your customer is on a tariff with contracted rates, and which rates are contractable? You can identify tariffs with contracted rates by using the hasContractedRates parameter when retrieving a list of tariffs. Rates with a chargeClass of CONTRACTED are eligible for replacement by third-party suppliers.

Here's an example of retrieving tariffs with contracted rates in New York City:

GET /rest/public/tariffs/?zipCode=10001&country=US&serviceTypes=ELECTRICITY&customerClasses=GENERAL&tariffTypes=ALTERNATIVE&effectiveOn=2017-11-01&populateRates=true&hasContractedRates=true

Below is a snippet of some contracted rates returned for ConEd's Small General (EL2) tariff:

{  
    "tariffRateId": 17827306,  
    "tariffId": 3282860,  
    "tariffSequenceNumber": 9,  
    "rateGroupName": "Merchant Function Charge",  
    "rateName": "Merchant Function Charge",  
    "fromDateTime": "2017-04-01T00:00:00-04:00",  
    "toDateTime": null,  
    "chargeType": "CONSUMPTION_BASED",  
    "chargeClass": "SUPPLY,CONTRACTED",  
    "chargePeriod": "MONTHLY",  
    "variableRateKey": "2252MerchantFunctionChargeSC2",  
    "rateBands": [  
        {  
            "tariffRateBandId": 11560550,  
            "tariffRateId": 17827306,  
            "rateSequenceNumber": 1,  
            "hasConsumptionLimit": false,  
            "hasDemandLimit": false,  
            "hasPropertyLimit": false,  
            "rateAmount": 0,  
            "rateUnit": "COST_PER_UNIT",  
            "isCredit": false,  
            "prevUpperLimit": null  
        }  
    ]  
},  
{  
    "tariffRateId": 17827307,  
    "tariffId": 3282860,  
    "tariffSequenceNumber": 10,  
    "rateGroupName": "Monthly Adjustment Clause",  
    "rateName": "Monthly Adjustment Clause",  
    "fromDateTime": "2017-04-01T00:00:00-04:00",  
    "toDateTime": null,  
    "chargeType": "CONSUMPTION_BASED",  
    "chargeClass": "DISTRIBUTION",  
    "chargePeriod": "MONTHLY",  
    "variableRateKey": "MonthlyAdjustmentClause2252",  
    "rateBands": [  
        {  
            "tariffRateBandId": 11560551,  
            "tariffRateId": 17827307,  
            "rateSequenceNumber": 1,  
            "hasConsumptionLimit": false,  
            "hasDemandLimit": false,  
            "hasPropertyLimit": false,  
            "rateAmount": 0,  
            "rateUnit": "COST_PER_UNIT",  
            "isCredit": false,  
            "prevUpperLimit": null  
        }  
    ]  
},  
{  
    "tariffRateId": 17827308,  
    "tariffId": 3282860,  
    "tariffSequenceNumber": 11,  
    "rateGroupName": "Ancillary Service Charge",  
    "rateName": "Ancillary Service Charge",  
    "fromDateTime": "2017-04-01T00:00:00-04:00",  
    "toDateTime": null,  
    "chargeType": "CONSUMPTION_BASED",  
    "chargeClass": "SUPPLY,CONTRACTED",  
    "chargePeriod": "MONTHLY",  
    "variableRateKey": "ancillaryServiceCharge",  
    "rateBands": [  
        {  
            "tariffRateBandId": 11560552,  
            "tariffRateId": 17827308,  
            "rateSequenceNumber": 1,  
            "hasConsumptionLimit": false,  
            "hasDemandLimit": false,  
            "hasPropertyLimit": false,  
            "rateAmount": 0,  
            "rateUnit": "COST_PER_UNIT",  
            "isCredit": false,  
            "prevUpperLimit": null  
        }  
    ]  
}

Setting a Contracted Rate on a Calculation

To include contracted rates in your calculation, pass those rates as rate inputs with the chargeClass set to "CONTRACTED". This tells the calculation engine to replace all rates with a charge class of CONTRACTED with the rate provided in the rate input. In this example, we're setting a contracted rate of $0.05/kWh for a calculation.

POST /rest/v1/ondemand/calculate/

Use the following request body:

{  
    "fromDateTime": "2018-04-03T00:00:00-04:00",  
    "toDateTime": "2018-05-02T00:00:00-04:00",  
    "masterTariffId": "122972",  
    "groupBy": "MONTH",  
    "detailLevel": "CHARGE_TYPE_AND_TOU",  
    "billingPeriod": true,  
    "rateInputs": [  
    {  
      "chargeClass": "CONTRACTED",  
      "chargePeriod": "MONTHLY",  
      "chargeType": "CONSUMPTION_BASED",  
      "rateName": "Contracted Rate",  
      "transactionType": "NET",  
      "rateBands": [  
        {  
          "hasPropertyLimit": false,  
          "rateAmount": "0.05",  
          "rateUnit": "COST_PER_UNIT",  
          "hasConsumptionLimit": false,  
          "hasDemandLimit": false  
        }  
      ]  
    }  
  ],  
    "propertyInputs": [  
       {  
            "keyName": "consumption",  
            "fromDateTime": "2018-04-03T00:00:00-04:00",  
            "duration": 900000,  
            "dataSeries": [  
                15.43451690673828,  
                13.85958480834961,  
                10.963741302490234,  
                18.40724182128906,  
                14.999061584472656,  
... // edited for length  
                18.467796325683594,  
                14.12566375732422,  
                12.47233581542969,  
                11.939910888671875,  
                10.56745147705078,  
                15.05100631713867,  
                9.197296142578125  
            ],  
            "unit": "kWh"  
        }  
    ]  
}

The key element here is the rateInputs section where you can pass in one or more contracted rates. Let's break down the request:

  • Since we're making an account update, we need to supply our providerAccountId (or, if you prefer, the Arcadia-generated accountId).
  • Even though we're setting a special rate for the customer's supply, they still have to pay the Transmission and Distribution (T&D) costs to deliver the energy to their home. This customer is residential in Pennsylvania, so they're on the "PD" tariff in PECO territory, which has a masterTariffId of 122972.
  • We want to replace all of this customer's kWh charges with our special $0.05 per kWh rate. To do that, we specify in our contracted rate that it only applies to a chargeType of CONSUMPTION_BASED, which means it applies only to the customer's energy consumption. There are many other charge types, including FIXED_PRICE (like service charges), DEMAND_BASED (kW charges), or QUANTITY (per meter or per lamp for certain tariffs). You can read more about all the different tariff and tariff rate parameters on the tariff page.
  • We have set transactionType = NET, meaning that if the customer sends kWh to the grid, they will be credited for kWh at the same rate they buy kWh. You also have the option to indicate that the customer gets no compensation (transactionType=BUY) when sending kWh to the grid.

Block and Index Rates

In the previous section, we saw a simple example of a contracted rate. In that example, we replaced the customer's normal supply rate with a custom rate of $0.05 per kWh. However, in deregulated markets, there are many different variations on contracted rate structures that are much more complicated. One example of a more complex rate structure is known as a "block and index" rate.

A block and index rate has two components: a fixed price for the first portion of the customer's monthly energy usage, and then a variable rate tied to some index price for the remainder. The advantage of this structure is that you usually get a fixed, low rate for most of your energy usage. The downside is that if you don't use enough energy to consume your entire block allocation, you still have to pay for it. In this next example, we'll see how to set this up using a contracted rate.

Here are the details of the block and index rate that we're going to set up for our account:

  • For the first 2,000 kWh of hourly usage, set a flat rate of $0.05 per kWh
  • For the next 600 kWh of hourly usage, the flat rate increases to $0.06 per kWh
  • After that, index the rate to PJM's hourly real-time price

The calculator request is more complicated for block and index contracted rates. Below is the snippet that should be passed into the rateInputs section:

{  
  "rateInputs": [  
    {  
      "rateName": "Multiple Block and Index Rate",  
      "tariffBookRateName": "Multiple Block and Index Rate",  
      "chargeClass": "CONTRACTED",  
      "chargeType": "CONSUMPTION_BASED",  
      "chargePeriod": "HOURLY",  
      "transactionType": "BUY",  
      "variableRateKey": "hourlyPricingRealTimePJM",  
      "variableRateSubKey": "51291",  
      "rateBands": [  
        {  
          "hasConsumptionLimit": true,  
          "consumptionUpperLimit": 2000,  
          "rateAmount": "0.05",  
          "rateUnit": "BLOCK",  
          "isCredit": false  
        },  
        {  
          "hasConsumptionLimit": true,  
          "consumptionUpperLimit": 2600,  
          "rateAmount": "0.06",  
          "rateUnit": "BLOCK",  
          "isCredit": false  
        },  
        {  
          "hasConsumptionLimit": true,  
          "rateAmount": null,  
          "rateUnit": "COST_PER_UNIT",  
          "isCredit": false  
        }  
      ]  
    }  
  ]  
}

You'll notice several similarities to the previous example, but also many new fields and parameters. Let's examine them. First, there are several new tariff properties:

  • "chargePeriod":"HOURLY" tells the API that for the block portions of the tariff, the consumption limits are defined hourly, and once we get to the index portion of the tariff, we're going to update their rate hourly.
  • "transactionType":"BUY" means that we're going to charge the customer for this energy. This is opposed to the "SELL" option, which would result in a credit.
  • "variableRateKey":"hourlyPricingRealTimePJM" specifies the particular index that we're going to use for buying energy. In this case, it's PJM. See below for information on how to get a different index.
  • "variableRateSubKey":"51291" - Within PJM's market, there are numerous delivery points. Here, we're specifying the AECO delivery point, which has the identifier 51291. See below for information on how to get a different delivery point.

Second, our rateBands are more complex than before. This makes sense since we have two tiers and an index in this rate instead of a single flat rate for all energy usage. We'll go through them one at a time:

  • "consumptionUpperLimit":2000 (and the subsequent one with a value of 2600) specifies that this block applies only to the first 2,000 kWh of energy usage for each hour in the billing period. Note that our second block has a consumptionUpperLimit value of 2,600 even though it only represents 600 kWh of usage. This is because the consumptionUpperLimit parameter refers to total consumption, not incremental consumption. For example, if you had three blocks of 300 kWh, 200 kWh, and 200 kWh, you would specify their consumptionUpperLimit values as 300, 500, and 700, respectively.
  • "rateUnit":"BLOCK" tells the API that this portion of the bill is fixed. Even if the customer doesn't use all 2,600 kWh that they've been allocated (2,000 + 600), they still have to pay for the entire block.
  • The final rate band doesn't have a rateAmount property, but it does have a different rateUnit: COST_PER_UNIT. This combination of properties indicates that once the customer has used up their entire allotment of fixed-price energy for the month, we fall back on the index that we defined earlier—PJM real-time pricing at the AECO delivery point—for the rest of their energy usage during that billing period.

With that, we've defined our block and index rate.

Getting More Indexes

We define the index using the variableRateKey. In the example above, we used hourlyPricingRealTimePJM and then defined a variableRateSubKey to specify the appropriate delivery point. The combination of these two elements—the index and the delivery point—determines exactly how much this customer will pay for their energy.

The Arcadia API has more indexes and more delivery points than just these. In fact, at the time of writing this How-To, we had 13 of them, and we add more all the time. To see them all, you can use the following request:

GET /rest/public/properties/?keySpace=market

This will return a list of all indexes in our database.

Delivery Points

Some, though not all, market indexes have different prices for different delivery points. The one that we used in this example, hourlyPricingRealTimePJM, has 20. To specify your delivery point, you'll need to add the variableRateSubKey property in addition to the variableRateKey that we already added. How do you know what to put there? Just use the following request, replacing hourlyPricingRealTimePJM with the particular index that you're interested in:

GET /rest/public/properties/hourlyPricingRealTimePJM/

This will return a list of all available variableRateSubKey values for this index. The list looks like this:

{  
  "status": "success",  
  "count": 1,  
  "type": "PropertyKey",  
  "results": [  
    {  
      "keyName": "hourlyPricingRealTimePJM",  
      "displayName": "Hourly Pricing Real Time PJM",  
      "family": "pjm",  
      "keyspace": "market",  
      "description": "Hourly Pricing Real Time PJM",  
      "dataType": "LOOKUP",  
      "choices": [  
        {  
          "displayValue": "AECO",  
          "value": "51291",  
          "dataValue": "51291",  
          "likelihood": null  
        },
        /* edited for length */
        {
          "displayValue": "RECO",
          "value": "7633629",
          "dataValue": "7633629",
          "likelihood": null
        }
      ]
    }
  ]
}

To specify your delivery point, use the dataValue field of that delivery point in the list of choices for the value of your variableRateSubKey property.

Block and Index Rates with Time of Use

Another flavor of third-party supply contracts are block and index rates with time-of-use pricing. These contracts behave like generic block and index rates but with separate prices and block sizes for each time-of-use definition (e.g., Summer On-Peak).

The key when creating time-of-use block and index rates is to ensure that all time-of-use definitions are included.

WARNING: Make sure that you create a rate for all time-of-use definitions in the time-of-use group. If you do not, there will be hours when your customer will not be charged. To get a list of all the time-of-use definitions in a time-of-use group, you should reference the Time of Use API endpoint.

The time-of-use definitions you use for your contracted rates do not have to match the time-of-use definition used by the utility's tariff.

Here's a sample call where there are two on-peak blocks and one off-peak block, in both Summer and Winter. For this, we set up four rates:

Summer On-Peak

  • $0.05/kWh up to 10 kWh
  • $0.06/kWh up to 20 kWh
  • Index price above 20 kWh

Winter On-Peak

  • $0.045/kWh up to 10 kWh
  • $0.055/kWh up to 20 kWh
  • Index price above 20 kWh

Summer Off-Peak

  • $0.05/kWh up to 10 kWh
  • Index price above 10 kWh

Winter Off-Peak

  • $0.04/kWh up to 10 kWh
  • Index price above 10 kWh

Below is the rateInputs snippet of the on-demand calculation request (not the full request):

{  
  "rateInputs": [{  
      "rateName": "Summer On-Peak Block and Index Rate",  
      "tariffBookRateName": "Summer On-Peak Block and Index Rate",  
      "chargeClass": "CONTRACTED",  
      "chargePeriod": "HOURLY",  
      "transactionType": "BUY",  
      "variableRateKey": "hourlyPricingRealTimePJM",  
      "variableRateSubKey": "51291",  
      "timeOfUse": {  
          "touId": 628  
      },  
      "rateBands": [{  
          "hasConsumptionLimit": true,  
          "consumptionUpperLimit": 10,  
          "rateAmount": "0.05",  
          "rateUnit": "BLOCK",  
          "isCredit": false  
      }, {  
          "hasConsumptionLimit": true,  
          "consumptionUpperLimit": 20,  
          "rateAmount": "0.06",  
          "rateUnit": "BLOCK",  
          "isCredit": false  
      }, {  
          "hasConsumptionLimit": true,  
          "rateAmount": null,  
          "rateUnit": "COST_PER_UNIT",  
          "isCredit": false  
      }]  
  }, {  
      "rateName": "Winter On-Peak Block and Index Rate",  
      "tariffBookRateName": "Winter On-Peak Block and Index Rate",  
      "chargeClass":"CONTRACTED",  
      "chargeType": "CONSUMPTION_BASED",  
      "chargePeriod": "HOURLY",  
      "transactionType": "BUY",  
      "variableRateKey": "hourlyPricingRealTimePJM",  
      "variableRateSubKey": "51291",  
      "timeOfUse": {  
          "touId": 629  
      },  
      "rateBands": [{  
          "hasConsumptionLimit": true,  
          "consumptionUpperLimit": 10,  
          "rateAmount": "0.045",  
          "rateUnit": "BLOCK",  
          "isCredit": false  
      }, {  
          "hasConsumptionLimit": true,  
          "consumptionUpperLimit": 20,  
          "rateAmount": "0.055",  
          "rateUnit": "BLOCK",  
          "isCredit": false  
      }, {  
          "hasConsumptionLimit": true,  
          "rateAmount": null,  
          "rateUnit": "COST_PER_UNIT",  
          "isCredit": false  
      }]  
  }, {  
      "rateName": "Summer Off-Peak Block and Index Rate",  
      "tariffBookRateName": "Summer Off-Peak Block and Index Rate",  
      "chargeClass":"CONTRACTED",  
      "chargeType": "CONSUMPTION_BASED",  
      "chargePeriod": "HOURLY",  
      "transactionType": "BUY",  
      "variableRateKey": "hourlyPricingRealTimePJM",  
      "variableRateSubKey": "51291",  
      "timeOfUse": {  
          "touId": 636  
      },  
      "rateBands": [{  
          "hasConsumptionLimit": true,  
          "consumptionUpperLimit": 10,  
          "rateAmount": "0.05",  
          "rateUnit": "BLOCK",  
          "isCredit": false  
      }, {  
          "hasConsumptionLimit": true,  
          "rateAmount": null,  
          "rateUnit": "COST_PER_UNIT",  
          "isCredit": false  
      }]  
  }, {  
      "rateName": "Winter Off-Peak Block and Index Rate",  
      "tariffBookRateName": "Winter Off-Peak Block and Index Rate",  
      "chargeClass":"CONTRACTED",  
      "chargeType": "CONSUMPTION_BASED",  
      "chargePeriod": "HOURLY",  
      "transactionType": "BUY",  
      "variableRateKey": "hourlyPricingRealTimePJM",  
      "variableRateSubKey": "51291",  
      "timeOfUse": {  
          "touId": 637  
      },  
      "rateBands": [{  
          "hasConsumptionLimit": true,  
          "consumptionUpperLimit": 10,  
          "rateAmount": "0.04",  
          "rateUnit": "BLOCK",  
          "isCredit": false  
      }, {  
          "hasConsumptionLimit": true,  
          "rateAmount": null,  
          "rateUnit": "COST_PER_UNIT",  
          "isCredit": false  
      }]  
  }]  
}

Block and Index Rates with Sellback Rates

Some block and index contracts allow customers to sell any unused kWh back to their energy supplier at the index price. This is called a "sellback" provision. In these contracts, the customer pays the block price and receives a credit for any unused kWh at the index price. The same index price will be used for both kWh in excess of the block and crediting unused kWh within the block.

To create a sellback block and index rate, you mirror the rate structure of a standard block and index rate but with a different rate unit: BLOCK_SELL_BACK.

Here's an example (again, just the rateInputs snippet of the full calculator request):

{  
  "rateInputs":[  
      {  
         "rateName":"Sellback Block and Index Rate",  
         "tariffBookRateName":"Sellback Block and Index Rate",  
         "chargeClass":"CONTRACTED",  
         "chargePeriod":"HOURLY",  
         "transactionType":"BUY",  
         "variableRateKey":"hourlyPricingRealTimePJM",  
         "variableRateSubKey":"51291",  
         "rateBands":[  
            {  
               "hasConsumptionLimit":true,  
               "consumptionUpperLimit":2000,  
               "rateAmount":"0.05",  
               "rateUnit":"BLOCK_SELL_BACK",  
               "isCredit":false  
            },  
            {  
               "hasConsumptionLimit":true,  
               "rateAmount":null,  
               "rateUnit":"COST_PER_UNIT",  
               "isCredit":false  
            }  
         ]  
      }  
   ]  
}