Package: ts-tariffs
Tariff calculation for time series consumption data.MotivationCalculating tariffs is a common task for technoeconomic modelling, particularly in industries like energy and water.The ts-tariffs library aims to provide convenient, easy-to-use tools for dealing with tariffs in modelling projects.The goal of this library is to expand its coverage of tariff structures as widely as possible, and where coverage is not provided, to act as a stable, extensible toolbase for the creation of bespoke tariff modelsWhile coverage of tariff types will increase over time, the scope of this library will remain narrow to ensure maintanability.Installationpip install ts-tariffsCoveragets-tariffs can presently deal with common tariffs (so far all derived from electricity billing, but some are applicable more broadly):Connection chargesSingle rate chargesTime of use chargesDemand charges, including those which are specify time of useBlock chargesCapacity chargesSoon to come:Critical peak chargesCoverage will continue to be expanded - feature pull requests are encouraged for all timeseries tariff typesHow toCreate TariffsTariffs can be instantiated by individually specifying parameters:fromts_tariffs.tariffsimport(SingleRateTariff,ConnectionTariff,TouTariff,DemandTariff,BlockTariff,CapacityTariff,)fromts_tariffs.ts_utilsimportSampleRatesingle_rate_tariff=SingleRateTariff(name='single_rate_tariff',charge_type="SingleRateTariff",rate=0.07,consumption_unit='kWh',rate_unit='dollars / kWh',sample_rate=SampleRate(multiplier=30,base_freq='minutes'),adjustment_factor=1.05)Or can be easily instantiated given a dict of appropriate structure:single_rate_dict={"name":"single_rate_tariff","charge_type":"SingleRateTariff","rate":0.07,"consumption_unit":"kWh","sample_rate":{"multiplier":30,"base_freq":"minutes"},"rate_unit":"dollars / kWh","adjustment_factor":1.005}tou_tariff_dict={"name":"retail_tou","charge_type":"TouTariff","consumption_unit":"kWh","sample_rate":{"multiplier":30,"base_freq":"minutes"},"rate_unit":"dollars / kWh","adjustment_factor":1.005,"tou":{"time_bins":[7,21,24],"bin_rates":[0.06,0.10,0.06],"bin_labels":["off-peak","peak","off-peak"]},}connection_tariff_dict={"name":"connection_tariff","charge_type":"ConnectionTariff","rate":315.0,"consumption_unit":"day","frequency_applied":"day","sample_rate":{"multiplier":30,"base_freq":"minutes"},"rate_unit":"dollars / day","adjustment_factor":1.0}single_rate_tariff=SingleRateTariff.from_dict(single_rate_dict)tou_tariff=TouTariff.from_dict(tou_tariff_dict)connection_tariff=ConnectionTariff.from_dict(connection_tariff_dict)Create consumption meter dataThe ts-tariffs library provides aMeterDataobject for handling timeseries consumption data. It accepts apd.Serieswith adatetimeindex as a representation of consumtion.The sample rate must be specified manually with atimedeltaorSampleRateobject (in future versions this may end up being inferred from the series index, but there are presently issues with this approach).Consumption units must also be specified such that they are coherent with the tariffs that are applied to them (this is particularly important forMetersobjects in which multiple tariffs can be bundled together with multi-channel meters - discussed later)Themeter_data_dfbelow is apd.DataFrameobject with a datetime index at 30min frequency, and a consumption column called'energy'. AMeterDataobject is then created as follows:fromts_tariffs.metersimportMeterDatafromts_tariffs.examples.data_gettersimporthoushold_consumption# Get consumption timeseries at 30min sample ratemeter_data_df=houshold_consumption(30,'minute')sample_rate=SampleRate(multiplier=30,base_freq='minutes')# Alternatively you could use timedelta(minutes=30) heremy_meter_data=MeterData(name='energy',tseries=meter_data_df['energy'],sample_rate=sample_rate,units='kWh')Calculate billsYou can calculate the cost of energy tariffs to meter data by calling theTariff.apply() method*. This returns anAppliedChargeobject which contains the total sum of charges, as well as other data/metadata, depending on the tariff type*Note: Presently theTariff.sample_ratemust be in agreement withMeterData.sample_rate. Future versions may automatically resample, assuming the resample rule (e.g.mean()orsum()) can be inferred from the unitssingle_rate_applied_charge=single_rate_tariff.apply(my_meter_data)ABillobject can be used to tabulate the charge totals for one or more tariffs if given aMeterData. ABillconsists of one or manyAppliedChargeobjects:fromts_tariffs.billingimportBillmy_bill=Bill(name='my_bill',charges=[single_rate_tariff.apply(my_meter_data),tou_tariff.apply(my_meter_data),connection_tariff.apply(my_meter_data),])print(my_bill.as_series)single_rate_tariff      1357.642382
retail_tou              1688.470396
connection_tariff     229635.000000
Name: my_bill, dtype: float64ExamplesCritical Peak Demandfromdatetimeimporttimedeltafromts_tariffs.examples.data_gettersimporthoushold_consumptionfromts_tariffs.metersimportMeterDatafromts_tariffs.tariffsimportCriticalPeakDemandTarifffromts_tariffs.ts_utilsimportDateWindow,DatetimeWindowdata=houshold_consumption(30,'minute')meter=MeterData('household_consumption',data['apparent_power'],timedelta(minutes=30),'kVA')cpd_tariff=CriticalPeakDemandTariff(name='cpd_tariff',charge_type='CriticalPeakDemandTariff',consumption_unit='kVA',rate_unit='dollars /kVA',sample_rate=timedelta(hours=0.5),adjustment_factor=1.0,rate=19.00,frequency_applied='month',period_active=DateWindow(start=(2008,4,1),end=(2009,3,31)),critical_period=DateWindow(start=(2007,12,1),end=(2008,3,1)),critical_peak_windows=[DatetimeWindow(start=(2007,12,12,15),end=(2007,12,12,19)),DatetimeWindow(start=(2008,1,5,15),end=(2008,1,5,19)),DatetimeWindow(start=(2008,1,30,15),end=(2008,1,30,19)),DatetimeWindow(start=(2008,2,24,15),end=(2008,2,24,19)),DatetimeWindow(start=(2008,3,12,15),end=(2008,3,12,19)),])applied_charge=cpd_tariff.apply(meter)print(applied_charge)Outputroot\ariff-module\ts_tariffs\tariffs.py:263: UserWarning: The critical period tariff, cpd_tariff, was not applied to the full period_active window because the consumption MeterData did not cover the full window
AppliedCharge(name='cpd_tariff', charge_ts=year  month
2008  4        51.181886
      5        51.181886
      6        51.181886
      7        51.181886
      8        51.181886
      9        51.181886
      10       51.181886
      11       51.181886
      12       51.181886
Name: charge, dtype: float64, rate_unit='dollars /kVA', consumption_units='kVA', total=460.63697215248004)Note that the AppliedCharge object specifies the charge for each period and the total chargeAlso note that a warning was encountered indicating that the calculation was not applied to the full period_active window because of insufficient consumption data