TOU Pricing and Storage

In [91]:
%reset
In [1]:
import pandas as pd
import numpy as np
from bs4 import BeautifulSoup as bs
import TOU_pricing
#reload(TOU_pricing)

References

Setting up Variables

In [2]:
inverter_controller_cost = 500. # ballpark

storage_cost_perkWh = 200./1.2 # cost per kilowatt-hour based on link above

cost_per_kWh = .12
cost_per_kWh_red = .08
cost_diff_kWh = cost_per_kWh - cost_per_kWh_red

storage_size_kWh = 6.*1.  # storage size in Watt-hours, starting point 6 hours at 1.5 kW

P_max_charge = 12 * 20 / 1000. # maximum charge rate 12 V * 20 A = .24 kW

initial_investment = inverter_controller_cost + storage_cost_perkWh * storage_size_kWh

Demand Data

Need to parse the xml file of the Green Button data.

In [3]:
xml_file = 'raw_data/Inland_Single_Family_Jan_1_2011_to_Jan_1_2012_RetailCustomer_9.xml'
soup = bs(open(xml_file))
In [4]:
# initiate a numpy array to store values
data_array = np.zeros((len(soup.find_all('value')),1))
In [5]:
# In the Green Button schema, the IntervalReading tag designates each reading
# Each IntervalReading has a 'time' element with start and duration children
# 'Value' element is actual hourly usage in Watt-hours

for i, intervalreading in enumerate(soup.find_all('intervalreading')):
    data_array[i,0]=intervalreading.value.get_text()
In [6]:
# Convert the array into a Pandas DataFrame for ease of time series use

data_start = '1/1/2011 08:00:00'
demand_data = pd.DataFrame(data_array*.001,columns=['USAGE'],index=pd.date_range(data_start, periods=len(soup.find_all('value')), freq='H'))
#demand_data.to_csv('raw_data/Green_Button_Sample_Inland_SingleFamily.csv')
In [7]:
# Plot
fig = plt.figure(figsize=[12,4])
plot1 = demand_data['USAGE'].resample('d',how=sum).plot(grid='off',linewidth=2)
ylabel('Daily Total Usage (kWh)')
title('Green Button Sample Hourly Data, Resampled to Daily \n "Inland Single Family Residence"')
fig.savefig('plots/Green_Button_Sample_Inland_Single_Family_Daily.png')
In [8]:
fig = plt.figure(figsize=[12,4])
plot1 = demand_data['USAGE'].plot(grid='off',linewidth=0.25)
ylabel('Hourly Usage (kWh)')
Out[8]:
<matplotlib.text.Text at 0xa6436d0>

BGE Residential Pricing Plans

BGE offers three residential pricing plans: R, RL, and EV. R is the basic residential (one electricity price). RL is a TOU option. EV is a more aggressive TOU option for residences that need to charge electric vehicles at night. See References section above.

In [9]:
hourly_state = TOU_pricing.BGE_elec_cost(demand_data)
In [10]:
fig = plt.figure(figsize=[8,4])
plot_start = '20-jun-2011'
plot_end = '20-jun-2011'
plot3 = hourly_state['BGE-EV_cost_perkWh'].ix[plot_start:plot_end].plot(color='green',grid='off',marker='o')
plot1 = hourly_state['BGE-RL_cost_perkWh'].ix[plot_start:plot_end].plot(color='blue',marker='o')
plot2 = hourly_state['BGE-R_cost_perkWh'].ix[plot_start:plot_end].plot(color='red',grid='off',marker='o')
ylabel('Cost of Elec. ($/kWh)')
xlabel('Hour of Day')
title('BGE Residential Pricing Plans, Weekday \n June 1 - September 30')
legend(['EV','RL','R'],loc='upper left')
ylim([0,.2])

#fig.savefig('plots/BGE_Pricing_Summer.png')
Out[10]:
(0, 0.2)
In [11]:
fig = plt.figure(figsize=[8,4])
plot_start = '22-nov-2011'
plot_end = '22-nov-2011'
plot3 = hourly_state['BGE-EV_cost_perkWh'].ix[plot_start:plot_end].plot(color='green',grid='off',marker='o')
plot1 = hourly_state['BGE-RL_cost_perkWh'].ix[plot_start:plot_end].plot(color='blue',marker='o')
plot2 = hourly_state['BGE-R_cost_perkWh'].ix[plot_start:plot_end].plot(color='red',grid='off',marker='o')
ylabel('Cost of Elec. ($/kWh)')
xlabel('Hour of Day')
title('BGE Residential Pricing Plans, Weekday \n October 1 - May 31')
legend(['EV','RL','R'],loc='upper left')
ylim([0,.2])
#fig.savefig('plots/BGE_Pricing_Non-Summer.png')
Out[11]:
(0, 0.2)

Logic

