diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py index a568dfb980f13f46b886593a6f82ef7378d64f9d..f9c22cc46649fe8485339bd4037dfb0b8e0484fd 100644 --- a/bpfin/financials/financial_lib.py +++ b/bpfin/financials/financial_lib.py @@ -4,58 +4,11 @@ import copy from bpfin.lib import other as lib from bpfin.utilbills.bill_lib import form_bill_year from numpy import mean -# from bpfin.tests.testdata import sample_data as db +from bpfin.tests.testdata import sample_data as db # import bpfin.utilbills.bill_lib as bl # import pprint -def income_statement_single_year(year, income_input, bill_overview): - """calculate income statement for one single year, with some inputs and energy bill overview - - Args: - year (int): the year of this income statement - income_input (dictionary): 4 elements of inputs - bill_overview (dictionary): bill_overview from UI, with blank cells, for 4 utility_types - Returns: - dictionary: income statement with standarized items - - Description Sample: - income_input = {revenue': 100000, 'utility_expense': 60000,'non_utility_expense': 3000} - bill_overview = {'electricity': electricity_bill, 'oil': oil_bill, 'gas': gas_bill, 'water': water_bill} - """ - revenue = income_input['revenue'] - utility_expense = income_input['utility_expense'] - non_utility_expense = income_input['non_utility_expense'] - - electricity_opex = bill_overview['electricity'][year] - gas_opex = bill_overview['gas'][year] - oil_opex = bill_overview['oil'][year] - water_opex = bill_overview['water'][year] - energy_opex = electricity_opex + oil_opex + gas_opex + water_opex - - other_utility = utility_expense - energy_opex - net_non_energy_opex = other_utility + non_utility_expense - total_opex = energy_opex + net_non_energy_opex - noi = revenue - total_opex # net operating income - - income_statement = { - 'year': year, - 'revenue': revenue, - 'utility_expense': utility_expense, - 'energy_opex': energy_opex, - 'electricity_opex': electricity_opex, - 'gas_opex': gas_opex, - 'oil_opex': oil_opex, - 'water_opex': water_opex, - 'other_utility': other_utility, - 'non_utility_expense': non_utility_expense, - 'net_non_energy_opex': net_non_energy_opex, - 'total_opex': total_opex, - 'noi': noi - } - return income_statement - - def organize_bill_overview(bill_overview, analysis_date): """take bill_overview as inputs, fill in the blank annual bill with average numbers @@ -503,14 +456,31 @@ class Income_Statement_Table(): return noi_dict -# ************ ugly tests*********** -# IS_table = Income_Statement_Table(db.raw_income_input, db.bill_overview_organized) -# IS_table.project(-1.0, db.analysis_date, db.bill_overview_organized) -# assert IS_table.get_hist_table() == db.income_statement_full # test get_hist_table -# print('\n cagr =', IS_table.get_cagr()) # test get_cagr -# print('\n average hist =', IS_table.get_average()) # test get_average -# print('\n noi dict =', IS_table.get_noi_dict()) # test get_noi_dict -# print('\n 2017 income statement =', IS_table.get_single_year(2017)) # test get_single_year +# # ************ guide for front end dev *********** +# # First, fill in bill overview, save it. + +# # Second, fill 3 years of in income statement, choose growth_rate_flag. Default value = -2.0, can be anything +# growth_rate_flag = -2.0 + +# # Click calculate, take in bill_overview, the one with manual inputs, with a lot zeros +# bill_overview_organized = organize_bill_overview(db.bill_overview, db.analysis_date) + +# # Then, backend create Income_Statement_Table instance +# IS_table = Income_Statement_Table(db.raw_income_input, bill_overview_organized) + +# # Now, historical table and cagr are ready to be fetched. Can do it later with other get() +# print('\n hist_table =', IS_table.get_hist_table()) +# print('\n cagr =', IS_table.get_cagr()) + +# # Then, backend does projection calculation, call project func in Income_Statement_Table instance +# IS_table.project(growth_rate_flag, db.analysis_date, bill_overview_organized) + +# # Now, front end can get any single year and average. please follow the instruction below +# print('\n next_column =', IS_table.get_single_year(IS_table.hist_end_year + 1)) +# print('\n average_column =', IS_table.get_average()) + +# ### front end doens't need this get yet +# print('\n noi dict =', IS_table.get_noi_dict()) # ************ test draft*********** # class test_stru(): @@ -524,23 +494,3 @@ class Income_Statement_Table(): # test_list = [test_1, test_2, test_3] # form_list = list(ob.number for ob in test_list) # print(form_list) - - -# def get_income_statement_single_year(self, year, income_statement_table): -# for current_income_statement in income_statement_table: -# if current_income_statement.year == year: -# return { -# 'year': current_income_statement.year, -# 'revenue': current_income_statement.revenue, -# 'utility_expense': current_income_statement.utility_expense, -# 'energy_opex': current_income_statement.energy_opex, -# 'electricity_opex': current_income_statement.electricity_opex, -# 'gas_opex': current_income_statement.gas_opex, -# 'oil_opex': current_income_statement.oil_opex, -# 'water_opex': current_income_statement.water_opex, -# 'other_utility': current_income_statement.other_utility, -# 'non_utility_expense': current_income_statement.non_utility_expense, -# 'net_non_energy_opex': current_income_statement.net_non_energy_opex, -# 'total_opex': current_income_statement.total_opex, -# 'noi': current_income_statement.noi} -# return None diff --git a/bpfin/financials/income_statement_form_hist.py b/bpfin/financials/income_statement_form_hist.py deleted file mode 100644 index 88e8d2d8bdbcab904f68fafd2b8dbbf34f46e70a..0000000000000000000000000000000000000000 --- a/bpfin/financials/income_statement_form_hist.py +++ /dev/null @@ -1,63 +0,0 @@ -import bpfin.financials.financial_lib as fl -from bpfin.lib import other as lib - - -def income_statement_character(income_statement_hist): - """Determine annual growth rate, other_utility_percentage, non_utility_expense_percentage - !!!! This function should be deleted or rephrased in next version !! - Args: - income_statement_hist (dictionary): full income statement, with all items filled, for available years - Return: - dictionary: three characters for future projection - - Description: - income_statement_hist = {2014:{'revenue': 100000, ... ,'noi':37000}, 2015:{}, 2016:{}} - output = {'cagr': 2.45, 'other_utility_percentage': 20.4%, 'non_utility_expense_percentage': 43.5%, ..} - Note: cagr == compound annual growht rate - """ - sorted_income_hist_year = sorted(income_statement_hist) - start_year = sorted_income_hist_year[0] - end_year = sorted_income_hist_year[-1] - # if start_year == None: return None - cagr = lib.cal_cagr( - income_statement_hist[start_year]['revenue'], - income_statement_hist[end_year]['revenue'], - end_year - start_year) - revenue_sum = 0 - other_utility_sum = 0 - non_utility_expense_sum = 0 - # revenue_average = 0 - for year in sorted_income_hist_year: - revenue_sum += income_statement_hist[year]['revenue'] - other_utility_sum += income_statement_hist[year]['other_utility'] - non_utility_expense_sum += income_statement_hist[year]['non_utility_expense'] - result_dict = { - 'start_year': start_year, - 'end_year': end_year, - 'cagr': cagr, - 'other_utility_percent': other_utility_sum/revenue_sum, - 'non_utility_expense_percent': non_utility_expense_sum/revenue_sum, - 'revenue_average': revenue_sum / (end_year - start_year + 1) # average revenue - } - return result_dict - - -def form_income_statement_hist(raw_income_input, bill_overview_organized): - """ form income statement table with raw inputs from UI, and organized bill_overview. NO projection - !!!! This function should be deleted or rephrased in next version !! - Args: - raw_income_input (dictionary): dictionary of dictionary. raw inputs for income statement for available years - bill_overview_organized (dictionary): dict of dict, 4 utility types, with blank charge filled with average - Returns: - Dictionary: dict of dict, full income statement for available years - - Description: - raw_income_input = {2014: {'revenue': 90000, 'utility_expense': 55000, 'non_utility_expense': 3500}, 2015:{},} - bill_overview_organized = {'electricity':{2012: 100, 2013: 120, ...}, 'gas':{2012:100,2013:130...},...} - Output = {2014: {'year': 2014, 'revenue': ...}, 2015:{...}, 2016:{...}} - """ - income_statement_full = {} - for year in sorted(raw_income_input): - income_statement_full[year] = fl.income_statement_single_year( - year, raw_income_input[year], bill_overview_organized) - return income_statement_full diff --git a/bpfin/financials/income_statement_next.py b/bpfin/financials/income_statement_next.py deleted file mode 100644 index 0faae06c999e87d08fa6a286ecb564350ebffd1b..0000000000000000000000000000000000000000 --- a/bpfin/financials/income_statement_next.py +++ /dev/null @@ -1,68 +0,0 @@ -import bpfin.financials.financial_lib as fl -import bpfin.tests.testdata.sample_data as db -import bpfin.utilbills.bill_lib as bl -from bpfin.lib import other as lib -from bpfin.financials.income_statement_form_hist import income_statement_character - - -def income_statement_next(income_statement_hist, bill_overview_organized, growth_rate_flag): - """Project income statement for UI input. inputs are whatever bill and financial statements are available - !!!! This function should be deleted or rephrased in next version !! - Args: - income_statement_hist (dictionary): historical income statement, with all items filled, for available years - bill_overview_organized (dictionary): annual bills for 4 utility types, with blank cells filled - analysis_date (dictionary): proforma's starting date and the years of proforma - growth_rate_flag (float): indicating assumed growth rate, -2.0 == cagr, -1.0 == historical average - Returns: - dictionary: 1 year full income statement, with itmes calculated. - """ - characters = income_statement_character(income_statement_hist) - - income_next = fl.Income_Statement() - income_next.year = characters['end_year'] + 1 - - if growth_rate_flag == -1.0: - income_next.revenue = characters['revenue_average'] - else: - if growth_rate_flag == -2.0: - growth_rate = characters['cagr'] - income_next.revenue = income_statement_hist[characters['end_year']]['revenue'] * (1 + growth_rate) - else: - growth_rate = growth_rate_flag # 0.00, 0.01, 0.02 ... - income_next.revenue = income_statement_hist[characters['end_year']]['revenue'] * (1 + growth_rate) - - income_next.assign_next(characters, bill_overview_organized) - result_dict = fl.convert_income_statement_class(income_next) - return result_dict - -# def income_statement_proj_input(income_statement_full, bill_overview_organized, growth_rate_flag): -# """Project income statement for UI input. inputs are whatever bill and financial statements are available -# Args: -# income_statement_full (dictionary) -# bill_overview_organized (dictionary): bill_overview from UI, with blank cells, for 4 utility_types -# analysis_date (dictionary): proforma's starting date and the years of proforma -# growth_rate_flag (float) -# Returns: -# dictionary: -# """ -# # proforma_year = bl.form_bill_year(analysis_date['proforma_start'], analysis_date['proforma_duration']) -# characters = income_statement_character(income_statement_full) -# cagr = characters['cagr'] -# other_utility_percent = characters['other_utility_percent'] -# non_utility_expense_percent = characters['non_utility_expense_percent'] -# growth_rate = cagr # !!!! need logic for growth_rate_flag -# end_year = sorted(income_statement_full)[-1] -# income_next = fl.Income_Statement() -# income_next.year = end_year + 1 -# income_next.revenue = income_statement_full[end_year]['revenue'] * (1 + growth_rate) -# income_next.electricity_opex = bill_overview_organized['electricity'][end_year + 1] -# income_next.gas_opex = bill_overview_organized['gas'][end_year + 1] -# income_next.oil_opex = bill_overview_organized['oil'][end_year + 1] -# income_next.water_opex = bill_overview_organized['water'][end_year + 1] -# income_next.assign_next_year(other_utility_percent, non_utility_expense_percent) -# result_dict = fl.convert_income_statement_class(income_next) -# return result_dict - -# income statements should be availabe for at least 1 year. If comes with >1 years, suppose to be continued. -# income_statement_proj_input(db.income_statement_full, db.bill_overview_organized, 0.01) -# income_next(2017, db.income_statement_full, db.bill_overview_organized, -2.0) diff --git a/bpfin/financials/income_statement_projection.py b/bpfin/financials/income_statement_projection.py deleted file mode 100644 index 221225d903f4c66d6ce2aa39893dd887a594e528..0000000000000000000000000000000000000000 --- a/bpfin/financials/income_statement_projection.py +++ /dev/null @@ -1,47 +0,0 @@ -import bpfin.financials.financial_lib as fl -import bpfin.tests.testdata.sample_data as db -import bpfin.utilbills.bill_lib as bl -from bpfin.lib import other as lib -from bpfin.financials.income_statement_form_hist import income_statement_character -import pprint - - -def income_statement_projection(income_statement_hist, bill_overview_organized, growth_rate_flag, analysis_date): - """ - !!!! This function should be deleted or rephrased in next version !! - Project income statement tp future multiple years. inputs are historical income statements and annual bills. - Args: - income_statement_hist (dictionary): historical income statement, with all items filled, for available years - bill_overview_organized (dictionary): annual bills for 4 utility types, with blank cells filled with average - growth_rate_flag (float): indicating assumed growth rate, -2.0 == cagr, -1.0 == historical average - analysis_date (dictionary): proforma's starting date and the years of proforma - Returns: - dictionary: multiple year full income statement proforma - Note: cagr == compound annual growht rate - """ - characters = income_statement_character(income_statement_hist) - proforma_year = bl.form_bill_year(analysis_date['proforma_start'], - analysis_date['proforma_duration']) - result_dict = {} - last_revenue = income_statement_hist[characters['end_year']]['revenue'] - - for year in proforma_year: - if year <= characters['end_year']: - continue - income_next = fl.Income_Statement() - income_next.year = year - - if growth_rate_flag == -1.0: - income_next.revenue = characters['revenue_average'] - else: - if growth_rate_flag == -2.0: - growth_rate = characters['cagr'] - # income_next.revenue = last_revenue * (1 + growth_rate) - else: - growth_rate = growth_rate_flag # 0.00, 0.01, 0.02 ... - income_next.revenue = last_revenue * (1 + growth_rate) - - income_next.assign_next(characters, bill_overview_organized) - result_dict[year] = fl.convert_income_statement_class(income_next) - last_revenue = income_next.revenue - return result_dict diff --git a/bpfin/tests/test_financials/test_financial_lib.py b/bpfin/tests/test_financials/test_financial_lib.py index 3d9c6e6deb499a386dd5f821c3938bb5a949ec70..f4b4a36242ab83f421151e29d5c9fbbadcdc9a74 100644 --- a/bpfin/tests/test_financials/test_financial_lib.py +++ b/bpfin/tests/test_financials/test_financial_lib.py @@ -1,7 +1,6 @@ import datetime -from bpfin.financials import financial_lib as fl +import bpfin.financials.financial_lib as fl from bpfin.tests.testdata import sample_data as db -from bpfin.financials.income_statement_form_hist import form_income_statement_hist from bpfin.financials.financial_lib import Income_Statement_Table @@ -13,14 +12,6 @@ def test_organize_bill_overview(): assert output_dict == result_dict -def test_income_statement_single_year(): - input_income = db.income_input_2016 - input_bill_overview_organized = db.bill_overview_organized - output_dict = db.income_statement_2016 - result_dict = fl.income_statement_single_year(2016, input_income, input_bill_overview_organized) - assert output_dict == result_dict - - def test_Income_Statement_Table(): input_raw_income_input = db.raw_income_input input_annual_bill_table = db.bill_overview_organized diff --git a/bpfin/tests/test_financials/test_income_statement_form_hist.py b/bpfin/tests/test_financials/test_income_statement_form_hist.py deleted file mode 100644 index 56803254f6c9cb2524531199f6765979b5a40878..0000000000000000000000000000000000000000 --- a/bpfin/tests/test_financials/test_income_statement_form_hist.py +++ /dev/null @@ -1,26 +0,0 @@ -from bpfin.tests.testdata import sample_data as db -from bpfin.financials.income_statement_form_hist import income_statement_character -from bpfin.financials.income_statement_form_hist import form_income_statement_hist - - -def test_income_statement_character(): - input_income_statement_hist = db.income_statement_full - output_dict = { - 'cagr': 0.05409255338945984, - 'other_utility_percent': 0.21880340182104946, - 'non_utility_expense_percent': 0.03333333333333333, - 'revenue_average': 95000.0, - 'start_year': 2014, - 'end_year': 2016} - result_dict = income_statement_character(input_income_statement_hist) - assert output_dict == result_dict - - -def test_form_income_statement_hist(): - input_raw_income_input = db.raw_income_input - input_bill_overview_organized = db.bill_overview_organized - output_dict = db.income_statement_full - result_dict = form_income_statement_hist( - input_raw_income_input, - input_bill_overview_organized) - assert output_dict == result_dict diff --git a/bpfin/tests/test_financials/test_income_statement_proj_input.py b/bpfin/tests/test_financials/test_income_statement_proj_input.py deleted file mode 100644 index d62d326eb734010da106f9442e1ff8470ff72deb..0000000000000000000000000000000000000000 --- a/bpfin/tests/test_financials/test_income_statement_proj_input.py +++ /dev/null @@ -1,17 +0,0 @@ -from bpfin.financials import financial_lib as fl -from bpfin.tests.testdata import sample_data as db -from bpfin.financials.income_statement_next import income_statement_next - - -def test_income_statement_next(): - input_income_statement_hist = db.income_statement_full - input_bill_overview_organized = db.bill_overview_organized - growth_flag_tuple = {1: 0.01, 2: 0.00, 3: -1.0, 4: -2.0} - for i in range(4): - input_growth_rate_flag = growth_flag_tuple[i + 1] - output_dict = db.income_next[i + 1] - result_dict = income_statement_next( - input_income_statement_hist, - input_bill_overview_organized, - input_growth_rate_flag) - assert output_dict == result_dict diff --git a/bpfin/tests/test_financials/test_income_statement_projection.py b/bpfin/tests/test_financials/test_income_statement_projection.py deleted file mode 100644 index ede9633e4ed671c14f9add675dbfdbb1ea6720a8..0000000000000000000000000000000000000000 --- a/bpfin/tests/test_financials/test_income_statement_projection.py +++ /dev/null @@ -1,21 +0,0 @@ -from bpfin.tests.testdata import sample_data as db -from bpfin.financials.income_statement_form_hist import income_statement_character -from bpfin.financials.income_statement_form_hist import form_income_statement_hist - - -from bpfin.tests.testdata import sample_data as db -from bpfin.financials.income_statement_projection import income_statement_projection - - -def test_income_statement_projection(): - input_income_statement_hist = db.income_statement_full - input_bill_overview_organized = db.bill_overview_organized - input_growth_rate_flag = -2.0 - input_analysis_date = db.analysis_date - output_dict = db.income_statement_projection_cagr - result_dict = income_statement_projection( - input_income_statement_hist, - input_bill_overview_organized, - input_growth_rate_flag, - input_analysis_date) - assert output_dict == result_dict