Skip to main content

PyTariff

PyTariff is a library for the generic representation of electrical tariffs in domain models.

Installation

pip install pytariff

Basic Usage: Defining a Tariff

In the below example, we create a simple time-of-use tariff consisting of a single import charge and a single export charge. The tariff is defined over the time period from the first of January 2023 until the first of January 2024 in UTC.

The import charge is applied at all times of day (because start_time=time(0) and end_time=time(0))), on all days within the tariff definition period without exceptions for holidays. It defines a single charge on the Consumption of energy in kWh in the Import TradeDirection with a value of 20.0 units in Australian dollars over the consumption range from 0 kWh to infinite kWh imported.

The charge is reset every three months (quarterly), starting from the anchor datetime, which is not useful in this example but becomes relevant if the UsageChargeMethod is not identity. Other UsageChargeMethods allow the user to define a tariff which charges on maximum demand in a quarter, for example, reset each quarter. The export charge is similar, but defined in the oposite TradeDirection.

Naturally, many other combinations are possible. Obvious restrictions on tariff construction is achieved by using specific subclasses of the base PyTariff GenericTariff object, such as the TimeofUseTariff shown below, or other classes such as the BlockTariff or MarketTariff, to name a few.

import pytariff as pt
from zoneinfo import ZoneInfo
from datetime import datetime, time


# Define a Time-Of-Use Tariff with import and export charges
import_charge = pt.TariffInterval(
    start_time=time(0),
    end_time=time(0),
    days_applied=pt.DaysApplied(day_types=pt.DayType.ALL_DAYS),
    tzinfo=ZoneInfo("UTC"),
    charge=pt.TariffCharge(
        blocks=(
            pt.TariffBlock(
                rate=pt.TariffRate(currency="AUD", value=20.0),
                from_quantity=0.0,
                to_quantity=float("inf")
            ),
        ),
        unit=pt.TariffUnit(
            metric=pt.Consumption.kWh,
            direction=pt.TradeDirection.Import,
            convention=pt.SignConvention.Passive
        ),
        reset_data=pt.ResetData(
            anchor=datetime(2023, 1, 1, tzinfo=ZoneInfo("UTC")),
            period=pt.ResetPeriod.FIRST_OF_QUARTER
        ),
        method=pt.UsageChargeMethod.identity,
    ),
)

# define the export charge
export_charge = pt.TariffInterval(
    start_time=time(0),
    end_time=time(0),
    days_applied=pt.DaysApplied(day_types=pt.DayType.ALL_DAYS),
    tzinfo=ZoneInfo("UTC"),
    charge=pt.TariffCharge(
        blocks=(
            pt.TariffBlock(
                rate=pt.TariffRate(currency="AUD", value=-1.0),
                from_quantity=0.0,
                to_quantity=float("inf")
            ),
        ),
        unit=pt.TariffUnit(
            metric=pt.Consumption.kWh,
            direction=pt.TradeDirection.Import,
            convention=pt.SignConvention.Passive
        ),
        reset_data=pt.ResetData(
            anchor=datetime(2023, 1, 1, tzinfo=ZoneInfo("UTC")),
            period=pt.ResetPeriod.FIRST_OF_QUARTER
        ),
        method=pt.UsageChargeMethod.identity,
    ),
)

# define the parent time-of-use tariff
tou_tariff = TimeOfUseTariff(
    start=datetime(2023, 1, 1),
    end=datetime(2024, 1, 1),
    tzinfo=ZoneInfo("UTC"),
    children=(import_charge, export_charge),
)

Basic Usage: Applying a Tariff to Metering Data

Now that we have defined a tariff, we are able to investigate how costs are levied against energy usage. Before we begin, we must define metering data for the tariff to be applied towards, and provide a MeterProfileHandler which can be used by PyTariff:

import pandas as pd
import numpy as np
from zoneinfo import ZoneInfo

meter_profile = pd.DataFrame(
    index=pd.date_range(
        start="2022-12-31T00:00:00",
        end="2023-01-04T00:00:00",
        tz=ZoneInfo("UTC"),
        freq="1h",
        inclusive="left",
    ),
    data={"profile": np.tile(np.array([0.0] * 8 + [5.0] * 8 + [-1.0] * 8), 3)},
)

handler = MeterProfileHandler(meter_profile)
cost_df = tou_tariff.apply_to(
    handler,
    tariff_unit=TariffUnit(
        metric=Consumption.kWh,
        convention=SignConvention.Passive
    ),
)

We can call .apply_to with our MeterProfileHandler and a TariffUnit which specifies that the metering data provided has the same units are the TariffCharges to which is it applied, and ensures the SignConvention of the metering data is respected (as either Active or Passive).

The output cost_df contains a breakdown of the costs by TariffCharge and TariffBlock combinations in each of the TradeDirections. It also contains columns which tally the total import_cost, export_cost, and total_cost. This dataframe, and all the cost components, can be easily visualised by passing the results to a TariffCostHandler:

cost_handler = TariffCostHandler(cost_df)
cost_handler.plot(include_additional_cost_components=True)

Example TOU Tariff

Metadata

Release files for pytariff 0.0.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pytariff 0.0.3
File Size Uploaded
pytariff-0.0.3.tar.gz 36.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pytariff 0.0.3
File Interpreter ABI Platform
pytariff-0.0.3-py3-none-any.whl Python 3 none any Details

Total release size: 78.3 kB

Release files / pytariff-0.0.3.tar.gz

Download URL pytariff-0.0.3.tar.gz
Size 36.2 kB
Tags Source
SHA-256 checksum
How to use checksums
11d944f377e6bcc5992a12cc9e873ad1fb4942a077a2155fff614945c23adc0e
BLAKE2b-256 checksum
How to use checksums
7a66d82410e1cf7a44fe03339f7778cbc16b7e7119d3cebb25c2337c1495631a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.12.1

Release files / pytariff-0.0.3-py3-none-any.whl

Download URL pytariff-0.0.3-py3-none-any.whl
Size 42.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8976bd58cf7939ecd464729887fe819884830e70bebed8eb8aa1b1ef63bb417c
BLAKE2b-256 checksum
How to use checksums
a26321adfb2cb22c1d43d1c163e5596811c6c6f448d76e6d4360774519f998a2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.12.1

Release history Release notifications | RSS feed

This release

0.0.3 This release

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page