In [46]:
hourly_state['storage_available'] = ones(len(hourly_state['USAGE'])) # kWh
hourly_state['purchase'] = zeros(len(hourly_state['USAGE'])) # kWh
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-46-8b1aa0155d75> in <module>()
----> 1 hourly_state['storage_available'] = ones(len(hourly_state['USAGE'])) # kWh
      2 hourly_state['purchase'] = zeros(len(hourly_state['USAGE'])) # kWh
      3 

NameError: name 'ones' is not defined
In [70]:
for i, value in enumerate(hourly_state['USAGE']):
    if hourly_state['USAGE'][i] > hourly_state['storage_available'][i]:
        hourly_state['purchase'][i] = hourly_state['USAGE'][i] - hourly_state['storage_available'][i]
        
        
In [100]:
#del hourly_state
reload(TOU_pricing)
hourly_state = TOU_pricing.period(demand_data)
hourly_state[40:80]
#demand_data[40:80]
Out[100]:
USAGE BGE-RL BGE-EV
2011-01-03 00:00:00 1.090 offpeak offpeak
2011-01-03 01:00:00 1.405 offpeak offpeak
2011-01-03 02:00:00 1.500 offpeak offpeak
2011-01-03 03:00:00 1.404 offpeak offpeak
2011-01-03 04:00:00 1.314 offpeak offpeak
2011-01-03 05:00:00 1.247 offpeak offpeak
2011-01-03 06:00:00 1.089 offpeak offpeak
2011-01-03 07:00:00 0.924 peak peak
2011-01-03 08:00:00 0.808 peak peak
2011-01-03 09:00:00 0.748 peak peak
2011-01-03 10:00:00 0.714 peak peak
2011-01-03 11:00:00 0.690 int offpeak
2011-01-03 12:00:00 0.711 int offpeak
2011-01-03 13:00:00 0.829 int offpeak
2011-01-03 14:00:00 0.964 int offpeak
2011-01-03 15:00:00 0.962 int offpeak
2011-01-03 16:00:00 1.050 int offpeak
2011-01-03 17:00:00 1.096 peak offpeak
2011-01-03 18:00:00 1.111 peak offpeak
2011-01-03 19:00:00 1.127 peak offpeak
2011-01-03 20:00:00 1.165 peak offpeak
2011-01-03 21:00:00 1.055 offpeak offpeak
2011-01-03 22:00:00 1.007 offpeak offpeak
2011-01-03 23:00:00 0.982 offpeak offpeak
2011-01-04 00:00:00 1.057 offpeak offpeak
2011-01-04 01:00:00 1.399 offpeak offpeak
2011-01-04 02:00:00 1.532 offpeak offpeak
2011-01-04 03:00:00 1.444 offpeak offpeak
2011-01-04 04:00:00 1.445 offpeak offpeak
2011-01-04 05:00:00 1.275 offpeak offpeak
2011-01-04 06:00:00 1.040 offpeak offpeak
2011-01-04 07:00:00 0.843 peak peak
2011-01-04 08:00:00 0.706 peak peak
2011-01-04 09:00:00 0.663 peak peak
2011-01-04 10:00:00 0.664 peak peak
2011-01-04 11:00:00 0.666 int offpeak
2011-01-04 12:00:00 0.726 int offpeak
2011-01-04 13:00:00 0.871 int offpeak
2011-01-04 14:00:00 0.999 int offpeak
2011-01-04 15:00:00 1.059 int offpeak
In [37]:
reload(TOU_pricing)
b = TOU_pricing.period(demand_data)

stupid = '2011-01-21'
print b.ix[stupid].index.weekday
b.ix[stupid]
[4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4]
Out[37]:
USAGE BGE-EV BGE-RL BGE-R_cost_perkWh BGE-RL_cost_perkWh BGE-EV_cost_perkWh
2011-01-21 00:00:00 0.997 offpeak offpeak 0.08616 0.06974 0.05209
2011-01-21 01:00:00 1.261 offpeak offpeak 0.08616 0.06974 0.05209
2011-01-21 02:00:00 1.429 offpeak offpeak 0.08616 0.06974 0.05209
2011-01-21 03:00:00 1.343 offpeak offpeak 0.08616 0.06974 0.05209
2011-01-21 04:00:00 1.300 offpeak offpeak 0.08616 0.06974 0.05209
2011-01-21 05:00:00 1.168 offpeak offpeak 0.08616 0.06974 0.05209
2011-01-21 06:00:00 0.980 offpeak offpeak 0.08616 0.06974 0.05209
2011-01-21 07:00:00 0.784 peak peak 0.08616 0.11924 0.18266
2011-01-21 08:00:00 0.669 peak peak 0.08616 0.11924 0.18266
2011-01-21 09:00:00 0.626 peak peak 0.08616 0.11924 0.18266
2011-01-21 10:00:00 0.628 peak peak 0.08616 0.11924 0.18266
2011-01-21 11:00:00 0.626 offpeak int 0.08616 0.08468 0.05209
2011-01-21 12:00:00 0.678 offpeak int 0.08616 0.08468 0.05209
2011-01-21 13:00:00 0.862 offpeak int 0.08616 0.08468 0.05209
2011-01-21 14:00:00 0.993 offpeak int 0.08616 0.08468 0.05209
2011-01-21 15:00:00 1.047 offpeak int 0.08616 0.08468 0.05209
2011-01-21 16:00:00 0.959 offpeak int 0.08616 0.08468 0.05209
2011-01-21 17:00:00 0.911 peak peak 0.08616 0.11924 0.18266
2011-01-21 18:00:00 0.914 peak peak 0.08616 0.11924 0.18266
2011-01-21 19:00:00 0.932 peak peak 0.08616 0.11924 0.18266
2011-01-21 20:00:00 0.927 peak peak 0.08616 0.11924 0.18266
2011-01-21 21:00:00 0.859 offpeak offpeak 0.08616 0.06974 0.05209
2011-01-21 22:00:00 0.862 offpeak offpeak 0.08616 0.06974 0.05209
2011-01-21 23:00:00 0.888 offpeak offpeak 0.08616 0.06974 0.05209
In [31]:
demand_data['BGE-EV'].plot()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-31-38517ef7470b> in <module>()
----> 1 demand_data['BGE-EV'].plot()

