diff --git a/bpfin/lib/date.py b/bpfin/lib/date.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/bpfin/lib/math.py b/bpfin/lib/math.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/bpfin/lib/other.py b/bpfin/lib/other.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..a5c6aec09b35dae80ca9891883fb160a5a968cdc --- /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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/bpfin/utilbills/***old_billprojections.py b/bpfin/utilbills/***old_billprojections.py new file mode 100644 index 0000000000000000000000000000000000000000..b345a4eae8f9347dcc40130f0ed00a7378877e3b --- /dev/null +++ b/bpfin/utilbills/***old_billprojections.py @@ -0,0 +1,543 @@ +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 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 + + +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 + + +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 + + +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 + + +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)] 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 0000000000000000000000000000000000000000..8aa7522ff0d7359cc48d5b9e0ecf06d43805ffda --- /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 0000000000000000000000000000000000000000..e7d365e4e7a3ff7601519cf12c07d7dcd95fccb0 --- /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 0000000000000000000000000000000000000000..18b204670788a9b89cf01a63be79d32f73a05d8f --- /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 0000000000000000000000000000000000000000..b6165deded2fe6f1674199c3b54e70a1d5adb9d9 --- /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 diff --git a/bpfin/utilbills/billprojections.py b/bpfin/utilbills/billprojections.py deleted file mode 100644 index 02119f7db8a4898be45158da2824f89a8300d6b9..0000000000000000000000000000000000000000 --- a/bpfin/utilbills/billprojections.py +++ /dev/null @@ -1,323 +0,0 @@ -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): - return [x + number for x in obj_list] - - -def cal_last_day(obj_year, obj_month): - _, last_day_num = calendar.monthrange(obj_year, obj_month) - return last_day_num - - -def form_bill_calendar(date_start, year_term): - 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): - 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): - 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): - 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, - present_date): # base_list is the base value near the present month - 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): - 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): - 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): - 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 daily_average_use_or_charge(from_date, to_date, total_utility_use_or_charge): - fromdate = [] - todate = [] - for x in from_date: - fromdate.append(x) - for y in to_date: - todate.append(y) - interstore = [list(x) for x in zip(fromdate, todate)] - finalstore = [] - for x in interstore: - f = (x[1] - x[0]) - finalstore.append(f.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) - 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 - 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)): - 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 - date = date + datetime.timedelta(1) - return monthmatrix - - -# returns 2d list -# [0, 4, 20...] means for jan, bill 1 has 0 days, bill 2 has 4 days -def finalmatrix(matrixchoice): - 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): - newlist = [] - for i in matrix_choice: - newlist.append((sum(list(i)))) - divider = [x / y for x, y in zip(newlist, year)] - return divider - - -# calculate charge and usage as one array with 12 values representing the month -def monthly_info(billing_info, matrix, divider): - 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)] - total = 0 - for i in range(len(z)): - total += z[i] - 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): - a = sum(oilcharge) - b = sum(oiluse) - oprice = a / b - newlist = [] - for i in range(1, 13): - newlist.append(oprice) - return newlist - - -def monthly_price(charge, use): - finalmonthprice = [x / y for x, y in zip(charge, use)] - return finalmonthprice - - -def occupancy_final_list(occupancy_rate_list): - hours_in_day = 24 - occupancy_list = [] - for x in occupancy_rate_list: - occupancy_list.append(x * 24) - return occupancy_list - - -def regression_base_sum(bill_start_utility, bill_end_utility, x_value_calendar, x_values): - 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): - X = x_list - Y = y_list - if is_intercept == True: - X = sm.add_constant(X) - model = sm.OLS(Y, X) - results = model.fit() - coefficients = results.params - return coefficients - - -def regression_predicting_y(reg_history, periodstart, periodend, x_value_calendar, x_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 - - -def rate_plan_cons(date, con, limit, leap, supply_charge, basic_charge, tax_rate, adjustments): - 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): - 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 [x * price for x in con_list] - - -def utility_charge_sum(list1, list2, list3): - return [x + y + z for x, y, z in zip(list1, list2, list3)] - - -def charge_dictionary(billperiod, charge_list): - bdday = [] - 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)] - - dicthelper = {key: value for key, value in zip(billperiod, charge_list)} - - return dicthelper - - -def charge_with_inflation(billperiod, bill_dictionary, inf_dictionary): - 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 a, b in bill_dictionary.items(): - for c, d in inf_dictionary.items(): - if a == c: - list_helper.append(b * d) - 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)]