From 0df7f23c2b281f01c25403def105ef3798be7c9a Mon Sep 17 00:00:00 2001 From: Sarey Hamarneh Date: Mon, 1 May 2017 15:26:08 -0400 Subject: [PATCH 01/15] Create balance sheet classes --- bpfin/financials/financial_lib.py | 228 ++++++++++++++++++++---------- 1 file changed, 154 insertions(+), 74 deletions(-) diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py index f9c22cc..b1e2573 100644 --- a/bpfin/financials/financial_lib.py +++ b/bpfin/financials/financial_lib.py @@ -5,6 +5,7 @@ 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 + # import bpfin.utilbills.bill_lib as bl # import pprint @@ -141,23 +142,28 @@ class Income_Statement(): self.water_opex = annual_bills['water'] self.energy_opex = self.electricity_opex + self.gas_opex + self.oil_opex + self.water_opex self.other_utility = self.revenue * characters['other_utility_percent'] - self.non_utility_expense = self.revenue * characters['non_utility_expense_percent'] + self.non_utility_expense = self.revenue * 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(self, income_statement_characters, bill_overview_organized): + 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.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.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 @@ -198,7 +204,8 @@ def convert_income_statement_class(income_statement_class): 'non_utility_expense': income_statement_class.non_utility_expense, 'net_non_energy_opex': income_statement_class.net_non_energy_opex, 'total_opex': income_statement_class.total_opex, - 'noi': income_statement_class.noi} + 'noi': income_statement_class.noi + } return income_statement_dict @@ -207,7 +214,9 @@ class Income_Statement_Next(): Create single year income_statement objective, with input of last year data, income statement characters, and projected annual bill """ - def __init__(self, year, last_revenue, growth_rate_flag, characters, annual_bill_table): + + def __init__(self, year, last_revenue, growth_rate_flag, characters, + annual_bill_table): """ Calculation is done in initiation. Args: @@ -247,7 +256,8 @@ class Income_Statement_Next(): self.water_opex = annual_bill_table['water'][self.year] self.energy_opex = self.electricity_opex + self.gas_opex + self.oil_opex + self.water_opex self.other_utility = self.revenue * characters['other_utility_percent'] - self.non_utility_expense = self.revenue * characters['non_utility_expense_percent'] + self.non_utility_expense = self.revenue * 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 @@ -261,6 +271,7 @@ class Income_Statement_Table(): hist_table (list): list of single year income_statement objectives, containing historical data table(list): list of single year income_statement objectives, containing historical and projected data """ + def __init__(self, raw_income_input, annual_bill_table): """ Create hist_table to store historical income statement data, and calculate some key characters. @@ -301,7 +312,8 @@ class Income_Statement_Table(): for year in raw_income_input: current_income_statement = Income_Statement() - current_income_statement.put_hist(year, raw_income_input[year], annual_bill_table) + current_income_statement.put_hist(year, raw_income_input[year], + annual_bill_table) self.hist_table.append(current_income_statement) sorted_income_hist_year = sorted(raw_income_input) @@ -321,9 +333,10 @@ class Income_Statement_Table(): other_utility_sum += current_income_statement.other_utility non_utility_expense_sum += current_income_statement.non_utility_expense - self.other_utility_percent = other_utility_sum/revenue_sum - self.non_utility_expense_percent = non_utility_expense_sum/revenue_sum - self.revenue_average = revenue_sum / (self.hist_end_year - self.hist_start_year + 1) + self.other_utility_percent = other_utility_sum / revenue_sum + self.non_utility_expense_percent = non_utility_expense_sum / revenue_sum + self.revenue_average = revenue_sum / ( + self.hist_end_year - self.hist_start_year + 1) self.table = self.hist_table self.characters = { @@ -332,7 +345,8 @@ class Income_Statement_Table(): 'cagr': self.cagr, 'other_utility_percent': self.other_utility_percent, 'non_utility_expense_percent': self.non_utility_expense_percent, - 'revenue_average': self.revenue_average} + 'revenue_average': self.revenue_average + } def project(self, growth_rate_flag, analysis_date, annual_bill_table): """ @@ -355,7 +369,8 @@ class Income_Statement_Table(): if year <= current_table[-1].year: continue current_income_statement = Income_Statement_Next( - year, last_revenue, growth_rate_flag, self.characters, annual_bill_table) + year, last_revenue, growth_rate_flag, self.characters, + annual_bill_table) current_table.append(current_income_statement) # print(current_income_statement.revenue, current_income_statement.noi) self.table = current_table @@ -372,19 +387,33 @@ class Income_Statement_Table(): hist_table_dict = {} for current_income_statement in self.hist_table: hist_table_dict[current_income_statement.year] = { - '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} + '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 hist_table_dict def get_cagr(self): @@ -407,12 +436,17 @@ class Income_Statement_Table(): current_income_statement = Income_Statement() average_revenue = mean(list(i_s.revenue for i_s in self.hist_table)) annual_bills = { - 'electricity': mean(list(i_s.electricity_opex for i_s in self.hist_table)), - 'gas': mean(list(i_s.gas_opex for i_s in self.hist_table)), - 'oil': mean(list(i_s.oil_opex for i_s in self.hist_table)), - 'water': mean(list(i_s.water_opex for i_s in self.hist_table)) + 'electricity': + mean(list(i_s.electricity_opex for i_s in self.hist_table)), + 'gas': + mean(list(i_s.gas_opex for i_s in self.hist_table)), + 'oil': + mean(list(i_s.oil_opex for i_s in self.hist_table)), + 'water': + mean(list(i_s.water_opex for i_s in self.hist_table)) } - current_income_statement.put_average(average_revenue, annual_bills, self.characters) + current_income_statement.put_average(average_revenue, annual_bills, + self.characters) return convert_income_statement_class(current_income_statement) @@ -429,19 +463,33 @@ class Income_Statement_Table(): for current_income_statement in self.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} + '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 def get_noi_dict(self): @@ -452,45 +500,77 @@ class Income_Statement_Table(): """ noi_dict = {} for current_income_statement in self.table: - noi_dict[current_income_statement.year] = current_income_statement.noi + noi_dict[ + current_income_statement.year] = current_income_statement.noi return noi_dict -# # ************ guide for front end dev *********** -# # First, fill in bill overview, save it. +class Balance_Sheet(): + def __init__(self): + self.year = None + self.cash_available = None + # self.current_assets = None + # self.fixed_assets = None + self.liability = None + # self.current_liabilities = None + # self.fixed_liablities = None + # self.bop_equity = None + # self.cap_holdings = None + # self.net_income = None + # self.eop_equity = None + + def put_hist_balance_sheet(self, year, balance_sheet_input): + # annual_bill_table is a parameter here but I do not believe I need it. + # is there something to replace is with? Or should I just delete it? + + self.year = year + self.cash_available = balance_sheet_input['cash available'] + self.liability = balance_sheet_input['liability'] + # where do I reference cash, noi, and liab? + # cash is defined in class above + # noi is from income statement + # liab is defined in class above + + + + + + + # # ************ 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 + # # 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) + # # 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) + # # 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()) + # # 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) + # # 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()) + # # 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()) + # ### front end doens't need this get yet + # print('\n noi dict =', IS_table.get_noi_dict()) -# ************ test draft*********** -# class test_stru(): -# def __init__(self, number): -# self.number = number + # ************ test draft*********** + # class test_stru(): + # def __init__(self, number): + # self.number = number -# test_1 = test_stru(2.0) -# test_2 = test_stru(3.0) -# test_3 = test_stru(5.0) + # test_1 = test_stru(2.0) + # test_2 = test_stru(3.0) + # test_3 = test_stru(5.0) -# test_list = [test_1, test_2, test_3] -# form_list = list(ob.number for ob in test_list) -# print(form_list) + # test_list = [test_1, test_2, test_3] + # form_list = list(ob.number for ob in test_list) + # print(form_list) -- GitLab From d58a29b9c4d6b27b59416313e3bc04af12964148 Mon Sep 17 00:00:00 2001 From: Sarey Hamarneh Date: Mon, 1 May 2017 17:05:39 -0400 Subject: [PATCH 02/15] Balance sheet --- bpfin/financials/financial_lib.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py index b1e2573..e55870f 100644 --- a/bpfin/financials/financial_lib.py +++ b/bpfin/financials/financial_lib.py @@ -508,15 +508,15 @@ class Income_Statement_Table(): class Balance_Sheet(): def __init__(self): self.year = None - self.cash_available = None + self.cash = None # self.current_assets = None # self.fixed_assets = None - self.liability = None + self.other_debt_service = None # self.current_liabilities = None # self.fixed_liablities = None # self.bop_equity = None # self.cap_holdings = None - # self.net_income = None + self.net_income = None # self.eop_equity = None def put_hist_balance_sheet(self, year, balance_sheet_input): @@ -524,12 +524,11 @@ class Balance_Sheet(): # is there something to replace is with? Or should I just delete it? self.year = year - self.cash_available = balance_sheet_input['cash available'] - self.liability = balance_sheet_input['liability'] - # where do I reference cash, noi, and liab? - # cash is defined in class above - # noi is from income statement - # liab is defined in class above + self.cash = balance_sheet_input['cash'] + self.other_debt_service = balance_sheet_input['other debt service'] + self.net_income = balance_sheet_input['net income'] + + -- GitLab From 63ccf6ee0bb18298a370622b1b580c4bc4a95f76 Mon Sep 17 00:00:00 2001 From: Sarey Hamarneh Date: Mon, 1 May 2017 17:54:34 -0400 Subject: [PATCH 03/15] Balance sheet class in financial_lib --- bpfin/financials/financial_lib.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py index e55870f..a51643b 100644 --- a/bpfin/financials/financial_lib.py +++ b/bpfin/financials/financial_lib.py @@ -529,8 +529,26 @@ class Balance_Sheet(): self.net_income = balance_sheet_input['net income'] +def convert_balance_sheet_class(balance_sheet_class): + """ + Convert single year balance sheet objective into a dictionary format + Args: + balance_sheet_class (objective): single year balance sheet objective + Return: + balance_sheet_dict (dictionary) + """ + balance_sheet_dict = { + 'year': balance_sheet_class.year, + 'cash': balance_sheet_class.cash, + 'other_debt_service': balance_sheet_class.other_debt_service, + 'net_income': balance_sheet_class.net_income + } + return balance_sheet_dict +# class Balance_Sheet_Next(): +# def __init__(self, year, cash, other_debt_service, net_income, +# noi_dict): -- GitLab From 9ed9006154dbe950fed83f7319d73c7af6de4bc9 Mon Sep 17 00:00:00 2001 From: Sarey Hamarneh Date: Mon, 1 May 2017 18:02:35 -0400 Subject: [PATCH 04/15] Change financial_lib --- bpfin/financials/financial_lib.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py index a51643b..cb05ec7 100644 --- a/bpfin/financials/financial_lib.py +++ b/bpfin/financials/financial_lib.py @@ -545,10 +545,10 @@ def convert_balance_sheet_class(balance_sheet_class): } return balance_sheet_dict -# class Balance_Sheet_Next(): +class Balance_Sheet_Next(): -# def __init__(self, year, cash, other_debt_service, net_income, -# noi_dict): + def __init__(self, year, cash, other_debt_service, net_income, noi_dict): + get -- GitLab From 0906999c2d5097c4cfb98e620f83b63b4584aaa5 Mon Sep 17 00:00:00 2001 From: Sarey Hamarneh Date: Mon, 1 May 2017 18:04:59 -0400 Subject: [PATCH 05/15] Pull changes --- bpfin/financials/balance_sheet_projection.py | 56 +++++++++++++++++++ bpfin/financials/cash_balance.py | 6 ++ bpfin/financials/liability.py | 6 +- .../test_balance_sheet_projection.py | 41 ++++++++++++++ bpfin/tests/test_financials/test_liability.py | 2 +- bpfin/tests/testdata/sample_data.py | 19 +++++-- requirements.txt | 1 + 7 files changed, 123 insertions(+), 8 deletions(-) create mode 100644 bpfin/financials/balance_sheet_projection.py create mode 100644 bpfin/tests/test_financials/test_balance_sheet_projection.py diff --git a/bpfin/financials/balance_sheet_projection.py b/bpfin/financials/balance_sheet_projection.py new file mode 100644 index 0000000..60a68da --- /dev/null +++ b/bpfin/financials/balance_sheet_projection.py @@ -0,0 +1,56 @@ +import datetime + + +def balance_sheet_projection(cash_balance, liability, + income_statement_projection, analysis_date): + """Return balance sheet projection. + Args: + cash_balance (dictionary): {year:value}, cash per year + liability (dictionary): {(year):value} value can be mortgage, loan debt, etc + income_statement_projection (dictionary): {year:income statement values - take NOI} + analysis_date (dictionary): proforma's starting date and the years of proforma + Returns: + dictionary: {year: balance sheet cash available} + The future balance sheet cash available = cash balance + NOI - liability for future. + The past balance sheet cash available = None. + The present balance sheet cash available = cash balance from bank statement or balance sheet + + """ + + analysis_years = {} + + for date in analysis_date: + start_year = date.year + duration = analysis_date[date] + for i in range(duration): + analysis_years[start_year + i] = [] + + smallest_year = min(cash_balance) + largest_year = max(cash_balance) + + for an_year in analysis_years: + if an_year in cash_balance: + analysis_years[an_year] = cash_balance[an_year] + # If the cash available value exists (balance sheet, bank statements), cash available = to that value + elif an_year < smallest_year: + analysis_years[an_year] = None + # If the analysis period of time starts before cash info is available, return None. + # Ex: If analysis date starts in 1999, but our starting cash balance info is from 2004, + # Then 1999-2003 will be None. + elif an_year > largest_year: + previous_year = an_year - 1 + cash_b = analysis_years[previous_year] + if an_year in liability: + liability_value = liability[an_year] + else: + liability_value = 0 + if an_year in income_statement_projection: + noi = income_statement_projection[an_year]['noi'] + else: + noi = 0 + analysis_years[an_year] = cash_b - liability_value + noi + # If we are asked to project the cash balance for future values, + # We use the most recent cash info + NOI - Liability. For example, if we only have information to 2016, + # Then 2017 = 2016 cash + 2017 NOI (projected) - 2017 liability (projected) + + return analysis_years diff --git a/bpfin/financials/cash_balance.py b/bpfin/financials/cash_balance.py index f8759ea..a73675d 100644 --- a/bpfin/financials/cash_balance.py +++ b/bpfin/financials/cash_balance.py @@ -1,4 +1,10 @@ def cash_balance(cash_dictionary): + """Returns current cash balance + Args: + cash_dictionary (dictionary): {datetime:(cash value,year)} + Returns: + dictionary: {datetime, cash value} + """ cash_balance_dictionary = {} diff --git a/bpfin/financials/liability.py b/bpfin/financials/liability.py index 01e5ceb..a946ba0 100644 --- a/bpfin/financials/liability.py +++ b/bpfin/financials/liability.py @@ -46,10 +46,10 @@ def liability_calendar(date, months): Return: list: list (calendar) of dates """ - calendar = [] + liability_calendar = [] for i in range(months): - calendar.append(add_months(date, i)) - return calendar + liability_calendar.append(add_months(date, i)) + return liability_calendar def create_liability_dict(liability_dictionary): diff --git a/bpfin/tests/test_financials/test_balance_sheet_projection.py b/bpfin/tests/test_financials/test_balance_sheet_projection.py new file mode 100644 index 0000000..05c4afe --- /dev/null +++ b/bpfin/tests/test_financials/test_balance_sheet_projection.py @@ -0,0 +1,41 @@ +from bpfin.financials.balance_sheet_projection import balance_sheet_projection +from bpfin.tests.testdata import sample_data as db +import datetime + + +def test_balance_sheet_projection(): + input_cash_balance = db.cash_balance + input_liability = db.liability_dictionary + input_noi = db.income_statement_projection_cagr + input_date_years = {datetime.date(2012, 1, 15): 25} + output = { + 2012: None, + 2013: None, + 2014: 5000.0, + 2015: 6000, + 2016: 4500.0, + 2017: 35778.43692755746, + 2018: 75992.72229401008, + 2019: 124835.35357997121, + 2020: 177567.28767315467, + 2021: 234506.6375641261, + 2022: 295993.759336618, + 2023: 362325.94364370033, + 2024: 433787.36982739856, + 2025: 510670.2474431231, + 2026: 593249.2143796427, + 2027: 681814.8219497779, + 2028: 776716.587140195, + 2029: 878344.3914861011, + 2030: 987109.6873789529, + 2031: 1103443.8773919346, + 2032: 1227793.8279146897, + 2033: 1360621.1623494846, + 2034: 1502409.5252755708, + 2035: 1653669.0253920422, + 2036: 1814938.615393169 + } + result = balance_sheet_projection(input_cash_balance, input_liability, + input_noi, input_date_years) + + assert output == result diff --git a/bpfin/tests/test_financials/test_liability.py b/bpfin/tests/test_financials/test_liability.py index 606f621..8c18ba5 100644 --- a/bpfin/tests/test_financials/test_liability.py +++ b/bpfin/tests/test_financials/test_liability.py @@ -5,7 +5,7 @@ from bpfin.tests.testdata import sample_data as db def test_final_liability_dict(): input_start_date = db.analysis_date['proforma_start'] - input_dict = db.liability_dictionary + input_dict = db.liability_input input_duration = db.analysis_date['proforma_duration'] output = { 2012: 650, diff --git a/bpfin/tests/testdata/sample_data.py b/bpfin/tests/testdata/sample_data.py index 32103e9..9fd24b8 100644 --- a/bpfin/tests/testdata/sample_data.py +++ b/bpfin/tests/testdata/sample_data.py @@ -508,12 +508,23 @@ income_statement_projection_cagr = { 'year': 2036}} -# liability, mortgage and other debt data +liability_input = {'debt1': (150, 'NYSERDA', 10, datetime.date(2012, 12, 31)), + 'debt2': (100, 'NYCEEC', 20, datetime.date(2012, 8, 31))} + + liability_dictionary = { - 'debt1': (150, 'NYSERDA', 10, datetime.date(2012, 12, 31)), - 'debt2': (100, 'NYCEEC', 20, datetime.date(2012, 8, 31)) + 2012: 650, + 2013: 2550, + 2014: 100, + 2015: 6000, + 2016: 15000, + 2017: 10000, + 2018: 5000 } - +# {year: value, is_balancesheet (boolean)} +cash_balance = { + 2014: 5000.0, 2015: 6000, 2016: 4500.0 +} # pro-forma date and bill projection - # proforma_date_from, proforma_date_to diff --git a/requirements.txt b/requirements.txt index 53ca6bb..203e6b2 100755 --- a/requirements.txt +++ b/requirements.txt @@ -5,3 +5,4 @@ pyparsing==2.1.10 python-dateutil==2.6.0 pytz==2016.7 xlrd==1.0.0 +scipy==0.18.1 -- GitLab From 49040d37f7ca8c34c290056cb365b00a9c229ed9 Mon Sep 17 00:00:00 2001 From: Sarey Hamarneh Date: Mon, 1 May 2017 18:29:11 -0400 Subject: [PATCH 06/15] More changes to balance sheet --- bpfin/financials/balance_sheet_projection.py | 8 ++++---- .../test_financials/test_balance_sheet_projection.py | 3 ++- bpfin/tests/testdata/sample_data.py | 6 ++++++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/bpfin/financials/balance_sheet_projection.py b/bpfin/financials/balance_sheet_projection.py index 60a68da..54d8dcd 100644 --- a/bpfin/financials/balance_sheet_projection.py +++ b/bpfin/financials/balance_sheet_projection.py @@ -2,12 +2,12 @@ import datetime def balance_sheet_projection(cash_balance, liability, - income_statement_projection, analysis_date): + noi_dict, analysis_date): """Return balance sheet projection. Args: cash_balance (dictionary): {year:value}, cash per year liability (dictionary): {(year):value} value can be mortgage, loan debt, etc - income_statement_projection (dictionary): {year:income statement values - take NOI} + noi_dict (dictionary): {year:income statement values - take NOI} analysis_date (dictionary): proforma's starting date and the years of proforma Returns: dictionary: {year: balance sheet cash available} @@ -44,8 +44,8 @@ def balance_sheet_projection(cash_balance, liability, liability_value = liability[an_year] else: liability_value = 0 - if an_year in income_statement_projection: - noi = income_statement_projection[an_year]['noi'] + if an_year in noi_dict: + noi = noi_dict[an_year] else: noi = 0 analysis_years[an_year] = cash_b - liability_value + noi diff --git a/bpfin/tests/test_financials/test_balance_sheet_projection.py b/bpfin/tests/test_financials/test_balance_sheet_projection.py index 05c4afe..fc0cc9c 100644 --- a/bpfin/tests/test_financials/test_balance_sheet_projection.py +++ b/bpfin/tests/test_financials/test_balance_sheet_projection.py @@ -1,4 +1,5 @@ from bpfin.financials.balance_sheet_projection import balance_sheet_projection +from bpfin.financials.financial_lib import Income_Statement_Table from bpfin.tests.testdata import sample_data as db import datetime @@ -6,7 +7,7 @@ import datetime def test_balance_sheet_projection(): input_cash_balance = db.cash_balance input_liability = db.liability_dictionary - input_noi = db.income_statement_projection_cagr + input_noi = db.noi_dictionary input_date_years = {datetime.date(2012, 1, 15): 25} output = { 2012: None, diff --git a/bpfin/tests/testdata/sample_data.py b/bpfin/tests/testdata/sample_data.py index 9fd24b8..33410d9 100644 --- a/bpfin/tests/testdata/sample_data.py +++ b/bpfin/tests/testdata/sample_data.py @@ -507,6 +507,12 @@ income_statement_projection_cagr = { 'water_opex': 0.0, 'year': 2036}} +noi_dictionary = {2017: 41278.43692755746, 2018 : 45214.28536645262, 2019 : 48842.631285961135, +2020: 52731.934093183474,2021: 56939.349890971425,2022:61487.1217724919, 2023 : 66332.18430708232, +2024: 71461.4261836982, 2025: 76882.87761572453, 2026: 82578.96693651963, 2027: 88565.60757013515, +2028: 94901.76519041706, 2029: 101627.80434590613, 2030: 108765.29589285178, 2031: 116334.19001298171, 2032: 124349.95052275498, +2033: 132827.33443479502, 2034: 141788.36292608615, 2035: 151259.5001164715, 2036: 161269.59000112678} + liability_input = {'debt1': (150, 'NYSERDA', 10, datetime.date(2012, 12, 31)), 'debt2': (100, 'NYCEEC', 20, datetime.date(2012, 8, 31))} -- GitLab From e0b214fdef8ab7377f1ef6073bf4aa8ba7f646d3 Mon Sep 17 00:00:00 2001 From: Sarey Hamarneh Date: Tue, 2 May 2017 13:26:33 -0400 Subject: [PATCH 07/15] Fixing classes in financial_lib for balance sheet --- bpfin/financials/financial_lib.py | 83 +++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 3 deletions(-) diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py index dcbfeef..1db6ef2 100644 --- a/bpfin/financials/financial_lib.py +++ b/bpfin/financials/financial_lib.py @@ -547,19 +547,96 @@ def convert_balance_sheet_class(balance_sheet_class): class Balance_Sheet_Next(): - def __init__(self, year, last_year_cash, last_year_other_debt_service, - last_year_net_income, balance_sheet_table): + last_year_net_income, balance_sheet_table): self.year = year - self.other_debt_service = balance_sheet_table['other_debt_service'][self.year] + self.other_debt_service = balance_sheet_table['other_debt_service'][ + self.year] self.net_income = balance_sheet_table['net_income'][self.year] self.cash = last_year_cash + self.other_debt_service + self.net_income +class Balance_Sheet_Table(): + def __init__(self, raw_balance_sheet_input): + + self.hist_start_year = None + self.hist_end_year = None + self.other_debt_service = 0.00 + self.net_income = 0.00 + self.cash = 0.00 + self.hist_balance_sheet_table = [] + self.bs_table = [] + self.characters = {} + + for year in raw_balance_sheet_input: + + current_balance_sheet = Balance_Sheet() + current_balance_sheet.put_hist_balance_sheet( + year, raw_balance_sheet_input[year]) + self.hist_balance_sheet_table.append(current_balance_sheet) + + sorted_balance_sheet_hist_year = sorted(raw_balance_sheet_input) + self.hist_start_year = sorted_balance_sheet_hist_year[0] + self.hist_end_year = sorted_balance_sheet_hist_year[-1] + + self.bs_table = self.hist_balance_sheet_table + self.characters = { + 'start_year': self.hist_start_year, + 'end_year': self.hist_end_year, + 'other_debt_service': self.other_debt_service, + 'net_income': self.net_income, + 'cash': self.cash, + } + + def project_balance_sheet(self, analysis_date): + + # characters = copy.deepcopy(self.characters) + proforma_year = form_bill_year(analysis_date['proforma_start'], + analysis_date['proforma_duration']) + current_table = copy.deepcopy(self.hist_balance_sheet_table) + for year in proforma_year: + last_revenue = current_table[-1].revenue + if year <= current_table[-1].year: + continue + current_balance_sheet = Balance_Sheet_Next(year, self.characters) + current_table.append(current_balance_sheet) + self.bs_table = current_table + return current_table + def get_hist_balance_sheet_table(self): + """ + Get historical table, in dictionary formatting + Return: + dictionary: dict of dict of income statement. Key is year + Description: + hist_table_dict = {2014: {'year': 2014, 'revenue': 100.0, ..., 'not': 5.0}, ... , 2016:{}} + """ + hist_balance_sheet_dict = {} + for current_balance_sheet in self.hist_balance_sheet_table: + hist_balance_sheet_dict[current_balance_sheet.year] = { + 'year': current_balance_sheet.year, + 'other_debt_service': current_balance_sheet.other_debt_service, + 'other_net_income': current_balance_sheet.net_income, + 'cash': current_balance_sheet.cash + } + return hist_balance_sheet_dict + def get_single_year_balance_sheet(self, year): + for current_balance_sheet in self.bs_table: + if current_balance_sheet.year == year: + return { + 'year': + current_balance_sheet.year, + 'other_debt_service': + current_balance_sheet.other_debt_service, + 'other_net_income': + current_balance_sheet.net_income, + 'cash': + current_balance_sheet.cash + } + return None # # ************ guide for front end dev *********** # # First, fill in bill overview, save it. -- GitLab From 6473b25884daeadd2426d611bc03b33a4864ff7d Mon Sep 17 00:00:00 2001 From: Sarey Hamarneh Date: Tue, 2 May 2017 13:49:37 -0400 Subject: [PATCH 08/15] Fix bug --- bpfin/financials/financial_lib.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py index 1db6ef2..a9d591f 100644 --- a/bpfin/financials/financial_lib.py +++ b/bpfin/financials/financial_lib.py @@ -547,13 +547,11 @@ def convert_balance_sheet_class(balance_sheet_class): class Balance_Sheet_Next(): - def __init__(self, year, last_year_cash, last_year_other_debt_service, - last_year_net_income, balance_sheet_table): + def __init__(self, year, last_year_cash, characters): self.year = year - self.other_debt_service = balance_sheet_table['other_debt_service'][ - self.year] - self.net_income = balance_sheet_table['net_income'][self.year] + self.other_debt_service = characters['other_debt_service'][self.year] + self.net_income = characters['net_income'][self.year] self.cash = last_year_cash + self.other_debt_service + self.net_income @@ -596,10 +594,11 @@ class Balance_Sheet_Table(): analysis_date['proforma_duration']) current_table = copy.deepcopy(self.hist_balance_sheet_table) for year in proforma_year: - last_revenue = current_table[-1].revenue + last_year_cash = current_table[-1].last_year_cash if year <= current_table[-1].year: continue - current_balance_sheet = Balance_Sheet_Next(year, self.characters) + current_balance_sheet = Balance_Sheet_Next(year, last_year_cash, + self.characters) current_table.append(current_balance_sheet) self.bs_table = current_table return current_table -- GitLab From 325cd739980225a2a987149987ac95cc36d0f40a Mon Sep 17 00:00:00 2001 From: Sarey Hamarneh Date: Tue, 2 May 2017 18:39:17 -0400 Subject: [PATCH 09/15] Balance sheet creation and projection --- bpfin/financials/financial_lib.py | 80 ++++++++++++----------------- bpfin/tests/testdata/sample_data.py | 3 ++ 2 files changed, 36 insertions(+), 47 deletions(-) diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py index a9d591f..7bd197e 100644 --- a/bpfin/financials/financial_lib.py +++ b/bpfin/financials/financial_lib.py @@ -524,9 +524,10 @@ class Balance_Sheet(): # is there something to replace is with? Or should I just delete it? self.year = year - self.cash = balance_sheet_input['cash'] - self.other_debt_service = balance_sheet_input['other debt service'] - self.net_income = balance_sheet_input['net income'] + self.cash = balance_sheet_input['cash'][year] + self.other_debt_service = balance_sheet_input['other_debt_service'][ + year] + self.net_income = balance_sheet_input['net_income'][year] def convert_balance_sheet_class(balance_sheet_class): @@ -547,70 +548,55 @@ def convert_balance_sheet_class(balance_sheet_class): class Balance_Sheet_Next(): - def __init__(self, year, last_year_cash, characters): + def __init__(self, year, last_year_cash, other_debt_service, + net_income_dictionary): self.year = year - self.other_debt_service = characters['other_debt_service'][self.year] - self.net_income = characters['net_income'][self.year] + self.other_debt_service = other_debt_service[self.year] + self.net_income = net_income_dictionary[self.year] self.cash = last_year_cash + self.other_debt_service + self.net_income class Balance_Sheet_Table(): - def __init__(self, raw_balance_sheet_input): + def __init__(self, balance_sheet_input): self.hist_start_year = None self.hist_end_year = None - self.other_debt_service = 0.00 - self.net_income = 0.00 - self.cash = 0.00 self.hist_balance_sheet_table = [] self.bs_table = [] - self.characters = {} + # entire table, not just historical - for year in raw_balance_sheet_input: + for year in balance_sheet_input['cash']: current_balance_sheet = Balance_Sheet() current_balance_sheet.put_hist_balance_sheet( - year, raw_balance_sheet_input[year]) + year, balance_sheet_input) self.hist_balance_sheet_table.append(current_balance_sheet) - sorted_balance_sheet_hist_year = sorted(raw_balance_sheet_input) + sorted_balance_sheet_hist_year = sorted(balance_sheet_input['cash']) self.hist_start_year = sorted_balance_sheet_hist_year[0] self.hist_end_year = sorted_balance_sheet_hist_year[-1] self.bs_table = self.hist_balance_sheet_table - self.characters = { - 'start_year': self.hist_start_year, - 'end_year': self.hist_end_year, - 'other_debt_service': self.other_debt_service, - 'net_income': self.net_income, - 'cash': self.cash, - } - def project_balance_sheet(self, analysis_date): + def project_balance_sheet(self, analysis_date, other_debt_service, + net_income_dictionary): - # characters = copy.deepcopy(self.characters) proforma_year = form_bill_year(analysis_date['proforma_start'], analysis_date['proforma_duration']) current_table = copy.deepcopy(self.hist_balance_sheet_table) for year in proforma_year: - last_year_cash = current_table[-1].last_year_cash + last_year_cash = current_table[-1].cash if year <= current_table[-1].year: continue current_balance_sheet = Balance_Sheet_Next(year, last_year_cash, - self.characters) + other_debt_service, + net_income_dictionary) current_table.append(current_balance_sheet) self.bs_table = current_table return current_table def get_hist_balance_sheet_table(self): - """ - Get historical table, in dictionary formatting - Return: - dictionary: dict of dict of income statement. Key is year - Description: - hist_table_dict = {2014: {'year': 2014, 'revenue': 100.0, ..., 'not': 5.0}, ... , 2016:{}} - """ hist_balance_sheet_dict = {} for current_balance_sheet in self.hist_balance_sheet_table: hist_balance_sheet_dict[current_balance_sheet.year] = { @@ -621,21 +607,21 @@ class Balance_Sheet_Table(): } return hist_balance_sheet_dict - def get_single_year_balance_sheet(self, year): - - for current_balance_sheet in self.bs_table: - if current_balance_sheet.year == year: - return { - 'year': - current_balance_sheet.year, - 'other_debt_service': - current_balance_sheet.other_debt_service, - 'other_net_income': - current_balance_sheet.net_income, - 'cash': - current_balance_sheet.cash - } - return None + # def get_single_year_balance_sheet(self, year): + + # for current_balance_sheet in self.bs_table: + # if current_balance_sheet.year == year: + # return { + # 'year': + # current_balance_sheet.year, + # 'other_debt_service': + # current_balance_sheet.other_debt_service, + # 'other_net_income': + # current_balance_sheet.net_income, + # 'cash': + # current_balance_sheet.cash + # } + # return None # # ************ guide for front end dev *********** # # First, fill in bill overview, save it. diff --git a/bpfin/tests/testdata/sample_data.py b/bpfin/tests/testdata/sample_data.py index 33410d9..377f1bc 100644 --- a/bpfin/tests/testdata/sample_data.py +++ b/bpfin/tests/testdata/sample_data.py @@ -532,6 +532,9 @@ cash_balance = { 2014: 5000.0, 2015: 6000, 2016: 4500.0 } +balance_sheet = {'cash':cash_balance, 'other_debt_service':liability_dictionary, + 'net_income':noi_dictionary} + # pro-forma date and bill projection - # proforma_date_from, proforma_date_to # prior_rough, post_rough -- GitLab From e09bddb525c300406a2fcca913316106817bae7a Mon Sep 17 00:00:00 2001 From: Sarey Hamarneh Date: Tue, 2 May 2017 19:38:44 -0400 Subject: [PATCH 10/15] Test files --- bpfin/financials/financial_lib.py | 30 +++++++++---------- .../test_financials/test_financial_lib.py | 22 ++++++++++++-- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py index 7bd197e..b05b414 100644 --- a/bpfin/financials/financial_lib.py +++ b/bpfin/financials/financial_lib.py @@ -607,21 +607,21 @@ class Balance_Sheet_Table(): } return hist_balance_sheet_dict - # def get_single_year_balance_sheet(self, year): - - # for current_balance_sheet in self.bs_table: - # if current_balance_sheet.year == year: - # return { - # 'year': - # current_balance_sheet.year, - # 'other_debt_service': - # current_balance_sheet.other_debt_service, - # 'other_net_income': - # current_balance_sheet.net_income, - # 'cash': - # current_balance_sheet.cash - # } - # return None + def get_single_year_balance_sheet(self, year): + + for current_balance_sheet in self.bs_table: + if current_balance_sheet.year == year: + return { + 'year': + current_balance_sheet.year, + 'other_debt_service': + current_balance_sheet.other_debt_service, + 'other_net_income': + current_balance_sheet.net_income, + 'cash': + current_balance_sheet.cash + } + return None # # ************ guide for front end dev *********** # # First, fill in bill overview, save it. diff --git a/bpfin/tests/test_financials/test_financial_lib.py b/bpfin/tests/test_financials/test_financial_lib.py index f4b4a36..025a52c 100644 --- a/bpfin/tests/test_financials/test_financial_lib.py +++ b/bpfin/tests/test_financials/test_financial_lib.py @@ -2,13 +2,15 @@ import datetime import bpfin.financials.financial_lib as fl 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 def test_organize_bill_overview(): input_bill_overview = db.bill_overview input_analysis_date = db.analysis_date output_dict = db.bill_overview_organized - result_dict = fl.organize_bill_overview(input_bill_overview, input_analysis_date) + result_dict = fl.organize_bill_overview(input_bill_overview, + input_analysis_date) assert output_dict == result_dict @@ -21,12 +23,26 @@ def test_Income_Statement_Table(): output_noi_dict = db.noi_dict_average output_single_year = db.income_statement_2017_avg - IS_table = Income_Statement_Table(input_raw_income_input, input_annual_bill_table) + IS_table = Income_Statement_Table(input_raw_income_input, + input_annual_bill_table) IS_table.project(-1.0, db.analysis_date, db.bill_overview_organized) assert IS_table.get_cagr() == output_cagr # test get_cagr assert IS_table.get_hist_table() == output_hist_table # test get_hist_table assert IS_table.get_average() == output_average_table # test get_average assert IS_table.get_noi_dict() == output_noi_dict # test get_noi_dict - assert IS_table.get_single_year(2017) == output_single_year # test get_single_year + assert IS_table.get_single_year( + 2017) == output_single_year # test get_single_year + +def test_Balance_Sheet_Table(): + input_raw_balance_sheet = db.balance_sheet + # output_hist_balance_sheet_table = + # output_single_year_bs = + + BS_table = Balance_Sheet_Table(input_raw_balance_sheet) + BS_table.project_balance_sheet(db.analysis_date, db.liability_dictionary, + db.noi_dictionary) + + assert BS_table.get_hist_balance_sheet_table() == output_hist_balance_sheet_table + assert BS_table.get_single_year_balance_sheet == output_single_year_bs -- GitLab From c1072c8be55b10670dcefb2975d8cfd5cff74cc3 Mon Sep 17 00:00:00 2001 From: Sarey Hamarneh Date: Wed, 3 May 2017 13:12:57 -0400 Subject: [PATCH 11/15] Test --- bpfin/financials/financial_lib.py | 1 - bpfin/tests/test_financials/test_financial_lib.py | 3 +-- bpfin/tests/testdata/sample_data.py | 8 +++++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py index b05b414..067dd30 100644 --- a/bpfin/financials/financial_lib.py +++ b/bpfin/financials/financial_lib.py @@ -600,7 +600,6 @@ class Balance_Sheet_Table(): hist_balance_sheet_dict = {} for current_balance_sheet in self.hist_balance_sheet_table: hist_balance_sheet_dict[current_balance_sheet.year] = { - 'year': current_balance_sheet.year, 'other_debt_service': current_balance_sheet.other_debt_service, 'other_net_income': current_balance_sheet.net_income, 'cash': current_balance_sheet.cash diff --git a/bpfin/tests/test_financials/test_financial_lib.py b/bpfin/tests/test_financials/test_financial_lib.py index 025a52c..fcade19 100644 --- a/bpfin/tests/test_financials/test_financial_lib.py +++ b/bpfin/tests/test_financials/test_financial_lib.py @@ -37,7 +37,7 @@ def test_Income_Statement_Table(): def test_Balance_Sheet_Table(): input_raw_balance_sheet = db.balance_sheet - # output_hist_balance_sheet_table = + output_hist_balance_sheet_table = db.hist_balance_sheet # output_single_year_bs = BS_table = Balance_Sheet_Table(input_raw_balance_sheet) @@ -45,4 +45,3 @@ def test_Balance_Sheet_Table(): db.noi_dictionary) assert BS_table.get_hist_balance_sheet_table() == output_hist_balance_sheet_table - assert BS_table.get_single_year_balance_sheet == output_single_year_bs diff --git a/bpfin/tests/testdata/sample_data.py b/bpfin/tests/testdata/sample_data.py index 377f1bc..982e736 100644 --- a/bpfin/tests/testdata/sample_data.py +++ b/bpfin/tests/testdata/sample_data.py @@ -507,7 +507,7 @@ income_statement_projection_cagr = { 'water_opex': 0.0, 'year': 2036}} -noi_dictionary = {2017: 41278.43692755746, 2018 : 45214.28536645262, 2019 : 48842.631285961135, +noi_dictionary = {2014: None, 2015: None, 2016: None, 2017: 41278.43692755746, 2018 : 45214.28536645262, 2019 : 48842.631285961135, 2020: 52731.934093183474,2021: 56939.349890971425,2022:61487.1217724919, 2023 : 66332.18430708232, 2024: 71461.4261836982, 2025: 76882.87761572453, 2026: 82578.96693651963, 2027: 88565.60757013515, 2028: 94901.76519041706, 2029: 101627.80434590613, 2030: 108765.29589285178, 2031: 116334.19001298171, 2032: 124349.95052275498, @@ -535,6 +535,12 @@ cash_balance = { balance_sheet = {'cash':cash_balance, 'other_debt_service':liability_dictionary, 'net_income':noi_dictionary} +hist_balance_sheet = {2014: {'cash': 5000, 'other_debt_service': 100, 'net_income': None}, + 2015: {'cash': 6000, 'other_debt_service': 6000, 'net_income': None}, + 2016: {'cash': 4500, 'other_debt_service': 15000, 'net_income': None}} + + + # pro-forma date and bill projection - # proforma_date_from, proforma_date_to # prior_rough, post_rough -- GitLab From 4c8b8220856fc82a2a3f5bf0192860fa84f7b7b5 Mon Sep 17 00:00:00 2001 From: Sarey Hamarneh Date: Wed, 3 May 2017 14:37:44 -0400 Subject: [PATCH 12/15] Fix tests for balance sheet --- bpfin/financials/financial_lib.py | 27 +++++++++++-------- .../test_financials/test_financial_lib.py | 6 ++++- bpfin/tests/testdata/sample_data.py | 8 ++++++ 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py index 067dd30..39c3afa 100644 --- a/bpfin/financials/financial_lib.py +++ b/bpfin/financials/financial_lib.py @@ -552,9 +552,9 @@ class Balance_Sheet_Next(): net_income_dictionary): self.year = year - self.other_debt_service = other_debt_service[self.year] - self.net_income = net_income_dictionary[self.year] - self.cash = last_year_cash + self.other_debt_service + self.net_income + self.other_debt_service = other_debt_service + self.net_income = net_income_dictionary + self.cash = last_year_cash - self.other_debt_service + self.net_income class Balance_Sheet_Table(): @@ -589,9 +589,15 @@ class Balance_Sheet_Table(): last_year_cash = current_table[-1].cash if year <= current_table[-1].year: continue + current_other_debt_service = 0.00 + current_net_income = 0.00 + if year in other_debt_service: + current_other_debt_service = other_debt_service[year] + if year in net_income_dictionary: + current_net_income = net_income_dictionary[year] current_balance_sheet = Balance_Sheet_Next(year, last_year_cash, - other_debt_service, - net_income_dictionary) + current_other_debt_service, + current_net_income) current_table.append(current_balance_sheet) self.bs_table = current_table return current_table @@ -601,7 +607,7 @@ class Balance_Sheet_Table(): for current_balance_sheet in self.hist_balance_sheet_table: hist_balance_sheet_dict[current_balance_sheet.year] = { 'other_debt_service': current_balance_sheet.other_debt_service, - 'other_net_income': current_balance_sheet.net_income, + 'net_income': current_balance_sheet.net_income, 'cash': current_balance_sheet.cash } return hist_balance_sheet_dict @@ -611,14 +617,13 @@ class Balance_Sheet_Table(): for current_balance_sheet in self.bs_table: if current_balance_sheet.year == year: return { - 'year': - current_balance_sheet.year, - 'other_debt_service': + current_balance_sheet.year: + {'other_debt_service': current_balance_sheet.other_debt_service, - 'other_net_income': + 'net_income': current_balance_sheet.net_income, 'cash': - current_balance_sheet.cash + current_balance_sheet.cash} } return None diff --git a/bpfin/tests/test_financials/test_financial_lib.py b/bpfin/tests/test_financials/test_financial_lib.py index fcade19..b11d9b7 100644 --- a/bpfin/tests/test_financials/test_financial_lib.py +++ b/bpfin/tests/test_financials/test_financial_lib.py @@ -38,10 +38,14 @@ def test_Income_Statement_Table(): def test_Balance_Sheet_Table(): input_raw_balance_sheet = db.balance_sheet output_hist_balance_sheet_table = db.hist_balance_sheet - # output_single_year_bs = + output_single_year_bs_2018 = db.balance_sheet_2018 + output_single_year_bs_2025 = db.balance_sheet_2025 + output_single_year_bs_2030 = db.balance_sheet_2030 BS_table = Balance_Sheet_Table(input_raw_balance_sheet) BS_table.project_balance_sheet(db.analysis_date, db.liability_dictionary, db.noi_dictionary) assert BS_table.get_hist_balance_sheet_table() == output_hist_balance_sheet_table + assert BS_table.get_single_year_balance_sheet(2018) == output_single_year_bs_2018 + diff --git a/bpfin/tests/testdata/sample_data.py b/bpfin/tests/testdata/sample_data.py index 982e736..30817d8 100644 --- a/bpfin/tests/testdata/sample_data.py +++ b/bpfin/tests/testdata/sample_data.py @@ -539,6 +539,14 @@ hist_balance_sheet = {2014: {'cash': 5000, 'other_debt_service': 100, 'net_incom 2015: {'cash': 6000, 'other_debt_service': 6000, 'net_income': None}, 2016: {'cash': 4500, 'other_debt_service': 15000, 'net_income': None}} +balance_sheet_2018 = {2018: {'cash': 75992.72229401008,'other_debt_service': 5000, +'net_income':45214.28536645262}} + +balance_sheet_2025 = {2025: {'cash': 510670.2474431231,'other_debt_service': 0.00, +'net_income':76882.87761572453}} + +balance_sheet_2030 = {2030: {'cash': 987109.6873789529,'other_debt_service': 0.00, +'net_income':108765.29589285178}} # pro-forma date and bill projection - -- GitLab From 55229ded9801b738960da6009df25ef93597ea72 Mon Sep 17 00:00:00 2001 From: Sarey Hamarneh Date: Wed, 3 May 2017 14:47:08 -0400 Subject: [PATCH 13/15] Add comments --- bpfin/financials/financial_lib.py | 51 ++++++++++--------- .../test_financials/test_financial_lib.py | 3 +- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py index 39c3afa..33aed0d 100644 --- a/bpfin/financials/financial_lib.py +++ b/bpfin/financials/financial_lib.py @@ -520,9 +520,13 @@ class Balance_Sheet(): # self.eop_equity = None def put_hist_balance_sheet(self, year, balance_sheet_input): - # annual_bill_table is a parameter here but I do not believe I need it. - # is there something to replace is with? Or should I just delete it? - + """Put historical data values into balance sheet based on the cash balance years. + Args: + year (int): year + balance_sheet_input (dictionary): dictionary of balance sheet items: cash, noi, debt_service + Returns: + dictionary: filled in balance sheet + """ self.year = year self.cash = balance_sheet_input['cash'][year] self.other_debt_service = balance_sheet_input['other_debt_service'][ @@ -531,13 +535,6 @@ class Balance_Sheet(): def convert_balance_sheet_class(balance_sheet_class): - """ - Convert single year balance sheet objective into a dictionary format - Args: - balance_sheet_class (objective): single year balance sheet objective - Return: - balance_sheet_dict (dictionary) - """ balance_sheet_dict = { 'year': balance_sheet_class.year, 'cash': balance_sheet_class.cash, @@ -548,12 +545,11 @@ def convert_balance_sheet_class(balance_sheet_class): class Balance_Sheet_Next(): - def __init__(self, year, last_year_cash, other_debt_service, - net_income_dictionary): + def __init__(self, year, last_year_cash, other_debt_service, net_income): self.year = year self.other_debt_service = other_debt_service - self.net_income = net_income_dictionary + self.net_income = net_income self.cash = last_year_cash - self.other_debt_service + self.net_income @@ -581,6 +577,14 @@ class Balance_Sheet_Table(): def project_balance_sheet(self, analysis_date, other_debt_service, net_income_dictionary): + """Create balance sheet projection. + Args: + analysis_date (dict): {pro_forma date: duration (years)} + other_debt_service (dict): dictionary of debt service values per year + net_income_dictionary (dict): dictionary of net income values per years + Returns: + dictionary: full dictionary of dictionaries of balance sheet entries + """ proforma_year = form_bill_year(analysis_date['proforma_start'], analysis_date['proforma_duration']) @@ -595,9 +599,9 @@ class Balance_Sheet_Table(): current_other_debt_service = other_debt_service[year] if year in net_income_dictionary: current_net_income = net_income_dictionary[year] - current_balance_sheet = Balance_Sheet_Next(year, last_year_cash, - current_other_debt_service, - current_net_income) + current_balance_sheet = Balance_Sheet_Next( + year, last_year_cash, current_other_debt_service, + current_net_income) current_table.append(current_balance_sheet) self.bs_table = current_table return current_table @@ -617,13 +621,14 @@ class Balance_Sheet_Table(): for current_balance_sheet in self.bs_table: if current_balance_sheet.year == year: return { - current_balance_sheet.year: - {'other_debt_service': - current_balance_sheet.other_debt_service, - 'net_income': - current_balance_sheet.net_income, - 'cash': - current_balance_sheet.cash} + current_balance_sheet.year: { + 'other_debt_service': + current_balance_sheet.other_debt_service, + 'nest_income': + current_balance_sheet.net_income, + 'cash': + current_balance_sheet.cash + } } return None diff --git a/bpfin/tests/test_financials/test_financial_lib.py b/bpfin/tests/test_financials/test_financial_lib.py index b11d9b7..4ce8a7a 100644 --- a/bpfin/tests/test_financials/test_financial_lib.py +++ b/bpfin/tests/test_financials/test_financial_lib.py @@ -48,4 +48,5 @@ def test_Balance_Sheet_Table(): assert BS_table.get_hist_balance_sheet_table() == output_hist_balance_sheet_table assert BS_table.get_single_year_balance_sheet(2018) == output_single_year_bs_2018 - + assert BS_table.get_single_year_balance_sheet(2025) == output_single_year_bs_2025 + assert BS_table.get_single_year_balance_sheet(2030) == output_single_year_bs_2030 -- GitLab From c03cbe3e28d747d60b445c98e9ea9681d7742f4f Mon Sep 17 00:00:00 2001 From: Sarey Hamarneh Date: Wed, 3 May 2017 15:48:23 -0400 Subject: [PATCH 14/15] Fix name and historical net income in test --- bpfin/financials/financial_lib.py | 2 +- bpfin/tests/test_financials/test_financial_lib.py | 2 +- bpfin/tests/testdata/sample_data.py | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py index 33aed0d..260111e 100644 --- a/bpfin/financials/financial_lib.py +++ b/bpfin/financials/financial_lib.py @@ -624,7 +624,7 @@ class Balance_Sheet_Table(): current_balance_sheet.year: { 'other_debt_service': current_balance_sheet.other_debt_service, - 'nest_income': + 'net_income': current_balance_sheet.net_income, 'cash': current_balance_sheet.cash diff --git a/bpfin/tests/test_financials/test_financial_lib.py b/bpfin/tests/test_financials/test_financial_lib.py index 4ce8a7a..977c3cc 100644 --- a/bpfin/tests/test_financials/test_financial_lib.py +++ b/bpfin/tests/test_financials/test_financial_lib.py @@ -36,7 +36,7 @@ def test_Income_Statement_Table(): def test_Balance_Sheet_Table(): - input_raw_balance_sheet = db.balance_sheet + input_raw_balance_sheet = db.raw_balance_sheet output_hist_balance_sheet_table = db.hist_balance_sheet output_single_year_bs_2018 = db.balance_sheet_2018 output_single_year_bs_2025 = db.balance_sheet_2025 diff --git a/bpfin/tests/testdata/sample_data.py b/bpfin/tests/testdata/sample_data.py index 30817d8..987f6f0 100644 --- a/bpfin/tests/testdata/sample_data.py +++ b/bpfin/tests/testdata/sample_data.py @@ -507,7 +507,7 @@ income_statement_projection_cagr = { 'water_opex': 0.0, 'year': 2036}} -noi_dictionary = {2014: None, 2015: None, 2016: None, 2017: 41278.43692755746, 2018 : 45214.28536645262, 2019 : 48842.631285961135, +noi_dictionary = {2014: 31500, 2015: 37000, 2016: 37000, 2017: 41278.43692755746, 2018 : 45214.28536645262, 2019 : 48842.631285961135, 2020: 52731.934093183474,2021: 56939.349890971425,2022:61487.1217724919, 2023 : 66332.18430708232, 2024: 71461.4261836982, 2025: 76882.87761572453, 2026: 82578.96693651963, 2027: 88565.60757013515, 2028: 94901.76519041706, 2029: 101627.80434590613, 2030: 108765.29589285178, 2031: 116334.19001298171, 2032: 124349.95052275498, @@ -532,12 +532,12 @@ cash_balance = { 2014: 5000.0, 2015: 6000, 2016: 4500.0 } -balance_sheet = {'cash':cash_balance, 'other_debt_service':liability_dictionary, +raw_balance_sheet = {'cash':cash_balance, 'other_debt_service':liability_dictionary, 'net_income':noi_dictionary} -hist_balance_sheet = {2014: {'cash': 5000, 'other_debt_service': 100, 'net_income': None}, - 2015: {'cash': 6000, 'other_debt_service': 6000, 'net_income': None}, - 2016: {'cash': 4500, 'other_debt_service': 15000, 'net_income': None}} +hist_balance_sheet = {2014: {'cash': 5000, 'other_debt_service': 100, 'net_income': 31500}, + 2015: {'cash': 6000, 'other_debt_service': 6000, 'net_income': 37000}, + 2016: {'cash': 4500, 'other_debt_service': 15000, 'net_income': 37000}} balance_sheet_2018 = {2018: {'cash': 75992.72229401008,'other_debt_service': 5000, 'net_income':45214.28536645262}} -- GitLab From 3729646831c4fb2342b52b9adac96a8e44532e4d Mon Sep 17 00:00:00 2001 From: Sarey Hamarneh Date: Wed, 3 May 2017 21:30:33 -0400 Subject: [PATCH 15/15] Get cash for first year after commission date --- bpfin/financials/financial_lib.py | 12 ++++++++++-- bpfin/tests/test_financials/test_financial_lib.py | 15 +++++++++++---- bpfin/tests/testdata/sample_data.py | 10 +++++----- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py index 260111e..1180799 100644 --- a/bpfin/financials/financial_lib.py +++ b/bpfin/financials/financial_lib.py @@ -1,5 +1,5 @@ -# import datetime -# import calendar +import datetime +import calendar import copy from bpfin.lib import other as lib from bpfin.utilbills.bill_lib import form_bill_year @@ -632,6 +632,14 @@ class Balance_Sheet_Table(): } return None + def get_first_year_cash(self, commission_date): + + first_year = commission_date.year+1 + for current_balance_sheet in self.bs_table: + if current_balance_sheet.year == first_year: + return current_balance_sheet.cash + + # # ************ guide for front end dev *********** # # First, fill in bill overview, save it. diff --git a/bpfin/tests/test_financials/test_financial_lib.py b/bpfin/tests/test_financials/test_financial_lib.py index 977c3cc..e5a1bcb 100644 --- a/bpfin/tests/test_financials/test_financial_lib.py +++ b/bpfin/tests/test_financials/test_financial_lib.py @@ -41,12 +41,19 @@ def test_Balance_Sheet_Table(): output_single_year_bs_2018 = db.balance_sheet_2018 output_single_year_bs_2025 = db.balance_sheet_2025 output_single_year_bs_2030 = db.balance_sheet_2030 + output_first_year_cash = db.hist_balance_sheet[2016]['cash'] BS_table = Balance_Sheet_Table(input_raw_balance_sheet) BS_table.project_balance_sheet(db.analysis_date, db.liability_dictionary, db.noi_dictionary) - assert BS_table.get_hist_balance_sheet_table() == output_hist_balance_sheet_table - assert BS_table.get_single_year_balance_sheet(2018) == output_single_year_bs_2018 - assert BS_table.get_single_year_balance_sheet(2025) == output_single_year_bs_2025 - assert BS_table.get_single_year_balance_sheet(2030) == output_single_year_bs_2030 + assert BS_table.get_hist_balance_sheet_table( + ) == output_hist_balance_sheet_table + assert BS_table.get_single_year_balance_sheet( + 2018) == output_single_year_bs_2018 + assert BS_table.get_single_year_balance_sheet( + 2025) == output_single_year_bs_2025 + assert BS_table.get_single_year_balance_sheet( + 2030) == output_single_year_bs_2030 + assert BS_table.get_first_year_cash( + datetime.date(2015, 10, 1)) == output_first_year_cash diff --git a/bpfin/tests/testdata/sample_data.py b/bpfin/tests/testdata/sample_data.py index 987f6f0..8d2ec02 100644 --- a/bpfin/tests/testdata/sample_data.py +++ b/bpfin/tests/testdata/sample_data.py @@ -532,21 +532,21 @@ cash_balance = { 2014: 5000.0, 2015: 6000, 2016: 4500.0 } -raw_balance_sheet = {'cash':cash_balance, 'other_debt_service':liability_dictionary, - 'net_income':noi_dictionary} +raw_balance_sheet = {'cash': cash_balance, 'other_debt_service': liability_dictionary, + 'net_income': noi_dictionary} hist_balance_sheet = {2014: {'cash': 5000, 'other_debt_service': 100, 'net_income': 31500}, 2015: {'cash': 6000, 'other_debt_service': 6000, 'net_income': 37000}, 2016: {'cash': 4500, 'other_debt_service': 15000, 'net_income': 37000}} balance_sheet_2018 = {2018: {'cash': 75992.72229401008,'other_debt_service': 5000, -'net_income':45214.28536645262}} +'net_income': 45214.28536645262}} balance_sheet_2025 = {2025: {'cash': 510670.2474431231,'other_debt_service': 0.00, -'net_income':76882.87761572453}} +'net_income': 76882.87761572453}} balance_sheet_2030 = {2030: {'cash': 987109.6873789529,'other_debt_service': 0.00, -'net_income':108765.29589285178}} +'net_income': 108765.29589285178}} # pro-forma date and bill projection - -- GitLab