diff --git a/bpfin/lib/__init__.py b/bpfin/lib/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/bpfin/lib/other.py b/bpfin/lib/other.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a2f081b4ff82b909e8194bcecaf9e10208a8d5eb 100644 --- a/bpfin/lib/other.py +++ b/bpfin/lib/other.py @@ -0,0 +1,480 @@ +import bpfin.lib.date +import bpfin.lib.math + +import statsmodels.api as sm +import datetime +import calendar +from dateutil.parser import * +import numpy as np +import pandas +import xlrd +from scipy.optimize import linprog +import matplotlib +matplotlib.use('TkAgg') + + +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 + + +########################################### need to check duplication ################### + +##math calculations +# divide list x by list y, return list z +def division(x, y): + z = [] + for (i, j) in zip(x, y): + if j == 0: + d = 0 + else: + d = i / j + z.append(d) + return z + + +def product2list(list1, list2): + return [x * y for x, y in zip(list1, list2)] + + +def product(list1): + a = 1 + for i in list1: + a = a * i + return a + + +def sum2list(list1, list2): + return [x + y for x, y in zip(list1, list2)] + + +def sum3list(list1, list2, list3): + return [x + y + z for x, y, z in zip(list1, list2, list3)] + + +def sublist(list1, list2): + return [x - y for x, y in zip(list1, list2)] + + +# def add_list(obj_list, number): +# return [x + number for x in obj_list] + + +def multiply_list(obj_list, number): + return [x * number for x in obj_list] + + +def form_dict(terms, obj): + obj_dict = dict(zip(terms, obj)) + return obj_dict + + +# calculate number of days in given month +# this fun is used for matrix +def days_in_month(month): + if month in {1, 3, 5, 7, 8, 10, 12}: return 31 + if month in {4, 6, 9, 11}: return 30 + if month in {2}: + return 28.25 + else: + return 0 + + +# calculate days in a range, for two list of dates +def date_diff(startdate, enddate): + return list(map(lambda x, y: (y - x).days, startdate, enddate)) + + +# 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): +# # year_term=1 +# bdstart = [] +# bdend = [] +# day = date_start +# for term in range(int(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_terms(year): + start_date = datetime.date(year, 1, 31) + terms = form_bill_calendar(start_date, 1) + return terms[1] + + +# print(form_year_terms(2013)) + +def convert_timestamp_date(list1): + return list(map(lambda x: datetime.date(x.year, x.month, x.day), list1)) + + +def cal_latest_day(terms_list): + latestday = datetime.date(1900, 1, 1) + for term_i in terms_list: + for term in term_i: + latestday = (term if term > latestday else latestday) + return latestday + + +def average(list1): + if len(list1) == 0: + return 0 + else: + return sum(list1) / len(list1) + + +def cal_CAGR(start_value, end_value, n): + if start_value != 0: + CAGR = (end_value / start_value) ** (1 / n) - 1 + else: + CAGR = 0 + return CAGR + + +# build the matrix to reflect #of days in each month +def form_month_matrix(bdstart, bdend): + monthmatrix = [[0 for i in range(12)] for j in range(len(bdstart))] + # rangeID=0 + for (fromdate, enddate, rangeID) in zip(bdstart, bdend, range(len(bdstart))): + 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 + + +def sumproduct(list1, list2): + return np.sum(m for m in np.multiply(np.array(list1), np.array(list2))) + + +# calculate monthly usage/charge with matrix, return a list +def monthly_average(daily, matrix): + month_average = [] + for month in range(1, 13): + matrixcolumn = list(map(lambda rangeID: matrix[rangeID][month - 1], range(len(daily)))) + total = sumproduct(daily, matrixcolumn) * days_in_month(month) / sum(matrixcolumn) + month_average.append(total) + return month_average + + +# oil price calculation +def cal_oil_price(oilcharge, oiluse): + if sum(oilcharge) == 0 or pd.isnull(sum(oilcharge)) == 1: + overall_price = 0 + else: + overall_price = sum(oilcharge) / sum(oiluse) + oil_price = [] + for i in range(1, 13): + oil_price.append(overall_price) + return oil_price + + +# list1=12 month values, target_terms = multiple years. Copy the values to all months +def duplicate2terms(list1, target_terms): + monthlist = range(1, 13) + dict1 = dict(zip(monthlist, list1)) + new_dict = dict(zip([], [])) + for term in target_terms: + new_dict[term] = dict1[term.month] + return [new_dict[term] for term in sorted(new_dict)] + + +# calculate max loan term and assign to total energy loan +def cal_max_term(loan_list): + max_length = 0 + max_ID = 0 + for loanID in range(len(loan_list)): + if len(loan_list[loanID].terms) >= max_length: + max_length = len(loan_list[loanID].terms) + max_ID = loanID + return loan_list[max_ID].terms + + +# calculate and assign cash flow for loans and for total energy loan +def align2term(terms1, list1, target_terms): + dict1 = dict(zip(terms1, list1)) + new_dict = dict(zip([], [])) + for term in target_terms: + if term in terms1: + new_dict[term] = dict1[term] + else: + new_dict[term] = 0 + return [new_dict[term] for term in sorted(new_dict)] + + +# calculate loan's (loan amount/debt service), just like a payback +def cal_loan_payback(interest, duration): + return ((1 + interest) ** duration - 1) / (interest * (1 + interest) ** duration) + + +# cauclate loan amount should be borrowed from each bank, given assumed total cost and loan info +def loan_allocate(total_cost, loan_list): + sum_loan_max = 0 + bound_list = [] + c_base = [] + for loan in loan_list: + sum_loan_max += loan.max_amount + c_base.append( + 1 / loan.payback) # loan amount / ratio = DS, targeting minimum total DS, equivalent to longest payback + bound_list.append((0, loan.max_amount)) + c = c_base # c_base is target function + A = [-1] * len(loan_list) + b = [max(0 - total_cost, 0 - sum_loan_max)] + bounds = bound_list + if total_cost > sum_loan_max: + print('alert: upfront cost > available loan amount') + res = linprog(c, A_ub=A, b_ub=b, bounds=bounds, options={'disp': False}) + for i in range(len(loan_list)): + loan_list[i].amount = res.x[i] + + +# return res.x + +##maybe we can use this, maybe not +# def transpose_matrix(matrix1): +# return [[r[col] for r in matrix1] for col in range(len(matrix1[0]))] + +def month_shift(month): + month_shift_dict = dict(zip([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1])) + return month_shift_dict[month] + + +####inflation calculation + +#product inflation rate from starting date to target date +# def cal_inflation_product(inflation_rate_dict,target_date): +# date_start=sorted(inflation_rate_dict)[0] +# # product=1 +# # for term in form_date_calendar(date_start,target_date)[1]: +# # product = product * inflation_rate_dict[term] +# product = np.prod(np.array([inflation_rate_dict[term] for term in form_date_calendar(date_start,target_date)[1]])) +# return product + +# def cal_previous_term(date): +# first_date=datetime.date(date.year,date.month,1) +# previous_term=first_date+datetime.timedelta(days=-1) +# return previous_term + +# ##calculate inflation_coeff_dict. Inflation=0.02, inflation rate =1.02, inflation coeff=1.02 or 0.98, or 1.00... +# # form inflation_rate_current_year +# def form_inflation_ratedict(inflationyears,inflationhist): +# hist_dict=dict(zip(inflationyears,inflationhist)) +# inflationterms=form_bill_calendar(datetime.date(inflationyears[0],1,31),len(inflationyears))[1] +# dict1={} +# for term in inflationterms: +# dict1[term]=hist_dict[term.year]/12+1 +# return dict1 #return monthly inflation rates (2016,2,29 : 100.67%) + +# 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 #return (2016,2,29 : 99.86%; present_date: 100%) + +# form inflated items, based on a 12 month list, present time is the last month of 12 months list +def form_inflated_item(base_list,target_terms,inflation_coeff_dict,present_date): + pre_year_date=datetime.date(present_date.year-1,present_date.month+1,cal_last_day(present_date.year-1,present_date.month+1)) + base_terms=form_date_calendar(pre_year_date,present_date)[1] + for term in base_terms: + base_list[term.month-1]=base_list[term.month-1]/inflation_coeff_dict[term] + 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)] + diff --git a/bpfin/prelim/prelimfuncs.py b/bpfin/prelim/prelimfuncs.py index dadda307ae1ab2e486fc97f85a2c265a432af877..f4e31c0a7d1e1047e9490c7d69e1763605ab9a39 100644 --- a/bpfin/prelim/prelimfuncs.py +++ b/bpfin/prelim/prelimfuncs.py @@ -9,310 +9,299 @@ import xlrd from scipy.optimize import linprog import matplotlib -import statsmodels.api as sm -from dateutil.parser import * -import calendar -import numpy as np -import pandas as pd -from datetime import * -import datetime, time -import xlrd -from scipy.optimize import linprog -import matplotlib - matplotlib.use('TkAgg') -##math calculations -# divide list x by list y, return list z -def division(x, y): - z = [] - for (i, j) in zip(x, y): - if j == 0: - d = 0 - else: - d = i / j - z.append(d) - return z +# ##math calculations +# # divide list x by list y, return list z +# def division(x, y): +# z = [] +# for (i, j) in zip(x, y): +# if j == 0: +# d = 0 +# else: +# d = i / j +# z.append(d) +# return z -def product2list(list1, list2): - return [x * y for x, y in zip(list1, list2)] +# def product2list(list1, list2): +# return [x * y for x, y in zip(list1, list2)] -def product(list1): - a = 1 - for i in list1: - a = a * i - return a +# def product(list1): +# a = 1 +# for i in list1: +# a = a * i +# return a -def sum2list(list1, list2): - return [x + y for x, y in zip(list1, list2)] +# def sum2list(list1, list2): +# return [x + y for x, y in zip(list1, list2)] -def sum3list(list1, list2, list3): - return [x + y + z for x, y, z in zip(list1, list2, list3)] +# def sum3list(list1, list2, list3): +# return [x + y + z for x, y, z in zip(list1, list2, list3)] -def sublist(list1, list2): - return [x - y for x, y in zip(list1, list2)] +# def sublist(list1, list2): +# return [x - y for x, y in zip(list1, list2)] -def add_list(obj_list, number): - return [x + number for x in obj_list] +# def add_list(obj_list, number): +# return [x + number for x in obj_list] -def multiply_list(obj_list, number): - return [x * number for x in obj_list] +# def multiply_list(obj_list, number): +# return [x * number for x in obj_list] -def form_dict(terms, obj): - obj_dict = dict(zip(terms, obj)) - return obj_dict +# def form_dict(terms, obj): +# obj_dict = dict(zip(terms, obj)) +# return obj_dict -# calculate number of days in given month -# this fun is used for matrix -def days_in_month(month): - if month in {1, 3, 5, 7, 8, 10, 12}: return 31 - if month in {4, 6, 9, 11}: return 30 - if month in {2}: - return 28.25 - else: - return 0 +# # calculate number of days in given month +# # this fun is used for matrix +# def days_in_month(month): +# if month in {1, 3, 5, 7, 8, 10, 12}: return 31 +# if month in {4, 6, 9, 11}: return 30 +# if month in {2}: +# return 28.25 +# else: +# return 0 -# calculate days in a range, for two list of dates -def date_diff(startdate, enddate): - return list(map(lambda x, y: (y - x).days, startdate, enddate)) +# # calculate days in a range, for two list of dates +# def date_diff(startdate, enddate): +# return list(map(lambda x, y: (y - x).days, startdate, enddate)) -def cal_last_day(obj_year, obj_month): - _, last_day_num = calendar.monthrange(obj_year, obj_month) - return last_day_num +# 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): - # year_term=1 - bdstart = [] - bdend = [] - day = date_start - for term in range(int(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_bill_calendar(date_start, year_term): +# # year_term=1 +# bdstart = [] +# bdend = [] +# day = date_start +# for term in range(int(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_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_terms(year): - start_date = datetime.date(year, 1, 31) - terms = form_bill_calendar(start_date, 1) - return terms[1] +# def form_year_terms(year): +# start_date = datetime.date(year, 1, 31) +# terms = form_bill_calendar(start_date, 1) +# return terms[1] -# print(form_year_terms(2013)) +# # print(form_year_terms(2013)) -def convert_timestamp_date(list1): - return list(map(lambda x: datetime.date(x.year, x.month, x.day), list1)) +# def convert_timestamp_date(list1): +# return list(map(lambda x: datetime.date(x.year, x.month, x.day), list1)) -def cal_latest_day(terms_list): - latestday = datetime.date(1900, 1, 1) - for term_i in terms_list: - for term in term_i: - latestday = (term if term > latestday else latestday) - return latestday +# def cal_latest_day(terms_list): +# latestday = datetime.date(1900, 1, 1) +# for term_i in terms_list: +# for term in term_i: +# latestday = (term if term > latestday else latestday) +# return latestday -def average(list1): - if len(list1) == 0: - return 0 - else: - return sum(list1) / len(list1) - - -def cal_CAGR(start_value, end_value, n): - if start_value != 0: - CAGR = (end_value / start_value) ** (1 / n) - 1 - else: - CAGR = 0 - return CAGR - - -# build the matrix to reflect #of days in each month -def form_month_matrix(bdstart, bdend): - monthmatrix = [[0 for i in range(12)] for j in range(len(bdstart))] - # rangeID=0 - for (fromdate, enddate, rangeID) in zip(bdstart, bdend, range(len(bdstart))): - 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 - - -def sumproduct(list1, list2): - return np.sum(m for m in np.multiply(np.array(list1), np.array(list2))) - - -# calculate monthly usage/charge with matrix, return a list -def monthly_average(daily, matrix): - month_average = [] - for month in range(1, 13): - matrixcolumn = list(map(lambda rangeID: matrix[rangeID][month - 1], range(len(daily)))) - total = sumproduct(daily, matrixcolumn) * days_in_month(month) / sum(matrixcolumn) - month_average.append(total) - return month_average - - -# oil price calculation -def cal_oil_price(oilcharge, oiluse): - if sum(oilcharge) == 0 or pd.isnull(sum(oilcharge)) == 1: - overall_price = 0 - else: - overall_price = sum(oilcharge) / sum(oiluse) - oil_price = [] - for i in range(1, 13): - oil_price.append(overall_price) - return oil_price - - -# list1=12 month values, target_terms = multiple years. Copy the values to all months -def duplicate2terms(list1, target_terms): - monthlist = range(1, 13) - dict1 = dict(zip(monthlist, list1)) - new_dict = dict(zip([], [])) - for term in target_terms: - new_dict[term] = dict1[term.month] - return [new_dict[term] for term in sorted(new_dict)] - - -# calculate max loan term and assign to total energy loan -def cal_max_term(loan_list): - max_length = 0 - max_ID = 0 - for loanID in range(len(loan_list)): - if len(loan_list[loanID].terms) >= max_length: - max_length = len(loan_list[loanID].terms) - max_ID = loanID - return loan_list[max_ID].terms - - -# calculate and assign cash flow for loans and for total energy loan -def align2term(terms1, list1, target_terms): - dict1 = dict(zip(terms1, list1)) - new_dict = dict(zip([], [])) - for term in target_terms: - if term in terms1: - new_dict[term] = dict1[term] - else: - new_dict[term] = 0 - return [new_dict[term] for term in sorted(new_dict)] - - -# calculate loan's (loan amount/debt service), just like a payback -def cal_loan_payback(interest, duration): - return ((1 + interest) ** duration - 1) / (interest * (1 + interest) ** duration) - - -# cauclate loan amount should be borrowed from each bank, given assumed total cost and loan info -def loan_allocate(total_cost, loan_list): - sum_loan_max = 0 - bound_list = [] - c_base = [] - for loan in loan_list: - sum_loan_max += loan.max_amount - c_base.append( - 1 / loan.payback) # loan amount / ratio = DS, targeting minimum total DS, equivalent to longest payback - bound_list.append((0, loan.max_amount)) - c = c_base # c_base is target function - A = [-1] * len(loan_list) - b = [max(0 - total_cost, 0 - sum_loan_max)] - bounds = bound_list - if total_cost > sum_loan_max: - print('alert: upfront cost > available loan amount') - res = linprog(c, A_ub=A, b_ub=b, bounds=bounds, options={'disp': False}) - for i in range(len(loan_list)): - loan_list[i].amount = res.x[i] - - -# return res.x - -##maybe we can use this, maybe not -# def transpose_matrix(matrix1): -# return [[r[col] for r in matrix1] for col in range(len(matrix1[0]))] - -def month_shift(month): - month_shift_dict = dict(zip([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1])) - return month_shift_dict[month] - - -####inflation calculation - -#product inflation rate from starting date to target date -def cal_inflation_product(inflation_rate_dict,target_date): - date_start=sorted(inflation_rate_dict)[0] -# product=1 -# for term in form_date_calendar(date_start,target_date)[1]: -# product = product * inflation_rate_dict[term] - product = np.prod(np.array([inflation_rate_dict[term] for term in form_date_calendar(date_start,target_date)[1]])) - return product - -def cal_previous_term(date): - first_date=datetime.date(date.year,date.month,1) - previous_term=first_date+datetime.timedelta(days=-1) - return previous_term - -##calculate inflation_coeff_dict. Inflation=0.02, inflation rate =1.02, inflation coeff=1.02 or 0.98, or 1.00... -# form inflation_rate_current_year -def form_inflation_ratedict(inflationyears,inflationhist): - hist_dict=dict(zip(inflationyears,inflationhist)) - inflationterms=form_bill_calendar(datetime.date(inflationyears[0],1,31),len(inflationyears))[1] - dict1={} - for term in inflationterms: - dict1[term]=hist_dict[term.year]/12+1 - return dict1 #return monthly inflation rates (2016,2,29 : 100.67%) - -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 #return (2016,2,29 : 99.86%; present_date: 100%) - -# form inflated items, based on a 12 month list, present time is the last month of 12 months list -def form_inflated_item(base_list,target_terms,inflation_coeff_dict,present_date): - pre_year_date=datetime.date(present_date.year-1,present_date.month+1,cal_last_day(present_date.year-1,present_date.month+1)) - base_terms=form_date_calendar(pre_year_date,present_date)[1] - for term in base_terms: - base_list[term.month-1]=base_list[term.month-1]/inflation_coeff_dict[term] - 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 average(list1): +# if len(list1) == 0: +# return 0 +# else: +# return sum(list1) / len(list1) + + +# def cal_CAGR(start_value, end_value, n): +# if start_value != 0: +# CAGR = (end_value / start_value) ** (1 / n) - 1 +# else: +# CAGR = 0 +# return CAGR + + +# # build the matrix to reflect #of days in each month +# def form_month_matrix(bdstart, bdend): +# monthmatrix = [[0 for i in range(12)] for j in range(len(bdstart))] +# # rangeID=0 +# for (fromdate, enddate, rangeID) in zip(bdstart, bdend, range(len(bdstart))): +# 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 + + +# def sumproduct(list1, list2): +# return np.sum(m for m in np.multiply(np.array(list1), np.array(list2))) + + +# # calculate monthly usage/charge with matrix, return a list +# def monthly_average(daily, matrix): +# month_average = [] +# for month in range(1, 13): +# matrixcolumn = list(map(lambda rangeID: matrix[rangeID][month - 1], range(len(daily)))) +# total = sumproduct(daily, matrixcolumn) * days_in_month(month) / sum(matrixcolumn) +# month_average.append(total) +# return month_average + + +# # oil price calculation +# def cal_oil_price(oilcharge, oiluse): +# if sum(oilcharge) == 0 or pd.isnull(sum(oilcharge)) == 1: +# overall_price = 0 +# else: +# overall_price = sum(oilcharge) / sum(oiluse) +# oil_price = [] +# for i in range(1, 13): +# oil_price.append(overall_price) +# return oil_price + + +# # list1=12 month values, target_terms = multiple years. Copy the values to all months +# def duplicate2terms(list1, target_terms): +# monthlist = range(1, 13) +# dict1 = dict(zip(monthlist, list1)) +# new_dict = dict(zip([], [])) +# for term in target_terms: +# new_dict[term] = dict1[term.month] +# return [new_dict[term] for term in sorted(new_dict)] + + +# # calculate max loan term and assign to total energy loan +# def cal_max_term(loan_list): +# max_length = 0 +# max_ID = 0 +# for loanID in range(len(loan_list)): +# if len(loan_list[loanID].terms) >= max_length: +# max_length = len(loan_list[loanID].terms) +# max_ID = loanID +# return loan_list[max_ID].terms + + +# # calculate and assign cash flow for loans and for total energy loan +# def align2term(terms1, list1, target_terms): +# dict1 = dict(zip(terms1, list1)) +# new_dict = dict(zip([], [])) +# for term in target_terms: +# if term in terms1: +# new_dict[term] = dict1[term] +# else: +# new_dict[term] = 0 +# return [new_dict[term] for term in sorted(new_dict)] + + +# # calculate loan's (loan amount/debt service), just like a payback +# def cal_loan_payback(interest, duration): +# return ((1 + interest) ** duration - 1) / (interest * (1 + interest) ** duration) + + +# # cauclate loan amount should be borrowed from each bank, given assumed total cost and loan info +# def loan_allocate(total_cost, loan_list): +# sum_loan_max = 0 +# bound_list = [] +# c_base = [] +# for loan in loan_list: +# sum_loan_max += loan.max_amount +# c_base.append( +# 1 / loan.payback) # loan amount / ratio = DS, targeting minimum total DS, equivalent to longest payback +# bound_list.append((0, loan.max_amount)) +# c = c_base # c_base is target function +# A = [-1] * len(loan_list) +# b = [max(0 - total_cost, 0 - sum_loan_max)] +# bounds = bound_list +# if total_cost > sum_loan_max: +# print('alert: upfront cost > available loan amount') +# res = linprog(c, A_ub=A, b_ub=b, bounds=bounds, options={'disp': False}) +# for i in range(len(loan_list)): +# loan_list[i].amount = res.x[i] + + +# # return res.x + +# ##maybe we can use this, maybe not +# # def transpose_matrix(matrix1): +# # return [[r[col] for r in matrix1] for col in range(len(matrix1[0]))] + +# def month_shift(month): +# month_shift_dict = dict(zip([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1])) +# return month_shift_dict[month] + + +# ####inflation calculation + +# #product inflation rate from starting date to target date +# def cal_inflation_product(inflation_rate_dict,target_date): +# date_start=sorted(inflation_rate_dict)[0] +# # product=1 +# # for term in form_date_calendar(date_start,target_date)[1]: +# # product = product * inflation_rate_dict[term] +# product = np.prod(np.array([inflation_rate_dict[term] for term in form_date_calendar(date_start,target_date)[1]])) +# return product + +# def cal_previous_term(date): +# first_date=datetime.date(date.year,date.month,1) +# previous_term=first_date+datetime.timedelta(days=-1) +# return previous_term + +# ##calculate inflation_coeff_dict. Inflation=0.02, inflation rate =1.02, inflation coeff=1.02 or 0.98, or 1.00... +# # form inflation_rate_current_year +# def form_inflation_ratedict(inflationyears,inflationhist): +# hist_dict=dict(zip(inflationyears,inflationhist)) +# inflationterms=form_bill_calendar(datetime.date(inflationyears[0],1,31),len(inflationyears))[1] +# dict1={} +# for term in inflationterms: +# dict1[term]=hist_dict[term.year]/12+1 +# return dict1 #return monthly inflation rates (2016,2,29 : 100.67%) + +# 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 #return (2016,2,29 : 99.86%; present_date: 100%) + +# # form inflated items, based on a 12 month list, present time is the last month of 12 months list +# def form_inflated_item(base_list,target_terms,inflation_coeff_dict,present_date): +# pre_year_date=datetime.date(present_date.year-1,present_date.month+1,cal_last_day(present_date.year-1,present_date.month+1)) +# base_terms=form_date_calendar(pre_year_date,present_date)[1] +# for term in base_terms: +# base_list[term.month-1]=base_list[term.month-1]/inflation_coeff_dict[term] +# 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)] ## define all classes # energy bill, including historical data, normalized bill on monthly basis diff --git a/bpfin/tests/test_utilbills/__init__.py b/bpfin/tests/test_utilbills/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/bpfin/tests/test_utilbills/test_month_normalize_rough.py b/bpfin/tests/test_utilbills/test_month_normalize_rough.py new file mode 100644 index 0000000000000000000000000000000000000000..63d7ee1e42483f845074f3d4f91d451edeb7cbd0 --- /dev/null +++ b/bpfin/tests/test_utilbills/test_month_normalize_rough.py @@ -0,0 +1,39 @@ +import bpfin.utilbills.bill_month_normalize_rough as ub +import datetime + + +test_raw_bill = {} + +test_raw_bill['date_from'] = [ + datetime.date(2014, 4, 17), datetime.date(2014, 5, 16), datetime.date(2014, 6, 17), + datetime.date(2014, 7, 17), datetime.date(2014, 8, 15), datetime.date(2014, 9, 16), + datetime.date(2014, 10, 16), datetime.date(2014, 11, 14), datetime.date(2014, 12, 17), + datetime.date(2015, 1, 16), datetime.date(2015, 2, 18), datetime.date(2015, 3, 19), + datetime.date(2015, 4, 17), datetime.date(2015, 5, 18), datetime.date(2015, 6, 17), + datetime.date(2015, 7, 17), datetime.date(2015, 8, 17), datetime.date(2015, 9, 16), + datetime.date(2015, 10, 16), datetime.date(2015, 11, 16), datetime.date(2015, 12, 17), + datetime.date(2016, 1, 19), datetime.date(2016, 2, 18), datetime.date(2016, 3, 18)] + +test_raw_bill['date_to'] = [ + datetime.date(2014, 5, 16), datetime.date(2014, 6, 17), datetime.date(2014, 7, 17), + datetime.date(2014, 8, 15), datetime.date(2014, 9, 16), datetime.date(2014, 10, 16), + datetime.date(2014, 11, 14), datetime.date(2014, 12, 17), datetime.date(2015, 1, 16), + datetime.date(2015, 2, 18), datetime.date(2015, 3, 19), datetime.date(2015, 4, 17), + datetime.date(2015, 5, 18), datetime.date(2015, 6, 17), datetime.date(2015, 7, 17), + datetime.date(2015, 8, 17), datetime.date(2015, 9, 16), datetime.date(2015, 10, 16), + datetime.date(2015, 11, 16), datetime.date(2015, 12, 17), datetime.date(2016, 1, 19), + datetime.date(2016, 2, 18), datetime.date(2016, 3, 18), datetime.date(2016, 4, 18)] + +test_raw_bill['charge'] = [ + 2601.6289696969693, 2642.1740261508003, 3437.551946607342, 2930.5070588449826, + 2514.1242835094554, 2804.4448749999997, 3237.7359972191325, 3289.4155027808674, + 2796.5700000000002, 2463.5113047830923, 2370.0007392051775, 2479.081440860215] + +test_raw_bill['usage'] = [ + 0.094265231101663627, 0.10175446346513953, 0.12248981352003527, 0.11229655777596657, + 0.092170964664193167, 0.094173672324921492, 0.095187070309577237, 0.097177529967719486, + 0.095676831493476874, 0.091583582602530869, 0.089122740090923164, 0.091516956021057888] + +test_raw_bill['utility_type'] = 'electricity' + +print(ub.bill_month_normalize_rough(test_raw_bill)) diff --git a/bpfin/utilbills/BPFINPATH b/bpfin/utilbills/BPFINPATH new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/bpfin/utilbills/bill_lib.py b/bpfin/utilbills/bill_lib.py index 8aa7522ff0d7359cc48d5b9e0ecf06d43805ffda..d872fbee0ed63811eee2b0ee9164680f1508f4ce 100644 --- a/bpfin/utilbills/bill_lib.py +++ b/bpfin/utilbills/bill_lib.py @@ -3,6 +3,7 @@ import datetime import calendar + def add_list(obj_list, number): """Add a number to each value in a list. diff --git a/bpfin/utilbills/bill_month_normalize_rough.py b/bpfin/utilbills/bill_month_normalize_rough.py new file mode 100644 index 0000000000000000000000000000000000000000..07d0772db98f0143714717418e845480823bdd71 --- /dev/null +++ b/bpfin/utilbills/bill_month_normalize_rough.py @@ -0,0 +1,77 @@ +import datetime +# import sys +import bpfin.lib.other as lib + +# sys.path.append('C:/Users/zheng/Documents/BlocPower_Work_File/7. Python/') + + +# class Bill(): +# def __init__(self, raw_bill): +# self.billstart = lib.convert_timestamp_date(raw_bill['date_from']) +# self.billend = lib.convert_timestamp_date(raw_bill['date_to']) +# self.usage = raw_bill['usage'] +# self.charge = raw_bill['charge'] +# self.utility_type = raw_bill['utility_type'] + +# def normalize_rough(self): +# if self.billstart != []: +# monthmatrix = lib.form_month_matrix(self.billstart, self.billend) +# # self.hist_daily_usage = lib.division(self.usage, lib.date_diff(self.billstart, self.billend)) +# # self.hist_daily_charge = lib.division(self.charge, lib.date_diff(self.billstart, self.billend)) +# # self.hist_monthly_usage = lib.monthly_average(self.hist_daily_usage, monthmatrix) +# # self.hist_monthly_charge = lib.monthly_average(self.hist_daily_charge, monthmatrix) +# # self.hist_monthly_price = lib.division(self.hist_monthly_charge, self.hist_monthly_usage) + +# daily_usage = lib.division(self.usage, lib.date_diff(self.billstart, self.billend)) +# daily_charge = lib.division(self.charge, lib.date_diff(self.billstart, self.billend)) +# month_norm_usage = lib.monthly_average(daily_usage, monthmatrix) +# month_norm_charge = lib.monthly_average(daily_charge, monthmatrix) +# month_norm_price = lib.division(month_norm_charge, month_norm_usage) +# else: +# month_norm_usage = [0] * 12 +# month_norm_charge = [0] * 12 +# month_norm_price = [0] * 12 + +# result_dict = { +# 'monthly_usage': month_norm_usage, +# 'monthly_charge': month_norm_charge, +# 'monthly_price': month_norm_price} +# return result_dict + + # def prior(self, FinancialDict): + # [self.prior_billstart, self.prior_billend] = form_bill_calendar(FinancialDict['ProForma_Start'], + # FinancialDict['ProForma_Duration']) + # self.prior_monthly_usage = duplicate2terms(self.hist_monthly_usage, self.prior_billend) + # self.prior_monthly_price = form_inflated_item(self.hist_monthly_price, self.prior_billend, + # FinancialDict['inflation_coeff_dict'], + # FinancialDict['present_date']) + # self.prior_monthly_charge = product2list(self.prior_monthly_usage, self.prior_monthly_price) + + +def bill_month_normalize_rough(raw_bill): + print('\n let the normalization starts') + print(raw_bill) + + billstart = lib.convert_timestamp_date(raw_bill['date_from']) + billend = lib.convert_timestamp_date(raw_bill['date_to']) + usage = raw_bill['usage'] + charge = raw_bill['charge'] + utility_type = raw_bill['utility_type'] + + if billstart != []: + monthmatrix = lib.form_month_matrix(billstart, billend) + daily_usage = lib.division(usage, lib.date_diff(billstart, billend)) + daily_charge = lib.division(charge, lib.date_diff(billstart, billend)) + + month_norm_usage = lib.monthly_average(daily_usage, monthmatrix) + month_norm_charge = lib.monthly_average(daily_charge, monthmatrix) + month_norm_price = lib.division(month_norm_charge, month_norm_usage) + else: + month_norm_usage = [0] * 12 + month_norm_charge = [0] * 12 + month_norm_price = [0] * 12 + + print("\n It goes ok") + return {'monthly_usage': month_norm_usage, + 'monthly_charge': month_norm_charge, + 'monthly_price': month_norm_price}