From 6d8f6a20d95124b86a927b22d85b08b8ff9a995e Mon Sep 17 00:00:00 2001 From: Sarey Hamarneh Date: Tue, 11 Apr 2017 15:23:41 -0400 Subject: [PATCH 1/3] Document functions in billprojections --- bpfin/utilbills/billprojections.py | 252 ++++++++++++++++++++++++++--- 1 file changed, 233 insertions(+), 19 deletions(-) diff --git a/bpfin/utilbills/billprojections.py b/bpfin/utilbills/billprojections.py index 02119f7..b1af894 100644 --- a/bpfin/utilbills/billprojections.py +++ b/bpfin/utilbills/billprojections.py @@ -6,15 +6,40 @@ year = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] def add_list(obj_list, number): + """Add a number to each value in a list. + + Args: + obj_list (list): list of numbers + number (int): number value + Returns: + list: numbers + number to each value + """ return [x + number for x in obj_list] def cal_last_day(obj_year, obj_month): + """Return last day of month given year,month. + + Args: + obj_year (int): year + obj_month (int): month + Returns: + int: last day of month + """ _, last_day_num = calendar.monthrange(obj_year, obj_month) return last_day_num def form_bill_calendar(date_start, year_term): + """Return single list value of first date in bill period and last date in bill period. + + Args: + date_start (datetime): date xx/yy/abcd + year_term (int): number of years in bill + Returns: + list: first date in bill period, last date in bill period + + """ bdstart = [] bdend = [] day = date_start @@ -28,6 +53,14 @@ def form_bill_calendar(date_start, year_term): def form_date_calendar(date_start, date_end): + """Return list of all calendar dates. + + Args: + date_start (datetime): date xx/yy/abcd + date_end (datetime): date xx/yy/abcd + Returns: + list: all calendar dates, first date is first day of calendar + """ bdstart = [] bdend = [] day = date_start @@ -45,6 +78,13 @@ def form_date_calendar(date_start, date_end): def form_year_month(target_terms): + """Return list of month,year of datetimes in a list. + + Args: + target_terms (list of datetimes): date xx/yy/abcd + Returns: + list: list of tuples containing year and month + """ obj_list = [] for term in target_terms: obj_list.append((term.year, term.month)) @@ -52,6 +92,15 @@ def form_year_month(target_terms): def cal_inflation_product(inflation_rate_dict, present_date): + """Return the inflation value for the current date. + + Args: + inflation_rate_dict (dictionary): dictionary of {date,inflation value} + present_date (datetime): present date + Returns: + integer: inflation rate + + """ date_start = sorted(inflation_rate_dict)[0] product = 1 for term in form_date_calendar(date_start, present_date)[1]: @@ -60,7 +109,19 @@ def cal_inflation_product(inflation_rate_dict, present_date): def cal_inflated_item(base_list, target_terms, inflation_coeff_dict, - present_date): # base_list is the base value near the present month + present_date): + # base_list is the base value near the present month + """ + + Args: + base_list: + target_terms: + inflation_coeff_dict (dictionary): + present_date: + Returns: + + + """ new_dict = dict(zip([], [])) for term in target_terms: new_dict[term] = base_list[term.month - 1] * inflation_coeff_dict[term] @@ -68,6 +129,14 @@ def cal_inflated_item(base_list, target_terms, inflation_coeff_dict, def form_inflation_ratedict(inflationyears, inflationhist): + """Create dictionary of {date,inflation}. + + Args: + inflationyears (list): list of years + inflationhist (list): list of inflation values + Returns: + dictionary: {datetime, adjusted inflation} + """ inflationterms = form_bill_calendar(datetime.date(int(inflationyears[0]), 1, 31), len(inflationyears))[1] inflation_rate = [] for year, rate in zip(inflationyears, inflationhist): @@ -79,6 +148,15 @@ def form_inflation_ratedict(inflationyears, inflationhist): def form_inflation_coeffdict(inflationyears, inflationhist, present_date): + """Create dictionary of date:inflation relative to present date. + + Args: + inflationyears (list): list of years + inflationhist (list): list of inflation values + present_date (datetime): present date + Returns: + dictionary: date:inflation relative to present date + """ inflation_rate_dict = form_inflation_ratedict(inflationyears, inflationhist) inflationterms = sorted(inflation_rate_dict) new_dict = dict(zip([], [])) @@ -89,38 +167,53 @@ def form_inflation_coeffdict(inflationyears, inflationhist, present_date): def daily_average_use_or_charge(from_date, to_date, total_utility_use_or_charge): + """Calculate average daily use or charge for a utility. + + Args: + from_date (list): list of datetimes + to_date (list): list of datetimes + total_utility_use_or_charge (list): list of charges or usage, integers + Returns: + list: list of average values + """ fromdate = [] todate = [] - for x in from_date: - fromdate.append(x) - for y in to_date: - todate.append(y) + for date in from_date: + fromdate.append(date) + for date in to_date: + todate.append(date) interstore = [list(x) for x in zip(fromdate, todate)] finalstore = [] - for x in interstore: - f = (x[1] - x[0]) - finalstore.append(f.days) + for value in interstore: + difference = (value[1] - value[0]) + finalstore.append(difference.days) bill_daily_average = [x / y for x, y in zip(total_utility_use_or_charge, finalstore)] perbill_useorcharge = [] - for x in bill_daily_average: - perbill_useorcharge.append(x) + for number in bill_daily_average: + perbill_useorcharge.append(number) return perbill_useorcharge -# returns 2d list -# [0, 4, 20...] means first bill with 4 days in feb and 20 days in march def firstmatrix(from_date, to_date): - rangeID = 0 + """Create 2D matrix, list of lists. + + Args: + from_date (list): list of datetimes of "from dates" for bills + to_date (list): list of datetimes of "end dates" for bills + Returns: + list: matrix (list of lists) of # of days in bill periods + """ + range_id = 0 for x in from_date: - rangeID += 1 - monthmatrix = [[0 for i in range(12)] for j in range(rangeID)] - for (fromdate, enddate, rangeID) in zip(from_date, to_date, range(rangeID)): + range_id += 1 + monthmatrix = [[0 for i in range(12)] for j in range(range_id)] + for (fromdate, enddate, range_id) in zip(from_date, to_date, range(range_id)): date = fromdate + datetime.timedelta(1) while date <= enddate: for month in range(1, 13): # range(1,13)=[1:12] if date.month == month: - monthmatrix[rangeID][month - 1] += 1 + monthmatrix[range_id][month - 1] += 1 date = date + datetime.timedelta(1) return monthmatrix @@ -128,6 +221,12 @@ def firstmatrix(from_date, to_date): # returns 2d list # [0, 4, 20...] means for jan, bill 1 has 0 days, bill 2 has 4 days def finalmatrix(matrixchoice): + """ + Args: + matrixchoice (list): list of lists (matrix) + Returns: + list: list of lists of normalized # of days in each bill + """ newmatrix = [] for i in range(len(matrixchoice[0])): bill = [] @@ -138,6 +237,12 @@ def finalmatrix(matrixchoice): def normalize_average(matrix_choice): + """ + Args: + list: list of lists of normalized + Returns: + list: a single list of number of days per month + """ newlist = [] for i in matrix_choice: newlist.append((sum(list(i)))) @@ -147,6 +252,13 @@ def normalize_average(matrix_choice): # calculate charge and usage as one array with 12 values representing the month def monthly_info(billing_info, matrix, divider): + """ + Args: + billing_info (: + matrix (list): + divider (list) + Returns: + """ monthly_average = [] for month in range(1, 13): matrixcolumn = [] @@ -163,6 +275,14 @@ def monthly_info(billing_info, matrix, divider): # 12 prices which are the same def hist_oil_price(oilcharge, oiluse): + """ + Args: + oilcharge (list): list of oil charges per bill + oiluse (list): list of oil usage per bill + Returns: + list: oil price per billing period, 12 times - + for oil, we calculate one average price, and apply that across all months + """ a = sum(oilcharge) b = sum(oiluse) oprice = a / b @@ -173,11 +293,23 @@ def hist_oil_price(oilcharge, oiluse): def monthly_price(charge, use): + """ + Args: + charge (list): list of charges + use (list): list of uses + Returns: + list: list of prices per month + """ finalmonthprice = [x / y for x, y in zip(charge, use)] return finalmonthprice - def occupancy_final_list(occupancy_rate_list): + """ + Args: + occupancy_rate_list (list): list of occupancy integers + Returns: + list: list of occupancy integers * 24, representing occupancy in hours + """ hours_in_day = 24 occupancy_list = [] for x in occupancy_rate_list: @@ -186,6 +318,15 @@ def occupancy_final_list(occupancy_rate_list): def regression_base_sum(bill_start_utility, bill_end_utility, x_value_calendar, x_values): + """ + Args: + bill_start_utility (list): list of datetimes (start-date) from bills + bill_end_utility (list): list of datetimes (end-date) from bills + x_value_calendar (list): + x_values (list): + Returns: + list: + """ day = [] month = [] year = [] @@ -231,6 +372,14 @@ def regression_base_sum(bill_start_utility, bill_end_utility, x_value_calendar, def regression_coefficients(x_list, y_list, is_intercept): + """ + Args: + x_list: list of base x values for regression + y_list: list of base y values for regression + is_intercept (boolean): it is true that we want an intercept value in our regression + Returns: + tuple: x and y coefficients from regression + """ X = x_list Y = y_list if is_intercept == True: @@ -242,6 +391,16 @@ def regression_coefficients(x_list, y_list, is_intercept): def regression_predicting_y(reg_history, periodstart, periodend, x_value_calendar, x_values): + """ + Args: + reg_history (list/tuple): tuple of x and y coefficient based on historical regression + periodstart (list): bill + periodend (list): + x_value_calendar (list): + x_values (list) : x values that we want for projection + Returns: + list: progrection of future y values + """ x_list = regression_base_sum(periodstart, periodend, x_value_calendar, x_values) future_y = [] for i in x_list: @@ -250,6 +409,19 @@ def regression_predicting_y(reg_history, periodstart, periodend, x_value_calenda def rate_plan_cons(date, con, limit, leap, supply_charge, basic_charge, tax_rate, adjustments): + """ + Args: + date (datetime): datetime aa/bb/xyzw + con (int): consumption value of utility use + limit (list): list of integer limits + leap (list): list of integer limits + supply_charge (list): supply charge of utility use + basic_charge (list): supply charge of utility use + tax_rate (list): tax rate of utility use + adjustments (list): value adjustments + Returns: + int: utility charge + """ temp_list = [] y = date.month - 1 for i in range(len(limit)): @@ -272,6 +444,19 @@ def rate_plan_cons(date, con, limit, leap, supply_charge, basic_charge, tax_rate # This function needs to be worked on def calc_charge_list(conlist, datelist, limit, leap, supply_charge, basic_charge, tax_rate, adjustments): + """ + Args: + conlist (list): list of utiltiy consumption + datelist (list): list of datetimes + limit (list): list of integer limits + leap (list): list of integer limits + supply_charge (list): supply charge of utility use + basic_charge (list): supply charge of utility use + tax_rate (list): tax rate of utility use + adjustments (list): value adjustments + Returns: + list: list of utility charges + """ charge = [] for con, date in zip(conlist, datelist): temp_charge = rate_plan_cons(date, con, limit, leap, supply_charge, basic_charge, tax_rate, adjustments) @@ -280,15 +465,36 @@ def calc_charge_list(conlist, datelist, limit, leap, supply_charge, basic_charge def price_x_consumption(price, con_list): + """ + Args: + price (list): list of prices + con_list (list): list of consumption + Returns: + list: list of charges + """ return [x * price for x in con_list] def utility_charge_sum(list1, list2, list3): + """ + Args: + list1 (list): list of utility charges + list2 (list): list of utility charges + list3 (list): list of utility charges + Returns: + list: sum of the three lists + """ return [x + y + z for x, y, z in zip(list1, list2, list3)] def charge_dictionary(billperiod, charge_list): - bdday = [] + """ + Args: + billperiod: datetime + charge_list: list of charges + Returns: + dictionary: ({month, year}, charge) + """ bdmonth = [] bdyear = [] @@ -305,6 +511,14 @@ def charge_dictionary(billperiod, charge_list): def charge_with_inflation(billperiod, bill_dictionary, inf_dictionary): + """ + Args: + billperiod (list): list of datetimes + bill_dictionary (dictionary): dictionary of bills (bill, {month, year} + inf_dictionary (dictionary): dictioanry of infs (inflation, {month, year}) + Returns: + dictionary: inflation adjusted dictionary of bills (bill, {month, year}) + """ bdmonth = [] bdyear = [] for i in billperiod: -- GitLab From 02879ed3bc7edd8511d3f217429542cb5fc21755 Mon Sep 17 00:00:00 2001 From: Sarey Hamarneh Date: Tue, 11 Apr 2017 18:10:01 -0400 Subject: [PATCH 2/3] Document code. --- bpfin/utilbills/billprojections.py | 140 +++++++++++++++-------------- 1 file changed, 74 insertions(+), 66 deletions(-) diff --git a/bpfin/utilbills/billprojections.py b/bpfin/utilbills/billprojections.py index b1af894..de83773 100644 --- a/bpfin/utilbills/billprojections.py +++ b/bpfin/utilbills/billprojections.py @@ -108,19 +108,16 @@ def cal_inflation_product(inflation_rate_dict, present_date): return product -def cal_inflated_item(base_list, target_terms, inflation_coeff_dict, - present_date): - # base_list is the base value near the present month - """ +def cal_inflated_item(base_list, target_terms, inflation_coeff_dict): + # Deleted "present_day" from inputs. + """Create dictionary of inflated terms. Args: - base_list: - target_terms: - inflation_coeff_dict (dictionary): - present_date: + base_list (integer): base value + target_terms (list): list of inflation values + inflation_coeff_dict (dictionary): dictioanry of inflation coefficients with date Returns: - - + dictionary: coefficients and dates """ new_dict = dict(zip([], [])) for term in target_terms: @@ -140,7 +137,7 @@ def form_inflation_ratedict(inflationyears, inflationhist): inflationterms = form_bill_calendar(datetime.date(int(inflationyears[0]), 1, 31), len(inflationyears))[1] inflation_rate = [] for year, rate in zip(inflationyears, inflationhist): - for i in range(12): + for number in range(12): inflation_rate.append(rate / 12) inflation_rate = add_list(inflation_rate, 1) dict1 = dict(zip(inflationterms, inflation_rate)) # return (2016,2,29 : 100.67%) @@ -205,7 +202,7 @@ def firstmatrix(from_date, to_date): list: matrix (list of lists) of # of days in bill periods """ range_id = 0 - for x in from_date: + for date in from_date: range_id += 1 monthmatrix = [[0 for i in range(12)] for j in range(range_id)] for (fromdate, enddate, range_id) in zip(from_date, to_date, range(range_id)): @@ -218,10 +215,9 @@ def firstmatrix(from_date, to_date): return monthmatrix -# returns 2d list -# [0, 4, 20...] means for jan, bill 1 has 0 days, bill 2 has 4 days def finalmatrix(matrixchoice): - """ + """Return final normalized matrix. + Args: matrixchoice (list): list of lists (matrix) Returns: @@ -237,11 +233,12 @@ def finalmatrix(matrixchoice): def normalize_average(matrix_choice): - """ + """Provide ratios necessary for bill averages. + Args: - list: list of lists of normalized + matrix_choice (list): list of lists of normalized # of days in each bill Returns: - list: a single list of number of days per month + list: ratios necessary for normalizing usage/charge per month """ newlist = [] for i in matrix_choice: @@ -250,32 +247,33 @@ def normalize_average(matrix_choice): return divider -# calculate charge and usage as one array with 12 values representing the month def monthly_info(billing_info, matrix, divider): - """ + """Generate normalized use/charge based on ratios. + Args: - billing_info (: - matrix (list): - divider (list) + billing_info (list): list of usage or charge + matrix (list): list of numbers of day + divider (list): list of ratios Returns: + list: normalized use/charge based on ratios """ monthly_average = [] for month in range(1, 13): matrixcolumn = [] - for rangeID in range(len(billing_info)): - matrixcolumn.append(matrix[rangeID][month - 1]) - z = [daily_avg * (days) for (daily_avg, days) in zip(billing_info, matrixcolumn)] + for range_id in range(len(billing_info)): + matrixcolumn.append(matrix[range_id][month - 1]) + value = [daily_avg * (days) for (daily_avg, days) in zip(billing_info, matrixcolumn)] total = 0 - for i in range(len(z)): - total += z[i] + for number in range(len(value)): + total += value[number] monthly_average.append(total) monthly_values = [x / y for x, y in zip(monthly_average, divider)] return monthly_values -# 12 prices which are the same def hist_oil_price(oilcharge, oiluse): - """ + """Return list of historical price for oil. + Args: oilcharge (list): list of oil charges per bill oiluse (list): list of oil usage per bill @@ -283,17 +281,18 @@ def hist_oil_price(oilcharge, oiluse): list: oil price per billing period, 12 times - for oil, we calculate one average price, and apply that across all months """ - a = sum(oilcharge) - b = sum(oiluse) - oprice = a / b + oilchargesum = sum(oilcharge) + oilusesum = sum(oiluse) + oprice = oilchargesum / oilusesum newlist = [] - for i in range(1, 13): + for number in range(1, 13): newlist.append(oprice) return newlist def monthly_price(charge, use): - """ + """Return Monthly prices per month. + Args: charge (list): list of charges use (list): list of uses @@ -303,29 +302,32 @@ def monthly_price(charge, use): finalmonthprice = [x / y for x, y in zip(charge, use)] return finalmonthprice + def occupancy_final_list(occupancy_rate_list): - """ + """Return list of occupancy values. + Args: occupancy_rate_list (list): list of occupancy integers Returns: list: list of occupancy integers * 24, representing occupancy in hours """ - hours_in_day = 24 occupancy_list = [] - for x in occupancy_rate_list: - occupancy_list.append(x * 24) + for occ in occupancy_rate_list: + occupancy_list.append(occ * 24) return occupancy_list def regression_base_sum(bill_start_utility, bill_end_utility, x_value_calendar, x_values): - """ + """Return x values for regression. + Args: bill_start_utility (list): list of datetimes (start-date) from bills bill_end_utility (list): list of datetimes (end-date) from bills - x_value_calendar (list): - x_values (list): + x_value_calendar (list): list of datetimes + x_values (list): x values corresponding to datetimes + Returns: - list: + list: x_values of a regression """ day = [] month = [] @@ -372,7 +374,8 @@ def regression_base_sum(bill_start_utility, bill_end_utility, x_value_calendar, def regression_coefficients(x_list, y_list, is_intercept): - """ + """Regress two lists of values. + Args: x_list: list of base x values for regression y_list: list of base y values for regression @@ -380,26 +383,27 @@ def regression_coefficients(x_list, y_list, is_intercept): Returns: tuple: x and y coefficients from regression """ - X = x_list - Y = y_list - if is_intercept == True: - X = sm.add_constant(X) - model = sm.OLS(Y, X) + x_values = x_list + y_values = y_list + if is_intercept is True: + x_values = sm.add_constant(x_values) + model = sm.OLS(y_values, x_values) results = model.fit() coefficients = results.params return coefficients def regression_predicting_y(reg_history, periodstart, periodend, x_value_calendar, x_values): - """ + """Return results of regression. + Args: - reg_history (list/tuple): tuple of x and y coefficient based on historical regression + reg_history (list): tuple of x and y coefficient based on historical regression periodstart (list): bill periodend (list): x_value_calendar (list): x_values (list) : x values that we want for projection Returns: - list: progrection of future y values + list: progression of future y values """ x_list = regression_base_sum(periodstart, periodend, x_value_calendar, x_values) future_y = [] @@ -409,7 +413,8 @@ def regression_predicting_y(reg_history, periodstart, periodend, x_value_calenda def rate_plan_cons(date, con, limit, leap, supply_charge, basic_charge, tax_rate, adjustments): - """ + """Generate correct charge per consumption. + Args: date (datetime): datetime aa/bb/xyzw con (int): consumption value of utility use @@ -420,7 +425,7 @@ def rate_plan_cons(date, con, limit, leap, supply_charge, basic_charge, tax_rate tax_rate (list): tax rate of utility use adjustments (list): value adjustments Returns: - int: utility charge + int: utility charge given consumption """ temp_list = [] y = date.month - 1 @@ -444,7 +449,8 @@ def rate_plan_cons(date, con, limit, leap, supply_charge, basic_charge, tax_rate # This function needs to be worked on def calc_charge_list(conlist, datelist, limit, leap, supply_charge, basic_charge, tax_rate, adjustments): - """ + """Return charge results of rate plan calculator. + Args: conlist (list): list of utiltiy consumption datelist (list): list of datetimes @@ -455,7 +461,7 @@ def calc_charge_list(conlist, datelist, limit, leap, supply_charge, basic_charge tax_rate (list): tax rate of utility use adjustments (list): value adjustments Returns: - list: list of utility charges + list: list of utility charges based on rate plan consumption """ charge = [] for con, date in zip(conlist, datelist): @@ -465,7 +471,8 @@ def calc_charge_list(conlist, datelist, limit, leap, supply_charge, basic_charge def price_x_consumption(price, con_list): - """ + """Return list of charges. + Args: price (list): list of prices con_list (list): list of consumption @@ -476,7 +483,8 @@ def price_x_consumption(price, con_list): def utility_charge_sum(list1, list2, list3): - """ + """Return sum of utility lists. + Args: list1 (list): list of utility charges list2 (list): list of utility charges @@ -488,7 +496,8 @@ def utility_charge_sum(list1, list2, list3): def charge_dictionary(billperiod, charge_list): - """ + """Create dictioanry of date and charge. + Args: billperiod: datetime charge_list: list of charges @@ -503,15 +512,14 @@ def charge_dictionary(billperiod, charge_list): for i in billperiod: bdyear.append(i.year) - bdzipper = [(x, y) for x, y in zip(bdyear, bdmonth)] - dicthelper = {key: value for key, value in zip(billperiod, charge_list)} return dicthelper def charge_with_inflation(billperiod, bill_dictionary, inf_dictionary): - """ + """Create dictionary of inflation adjusted bills with date. + Args: billperiod (list): list of datetimes bill_dictionary (dictionary): dictionary of bills (bill, {month, year} @@ -527,10 +535,10 @@ def charge_with_inflation(billperiod, bill_dictionary, inf_dictionary): bdyear.append(i.year) bdzipper = [(x, y) for x, y in zip(bdyear, bdmonth)] list_helper = [] - for a, b in bill_dictionary.items(): - for c, d in inf_dictionary.items(): - if a == c: - list_helper.append(b * d) + for first, second in bill_dictionary.items(): + for third, fourth in inf_dictionary.items(): + if first == third: + list_helper.append(second * fourth) dict_final = {key: value for key, value in zip(bdzipper, list_helper)} # return dict_final -- GitLab From d78f2585b5d393bd5f6277c765816a3ba3e89c50 Mon Sep 17 00:00:00 2001 From: Sarey Hamarneh Date: Wed, 12 Apr 2017 18:57:44 -0400 Subject: [PATCH 3/3] Create python files and folders to organize code --- bpfin/lib/date.py | 0 bpfin/lib/math.py | 0 bpfin/lib/other.py | 0 .../{ => test_financials}/test_prelim.py | 0 .../***old_test_utilbills.py} | 0 bpfin/tests/test_utilbills/test_bill_lib.py | 12 ++ .../test_utilbills/test_bill_normalize.py | 0 .../test_utilbills/test_bill_proj_charge.py | 0 .../test_utilbills/test_bill_proj_reg.py | 0 ...ojections.py => ***old_billprojections.py} | 8 +- .../{calcbill.py => ***old_calcbill.py} | 0 bpfin/utilbills/bill_lib.py | 175 ++++++++++++++++++ bpfin/utilbills/bill_normalize.py | 110 +++++++++++ bpfin/utilbills/bill_proj_charge.py | 166 +++++++++++++++++ bpfin/utilbills/bill_proj_reg.py | 98 ++++++++++ 15 files changed, 564 insertions(+), 5 deletions(-) create mode 100644 bpfin/lib/date.py create mode 100644 bpfin/lib/math.py create mode 100644 bpfin/lib/other.py rename bpfin/tests/{ => test_financials}/test_prelim.py (100%) rename bpfin/tests/{test_utilbills.py => test_utilbills/***old_test_utilbills.py} (100%) create mode 100644 bpfin/tests/test_utilbills/test_bill_lib.py create mode 100644 bpfin/tests/test_utilbills/test_bill_normalize.py create mode 100644 bpfin/tests/test_utilbills/test_bill_proj_charge.py create mode 100644 bpfin/tests/test_utilbills/test_bill_proj_reg.py rename bpfin/utilbills/{billprojections.py => ***old_billprojections.py} (98%) rename bpfin/utilbills/{calcbill.py => ***old_calcbill.py} (100%) create mode 100644 bpfin/utilbills/bill_lib.py create mode 100644 bpfin/utilbills/bill_normalize.py create mode 100644 bpfin/utilbills/bill_proj_charge.py create mode 100644 bpfin/utilbills/bill_proj_reg.py diff --git a/bpfin/lib/date.py b/bpfin/lib/date.py new file mode 100644 index 0000000..e69de29 diff --git a/bpfin/lib/math.py b/bpfin/lib/math.py new file mode 100644 index 0000000..e69de29 diff --git a/bpfin/lib/other.py b/bpfin/lib/other.py new file mode 100644 index 0000000..e69de29 diff --git a/bpfin/tests/test_prelim.py b/bpfin/tests/test_financials/test_prelim.py similarity index 100% rename from bpfin/tests/test_prelim.py rename to bpfin/tests/test_financials/test_prelim.py diff --git a/bpfin/tests/test_utilbills.py b/bpfin/tests/test_utilbills/***old_test_utilbills.py similarity index 100% rename from bpfin/tests/test_utilbills.py rename to bpfin/tests/test_utilbills/***old_test_utilbills.py diff --git a/bpfin/tests/test_utilbills/test_bill_lib.py b/bpfin/tests/test_utilbills/test_bill_lib.py new file mode 100644 index 0000000..a5c6aec --- /dev/null +++ b/bpfin/tests/test_utilbills/test_bill_lib.py @@ -0,0 +1,12 @@ +from bpfin.utilbills.0bill_lib import add_list + + +def test_add_list(): + input = [1, 2] + output = [3, 4] + result = add_list(input, 2) + + for i in result: + assert result[i] == output[i] + + diff --git a/bpfin/tests/test_utilbills/test_bill_normalize.py b/bpfin/tests/test_utilbills/test_bill_normalize.py new file mode 100644 index 0000000..e69de29 diff --git a/bpfin/tests/test_utilbills/test_bill_proj_charge.py b/bpfin/tests/test_utilbills/test_bill_proj_charge.py new file mode 100644 index 0000000..e69de29 diff --git a/bpfin/tests/test_utilbills/test_bill_proj_reg.py b/bpfin/tests/test_utilbills/test_bill_proj_reg.py new file mode 100644 index 0000000..e69de29 diff --git a/bpfin/utilbills/billprojections.py b/bpfin/utilbills/***old_billprojections.py similarity index 98% rename from bpfin/utilbills/billprojections.py rename to bpfin/utilbills/***old_billprojections.py index de83773..b345a4e 100644 --- a/bpfin/utilbills/billprojections.py +++ b/bpfin/utilbills/***old_billprojections.py @@ -2,8 +2,6 @@ import statsmodels.api as sm import datetime import calendar -year = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] - def add_list(obj_list, number): """Add a number to each value in a list. @@ -243,7 +241,7 @@ def normalize_average(matrix_choice): newlist = [] for i in matrix_choice: newlist.append((sum(list(i)))) - divider = [x / y for x, y in zip(newlist, year)] + divider = [x / y for x, y in zip(newlist, [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31])] return divider @@ -499,8 +497,8 @@ def charge_dictionary(billperiod, charge_list): """Create dictioanry of date and charge. Args: - billperiod: datetime - charge_list: list of charges + billperiod (datetime): datetime + charge_list (list): list of charges Returns: dictionary: ({month, year}, charge) """ diff --git a/bpfin/utilbills/calcbill.py b/bpfin/utilbills/***old_calcbill.py similarity index 100% rename from bpfin/utilbills/calcbill.py rename to bpfin/utilbills/***old_calcbill.py diff --git a/bpfin/utilbills/bill_lib.py b/bpfin/utilbills/bill_lib.py new file mode 100644 index 0000000..8aa7522 --- /dev/null +++ b/bpfin/utilbills/bill_lib.py @@ -0,0 +1,175 @@ +import statsmodels.api as sm +import datetime +import calendar + + +def add_list(obj_list, number): + """Add a number to each value in a list. + + Args: + obj_list (list): list of numbers + number (int): number value + Returns: + list: numbers + number to each value + """ + return [x + number for x in obj_list] + + +def cal_last_day(obj_year, obj_month): + """Return last day of month given year,month. + + Args: + obj_year (int): year + obj_month (int): month + Returns: + int: last day of month + """ + _, last_day_num = calendar.monthrange(obj_year, obj_month) + return last_day_num + + +def form_bill_calendar(date_start, year_term): + """Return single list value of first date in bill period and last date in bill period. + + Args: + date_start (datetime): date xx/yy/abcd + year_term (int): number of years in bill + Returns: + list: first date in bill period, last date in bill period + + """ + bdstart = [] + bdend = [] + day = date_start + for term in range(12 * year_term): + first = datetime.date(day=1, month=day.month, year=day.year) + bdstart.append(first) + last = datetime.date(day.year, day.month, cal_last_day(day.year, day.month)) + bdend.append(last) + day = last + datetime.timedelta(days=1) + return [bdstart, bdend] + + +def form_date_calendar(date_start, date_end): + """Return list of all calendar dates. + + Args: + date_start (datetime): date xx/yy/abcd + date_end (datetime): date xx/yy/abcd + Returns: + list: all calendar dates, first date is first day of calendar + """ + bdstart = [] + bdend = [] + day = date_start + i = 1 + while day <= date_end: + if i > 9999: + return False + first = datetime.date(day=1, month=day.month, year=day.year) + bdstart.append(first) + last = datetime.date(day.year, day.month, cal_last_day(day.year, day.month)) + bdend.append(last) + day = last + datetime.timedelta(days=1) + i += 1 + return [bdstart, bdend] + + +def form_year_month(target_terms): + """Return list of month,year of datetimes in a list. + + Args: + target_terms (list of datetimes): date xx/yy/abcd + Returns: + list: list of tuples containing year and month + """ + obj_list = [] + for term in target_terms: + obj_list.append((term.year, term.month)) + return obj_list + + +def cal_inflation_product(inflation_rate_dict, present_date): + """Return the inflation value for the current date. + + Args: + inflation_rate_dict (dictionary): dictionary of {date,inflation value} + present_date (datetime): present date + Returns: + integer: inflation rate + + """ + date_start = sorted(inflation_rate_dict)[0] + product = 1 + for term in form_date_calendar(date_start, present_date)[1]: + product = product * inflation_rate_dict[term] + return product + + +def cal_inflated_item(base_list, target_terms, inflation_coeff_dict): + # Deleted "present_day" from inputs. + """Create dictionary of inflated terms. + + Args: + base_list (integer): base value + target_terms (list): list of inflation values + inflation_coeff_dict (dictionary): dictioanry of inflation coefficients with date + Returns: + dictionary: coefficients and dates + """ + new_dict = dict(zip([], [])) + for term in target_terms: + new_dict[term] = base_list[term.month - 1] * inflation_coeff_dict[term] + return [new_dict[term] for term in sorted(new_dict)] + + +def form_inflation_ratedict(inflationyears, inflationhist): + """Create dictionary of {date,inflation}. + + Args: + inflationyears (list): list of years + inflationhist (list): list of inflation values + Returns: + dictionary: {datetime, adjusted inflation} + """ + inflationterms = form_bill_calendar(datetime.date(int(inflationyears[0]), 1, 31), len(inflationyears))[1] + inflation_rate = [] + for year, rate in zip(inflationyears, inflationhist): + for number in range(12): + inflation_rate.append(rate / 12) + inflation_rate = add_list(inflation_rate, 1) + dict1 = dict(zip(inflationterms, inflation_rate)) # return (2016,2,29 : 100.67%) + return dict1 + + +def form_inflation_coeffdict(inflationyears, inflationhist, present_date): + """Create dictionary of date:inflation relative to present date. + + Args: + inflationyears (list): list of years + inflationhist (list): list of inflation values + present_date (datetime): present date + Returns: + dictionary: date:inflation relative to present date + """ + inflation_rate_dict = form_inflation_ratedict(inflationyears, inflationhist) + inflationterms = sorted(inflation_rate_dict) + new_dict = dict(zip([], [])) + for term in inflationterms: + new_dict[term] = cal_inflation_product(inflation_rate_dict, term) / cal_inflation_product(inflation_rate_dict, + present_date) + return new_dict + + +def occupancy_final_list(occupancy_rate_list): + """Return list of occupancy values. + + Args: + occupancy_rate_list (list): list of occupancy integers + Returns: + list: list of occupancy integers * 24, representing occupancy in hours + """ + occupancy_list = [] + for occ in occupancy_rate_list: + occupancy_list.append(occ * 24) + return occupancy_list diff --git a/bpfin/utilbills/bill_normalize.py b/bpfin/utilbills/bill_normalize.py new file mode 100644 index 0000000..e7d365e --- /dev/null +++ b/bpfin/utilbills/bill_normalize.py @@ -0,0 +1,110 @@ +import statsmodels.api as sm +import datetime +import calendar + +def daily_average_use_or_charge(from_date, to_date, total_utility_use_or_charge): + """Calculate average daily use or charge for a utility. + + Args: + from_date (list): list of datetimes + to_date (list): list of datetimes + total_utility_use_or_charge (list): list of charges or usage, integers + Returns: + list: list of average values + """ + fromdate = [] + todate = [] + for date in from_date: + fromdate.append(date) + for date in to_date: + todate.append(date) + interstore = [list(x) for x in zip(fromdate, todate)] + finalstore = [] + for value in interstore: + difference = (value[1] - value[0]) + finalstore.append(difference.days) + + bill_daily_average = [x / y for x, y in zip(total_utility_use_or_charge, finalstore)] + perbill_useorcharge = [] + for number in bill_daily_average: + perbill_useorcharge.append(number) + return perbill_useorcharge + + +def firstmatrix(from_date, to_date): + """Create 2D matrix, list of lists. + + Args: + from_date (list): list of datetimes of "from dates" for bills + to_date (list): list of datetimes of "end dates" for bills + Returns: + list: matrix (list of lists) of # of days in bill periods + """ + range_id = 0 + for date in from_date: + range_id += 1 + monthmatrix = [[0 for i in range(12)] for j in range(range_id)] + for (fromdate, enddate, range_id) in zip(from_date, to_date, range(range_id)): + date = fromdate + datetime.timedelta(1) + while date <= enddate: + for month in range(1, 13): # range(1,13)=[1:12] + if date.month == month: + monthmatrix[range_id][month - 1] += 1 + date = date + datetime.timedelta(1) + return monthmatrix + + +def finalmatrix(matrixchoice): + """Return final normalized matrix. + + Args: + matrixchoice (list): list of lists (matrix) + Returns: + list: list of lists of normalized # of days in each bill + """ + newmatrix = [] + for i in range(len(matrixchoice[0])): + bill = [] + for item in matrixchoice: + bill.append(item[i]) + newmatrix.append(bill) + return newmatrix + + +def normalize_average(matrix_choice): + """Provide ratios necessary for bill averages. + + Args: + matrix_choice (list): list of lists of normalized # of days in each bill + Returns: + list: ratios necessary for normalizing usage/charge per month + """ + newlist = [] + for i in matrix_choice: + newlist.append((sum(list(i)))) + divider = [x / y for x, y in zip(newlist, [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31])] + return divider + + +def monthly_info(billing_info, matrix, divider): + """Generate normalized use/charge based on ratios. + + Args: + billing_info (list): list of usage or charge + matrix (list): list of numbers of day + divider (list): list of ratios + Returns: + list: normalized use/charge based on ratios + """ + monthly_average = [] + for month in range(1, 13): + matrixcolumn = [] + for range_id in range(len(billing_info)): + matrixcolumn.append(matrix[range_id][month - 1]) + value = [daily_avg * (days) for (daily_avg, days) in zip(billing_info, matrixcolumn)] + total = 0 + for number in range(len(value)): + total += value[number] + monthly_average.append(total) + monthly_values = [x / y for x, y in zip(monthly_average, divider)] + return monthly_values diff --git a/bpfin/utilbills/bill_proj_charge.py b/bpfin/utilbills/bill_proj_charge.py new file mode 100644 index 0000000..18b2046 --- /dev/null +++ b/bpfin/utilbills/bill_proj_charge.py @@ -0,0 +1,166 @@ + + +def rate_plan_cons(date, con, limit, leap, supply_charge, basic_charge, tax_rate, adjustments): + """Generate correct charge per consumption. + + Args: + date (datetime): datetime aa/bb/xyzw + con (int): consumption value of utility use + limit (list): list of integer limits + leap (list): list of integer limits + supply_charge (list): supply charge of utility use + basic_charge (list): supply charge of utility use + tax_rate (list): tax rate of utility use + adjustments (list): value adjustments + Returns: + int: utility charge given consumption + """ + temp_list = [] + y = date.month - 1 + for i in range(len(limit)): + if (i + 1) < (len(limit)) and con > limit[i + 1][y]: + first = ((limit[i + 1][y] - limit[i][y]) * leap[i][y]) + temp_list.append(first) + if (i + 1) < (len(limit)) and con < limit[i + 1][y] and con > limit[i][y]: + second = ((con - limit[i][y]) * leap[i][y]) + temp_list.append(second) + if (i + 1) == len(limit): + third = max(((con - limit[len(leap) - 1][y]) * leap[i][y]), 0) + temp_list.append(third) + else: + temp_list.append(0) + result = sum(temp_list) + con * (supply_charge[y]) + basic_charge[y] + final_result = result * (1 + tax_rate[y]) * (1 + adjustments[y]) + + return final_result + + +# This function needs to be worked on +def calc_charge_list(conlist, datelist, limit, leap, supply_charge, basic_charge, tax_rate, adjustments): + """Return charge results of rate plan calculator. + + Args: + conlist (list): list of utiltiy consumption + datelist (list): list of datetimes + limit (list): list of integer limits + leap (list): list of integer limits + supply_charge (list): supply charge of utility use + basic_charge (list): supply charge of utility use + tax_rate (list): tax rate of utility use + adjustments (list): value adjustments + Returns: + list: list of utility charges based on rate plan consumption + """ + charge = [] + for con, date in zip(conlist, datelist): + temp_charge = rate_plan_cons(date, con, limit, leap, supply_charge, basic_charge, tax_rate, adjustments) + charge.append(temp_charge) + return charge + + +def price_x_consumption(price, con_list): + """Return list of charges. + + Args: + price (list): list of prices + con_list (list): list of consumption + Returns: + list: list of charges + """ + return [x * price for x in con_list] + + +def utility_charge_sum(list1, list2, list3): + """Return sum of utility lists. + + Args: + list1 (list): list of utility charges + list2 (list): list of utility charges + list3 (list): list of utility charges + Returns: + list: sum of the three lists + """ + return [x + y + z for x, y, z in zip(list1, list2, list3)] + + +def charge_dictionary(billperiod, charge_list): + """Create dictioanry of date and charge. + + Args: + billperiod (datetime): datetime + charge_list (list): list of charges + Returns: + dictionary: ({month, year}, charge) + """ + bdmonth = [] + bdyear = [] + + for i in billperiod: + bdmonth.append(i.month) + for i in billperiod: + bdyear.append(i.year) + + dicthelper = {key: value for key, value in zip(billperiod, charge_list)} + + return dicthelper + + +def charge_with_inflation(billperiod, bill_dictionary, inf_dictionary): + """Create dictionary of inflation adjusted bills with date. + + Args: + billperiod (list): list of datetimes + bill_dictionary (dictionary): dictionary of bills (bill, {month, year} + inf_dictionary (dictionary): dictioanry of infs (inflation, {month, year}) + Returns: + dictionary: inflation adjusted dictionary of bills (bill, {month, year}) + """ + bdmonth = [] + bdyear = [] + for i in billperiod: + bdmonth.append(i.month) + for i in billperiod: + bdyear.append(i.year) + bdzipper = [(x, y) for x, y in zip(bdyear, bdmonth)] + list_helper = [] + for first, second in bill_dictionary.items(): + for third, fourth in inf_dictionary.items(): + if first == third: + list_helper.append(second * fourth) + dict_final = {key: value for key, value in zip(bdzipper, list_helper)} + + # return dict_final + return [(x, dict_final[x]) for x in sorted(dict_final)] + + +def hist_oil_price(oilcharge, oiluse): + """Return list of historical price for oil. + + Args: + oilcharge (list): list of oil charges per bill + oiluse (list): list of oil usage per bill + Returns: + list: oil price per billing period, 12 times - + for oil, we calculate one average price, and apply that across all months + """ + oilchargesum = sum(oilcharge) + oilusesum = sum(oiluse) + oprice = oilchargesum / oilusesum + newlist = [] + for number in range(1, 13): + newlist.append(oprice) + return newlist + + +def monthly_price(charge, use): + """Return Monthly prices per month. + + Args: + charge (list): list of charges + use (list): list of uses + Returns: + list: list of prices per month + """ + finalmonthprice = [x / y for x, y in zip(charge, use)] + return finalmonthprice + diff --git a/bpfin/utilbills/bill_proj_reg.py b/bpfin/utilbills/bill_proj_reg.py new file mode 100644 index 0000000..b6165de --- /dev/null +++ b/bpfin/utilbills/bill_proj_reg.py @@ -0,0 +1,98 @@ +import statsmodels.api as sm +import datetime +import calendar + + +def regression_base_sum(bill_start_utility, bill_end_utility, x_value_calendar, x_values): + """Return x values for regression. + + Args: + bill_start_utility (list): list of datetimes (start-date) from bills + bill_end_utility (list): list of datetimes (end-date) from bills + x_value_calendar (list): list of datetimes + x_values (list): x values corresponding to datetimes + + Returns: + list: x_values of a regression + """ + day = [] + month = [] + year = [] + for i in bill_start_utility: + day.append(i.day) + month.append(i.month) + year.append(i.year) + + day2 = [] + month2 = [] + year2 = [] + for i in x_value_calendar: + day2.append(i.day) + month2.append(i.month) + year2.append(i.year) + + datezipper = [(x, y, z) for x, y, z in zip(year, month, day)] + datezipper2 = [(x, y, z) for x, y, z in zip(year2, month2, day2)] + + list_subtractor = [x - y for x, y in zip(bill_end_utility, bill_start_utility)] + day_counter = [] + for number in list_subtractor: + if number is not None: + day_counter.append(abs(number.days)) + else: + day_counter.append(0) + + index_finder = [] + for i in datezipper: + for x in datezipper2: + if x == i: + index_finder.append(datezipper2.index(x)) + + list_creator = [] + for i in range(len(index_finder)): + list_creator.append(x_values[index_finder[i]:index_finder[i] + day_counter[i]]) + + x_totals = [] + for i in list_creator: + x_totals.append(sum(i)) + + return x_totals + + +def regression_coefficients(x_list, y_list, is_intercept): + """Regress two lists of values. + + Args: + x_list: list of base x values for regression + y_list: list of base y values for regression + is_intercept (boolean): it is true that we want an intercept value in our regression + Returns: + tuple: x and y coefficients from regression + """ + x_values = x_list + y_values = y_list + if is_intercept is True: + x_values = sm.add_constant(x_values) + model = sm.OLS(y_values, x_values) + results = model.fit() + coefficients = results.params + return coefficients + + +def regression_predicting_y(reg_history, periodstart, periodend, x_value_calendar, x_values): + """Return results of regression. + + Args: + reg_history (list): tuple of x and y coefficient based on historical regression + periodstart (list): bill + periodend (list): + x_value_calendar (list): + x_values (list) : x values that we want for projection + Returns: + list: progression of future y values + """ + x_list = regression_base_sum(periodstart, periodend, x_value_calendar, x_values) + future_y = [] + for i in x_list: + future_y.append(reg_history[0] + reg_history[1] * i) + return future_y -- GitLab