From e9885f1072349b96daade976f4312834a0002157 Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Thu, 4 May 2017 11:01:09 -0400 Subject: [PATCH 01/11] Create scenario file fix print issue i loan_allocation --- bpfin/financials/loan_allocation.py | 3 +-- bpfin/financials/scenario.py | 0 2 files changed, 1 insertion(+), 2 deletions(-) create mode 100644 bpfin/financials/scenario.py diff --git a/bpfin/financials/loan_allocation.py b/bpfin/financials/loan_allocation.py index c0d8149..0833d30 100644 --- a/bpfin/financials/loan_allocation.py +++ b/bpfin/financials/loan_allocation.py @@ -67,10 +67,9 @@ def loan_allocation( if customer wants to S-F, but SF first -> max(xi) = cost - SF_max """ sum_loan_max_amount = sum(list(current_loan.max_amount for current_loan in loan_list)) - print('\n sum_loan_max_amount=', sum_loan_max_amount) # pre-request judge: project cost should be lower than total available financing if (sum_loan_max_amount + customer_preference['downpayment_max']) <= scenario['cost_estimation']: - print('alert: not financiable') + # print('alert: not financiable') return None # linear programming (LP) diff --git a/bpfin/financials/scenario.py b/bpfin/financials/scenario.py new file mode 100644 index 0000000..e69de29 -- GitLab From b0f1749af02907ba5ae7318db71247952bec16e9 Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Thu, 4 May 2017 11:43:10 -0400 Subject: [PATCH 02/11] Move loan_test to a separate file --- bpfin/financials/saving.py | 2 +- bpfin/financials/scenario.py | 24 +++++++++++++++++ .../test_financials/test_financial_lib.py | 24 ----------------- bpfin/tests/test_financials/test_loan.py | 26 +++++++++++++++++++ bpfin/tests/testdata/sample_data.py | 6 ++--- 5 files changed, 54 insertions(+), 28 deletions(-) create mode 100644 bpfin/tests/test_financials/test_loan.py diff --git a/bpfin/financials/saving.py b/bpfin/financials/saving.py index befb92a..4d2e45f 100644 --- a/bpfin/financials/saving.py +++ b/bpfin/financials/saving.py @@ -220,7 +220,7 @@ class Saving_Overview(): self, bill_overview, prior_annual_bill_table, - analysis_date, + analysis_date, # consider to replace it with proforma_date commissioning_date): """ Initiate Saving_Overview. diff --git a/bpfin/financials/scenario.py b/bpfin/financials/scenario.py index e69de29..615dd72 100644 --- a/bpfin/financials/scenario.py +++ b/bpfin/financials/scenario.py @@ -0,0 +1,24 @@ +from bpfin.financials.financial_lib import Income_Statement_Table +from bpfin.utilbills.bill_lib import form_bill_calendar +from bpfin.financials.saving import Saving_Overview +from bpfin.financials.loan import Loan_List +import copy + + +class Scenario(): + def __init__(self, prior_income_statement, prior_balance_sheet, + analysis_date, commission_date, construction_cost, + bill_overview, prior_annual_bill_table, loan_input_list): + self.prior_income_statement = copy.deepcopy(prior_income_statement) + self.prior_balance_sheet = copy.deepcopy(prior_balance_sheet) + self.proforma_date = form_bill_calendar(analysis_date['proforma_start'], analysis_date['proforma_duration'])[1] + self.commission_date = copy.deepcopy(commission_date) + self.construction_cost = copy.deepcopy(construction_cost) + + self.saving_overview = Saving_Overview( + bill_overview=copy.deepcopy(bill_overview), + prior_annual_bill_table=copy.deepcopy(prior_annual_bill_table), + analysis_date=copy.deepcopy(analysis_date), + commissioning_date=copy.deepcopy(commission_date) + ) + self.loan_list = Loan_List(loan_input_list) diff --git a/bpfin/tests/test_financials/test_financial_lib.py b/bpfin/tests/test_financials/test_financial_lib.py index f853cc7..0799fdb 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 import bpfin.financials.financial_lib as fl from bpfin.tests.testdata import sample_data as db -from bpfin.financials.loan import Loan_List from bpfin.financials.financial_lib import Income_Statement_Table from bpfin.financials.financial_lib import Balance_Sheet_Table @@ -39,29 +38,6 @@ def test_Income_Statement_Table(): assert IS_table.get_first_year_noi(datetime.date(2017, 3, 14)) == output_first_year_noi -def test_Loan_List(): - """ - test Loan and Loan_List classes. - by calling Loan_List.get_schedule(), all calculation functions are called and tested. - """ - input_loan_input_list = db.loan_input_list - input_customer_preference = db.customer_preference - input_scenario = db.scenario - input_req_dscr = db.req_dscr - input_loan_start_date = datetime.date(2017, 1, 12) - output_loan1_end_balance = db.loan1_end_balance - sample_loan_list = Loan_List(input_loan_input_list) - result_loan_list = sample_loan_list.get_schedule( - input_customer_preference, - input_scenario, - input_req_dscr, - input_loan_start_date, - 28000.0, - 28000.0, - 100000.0) - assert output_loan1_end_balance == result_loan_list[0].principal_end_balance - - def test_Balance_Sheet_Table(): input_raw_balance_sheet = db.raw_balance_sheet output_hist_balance_sheet_table = db.hist_balance_sheet diff --git a/bpfin/tests/test_financials/test_loan.py b/bpfin/tests/test_financials/test_loan.py new file mode 100644 index 0000000..015bea7 --- /dev/null +++ b/bpfin/tests/test_financials/test_loan.py @@ -0,0 +1,26 @@ +import datetime +from bpfin.tests.testdata import sample_data as db +from bpfin.financials.loan import Loan_List + + +def test_Loan_List(): + """ + test Loan and Loan_List classes. + by calling Loan_List.get_schedule(), all calculation functions are called and tested. + """ + input_loan_input_list = db.loan_input_list + input_customer_preference = db.customer_preference + input_scenario = db.scenario_input + input_req_dscr = db.req_dscr + input_loan_start_date = db.commision_date + output_loan1_end_balance = db.loan1_end_balance + sample_loan_list = Loan_List(input_loan_input_list) + result_loan_list = sample_loan_list.get_schedule( + input_customer_preference, + input_scenario, + input_req_dscr, + input_loan_start_date, + 28000.0, + 28000.0, + 100000.0) + assert output_loan1_end_balance == result_loan_list[0].principal_end_balance diff --git a/bpfin/tests/testdata/sample_data.py b/bpfin/tests/testdata/sample_data.py index 1f1c41f..8208b87 100644 --- a/bpfin/tests/testdata/sample_data.py +++ b/bpfin/tests/testdata/sample_data.py @@ -549,13 +549,13 @@ customer_preference = { } # Engineering Scenarios -scenario = { +scenario_input = { 'cost_estimation': 150000.00, - # 'saving': saving_dict, - # 'post_income_statement': post_income_statement } +commision_date = datetime.date(2017, 3, 14) + # Financing plan loan1_end_balance = [ 24863.347680778272, 24725.784346095064, 24587.303922513969, -- GitLab From c49228552a64b21b91a6a39f353ad8f934b6e433 Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Thu, 4 May 2017 11:50:47 -0400 Subject: [PATCH 03/11] Modify loan_allocation, replace scenario dict input with cost input --- bpfin/financials/loan.py | 18 ++++++------------ bpfin/financials/loan_allocation.py | 17 +++++++++-------- bpfin/tests/test_financials/test_loan.py | 4 ++-- bpfin/tests/testdata/sample_data.py | 6 +----- 4 files changed, 18 insertions(+), 27 deletions(-) diff --git a/bpfin/financials/loan.py b/bpfin/financials/loan.py index 7b34897..966ed12 100644 --- a/bpfin/financials/loan.py +++ b/bpfin/financials/loan.py @@ -133,7 +133,7 @@ class Loan_List(): temp_loan = Loan(current_loan) self.loan_list.append(temp_loan) - def allocate(self, customer_preference, scenario, req_dscr, first_year_saving, first_year_noi, first_year_cash): + def allocate(self, customer_preference, cost, req_dscr, first_year_saving, first_year_noi, first_year_cash): """ Allocate loan amount based on project cost, loan terms, income statements, scenario, other requirements. Apply linear programming method to allocate loan amount among loans, create financing plan. @@ -143,10 +143,7 @@ class Loan_List(): 'expected_payback': int, months that customer expect the project can payback, 'cust_saving_dscr': float, customer required lower limit of (saving / debt service) ratio } - scenario (dictionary): dict of project economics and saving scenario, { - 'cost_estimation': float, estimated project cost - 'post_income_statement': objective of Income_Statement_Table , projected income_statement with savings - } + cost (float): construction cost, can be estimated or quoted req_dscr (dictionary): dict of required debt service coverage ratios, { 'req_noi_dscr': 1.15, 'req_cash_dscr': 1.15, @@ -160,13 +157,13 @@ class Loan_List(): """ current_loan_list = copy.deepcopy(self.loan_list) allocation = loan_allocation(current_loan_list, customer_preference, - scenario, req_dscr, first_year_saving, + cost, req_dscr, first_year_saving, first_year_noi, first_year_cash) for current_loan, current_amount in zip(current_loan_list, allocation): current_loan.put_amount(current_amount) return current_loan_list - def get_schedule(self, customer_preference, scenario, req_dscr, + def get_schedule(self, customer_preference, cost, req_dscr, loan_start_date, first_year_saving, first_year_noi, first_year_cash): """ @@ -177,10 +174,7 @@ class Loan_List(): 'expected_payback': int, months that customer expect the project can payback, 'cust_saving_dscr': float, customer required lower limit of (saving / debt service) ratio } - scenario (dictionary): dict of project economics and saving scenario, { - 'cost_estimation': float, estimated project cost - 'post_income_statement': objective of Income_Statement_Table , projected income_statement with savings - } + cost (float): construction cost, can be estimated or quoted req_dscr (dictionary): dict of required debt service coverage ratios, { 'req_noi_dscr': 1.15, 'req_cash_dscr': 1.15, @@ -194,7 +188,7 @@ class Loan_List(): Returns: list: list of Loan objects, with amounts and schedules assigned """ - allocated_loan_list = self.allocate(customer_preference, scenario, + allocated_loan_list = self.allocate(customer_preference, cost, req_dscr, first_year_saving, first_year_noi, first_year_cash) for current_loan in allocated_loan_list: diff --git a/bpfin/financials/loan_allocation.py b/bpfin/financials/loan_allocation.py index 0833d30..020f9c3 100644 --- a/bpfin/financials/loan_allocation.py +++ b/bpfin/financials/loan_allocation.py @@ -4,7 +4,7 @@ from scipy.optimize import linprog def loan_allocation( loan_list, customer_preference, - scenario, + cost, req_dscr, first_year_saving, first_year_noi, @@ -34,12 +34,13 @@ def loan_allocation( loan_list (list): list of objectives of loans customer_preference (dictionary): customer preference for financing plan req_dscr(dictionary): required dscr - scenario (dictionary): package of energy conservation measures (ECMs) + cost (float): construction cost, can be estimated or quoted first_year_saving (float): first year saving. # maybe it can be min_annual_saving first_year_noi (float): first year noi, after commissioning date. # maybe it can be min_noi first_year_cash (float): first year cash, after commissioning date # liability: do we need this? it's already calculated in balance sheet # commissioning_date (date): construction finish date. Saving start at NEXT month + # scenario (dictionary): package of energy conservation measures (ECMs) Return: list: list of loan amount that borrowed from each lender @@ -49,15 +50,15 @@ def loan_allocation( 'expected_payback': int, months that customer expect the project can payback, 'cust_saving_dscr': float, customer required lower limit of (saving / debt service) ratio } - scenario (dictionary): dict of project economics and saving scenario, { - 'cost_estimation': float, estimated project cost - 'post_income_statement': objective of Income_Statement_Table , projected income_statement with savings - } req_dscr (dictionary): dict of required debt service coverage ratios, { 'req_noi_dscr': 1.15, 'req_cash_dscr': 1.15, 'req_saving_dscr': 1.10 } + # scenario (dictionary): dict of project economics and saving scenario, { + # 'cost_estimation': float, estimated project cost + # 'post_income_statement': objective of Income_Statement_Table , projected income_statement with savings + # } Note: noi == net operating income dscr == debt service coverage ratio @@ -68,7 +69,7 @@ def loan_allocation( """ sum_loan_max_amount = sum(list(current_loan.max_amount for current_loan in loan_list)) # pre-request judge: project cost should be lower than total available financing - if (sum_loan_max_amount + customer_preference['downpayment_max']) <= scenario['cost_estimation']: + if (sum_loan_max_amount + customer_preference['downpayment_max']) <= cost: # print('alert: not financiable') return None @@ -82,7 +83,7 @@ def loan_allocation( A.append([-1] * len(loan_list)) # -x1 -x2 -x3 <= -max b = [] b.append( - 0 - scenario['cost_estimation'] + 0 - cost # 0 - sum_loan_max_amount, ) A.append(c) # sum(x_i/payback_i) <= required. aka. sum(debt_service) <= min_required_debt_service diff --git a/bpfin/tests/test_financials/test_loan.py b/bpfin/tests/test_financials/test_loan.py index 015bea7..9ccd79a 100644 --- a/bpfin/tests/test_financials/test_loan.py +++ b/bpfin/tests/test_financials/test_loan.py @@ -10,14 +10,14 @@ def test_Loan_List(): """ input_loan_input_list = db.loan_input_list input_customer_preference = db.customer_preference - input_scenario = db.scenario_input + input_cost = db.cost_estimation input_req_dscr = db.req_dscr input_loan_start_date = db.commision_date output_loan1_end_balance = db.loan1_end_balance sample_loan_list = Loan_List(input_loan_input_list) result_loan_list = sample_loan_list.get_schedule( input_customer_preference, - input_scenario, + input_cost, input_req_dscr, input_loan_start_date, 28000.0, diff --git a/bpfin/tests/testdata/sample_data.py b/bpfin/tests/testdata/sample_data.py index 8208b87..4bc3fc3 100644 --- a/bpfin/tests/testdata/sample_data.py +++ b/bpfin/tests/testdata/sample_data.py @@ -549,11 +549,7 @@ customer_preference = { } # Engineering Scenarios -scenario_input = { - 'cost_estimation': 150000.00, -} - - +cost_estimation = 150000.00 commision_date = datetime.date(2017, 3, 14) # Financing plan -- GitLab From 632049591bc5000052d5e3a2535711360c973e8c Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Thu, 4 May 2017 12:16:23 -0400 Subject: [PATCH 04/11] Create prelim_analysis func in Scenario --- bpfin/financials/scenario.py | 48 ++++++++++++++++++++++++----- bpfin/tests/testdata/sample_data.py | 7 ++++- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/bpfin/financials/scenario.py b/bpfin/financials/scenario.py index 615dd72..d19fed4 100644 --- a/bpfin/financials/scenario.py +++ b/bpfin/financials/scenario.py @@ -6,19 +6,53 @@ import copy class Scenario(): - def __init__(self, prior_income_statement, prior_balance_sheet, - analysis_date, commission_date, construction_cost, - bill_overview, prior_annual_bill_table, loan_input_list): - self.prior_income_statement = copy.deepcopy(prior_income_statement) - self.prior_balance_sheet = copy.deepcopy(prior_balance_sheet) - self.proforma_date = form_bill_calendar(analysis_date['proforma_start'], analysis_date['proforma_duration'])[1] + def __init__(self, + analysis_date, + commission_date, + construction_cost, + bill_overview, + prior_annual_bill_table, + liability, + cash_balance, + prior_income_statement_table, + prior_balance_sheet_table, + loan_input_list): + self.analysis_date = analysis_date + # self.proforma_date = form_bill_calendar(analysis_date['proforma_start'], analysis_date['proforma_duration'])[1] self.commission_date = copy.deepcopy(commission_date) self.construction_cost = copy.deepcopy(construction_cost) + self.prior_annual_bill_table = copy.deepcopy(prior_annual_bill_table) + self.cash_balance = copy.deepcopy(cash_balance) + self.liability = copy.deepcopy(liability) + + self.prior_income_statement_table = copy.deepcopy(prior_income_statement_table) + self.prior_balance_sheet_table = copy.deepcopy(prior_balance_sheet_table) + self.post_income_statement_table = None + self.post_balance_sheet_table = None + + self.loan_list = Loan_List(loan_input_list) self.saving_overview = Saving_Overview( bill_overview=copy.deepcopy(bill_overview), prior_annual_bill_table=copy.deepcopy(prior_annual_bill_table), analysis_date=copy.deepcopy(analysis_date), commissioning_date=copy.deepcopy(commission_date) ) - self.loan_list = Loan_List(loan_input_list) + + def prelim_anlaysis(self, + prior_month_bill, + percent_saving_dict, + full_saving_dict, + req_dscr, + customer_preference): + self.saving_overview.put_saving( + prior_month_bill=prior_month_bill, + percent_saving_dict=percent_saving_dict, + full_saving_dict=full_saving_dict) + # post_annual_bill_table = copy.deepcopy(saving_overview.get_post_annual_bill_table()) + + post_income_statement_table = copy.deepcopy(self.prior_income_statement_table) + # post_income_statement.project(-2.0, ) + + first_year_saving = copy.deepcopy(self.saving_overview.get_total_first_year_saving()) + diff --git a/bpfin/tests/testdata/sample_data.py b/bpfin/tests/testdata/sample_data.py index 4bc3fc3..643528a 100644 --- a/bpfin/tests/testdata/sample_data.py +++ b/bpfin/tests/testdata/sample_data.py @@ -548,7 +548,12 @@ customer_preference = { 'cust_saving_dscr': 1.15 } -# Engineering Scenarios +# loan_requirement = { +# 'dscr': req_dscr, +# 'customer': customer_preference +# } + +# Engineering Scenarios and project economics cost_estimation = 150000.00 commision_date = datetime.date(2017, 3, 14) -- GitLab From 630042f8b0488726d2b0d2782e8902d7b5b57d1c Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Thu, 4 May 2017 12:39:58 -0400 Subject: [PATCH 05/11] Create get_post_annual_bill_table in Saving_Overview class. Create test file for it --- bpfin/financials/financial_lib.py | 2 +- bpfin/financials/saving.py | 21 +++- bpfin/tests/test_financials/test_saving.py | 3 + bpfin/tests/testdata/sample_data.py | 112 +++++++++++++++++++++ bpfin/utilbills/data_generation.py | 3 + 5 files changed, 135 insertions(+), 6 deletions(-) diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py index 4479bcf..067ca6c 100644 --- a/bpfin/financials/financial_lib.py +++ b/bpfin/financials/financial_lib.py @@ -289,7 +289,7 @@ class Income_Statement_Table(): Description: raw_income_input = {2014: {'revenue': 90.0, 'utility_expense': 55.0, 'non_utility_expense': 35.0}, 2015:{},} annual_bill_table = {'electricity': electricity_bill, 'oil': oil_bill, 'gas': gas_bill, 'water': water_bill} - electricity_bill = {2014: 100, 2015:200, ...} + electricity_bill = {2014: 100, 2015:200, ...} characters = { 'start_year': (int) 2014, 'end_year': (int) 2016, diff --git a/bpfin/financials/saving.py b/bpfin/financials/saving.py index 4d2e45f..e5d408e 100644 --- a/bpfin/financials/saving.py +++ b/bpfin/financials/saving.py @@ -4,9 +4,8 @@ from bpfin.utilbills.bill_lib import cal_last_day from bpfin.utilbills.bill_lib import annualizing_projection from bpfin.utilbills.bill_lib import form_year_calendar from bpfin.utilbills.bill_lib import form_bill_calendar -# from bpfin.tests.testdata import sample_data as db from bpfin.utilbills.bill_post_proj_rough import bill_post_proj_rough - +from bpfin.tests.testdata import sample_data as db class Saving(): """ @@ -337,10 +336,22 @@ class Saving_Overview(): """ return self.total_saving_percent - def get_total_annual_saving_charge(self): + def get_post_annual_bill_table(self): """ + Generate annual bill table for pro-forma, consiering commission date. + Return: + dictionary: dict of dict of annual charges, for 4 utility types + Description: + output = {'electricity': electricity_bill, 'oil': oil_bill, 'gas': gas_bill, 'water': water_bill} + electricity_bill = {2014: 100, 2015:200, ...} + } """ - pass + post_annual_bill_table = {} + utility_type_list = ['electricity', 'gas', 'oil', 'water'] + for utility_type in utility_type_list: + post_annual_bill_table[utility_type] = copy.deepcopy( + self.utility_saving_dict[utility_type].get_annual_proforma_charge()) + return post_annual_bill_table def get_utility_annual_saving_charge(self, utility_type): """ @@ -366,4 +377,4 @@ class Saving_Overview(): # print('\n simple payback =', so.get_simple_payback(50000)) # print('\n total saving percent =', so.get_total_saving_percent()) # print('\n electricity_annual_saving_charge', so.get_utility_annual_saving_charge('electricity')) - +# print(so.get_post_annual_bill_table()) diff --git a/bpfin/tests/test_financials/test_saving.py b/bpfin/tests/test_financials/test_saving.py index bc1c48c..042a2e9 100644 --- a/bpfin/tests/test_financials/test_saving.py +++ b/bpfin/tests/test_financials/test_saving.py @@ -124,6 +124,7 @@ def test_Saving_Overview(): 2035: 12430.56386264111, 2036: 12679.70824604718 } + output_post_annual_bill_table = db.bill_overview_post saving_overview = Saving_Overview( input_bill_overview, input_prior_annual_bill_table, input_analysis_date, input_commissioning_date) @@ -133,8 +134,10 @@ def test_Saving_Overview(): result_simple_payback = saving_overview.get_simple_payback(50000) result_total_saving_percent = saving_overview.get_total_saving_percent() result_electricity_annual_saving_charge = saving_overview.get_utility_annual_saving_charge('electricity') + result_post_annual_bill_table = saving_overview.get_post_annual_bill_table() assert result_first_year_saving == output_first_year_saving assert result_simple_payback == output_simple_payback assert result_total_saving_percent == output_total_saving_percent assert result_electricity_annual_saving_charge == output_electricity_annual_saving_charge + assert result_post_annual_bill_table == output_post_annual_bill_table diff --git a/bpfin/tests/testdata/sample_data.py b/bpfin/tests/testdata/sample_data.py index 643528a..8ae30f5 100644 --- a/bpfin/tests/testdata/sample_data.py +++ b/bpfin/tests/testdata/sample_data.py @@ -134,6 +134,118 @@ bill_overview_organized = { 2031: 0.0, 2032: 0.0, 2033: 0.0, 2034: 0.0, 2035: 0.0, 2036: 0.0} } +bill_overview_post = { + 'electricity': { + 2012: 32220.590596217822, + 2013: 32782.518348207, + 2014: 33293.10053024947, + 2015: 33546.76158045131, + 2016: 33844.501703633454, + 2017: 27765.310595972387, + 2018: 26538.724712295312, + 2019: 27188.618071137025, + 2020: 27825.148026928808, + 2021: 28415.31151022465, + 2022: 28952.82377820487, + 2023: 29480.94391241407, + 2024: 30021.058259530582, + 2025: 30579.321946790835, + 2026: 31181.75023905945, + 2027: 31829.938943047797, + 2028: 32493.926597686295, + 2029: 33158.47409684726, + 2030: 33823.25084758239, + 2031: 34489.99899723802, + 2032: 35164.72907151292, + 2033: 35854.93418165298, + 2034: 36563.663320523345, + 2035: 37291.69158792331, + 2036: 38039.124738141574 + }, + 'gas': { + 2012: 1253.3333333333333, + 2013: 1253.3333333333333, + 2014: 1253.3333333333333, + 2015: 1020, + 2016: 1220, + 2017: 1406.0, + 2018: 1128.0, + 2019: 1128.0, + 2020: 1128.0, + 2021: 1128.0, + 2022: 1128.0, + 2023: 1128.0, + 2024: 1128.0, + 2025: 1128.0, + 2026: 1128.0, + 2027: 1128.0, + 2028: 1128.0, + 2029: 1128.0, + 2030: 1128.0, + 2031: 1128.0, + 2032: 1128.0, + 2033: 1128.0, + 2034: 1128.0, + 2035: 1128.0, + 2036: 1128.0 + }, + 'oil': { + 2012: 1243.3333333333333, + 2013: 1243.3333333333333, + 2014: 1243.3333333333333, + 2015: 1010, + 2016: 1210, + 2017: 603.9999999999999, + 2018: 248.6666666666666, + 2019: 248.6666666666666, + 2020: 248.6666666666666, + 2021: 248.6666666666666, + 2022: 248.6666666666666, + 2023: 248.6666666666666, + 2024: 248.6666666666666, + 2025: 248.6666666666666, + 2026: 248.6666666666666, + 2027: 248.6666666666666, + 2028: 248.6666666666666, + 2029: 248.6666666666666, + 2030: 248.6666666666666, + 2031: 248.6666666666666, + 2032: 248.6666666666666, + 2033: 248.6666666666666, + 2034: 248.6666666666666, + 2035: 248.6666666666666, + 2036: 248.6666666666666 + }, + 'water': { + 2012: 0.0, + 2013: 0.0, + 2014: 0.0, + 2015: 0, + 2016: 0, + 2017: 0.0, + 2018: 0.0, + 2019: 0.0, + 2020: 0.0, + 2021: 0.0, + 2022: 0.0, + 2023: 0.0, + 2024: 0.0, + 2025: 0.0, + 2026: 0.0, + 2027: 0.0, + 2028: 0.0, + 2029: 0.0, + 2030: 0.0, + 2031: 0.0, + 2032: 0.0, + 2033: 0.0, + 2034: 0.0, + 2035: 0.0, + 2036: 0.0 + } +} + + # income statement test income_input_2016 = { 'revenue': 100000, diff --git a/bpfin/utilbills/data_generation.py b/bpfin/utilbills/data_generation.py index d3a2bde..dd81a5a 100644 --- a/bpfin/utilbills/data_generation.py +++ b/bpfin/utilbills/data_generation.py @@ -33,3 +33,6 @@ # print(lib.sublist(post_noi, prior_noi)) # # print(bl.annualizing_projection(saving.proforma_date, saving.get_proforma_saving())) + + + -- GitLab From 47527ec88197914de268eab416d15f8ddfcbf565 Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Thu, 4 May 2017 13:32:17 -0400 Subject: [PATCH 06/11] Create saving, is, bs, loan calculation in prelim_analysis in Scenario class --- bpfin/financials/financial_lib.py | 45 +++++-------- bpfin/financials/scenario.py | 83 +++++++++++++++++++++--- bpfin/tests/test_financials/test_loan.py | 2 +- bpfin/tests/testdata/sample_data.py | 2 +- 4 files changed, 92 insertions(+), 40 deletions(-) diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py index 067ca6c..c04e350 100644 --- a/bpfin/financials/financial_lib.py +++ b/bpfin/financials/financial_lib.py @@ -148,34 +148,21 @@ class Income_Statement(): self.total_opex = self.energy_opex + self.net_non_energy_opex self.noi = self.revenue - self.total_opex - def assign_next(self, income_statement_characters, - bill_overview_organized): - """ - !!! this function will be deleted in the next version!! - """ - self.electricity_opex = bill_overview_organized['electricity'][ - self.year] - self.gas_opex = bill_overview_organized['gas'][self.year] - self.oil_opex = bill_overview_organized['oil'][self.year] - self.water_opex = bill_overview_organized['water'][self.year] - self.energy_opex = self.electricity_opex + self.gas_opex + self.oil_opex + self.water_opex - self.other_utility = self.revenue * income_statement_characters[ - 'other_utility_percent'] - self.non_utility_expense = self.revenue * income_statement_characters[ - 'non_utility_expense_percent'] - self.utility_expense = self.energy_opex + self.other_utility - self.net_non_energy_opex = self.other_utility + self.non_utility_expense - self.total_opex = self.energy_opex + self.net_non_energy_opex - self.noi = self.revenue - self.total_opex - - # def assign_next_year(self, other_utility_percent, non_utility_expense_percent): - # # print('\n other_utility_percent',other_utility_percent) - # # print('\n non_utility_expense_percent',non_utility_expense_percent) + # def assign_next(self, income_statement_characters, + # bill_overview_organized): + # """ + # !!! this function will be deleted in the next version!! + # """ + # self.electricity_opex = bill_overview_organized['electricity'][ + # self.year] + # self.gas_opex = bill_overview_organized['gas'][self.year] + # self.oil_opex = bill_overview_organized['oil'][self.year] + # self.water_opex = bill_overview_organized['water'][self.year] # self.energy_opex = self.electricity_opex + self.gas_opex + self.oil_opex + self.water_opex - # # print('\n',self.energy_opex) - # # print('\n revenue', self.revenue) - # self.other_utility = self.revenue * other_utility_percent - # self.non_utility_expense = self.revenue * non_utility_expense_percent + # self.other_utility = self.revenue * income_statement_characters[ + # 'other_utility_percent'] + # self.non_utility_expense = self.revenue * income_statement_characters[ + # 'non_utility_expense_percent'] # self.utility_expense = self.energy_opex + self.other_utility # self.net_non_energy_opex = self.other_utility + self.non_utility_expense # self.total_opex = self.energy_opex + self.net_non_energy_opex @@ -372,7 +359,7 @@ class Income_Statement_Table(): annual_bill_table) current_table.append(current_income_statement) self.table = current_table - return current_table + # return current_table def get_hist_table(self): """ @@ -615,7 +602,7 @@ class Balance_Sheet_Table(): current_net_income) current_table.append(current_balance_sheet) self.bs_table = current_table - return current_table + # return current_table def get_hist_balance_sheet_table(self): hist_balance_sheet_dict = {} diff --git a/bpfin/financials/scenario.py b/bpfin/financials/scenario.py index d19fed4..499e3d0 100644 --- a/bpfin/financials/scenario.py +++ b/bpfin/financials/scenario.py @@ -1,8 +1,10 @@ -from bpfin.financials.financial_lib import Income_Statement_Table -from bpfin.utilbills.bill_lib import form_bill_calendar +import copy +# from bpfin.utilbills.bill_lib import form_bill_calendar from bpfin.financials.saving import Saving_Overview from bpfin.financials.loan import Loan_List -import copy +from bpfin.tests.testdata import sample_data as db +from bpfin.financials.financial_lib import Income_Statement_Table +from bpfin.financials.financial_lib import Balance_Sheet_Table class Scenario(): @@ -12,19 +14,22 @@ class Scenario(): construction_cost, bill_overview, prior_annual_bill_table, - liability, - cash_balance, + other_debt_service, + # cash_balance, prior_income_statement_table, prior_balance_sheet_table, loan_input_list): + """ + other_debt_service (dict): dictionary of debt service values per year + """ self.analysis_date = analysis_date # self.proforma_date = form_bill_calendar(analysis_date['proforma_start'], analysis_date['proforma_duration'])[1] self.commission_date = copy.deepcopy(commission_date) self.construction_cost = copy.deepcopy(construction_cost) self.prior_annual_bill_table = copy.deepcopy(prior_annual_bill_table) - self.cash_balance = copy.deepcopy(cash_balance) - self.liability = copy.deepcopy(liability) + # self.cash_balance = copy.deepcopy(cash_balance) + self.other_debt_service = copy.deepcopy(other_debt_service) self.prior_income_statement_table = copy.deepcopy(prior_income_statement_table) self.prior_balance_sheet_table = copy.deepcopy(prior_balance_sheet_table) @@ -43,16 +48,76 @@ class Scenario(): prior_month_bill, percent_saving_dict, full_saving_dict, + growth_rate_flag, req_dscr, customer_preference): + """ + growth_rate_flag (float): indicating assumed growth rate, -2.0 == cagr, -1.0 == historical average + + To Do: clarify commission date and loan start date + """ + # calculate saving, by generating saving_overview object self.saving_overview.put_saving( prior_month_bill=prior_month_bill, percent_saving_dict=percent_saving_dict, full_saving_dict=full_saving_dict) - # post_annual_bill_table = copy.deepcopy(saving_overview.get_post_annual_bill_table()) + # generate post_saving income_statement_table object + post_annual_bill_table = copy.deepcopy(self.saving_overview.get_post_annual_bill_table()) post_income_statement_table = copy.deepcopy(self.prior_income_statement_table) - # post_income_statement.project(-2.0, ) + post_income_statement_table.project(-2.0, growth_rate_flag, post_annual_bill_table) + self.post_income_statement_table = post_income_statement_table + # generate post_saving balance_sheet_table object + post_saving_noi_dict = copy.deepcopy(self.post_income_statement_table.get_noi_dict()) + post_balance_sheet_table = copy.deepcopy(self.prior_balance_sheet_table) + post_balance_sheet_table.project_balance_sheet( + self.analysis_date, self.other_debt_service, post_saving_noi_dict) + self.post_balance_sheet_table = post_balance_sheet_table + + # allocate loan and get loan schedules first_year_saving = copy.deepcopy(self.saving_overview.get_total_first_year_saving()) + first_year_noi = copy.deepcopy(self.post_income_statement_table.get_first_year_noi()) + first_year_cash = copy.deepcopy(self.post_balance_sheet_table.get_first_year_cash()) + + allocated_loan_list = self.loan_list.get_schedule( + customer_preference=customer_preference, + cost=self.construction_cost, + req_dscr=req_dscr, + loan_start_date=self.commission_date, + first_year_saving=first_year_saving, + first_year_noi=first_year_noi, + first_year_cash=first_year_cash) + print(allocated_loan_list[0].principal_end_balance) + + +# ***** ugly test ***** +prior_IS_table = Income_Statement_Table( + db.raw_income_input, + db.bill_overview_organized) +prior_IS_table.project(0.01, db.analysis_date, db.bill_overview_organized) +prior_BS_table = Balance_Sheet_Table(db.raw_balance_sheet) +prior_BS_table.project_balance_sheet( + db.analysis_date, + db.liability_dictionary, + prior_IS_table.get_noi_dict()) + +scenario = Scenario( + analysis_date=db.analysis_date, + commission_date=db.commission_date, + construction_cost=db.cost_estimation, + bill_overview=db.bill_overview, + prior_annual_bill_table=db.bill_overview_organized, + other_debt_service=db.liability_dictionary, + prior_income_statement_table=prior_IS_table, + prior_balance_sheet_table=prior_BS_table, + loan_input_list=db.loan_input_list +) +scenario.prelim_anlaysis( + prior_month_bill=db.prior_month_bill, + percent_saving_dict=db.percent_saving_dict, + full_saving_dict=db.full_saving_dict, + growth_rate_flag=0.01, + req_dscr=db.req_dscr, + customer_preference=db.customer_preference) diff --git a/bpfin/tests/test_financials/test_loan.py b/bpfin/tests/test_financials/test_loan.py index 9ccd79a..cbfa0a0 100644 --- a/bpfin/tests/test_financials/test_loan.py +++ b/bpfin/tests/test_financials/test_loan.py @@ -12,7 +12,7 @@ def test_Loan_List(): input_customer_preference = db.customer_preference input_cost = db.cost_estimation input_req_dscr = db.req_dscr - input_loan_start_date = db.commision_date + input_loan_start_date = db.commission_date output_loan1_end_balance = db.loan1_end_balance sample_loan_list = Loan_List(input_loan_input_list) result_loan_list = sample_loan_list.get_schedule( diff --git a/bpfin/tests/testdata/sample_data.py b/bpfin/tests/testdata/sample_data.py index 8ae30f5..25b1038 100644 --- a/bpfin/tests/testdata/sample_data.py +++ b/bpfin/tests/testdata/sample_data.py @@ -667,7 +667,7 @@ customer_preference = { # Engineering Scenarios and project economics cost_estimation = 150000.00 -commision_date = datetime.date(2017, 3, 14) +commission_date = datetime.date(2017, 3, 14) # Financing plan loan1_end_balance = [ -- GitLab From c9238cd5ccc7292f6db9a4c249df8d77fa490186 Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Thu, 4 May 2017 15:40:37 -0400 Subject: [PATCH 07/11] Test out loan allocation in scenario. Update and debug loan_allocation --- bpfin/financials/loan_allocation.py | 6 ++++-- bpfin/financials/scenario.py | 17 +++++++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/bpfin/financials/loan_allocation.py b/bpfin/financials/loan_allocation.py index 020f9c3..d3e0b35 100644 --- a/bpfin/financials/loan_allocation.py +++ b/bpfin/financials/loan_allocation.py @@ -71,8 +71,7 @@ def loan_allocation( # pre-request judge: project cost should be lower than total available financing if (sum_loan_max_amount + customer_preference['downpayment_max']) <= cost: # print('alert: not financiable') - return None - + return [0] * len(loan_list) # linear programming (LP) # Set LP constrains. # objective function: x1/payback1, x2/payback2, x3/payback3 = minimum @@ -95,8 +94,11 @@ def loan_allocation( )) # x variables bounds, 0 <= x[i] <= loan[i]_max_amount bound_list = list((0, current_loan.max_amount) for current_loan in loan_list) + # print('\nLP constraints =', A, b, bound_list) # LP calculation. x[i] == loan amount from loan[i] res = linprog(c, A_ub=A, b_ub=b, bounds=bound_list, options={'disp': False}) + if res.success is False: + return [0] * len(loan_list) return res.x diff --git a/bpfin/financials/scenario.py b/bpfin/financials/scenario.py index 499e3d0..f24d02c 100644 --- a/bpfin/financials/scenario.py +++ b/bpfin/financials/scenario.py @@ -65,7 +65,7 @@ class Scenario(): # generate post_saving income_statement_table object post_annual_bill_table = copy.deepcopy(self.saving_overview.get_post_annual_bill_table()) post_income_statement_table = copy.deepcopy(self.prior_income_statement_table) - post_income_statement_table.project(-2.0, growth_rate_flag, post_annual_bill_table) + post_income_statement_table.project(growth_rate_flag, self.analysis_date, post_annual_bill_table) self.post_income_statement_table = post_income_statement_table # generate post_saving balance_sheet_table object @@ -77,9 +77,11 @@ class Scenario(): # allocate loan and get loan schedules first_year_saving = copy.deepcopy(self.saving_overview.get_total_first_year_saving()) - first_year_noi = copy.deepcopy(self.post_income_statement_table.get_first_year_noi()) - first_year_cash = copy.deepcopy(self.post_balance_sheet_table.get_first_year_cash()) + first_year_noi = copy.deepcopy(self.post_income_statement_table.get_first_year_noi(self.commission_date)) + first_year_cash = copy.deepcopy(self.post_balance_sheet_table.get_first_year_cash(self.commission_date)) + # print('first year =', first_year_saving, first_year_noi, first_year_cash) + # print(self.loan_list.loan_list[0].institute) allocated_loan_list = self.loan_list.get_schedule( customer_preference=customer_preference, cost=self.construction_cost, @@ -89,13 +91,16 @@ class Scenario(): first_year_noi=first_year_noi, first_year_cash=first_year_cash) print(allocated_loan_list[0].principal_end_balance) + print(allocated_loan_list[1].principal_end_balance) + print(allocated_loan_list[2].principal_end_balance) # ***** ugly test ***** +growth_toggle = 0.01 prior_IS_table = Income_Statement_Table( db.raw_income_input, db.bill_overview_organized) -prior_IS_table.project(0.01, db.analysis_date, db.bill_overview_organized) +prior_IS_table.project(growth_toggle, db.analysis_date, db.bill_overview_organized) prior_BS_table = Balance_Sheet_Table(db.raw_balance_sheet) prior_BS_table.project_balance_sheet( db.analysis_date, @@ -105,7 +110,7 @@ prior_BS_table.project_balance_sheet( scenario = Scenario( analysis_date=db.analysis_date, commission_date=db.commission_date, - construction_cost=db.cost_estimation, + construction_cost=90000, bill_overview=db.bill_overview, prior_annual_bill_table=db.bill_overview_organized, other_debt_service=db.liability_dictionary, @@ -118,6 +123,6 @@ scenario.prelim_anlaysis( prior_month_bill=db.prior_month_bill, percent_saving_dict=db.percent_saving_dict, full_saving_dict=db.full_saving_dict, - growth_rate_flag=0.01, + growth_rate_flag=growth_toggle, req_dscr=db.req_dscr, customer_preference=db.customer_preference) -- GitLab From b4b769b45345064f51e03bdb051631d6a121dd51 Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Thu, 4 May 2017 15:52:53 -0400 Subject: [PATCH 08/11] Clean loan_allocation and scenaro comments --- bpfin/financials/loan_allocation.py | 1 + bpfin/financials/scenario.py | 14 +++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/bpfin/financials/loan_allocation.py b/bpfin/financials/loan_allocation.py index d3e0b35..5bcc9d1 100644 --- a/bpfin/financials/loan_allocation.py +++ b/bpfin/financials/loan_allocation.py @@ -94,6 +94,7 @@ def loan_allocation( )) # x variables bounds, 0 <= x[i] <= loan[i]_max_amount bound_list = list((0, current_loan.max_amount) for current_loan in loan_list) + # print('req_dscr', first_year_saving / req_dscr['req_saving_dscr'], first_year_noi / req_dscr['req_noi_dscr'], first_year_cash / req_dscr['req_cash_dscr']) # print('\nLP constraints =', A, b, bound_list) # LP calculation. x[i] == loan amount from loan[i] res = linprog(c, A_ub=A, b_ub=b, bounds=bound_list, options={'disp': False}) diff --git a/bpfin/financials/scenario.py b/bpfin/financials/scenario.py index f24d02c..70d6e66 100644 --- a/bpfin/financials/scenario.py +++ b/bpfin/financials/scenario.py @@ -43,6 +43,7 @@ class Scenario(): analysis_date=copy.deepcopy(analysis_date), commissioning_date=copy.deepcopy(commission_date) ) + self.scheduled_loan_list = None def prelim_anlaysis(self, prior_month_bill, @@ -82,7 +83,7 @@ class Scenario(): # print('first year =', first_year_saving, first_year_noi, first_year_cash) # print(self.loan_list.loan_list[0].institute) - allocated_loan_list = self.loan_list.get_schedule( + scheduled_loan_list = self.loan_list.get_schedule( customer_preference=customer_preference, cost=self.construction_cost, req_dscr=req_dscr, @@ -90,9 +91,12 @@ class Scenario(): first_year_saving=first_year_saving, first_year_noi=first_year_noi, first_year_cash=first_year_cash) - print(allocated_loan_list[0].principal_end_balance) - print(allocated_loan_list[1].principal_end_balance) - print(allocated_loan_list[2].principal_end_balance) + self.scheduled_loan_list = scheduled_loan_list + + def get_graph(self): + """ + """ + pass # ***** ugly test ***** @@ -110,7 +114,7 @@ prior_BS_table.project_balance_sheet( scenario = Scenario( analysis_date=db.analysis_date, commission_date=db.commission_date, - construction_cost=90000, + construction_cost=50000, bill_overview=db.bill_overview, prior_annual_bill_table=db.bill_overview_organized, other_debt_service=db.liability_dictionary, -- GitLab From 3db393fe054b545d62bf2f419340a2d6beac9e9c Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Thu, 4 May 2017 16:19:15 -0400 Subject: [PATCH 09/11] Create get_post_energy_bill --- bpfin/financials/saving.py | 3 +++ bpfin/financials/scenario.py | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/bpfin/financials/saving.py b/bpfin/financials/saving.py index e5d408e..0acaff9 100644 --- a/bpfin/financials/saving.py +++ b/bpfin/financials/saving.py @@ -369,6 +369,9 @@ class Saving_Overview(): return saving_dict + + + # **** ugly test **** # so = Saving_Overview(db.bill_overview, db.bill_overview_organized, db.analysis_date, datetime.date(2017, 3, 14)) # so.put_saving(db.prior_month_bill, db.percent_saving_dict, db.full_saving_dict) diff --git a/bpfin/financials/scenario.py b/bpfin/financials/scenario.py index 70d6e66..c5d6974 100644 --- a/bpfin/financials/scenario.py +++ b/bpfin/financials/scenario.py @@ -15,7 +15,6 @@ class Scenario(): bill_overview, prior_annual_bill_table, other_debt_service, - # cash_balance, prior_income_statement_table, prior_balance_sheet_table, loan_input_list): @@ -23,12 +22,10 @@ class Scenario(): other_debt_service (dict): dictionary of debt service values per year """ self.analysis_date = analysis_date - # self.proforma_date = form_bill_calendar(analysis_date['proforma_start'], analysis_date['proforma_duration'])[1] self.commission_date = copy.deepcopy(commission_date) self.construction_cost = copy.deepcopy(construction_cost) self.prior_annual_bill_table = copy.deepcopy(prior_annual_bill_table) - # self.cash_balance = copy.deepcopy(cash_balance) self.other_debt_service = copy.deepcopy(other_debt_service) self.prior_income_statement_table = copy.deepcopy(prior_income_statement_table) @@ -93,9 +90,37 @@ class Scenario(): first_year_cash=first_year_cash) self.scheduled_loan_list = scheduled_loan_list - def get_graph(self): + def get_post_energy_bill(self): + start_year = self.analysis_date['proforma_start'].year + end_year = start_year + self.analysis_date['duration'].year + post_annual_bill_table = copy.deepcopy(self.saving_overview.get_post_annual_bill_table()) + utility_type_list = ['electricity', 'gas', 'oil', 'water'] + + post_energy_bill = {} + year = start_year + while year <= end_year: + current_total_energy_bill = 0 + for utility_type in utility_type_list: + current_total_energy_bill += post_annual_bill_table[utility_type][year] + post_energy_bill[year] = current_total_energy_bill + year += 1 + return post_energy_bill + + + + def get_graph_dict(self): """ + Return: + dictionary: dict of dict of total pro-forma items + Description: + graph_dict = { + 'energy_expenses': {year: float} + 'total_loan': {year: float} + 'net_savings': {year: float} + } """ + graph_dict = {} + proforma_bill = self. pass @@ -130,3 +155,4 @@ scenario.prelim_anlaysis( growth_rate_flag=growth_toggle, req_dscr=db.req_dscr, customer_preference=db.customer_preference) + -- GitLab From 381b470800817cc2586d634457ce4391500807b9 Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Thu, 4 May 2017 16:46:15 -0400 Subject: [PATCH 10/11] Add get_total_energy_dict in Income_Statement_Table --- bpfin/financials/financial_lib.py | 7 ++++++ bpfin/financials/scenario.py | 36 ++++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py index c04e350..d452d45 100644 --- a/bpfin/financials/financial_lib.py +++ b/bpfin/financials/financial_lib.py @@ -502,6 +502,13 @@ class Income_Statement_Table(): if current_income_statement.year == first_year: return current_income_statement.noi + def get_total_energy_dict(self): + total_energy_dict = {} + for current_income_statement in self.table: + total_energy_dict[ + current_income_statement.year] = current_income_statement.energy_opex + return total_energy_dict + class Balance_Sheet(): def __init__(self): diff --git a/bpfin/financials/scenario.py b/bpfin/financials/scenario.py index c5d6974..1661942 100644 --- a/bpfin/financials/scenario.py +++ b/bpfin/financials/scenario.py @@ -3,8 +3,8 @@ import copy from bpfin.financials.saving import Saving_Overview from bpfin.financials.loan import Loan_List from bpfin.tests.testdata import sample_data as db -from bpfin.financials.financial_lib import Income_Statement_Table -from bpfin.financials.financial_lib import Balance_Sheet_Table +from bpfin.financials.financial_lib import Income_Statement_Table, Balance_Sheet_Table +from bpfin.utilbills.bill_lib import form_bill_year, annualizing_projection class Scenario(): @@ -91,22 +91,33 @@ class Scenario(): self.scheduled_loan_list = scheduled_loan_list def get_post_energy_bill(self): - start_year = self.analysis_date['proforma_start'].year - end_year = start_year + self.analysis_date['duration'].year + proforma_year = form_bill_year(self.analysis_date['proforma_start'], + self.analysis_date['proforma_duration']) post_annual_bill_table = copy.deepcopy(self.saving_overview.get_post_annual_bill_table()) utility_type_list = ['electricity', 'gas', 'oil', 'water'] post_energy_bill = {} - year = start_year - while year <= end_year: + for year in proforma_year: current_total_energy_bill = 0 for utility_type in utility_type_list: current_total_energy_bill += post_annual_bill_table[utility_type][year] post_energy_bill[year] = current_total_energy_bill - year += 1 return post_energy_bill - + def get_annual_debt_service(self): + proforma_year = form_bill_year(self.analysis_date['proforma_start'], + self.analysis_date['proforma_duration']) + annual_debt_service_dict = {} + for year in proforma_year: + annual_debt_service_dict[year] = 0 + + for current_loan in self.scheduled_loan_list: + current_loan_annual = annualizing_projection( + current_loan.terms, current_loan.debt_service_due) + for year in proforma_year: + if year in current_loan_annual: + annual_debt_service_dict[year] += current_loan_annual[year] + return annual_debt_service_dict def get_graph_dict(self): """ @@ -118,9 +129,12 @@ class Scenario(): 'total_loan': {year: float} 'net_savings': {year: float} } - """ + # """ graph_dict = {} - proforma_bill = self. + proforma_bill = self.get_post_energy_bill() + annual_debt_service = self.get_annual_debt_service() + prior_annual_bill = + print(proforma_bill) pass @@ -156,3 +170,5 @@ scenario.prelim_anlaysis( req_dscr=db.req_dscr, customer_preference=db.customer_preference) +print(scenario.get_annual_debt_service()) +# print(scenario.get_graph_dict()) -- GitLab From d945dbc9b392adf4dded36e2c26997fb3d1639a2 Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Thu, 4 May 2017 17:01:33 -0400 Subject: [PATCH 11/11] Temporary finish of scenario class --- bpfin/financials/scenario.py | 84 ++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/bpfin/financials/scenario.py b/bpfin/financials/scenario.py index 1661942..c606285 100644 --- a/bpfin/financials/scenario.py +++ b/bpfin/financials/scenario.py @@ -133,42 +133,50 @@ class Scenario(): graph_dict = {} proforma_bill = self.get_post_energy_bill() annual_debt_service = self.get_annual_debt_service() - prior_annual_bill = - print(proforma_bill) - pass - - -# ***** ugly test ***** -growth_toggle = 0.01 -prior_IS_table = Income_Statement_Table( - db.raw_income_input, - db.bill_overview_organized) -prior_IS_table.project(growth_toggle, db.analysis_date, db.bill_overview_organized) -prior_BS_table = Balance_Sheet_Table(db.raw_balance_sheet) -prior_BS_table.project_balance_sheet( - db.analysis_date, - db.liability_dictionary, - prior_IS_table.get_noi_dict()) - -scenario = Scenario( - analysis_date=db.analysis_date, - commission_date=db.commission_date, - construction_cost=50000, - bill_overview=db.bill_overview, - prior_annual_bill_table=db.bill_overview_organized, - other_debt_service=db.liability_dictionary, - prior_income_statement_table=prior_IS_table, - prior_balance_sheet_table=prior_BS_table, - loan_input_list=db.loan_input_list -) - -scenario.prelim_anlaysis( - prior_month_bill=db.prior_month_bill, - percent_saving_dict=db.percent_saving_dict, - full_saving_dict=db.full_saving_dict, - growth_rate_flag=growth_toggle, - req_dscr=db.req_dscr, - customer_preference=db.customer_preference) - -print(scenario.get_annual_debt_service()) + prior_annual_bill = self.prior_income_statement_table.get_total_energy_dict() + net_saving_dict = {} + print(prior_annual_bill) + for year in prior_annual_bill: + net_saving_dict[year] = prior_annual_bill[year] - proforma_bill[year] - annual_debt_service[year] + graph_dict = { + 'energy_expenses': proforma_bill, + 'total_loan': annual_debt_service, + 'net_savings': net_saving_dict} + return graph_dict + + +# ***** ugly test that can be a guide for front end dev ***** +# growth_toggle = 0.01 +# prior_IS_table = Income_Statement_Table( +# db.raw_income_input, +# db.bill_overview_organized) +# prior_IS_table.project(growth_toggle, db.analysis_date, db.bill_overview_organized) +# prior_BS_table = Balance_Sheet_Table(db.raw_balance_sheet) +# prior_BS_table.project_balance_sheet( +# db.analysis_date, +# db.liability_dictionary, +# prior_IS_table.get_noi_dict()) + +# scenario = Scenario( +# analysis_date=db.analysis_date, +# commission_date=db.commission_date, +# construction_cost=50000, +# bill_overview=db.bill_overview, +# prior_annual_bill_table=db.bill_overview_organized, +# other_debt_service=db.liability_dictionary, +# prior_income_statement_table=prior_IS_table, +# prior_balance_sheet_table=prior_BS_table, +# loan_input_list=db.loan_input_list +# ) + +# scenario.prelim_anlaysis( +# prior_month_bill=db.prior_month_bill, +# percent_saving_dict=db.percent_saving_dict, +# full_saving_dict=db.full_saving_dict, +# growth_rate_flag=growth_toggle, +# req_dscr=db.req_dscr, +# customer_preference=db.customer_preference) + +# print(scenario.get_annual_debt_service()) +# print(scenario.get_graph_dict()) # print(scenario.get_graph_dict()) -- GitLab