Package: pytariff
PyTariffPyTariff is a library for the generic representation of electrical tariffs in domain models.InstallationpipinstallpytariffBasic Usage: Defining a TariffIn 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 (becausestart_time=time(0)andend_time=time(0))), on all days within the tariff definition period without exceptions for holidays. It defines a single charge on theConsumptionof energy in kWh in theImportTradeDirectionwith 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 theUsageChargeMethodis notidentity. OtherUsageChargeMethods 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 opositeTradeDirection.Naturally, many other combinations are possible. Obvious restrictions on tariff construction is achieved by using specific subclasses of the base PyTariffGenericTariffobject, such as theTimeofUseTariffshown below, or other classes such as theBlockTarifforMarketTariff, to name a few.importpytariffasptfromzoneinfoimportZoneInfofromdatetimeimportdatetime,time# Define a Time-Of-Use Tariff with import and export chargesimport_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 chargeexport_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 tarifftou_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 DataNow 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 aMeterProfileHandlerwhich can be used by PyTariff:importpandasaspdimportnumpyasnpfromzoneinfoimportZoneInfometer_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_towith ourMeterProfileHandlerand aTariffUnitwhich specifies that the metering data provided has the same units are the TariffCharges to which is it applied, and ensures theSignConventionof the metering data is respected (as either Active or Passive).The outputcost_dfcontains a breakdown of the costs byTariffChargeandTariffBlockcombinations in each of theTradeDirections. It also contains columns which tally the totalimport_cost,export_cost, andtotal_cost. This dataframe, and all the cost components, can be easily visualised by passing the results to aTariffCostHandler:cost_handler=TariffCostHandler(cost_df)cost_handler.plot(include_additional_cost_components=True)