/Library/Frameworks/Python.framework/Versions/7.3/lib/python2.7/site-packages/pandas-0.12.0-py2.7-macosx-10.5-i386.egg/pandas/tools/plotting.pyc in plot_series(series, label, kind, use_index, rot, xticks, yticks, xlim, ylim, ax, style, grid, legend, logx, logy, secondary_y, **kwds)
   1728                      secondary_y=secondary_y, **kwds)
   1729 
-> 1730     plot_obj.generate()
   1731     plot_obj.draw()
   1732 

/Library/Frameworks/Python.framework/Versions/7.3/lib/python2.7/site-packages/pandas-0.12.0-py2.7-macosx-10.5-i386.egg/pandas/tools/plotting.pyc in generate(self)
    852     def generate(self):
    853         self._args_adjust()
--> 854         self._compute_plot_data()
    855         self._setup_subplots()
    856         self._make_plot()

/Library/Frameworks/Python.framework/Versions/7.3/lib/python2.7/site-packages/pandas-0.12.0-py2.7-macosx-10.5-i386.egg/pandas/tools/plotting.pyc in _compute_plot_data(self)
    936                 # still an object dtype so we can't plot it
    937                 if numeric_data.dtype == np.object_:
--> 938                     raise TypeError('Series has object dtype and cannot be'
    939                                     ' converted: no numeric data to plot')
    940 

TypeError: Series has object dtype and cannot be converted: no numeric data to plot
In [50]:
a = demand_data

a['BGE-EV'] = 'offpeak'
a['BGE-EV'].ix[(a[a.index.weekday<5].between_time('7:00','10:00')).index] = 'peak'
a['BGE-EV'].ix[(a[a.index.weekday<5].between_time('17:00','21:00')).index] = 'peak'
a[40:72]
Out[50]:
USAGE BGE-EV
2011-01-03 00:00:00 1.090 offpeak
2011-01-03 01:00:00 1.405 offpeak
2011-01-03 02:00:00 1.500 offpeak
2011-01-03 03:00:00 1.404 offpeak
2011-01-03 04:00:00 1.314 offpeak
2011-01-03 05:00:00 1.247 offpeak
2011-01-03 06:00:00 1.089 offpeak
2011-01-03 07:00:00 0.924 peak
2011-01-03 08:00:00 0.808 peak
2011-01-03 09:00:00 0.748 peak
2011-01-03 10:00:00 0.714 peak
2011-01-03 11:00:00 0.690 offpeak
2011-01-03 12:00:00 0.711 offpeak
2011-01-03 13:00:00 0.829 offpeak
2011-01-03 14:00:00 0.964 offpeak
2011-01-03 15:00:00 0.962 offpeak
2011-01-03 16:00:00 1.050 offpeak
2011-01-03 17:00:00 1.096 peak
2011-01-03 18:00:00 1.111 peak
2011-01-03 19:00:00 1.127 peak
2011-01-03 20:00:00 1.165 peak
2011-01-03 21:00:00 1.055 peak
2011-01-03 22:00:00 1.007 offpeak
2011-01-03 23:00:00 0.982 offpeak
2011-01-04 00:00:00 1.057 offpeak
2011-01-04 01:00:00 1.399 offpeak
2011-01-04 02:00:00 1.532 offpeak
2011-01-04 03:00:00 1.444 offpeak
2011-01-04 04:00:00 1.445 offpeak
2011-01-04 05:00:00 1.275 offpeak
2011-01-04 06:00:00 1.040 offpeak
2011-01-04 07:00:00 0.843 peak
In [76]:
a = 2
In [77]:
del a
In [78]:
a
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-78-60b725f10c9c> in <module>()
----> 1 a

NameError: name 'a' is not defined