From 0ef1e95855d15d7bb54212b2feaab6124ebdfaf1 Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Tue, 26 Sep 2017 17:08:29 -0400 Subject: [PATCH 01/10] Improve budget simulator calculation. Correct calculation to consider customer's payback expectation not related to required_saving, aka, no net saving is needed when think about payback on self-finance. --- .../financials/financial_budget_simulator.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/bpfin/financials/financial_budget_simulator.py b/bpfin/financials/financial_budget_simulator.py index 6fd3826..50d4b78 100644 --- a/bpfin/financials/financial_budget_simulator.py +++ b/bpfin/financials/financial_budget_simulator.py @@ -119,18 +119,23 @@ def cal_max_budget( a_1 = copy.deepcopy(a_0) a_2 = copy.deepcopy(a_0) a_3 = copy.deepcopy(a_0) - a_1.append(1 / expected_payback * 12 if expected_payback else 0) + a_4 = copy.deepcopy(a_0) + + a_1.append(0) a_2.append(0) a_3.append(0) + a_4.append(1 / expected_payback * 12 if expected_payback else 0) + + A_matrix.append(multiply_list(a_1, (req_dscr['req_saving_dscr'] if savings is not None else 0))) + A_matrix.append(multiply_list(a_2, (req_dscr['req_noi_dscr'] if first_year_noi is not None else 0))) + A_matrix.append(multiply_list(a_3, (req_dscr['req_cash_dscr'] if first_year_cash is not None else 0))) + A_matrix.append(multiply_list(a_4, (1 if savings is not None else 0))) b_list = [] b_list.append(savings if savings else 0) b_list.append(first_year_noi if first_year_noi else 0) b_list.append(first_year_cash if first_year_cash else 0) - - A_matrix.append(multiply_list(a_1, (req_dscr['req_saving_dscr'] if savings is not None else 0))) - A_matrix.append(multiply_list(a_2, (req_dscr['req_noi_dscr'] if first_year_noi is not None else 0))) - A_matrix.append(multiply_list(a_2, (req_dscr['req_cash_dscr'] if first_year_cash is not None else 0))) + b_list.append(savings if savings else 0) # print('\n A_matrix =', A_matrix) # print('\n b_list =', b_list) @@ -148,8 +153,8 @@ def cal_max_budget( # Calculate self-finance amount if loan_fist is True if is_loan_first: if savings is not None and req_dscr['req_saving_dscr'] and expected_payback is not None: - # self finance amount is capped by extra_saving, which is Savings/req_dscr - total loan burden - extra_saving = float("{0:.4f}".format((savings/req_dscr['req_saving_dscr'] - total_ds))) + # self finance amount is capped by extra_saving, which is (Savings - loan DS) + extra_saving = float("{0:.4f}".format((savings - total_ds))) downpayment = (min(max([0, extra_saving]) * expected_payback / 12, downpayment_max)) else: downpayment = downpayment_max -- GitLab From cab83ede46204b5adfad2c36b4167d89ed2246ff Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Tue, 26 Sep 2017 17:17:32 -0400 Subject: [PATCH 02/10] Update unit test data for budget_simulator --- bpfin/tests/testdata/feature_data.py | 61 +++++++++++++++++----------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/bpfin/tests/testdata/feature_data.py b/bpfin/tests/testdata/feature_data.py index a6080ef..bedc46d 100644 --- a/bpfin/tests/testdata/feature_data.py +++ b/bpfin/tests/testdata/feature_data.py @@ -711,30 +711,45 @@ historical_cagr = 0.01242283656582921 growth_rate_flag = -2.0 budget_simulation_result = [ - [['saving_percentage', 0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5], - ['Budget', 0.0, 37723.783022506694, 68031.962268808478, 68031.962268808478, 68031.962268808478, 68031.962268808478], - ['NYSERDA', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [['saving_percentage', 0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5], [ + 'Budget', 0.0, 37723.783022506694, 68031.962268808478, + 68031.962268808478, 68031.962268808478, 68031.962268808478 + ], ['NYSERDA', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + ['Joe Fund', 0.0, 37723.783022506694, 50000.0, 50000.0, 50000.0, + 50000.0], [ + 'Tooraj Capital', 0.0, 0.0, 18031.962268808486, 18031.962268808486, + 18031.962268808486, 18031.962268808486 + ], ['Self Finance', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]], + [['saving_percentage', 0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5], [ + 'Budget', 0.0, 43031.145022506695, 87828.359268808475, + 118031.96226880848, 118031.96226880848, 118031.96226880848 + ], ['NYSERDA', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + ['Joe Fund', 0.0, 37723.783022506694, 50000.0, 50000.0, 50000.0, + 50000.0], [ + 'Tooraj Capital', 0.0, 0.0, 18031.962268808486, 18031.962268808486, + 18031.962268808486, 18031.962268808486 + ], [ + 'Self Finance', 0.0, 5307.3620000000001, 19796.397000000001, 50000.0, + 50000.0, 50000.0 + ]], [['saving_percentage', 0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5], [ + 'Budget', 0.0, 55957.052946537078, 97453.214271294448, + 118031.96226880848, 118031.96226880848, 118031.96226880848 + ], ['NYSERDA', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [ + 'Joe Fund', 0.0, 5957.0529465370792, 47453.214271294455, 50000.0, + 50000.0, 50000.0 + ], [ + 'Tooraj Capital', 0.0, 0.0, 0.0, 18031.962268808486, + 18031.962268808486, 18031.962268808486 + ], ['Self Finance', 0.0, 50000.0, 50000.0, 50000.0, 50000.0, 50000.0]], + [['saving_percentage', 0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5], [ + 'Budget', 50000.0, 87723.783022506686, 118031.96226880848, + 118031.96226880848, 118031.96226880848, 118031.96226880848 + ], ['NYSERDA', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], ['Joe Fund', 0.0, 37723.783022506694, 50000.0, 50000.0, 50000.0, 50000.0], - ['Tooraj Capital', 0.0, 0.0, 18031.962268808486, 18031.962268808486, 18031.962268808486, 18031.962268808486], - ['Self Finance', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]], - [['saving_percentage', 0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5], - ['Budget', 0.0, 37723.783022506694, 77213.635268808473, 118031.96226880848, 118031.96226880848, 118031.96226880848], - ['NYSERDA', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - ['Joe Fund', 0.0, 37723.783022506694, 50000.0, 50000.0, 50000.0, 50000.0], - ['Tooraj Capital', 0.0, 0.0, 18031.962268808486, 18031.962268808486, 18031.962268808486, 18031.962268808486], - ['Self Finance', 0.0, 0.0, 9181.6730000000007, 50000.0, 50000.0, 50000.0]], - [['saving_percentage', 0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5], - ['Budget', 0.0, 52184.67464428641, 89908.457666793111, 118031.96226880848, 118031.96226880848, 118031.96226880848], - ['NYSERDA', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - ['Joe Fund', 0.0, 2184.6746442864069, 39908.457666793111, 50000.0, 50000.0, 50000.0], - ['Tooraj Capital', 0.0, 0.0, 0.0, 18031.962268808486, 18031.962268808486, 18031.962268808486], - ['Self Finance', 0.0, 50000.0, 50000.0, 50000.0, 50000.0, 50000.0]], - [['saving_percentage', 0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5], - ['Budget', 50000.0, 87723.783022506686, 118031.96226880848, 118031.96226880848, 118031.96226880848, 118031.96226880848], - ['NYSERDA', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - ['Joe Fund', 0.0, 37723.783022506694, 50000.0, 50000.0, 50000.0, 50000.0], - ['Tooraj Capital', 0.0, 0.0, 18031.962268808486, 18031.962268808486, 18031.962268808486, 18031.962268808486], - ['Self Finance', 50000.0, 50000.0, 50000.0, 50000.0, 50000.0, 50000.0]] + [ + 'Tooraj Capital', 0.0, 0.0, 18031.962268808486, 18031.962268808486, + 18031.962268808486, 18031.962268808486 + ], ['Self Finance', 50000.0, 50000.0, 50000.0, 50000.0, 50000.0, 50000.0]] ] post_annual_bill = { -- GitLab From fc563d03fc5e477af63177e0d7a3f0f6106b24f9 Mon Sep 17 00:00:00 2001 From: chen Date: Mon, 12 Mar 2018 12:25:31 -0400 Subject: [PATCH 03/10] add comment for a description of expected_payback --- bpfin/financials/financial_budget_simulator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bpfin/financials/financial_budget_simulator.py b/bpfin/financials/financial_budget_simulator.py index 50d4b78..870cfc6 100644 --- a/bpfin/financials/financial_budget_simulator.py +++ b/bpfin/financials/financial_budget_simulator.py @@ -124,7 +124,7 @@ def cal_max_budget( a_1.append(0) a_2.append(0) a_3.append(0) - a_4.append(1 / expected_payback * 12 if expected_payback else 0) + a_4.append(1 / expected_payback * 12 if expected_payback else 0) #expected_payback is in month A_matrix.append(multiply_list(a_1, (req_dscr['req_saving_dscr'] if savings is not None else 0))) A_matrix.append(multiply_list(a_2, (req_dscr['req_noi_dscr'] if first_year_noi is not None else 0))) -- GitLab From f7046b8ec562fa51fba436ef4965a2d2a2aae190 Mon Sep 17 00:00:00 2001 From: chen Date: Wed, 20 Feb 2019 17:47:22 -0500 Subject: [PATCH 04/10] update description of math method for budget simulator --- bpfin/financials/financial_budget_simulator.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/bpfin/financials/financial_budget_simulator.py b/bpfin/financials/financial_budget_simulator.py index 870cfc6..a1e664c 100644 --- a/bpfin/financials/financial_budget_simulator.py +++ b/bpfin/financials/financial_budget_simulator.py @@ -26,8 +26,10 @@ def cal_max_budget( x_1 + x_2 + x_3 + ... + x_n = max * x_i is loan amount, x_n is self-finance amount 2. x variables constraints - sum(x_i / payback_i) <= saving/dscr - * sum of annual debt service and self-finance payback <= saving/dscr + sum(x_i / payback_i) - (x_n / payback_n) <= saving/dscr + * sum of annual debt service <= saving/dscr + sum(x_i / payback_i) + x_n <= saving + * sum of annual debt service and self-finance payback <= saving sum(x_i / payback_i) - (x_n / payback_n) <= noi/dscr * sum of loan debt service <= noi constraint, making project financially feasibile sum(x_i / payback_i) - (x_n / payback_n) <= cash/dscr @@ -40,10 +42,10 @@ def cal_max_budget( downpayment_max = 0 4.2 use loan first, leftover saving can support some self-finance amount downpayment_max = 0 - when x_i are determined: - x_n = min(saving/dscr - sum(x_i), downpayment_max) - 4.3 use self-finance first, leftover saving can support some loan amount - no additional constrain applied + after x_i are determined: + x_n = min( (saving-sum(DS_i))*payback_n, downpayment_max) + 4.3 use self-finance first as max as possible, leftover saving can support some loan amount + x_n = min (saving * payback_n, downpayment_max) 4.4 use all available financing, self-finance's expected payback is infinite expected_payback = None -- GitLab From bddb35d5e60cece03df4a2f5f799a84010e2bbb4 Mon Sep 17 00:00:00 2001 From: chen Date: Thu, 21 Feb 2019 17:51:40 -0500 Subject: [PATCH 05/10] Changed algo for SF_first. Update ugly test and feature data --- .../financials/financial_budget_simulator.py | 24 +++++++++++++++---- bpfin/tests/testdata/feature_data.py | 1 - 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/bpfin/financials/financial_budget_simulator.py b/bpfin/financials/financial_budget_simulator.py index a1e664c..7e2f542 100644 --- a/bpfin/financials/financial_budget_simulator.py +++ b/bpfin/financials/financial_budget_simulator.py @@ -155,7 +155,7 @@ def cal_max_budget( # Calculate self-finance amount if loan_fist is True if is_loan_first: if savings is not None and req_dscr['req_saving_dscr'] and expected_payback is not None: - # self finance amount is capped by extra_saving, which is (Savings - loan DS) + # self finance amount is capped by extra_saving = (Savings - loan DS) extra_saving = float("{0:.4f}".format((savings - total_ds))) downpayment = (min(max([0, extra_saving]) * expected_payback / 12, downpayment_max)) else: @@ -216,7 +216,8 @@ def form_max_financing( result = cal_max_budget( loan_list=loan_list, - downpayment_max=downpayment_max, + # downpayment_max=downpayment_max, + downpayment_max=(min(savings*expected_payback/12, downpayment_max) if expected_payback else downpayment_max), expected_payback=expected_payback, req_dscr=req_dscr, first_year_noi=first_year_noi, @@ -298,14 +299,29 @@ def validate_list_one_true(param_list): # **** ugly test **** -# from bpfin.tests.testdata import sample_data as db +# from bpfin.tests.testdata import feature_data as db # from bpfin.financials.loan import Loan_List + +# import pprint +# pp = pprint.PrettyPrinter(width=120, indent=4, compact=True) + +# print('\n Feature data cases:') +# pp.pprint(form_max_financing( +# loan_list=Loan_List(db.raw_loan_input_list).loan_list, +# downpayment_max = db.customer_preference['downpayment_max'], # 60006 is a number to show effect +# expected_payback= db.customer_preference['expected_payback'], +# req_dscr = db.req_dscr, +# first_year_noi = db.next_year_income['noi'], +# first_year_cash = 50000, +# savings = 15000, +# )) + +# from bpfin.tests.testdata import sample_data as db # req_dscr = { # 'req_noi_dscr': 1.15, # 'req_cash_dscr': 1.05, # 'req_saving_dscr': 1.10 # } - # test cases # print('\n Base Case:') # print(cal_max_budget( diff --git a/bpfin/tests/testdata/feature_data.py b/bpfin/tests/testdata/feature_data.py index bedc46d..4d48647 100644 --- a/bpfin/tests/testdata/feature_data.py +++ b/bpfin/tests/testdata/feature_data.py @@ -41,7 +41,6 @@ req_dscr = { customer_preference = { 'downpayment_max': 50000.00, 'expected_payback': 120, # in months, default 120, extreme case 24 - 'cust_saving_dscr': 1.15 } -- GitLab From f6f675ff2b95cf9ebb6ff0e2af3b9e2dde5a5f5e Mon Sep 17 00:00:00 2001 From: chen Date: Thu, 21 Feb 2019 18:40:37 -0500 Subject: [PATCH 06/10] Refactor loan's payback algo in Loan. Add unit test for cal_max_budget and cal_max_budget --- bpfin/financials/loan.py | 6 ++- .../test_financials/test_financial_budget.py | 37 +++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 bpfin/tests/test_financials/test_financial_budget.py diff --git a/bpfin/financials/loan.py b/bpfin/financials/loan.py index 3273712..6b893d1 100644 --- a/bpfin/financials/loan.py +++ b/bpfin/financials/loan.py @@ -36,8 +36,10 @@ class Loan(): self.max_amount = loan_term['max_amount'] self.interest = loan_term['interest'] self.duration = loan_term['duration'] # in month - self.payback = ((1 + self.interest) ** (self.duration / 12) - 1) / (self.interest * ( - 1 + self.interest) ** (self.duration / 12)) + # self.payback = ((1 + self.interest) ** (self.duration / 12) - 1) / (self.interest * ( + # 1 + self.interest) ** (self.duration / 12)) + self.payback = (((1 + self.interest/12) ** (self.duration) - 1) / (self.interest/12 * ( + 1 + self.interest/12) ** (self.duration)))/12 # optionally, we can use monthly payback calculation. self.amount = 0 self.debt_service = 0 self.terms = [] diff --git a/bpfin/tests/test_financials/test_financial_budget.py b/bpfin/tests/test_financials/test_financial_budget.py new file mode 100644 index 0000000..449c8b7 --- /dev/null +++ b/bpfin/tests/test_financials/test_financial_budget.py @@ -0,0 +1,37 @@ +from bpfin.tests.testdata import feature_data as db +from bpfin.financials.loan import Loan_List +from bpfin.financials.financial_budget_simulator import cal_max_budget,form_max_financing, form_budget_simulation_result + + +def test_cal_max_budget(): + result = cal_max_budget( + loan_list=Loan_List(db.raw_loan_input_list).loan_list, + downpayment_max=90000, + expected_payback=120, + req_dscr=db.req_dscr, + first_year_noi=10000, + first_year_cash=10000, + savings=15000, + is_loan_first=1) + + expected_outcome = ([0.0, 50000.0, 12362.659604722925, 63043.477999999996]) + assert result == expected_outcome + +def test_cal_max_budget(): + loan_input_list = [ + {'institute': 'OneCapital', 'max_amount': 80000, 'interest': 0.12, 'duration': 120} + ] + result = cal_max_budget( + loan_list=Loan_List(loan_input_list).loan_list, + downpayment_max = 20000, + expected_payback = 7*12, + req_dscr = { + 'req_saving_dscr': 1.10, + 'req_cash_dscr': None, + 'req_noi_dscr': None}, + first_year_noi = 63452, + first_year_cash = 999999, + savings = 13452, + is_loan_first=1) + expected_outcome = ([71031.16836108758, 8560.3637]) + assert result == expected_outcome -- GitLab From 17464f4ea8e0bd1e994d9e8ccf541552fbf83cf7 Mon Sep 17 00:00:00 2001 From: chen Date: Fri, 22 Feb 2019 15:35:15 -0500 Subject: [PATCH 07/10] Create full case test for financial_budget --- .../test_financials/test_financial_budget.py | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/bpfin/tests/test_financials/test_financial_budget.py b/bpfin/tests/test_financials/test_financial_budget.py index 449c8b7..b34b38e 100644 --- a/bpfin/tests/test_financials/test_financial_budget.py +++ b/bpfin/tests/test_financials/test_financial_budget.py @@ -1,9 +1,9 @@ from bpfin.tests.testdata import feature_data as db from bpfin.financials.loan import Loan_List -from bpfin.financials.financial_budget_simulator import cal_max_budget,form_max_financing, form_budget_simulation_result +from bpfin.financials.financial_budget_simulator import cal_max_budget, form_max_financing -def test_cal_max_budget(): +def test_cal_max_budget_1(): result = cal_max_budget( loan_list=Loan_List(db.raw_loan_input_list).loan_list, downpayment_max=90000, @@ -17,7 +17,7 @@ def test_cal_max_budget(): expected_outcome = ([0.0, 50000.0, 12362.659604722925, 63043.477999999996]) assert result == expected_outcome -def test_cal_max_budget(): +def test_cal_max_budget_2(): loan_input_list = [ {'institute': 'OneCapital', 'max_amount': 80000, 'interest': 0.12, 'duration': 120} ] @@ -35,3 +35,38 @@ def test_cal_max_budget(): is_loan_first=1) expected_outcome = ([71031.16836108758, 8560.3637]) assert result == expected_outcome + +def test_form_max_financing_1(): + loan_term_1 = {'institute': 'NYSERDA', 'max_amount': 500000, 'interest': 0.08, 'duration': 120} + loan_term_2 = {'institute': 'Joe Fund', 'max_amount': 50000, 'interest': 0.05, 'duration': 108} + loan_term_3 = {'institute': 'Tooraj Capital', 'max_amount': 75000, 'interest': 0.07, 'duration': 114} + raw_loan_input_list = [loan_term_1, loan_term_2, loan_term_3] + + req_dscr = { + 'req_saving_dscr': 1.10 + 'req_noi_dscr': 1.15, + 'req_cash_dscr': 1.15, + } + + customer_preference = { + 'downpayment_max': 50000.00, + 'expected_payback': 120, # in months, default 120, extreme case 24 + } + + result = form_max_financing( + loan_list = Loan_List(raw_loan_input_list).loan_list, + downpayment_max = customer_preference['downpayment_max'], + expected_payback = customer_preference['expected_payback'], + req_dscr = req_dscr, + first_year_noi = 12000, + first_year_cash = 50000, + savings = 15000, + ) + print(result) + expected_outcome = { + 'loan_only': [74405.68811718613, 0.0, 50000.0, 24405.68811718613, 0.0], + 'loan_first': [120057.86211718613, 0.0, 50000.0, 24405.68811718613, 45652.174000000006], + 'sf_first': [121394.93098907033, 0.0, 50000.0, 21394.930989070326, 50000.0], + 'sf_max': [124405.68811718613, 0.0, 50000.0, 24405.68811718613, 50000.0] + } + assert result == expected_outcome -- GitLab From b0b336a85cf7c224732bac1d14149dbc2b0e34de Mon Sep 17 00:00:00 2001 From: chen Date: Fri, 22 Feb 2019 15:38:34 -0500 Subject: [PATCH 08/10] Update bpfin v0.2.4 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index ac4123d..135817d 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ reqs = [str(req.req) for req in install_reqs] setup( name='bpfin', - version='0.2.3', + version='0.2.4', description='Finance models and utilites', author='BlocPower', author_email='admin@blocpower.org', -- GitLab From 9fbdefcc3f9422b4347d4d353d9cd9a21d8ff4dc Mon Sep 17 00:00:00 2001 From: chen Date: Thu, 28 Feb 2019 15:58:15 -0500 Subject: [PATCH 09/10] In loan.py, add if interest == 0. modify test and test_data files --- bpfin/financials/loan.py | 14 +++-- bpfin/tests/test_financials/test_loan.py | 79 +++++++++++++++++++++++- bpfin/tests/testdata/feature_data.py | 44 ++++++++++++- bpfin/tests/testdata/sample_data.py | 1 - 4 files changed, 127 insertions(+), 11 deletions(-) diff --git a/bpfin/financials/loan.py b/bpfin/financials/loan.py index 6b893d1..d18e18b 100644 --- a/bpfin/financials/loan.py +++ b/bpfin/financials/loan.py @@ -37,9 +37,12 @@ class Loan(): self.interest = loan_term['interest'] self.duration = loan_term['duration'] # in month # self.payback = ((1 + self.interest) ** (self.duration / 12) - 1) / (self.interest * ( - # 1 + self.interest) ** (self.duration / 12)) - self.payback = (((1 + self.interest/12) ** (self.duration) - 1) / (self.interest/12 * ( - 1 + self.interest/12) ** (self.duration)))/12 # optionally, we can use monthly payback calculation. + # 1 + self.interest) ** (self.duration / 12)) # optionally, we can use monthly payback calculation. + if self.interest == 0: + self.payback = self.duration/12 + else: + self.payback = (((1 + self.interest/12) ** (self.duration) - 1) / (self.interest/12 * ( + 1 + self.interest/12) ** (self.duration)))/12 self.amount = 0 self.debt_service = 0 self.terms = [] @@ -72,8 +75,9 @@ class Loan(): amount (float): loan amount that calculated or suggested to borrow """ self.amount = amount - self.debt_service = self.amount * ((self.interest / 12) * (1 + self.interest / 12) ** (self.duration)) / ( - (1 + self.interest / 12) ** (self.duration) - 1) + # self.debt_service = self.amount * ((self.interest / 12) * (1 + self.interest / 12) ** (self.duration)) / ( + # (1 + self.interest / 12) ** (self.duration) - 1) + self.debt_service = self.amount/self.payback/12 def put_terms(self, loan_start_date): """ diff --git a/bpfin/tests/test_financials/test_loan.py b/bpfin/tests/test_financials/test_loan.py index cbfa0a0..a3ef64f 100644 --- a/bpfin/tests/test_financials/test_loan.py +++ b/bpfin/tests/test_financials/test_loan.py @@ -1,14 +1,87 @@ import datetime -from bpfin.tests.testdata import sample_data as db +from bpfin.tests.testdata import feature_data as db from bpfin.financials.loan import Loan_List +# import pprint +# pp = pprint.PrettyPrinter(width=120, indent=4, compact=True) -def test_Loan_List(): +def test_Loan_List_1(): + """ + test Loan and Loan_List classes. + by calling Loan_List.get_schedule(), all calculation functions are called and tested + including allocation and loan origination + """ + loan_term_1 = {'institute': 'NYSERDA', 'max_amount': 100000, 'interest': 0.00, 'duration': 120} + loan_term_2 = {'institute': 'Joe Fund', 'max_amount': 50000, 'interest': 0.05, 'duration': 108} + loan_term_3 = {'institute': 'Tooraj Capital', 'max_amount': 75000, 'interest': 0.07, 'duration': 114} + loan_input_list = [loan_term_1, loan_term_2, loan_term_3] + + customer_preference = { + 'downpayment_max': 5000.00, + 'expected_payback': 120, # in months + 'cust_saving_dscr': 1.15 + } + + cost_estimation = 150000.00 + commission_date = datetime.date(2017, 3, 14) + + req_dscr = { + 'req_noi_dscr': 1.15, + 'req_cash_dscr': 1.15, + 'req_saving_dscr': 1.10 + } + + output_loan1_end_balance = [ + 99166.66666666667, 98333.33333333334, 97500.00000000001, 96666.66666666669, 95833.33333333336, 95000.00000000003, + 94166.6666666667, 93333.33333333337, 92500.00000000004, 91666.66666666672, 90833.33333333339, 90000.00000000006, + 89166.66666666673, 88333.3333333334, 87500.00000000007, 86666.66666666674, 85833.33333333342, 85000.00000000009, + 84166.66666666676, 83333.33333333343, 82500.0000000001, 81666.66666666677, 80833.33333333344, 80000.00000000012, + 79166.66666666679, 78333.33333333346, 77500.00000000013, 76666.6666666668, 75833.33333333347, 75000.00000000015, + 74166.66666666682, 73333.33333333349, 72500.00000000016, 71666.66666666683, 70833.3333333335, 70000.00000000017, + 69166.66666666685, 68333.33333333352, 67500.00000000019, 66666.66666666686, 65833.33333333353, 65000.0000000002, + 64166.66666666686, 63333.333333333525, 62500.00000000019, 61666.66666666685, 60833.33333333352, 60000.00000000018, + 59166.666666666846, 58333.33333333351, 57500.000000000175, 56666.66666666684, 55833.3333333335, 55000.00000000017, + 54166.66666666683, 53333.333333333496, 52500.00000000016, 51666.666666666824, 50833.33333333349, 50000.00000000015, + 49166.66666666682, 48333.33333333348, 47500.000000000146, 46666.66666666681, 45833.333333333474, 45000.00000000014, + 44166.6666666668, 43333.33333333347, 42500.00000000013, 41666.666666666795, 40833.33333333346, 40000.000000000124, + 39166.66666666679, 38333.33333333345, 37500.00000000012, 36666.66666666678, 35833.333333333445, 35000.00000000011, + 34166.66666666677, 33333.33333333344, 32500.000000000106, 31666.666666666773, 30833.33333333344, 30000.00000000011, + 29166.666666666777, 28333.333333333445, 27500.000000000113, 26666.66666666678, 25833.33333333345, + 25000.000000000116, 24166.666666666784, 23333.333333333452, 22500.00000000012, 21666.666666666788, + 20833.333333333456, 20000.000000000124, 19166.66666666679, 18333.33333333346, 17500.000000000127, + 16666.666666666795, 15833.333333333461, 15000.000000000127, 14166.666666666793, 13333.33333333346, + 12500.000000000126, 11666.666666666792, 10833.333333333458, 10000.000000000124, 9166.66666666679, 8333.333333333456, + 7500.000000000123, 6666.66666666679, 5833.333333333457, 5000.000000000124, 4166.666666666791, 3333.333333333457, + 2500.0000000001237, 1666.6666666667902, 833.3333333334568, 0] + output_loan2_debt_service = 575.8636584182361 + output_loan3_amount = 0.0 + + input_loan_input_list = loan_input_list + input_customer_preference = customer_preference + input_cost = cost_estimation + input_req_dscr = req_dscr + input_loan_start_date = commission_date + sample_loan_list = Loan_List(input_loan_input_list) + result_loan_list = sample_loan_list.get_schedule( + customer_preference = input_customer_preference, + cost = input_cost, + req_dscr = input_req_dscr, + loan_start_date = input_loan_start_date, + first_year_saving = 28000.0, + first_year_noi = 28000.0, + first_year_cash = 100000.0) + + assert output_loan1_end_balance == result_loan_list[0].principal_end_balance + assert output_loan2_debt_service == result_loan_list[1].debt_service_due[0] + assert output_loan3_amount == result_loan_list[2].amount + + +def test_Loan_List_2(): """ 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_loan_input_list = db.raw_loan_input_list input_customer_preference = db.customer_preference input_cost = db.cost_estimation input_req_dscr = db.req_dscr diff --git a/bpfin/tests/testdata/feature_data.py b/bpfin/tests/testdata/feature_data.py index 4d48647..e10a745 100644 --- a/bpfin/tests/testdata/feature_data.py +++ b/bpfin/tests/testdata/feature_data.py @@ -283,10 +283,50 @@ raw_cash_balance = { loan_term_1 = {'institute': 'NYSERDA', 'max_amount': 500000, 'interest': 0.08, 'duration': 120} loan_term_2 = {'institute': 'Joe Fund', 'max_amount': 50000, 'interest': 0.05, 'duration': 108} loan_term_3 = {'institute': 'Tooraj Capital', 'max_amount': 75000, 'interest': 0.07, 'duration': 114} -loan_term_dict = {1: loan_term_1, 2: loan_term_2, 3: loan_term_3} +# loan_term_dict = {1: loan_term_1, 2: loan_term_2, 3: loan_term_3} #should be deleted if whole tests runs good raw_loan_input_list = [loan_term_1, loan_term_2, loan_term_3] # raw_loan_input_list = None - +loan1_end_balance = [ + 24863.347680778272, 24725.784346095064, 24587.303922513969, + 24447.900296109001, 24307.567312194667, 24166.298775054238, + 24024.088447666207, 23880.930051428921, 23736.817265883386, + 23591.743728434216, 23445.703034068716, 23298.688735074113, + 23150.694340752878, 23001.713317136171, 22851.73908669535, + 22700.765028051592, 22548.78447568354, 22395.790719633034, + 22241.77700520886, 22086.736532688523, 21930.66245701805, + 21773.547887509776, 21615.385887538112, 21456.169474233306, + 21295.891618173133, 21134.54524307256, 20972.123225471318, + 20808.618394419398, 20644.023531160467, 20478.331368813142, + 20311.534592050168, 20143.625836775442, 19974.597689798884, + 19804.442688509149, 19633.153320544148, 19460.722023459381, + 19287.141184394048, 19112.403139734946, 18936.500174778117, + 18759.424523388243, 18581.16836765577, 18401.723837551748, + 18221.083010580365, 18039.237911429173, 17856.180511616974, + 17671.902729139361, 17486.396428111897, 17299.653418410915, + 17111.665455311926, 16922.424239125612, 16731.921414831388, + 16540.148571708534, 16347.097242964863, 16152.758905362902, + 15957.124978843593, 15760.186826147488, 15561.93575243341, + 15362.363004894572, 15161.459772372142, 14959.217184966228, + 14755.626313644276, 14550.678169846844, 14344.363705090762, + 14136.673810569639, 13927.599316751708, 13717.130992974991, + 13505.259547039763, 13291.9756247983, 13077.269809741894, + 12861.132622585112, 12643.554520847285, 12424.525898431206, + 12204.037085199019, 11982.078346545284, 11758.639882967193, + 11533.711829631913, 11307.284255941066, 11079.347165092278, + 10849.890493637833, 10618.904111040358, 10386.377819225565, + 10152.301352132008, 9916.6643752578275, 9679.4564852044859, + 9440.667209217454, 9200.2860047238428, 8958.302258866941, + 8714.7052880376596, 8469.4843374028496, 8222.6285804304734, + 7974.1271184116158, 7723.9689799792986, 7472.1431206240995, + 7218.6384222065326, 6963.4436924661813, 6706.5476645275612, + 6447.9389964026841, 6187.6062704903079, 5925.5379930718491, + 5661.7225938039337, 5396.1484252075652, 5128.8037621538879, + 4859.6768013465198, 4588.7556608004352, 4316.0283793173767, + 4041.4829159577648, 3765.1071495090891, 3486.8888779507552, + 3206.8158179153656, 2924.8756041464071, 2641.055788952322, + 2355.3438416569434, 2067.7271480462618, 1778.1930098115092, + 1486.7286439885249, 1193.3211823933875, 897.9576710542824, + 600.62506963958322, 301.31025088211942, 0] # ****** result ***** prior_annual_bill = { diff --git a/bpfin/tests/testdata/sample_data.py b/bpfin/tests/testdata/sample_data.py index 434f969..3af64d1 100644 --- a/bpfin/tests/testdata/sample_data.py +++ b/bpfin/tests/testdata/sample_data.py @@ -669,7 +669,6 @@ req_dscr = { customer_preference = { 'downpayment_max': 5000.00, 'expected_payback': 120, # in months - 'cust_saving_dscr': 1.15 } # loan_requirement = { -- GitLab From 182a3a04c3e4d4d7ba1abf37928749f740990184 Mon Sep 17 00:00:00 2001 From: chen Date: Fri, 1 Mar 2019 11:58:35 -0500 Subject: [PATCH 10/10] move budget simulator ugly test to test_financial_budget --- .../financials/financial_budget_simulator.py | 203 ----------------- .../test_financials/test_financial_budget.py | 208 +++++++++++++++++- 2 files changed, 206 insertions(+), 205 deletions(-) diff --git a/bpfin/financials/financial_budget_simulator.py b/bpfin/financials/financial_budget_simulator.py index 7e2f542..eda9c5c 100644 --- a/bpfin/financials/financial_budget_simulator.py +++ b/bpfin/financials/financial_budget_simulator.py @@ -297,207 +297,4 @@ def validate_list_one_true(param_list): return True return False - -# **** ugly test **** -# from bpfin.tests.testdata import feature_data as db -# from bpfin.financials.loan import Loan_List - -# import pprint -# pp = pprint.PrettyPrinter(width=120, indent=4, compact=True) - -# print('\n Feature data cases:') -# pp.pprint(form_max_financing( -# loan_list=Loan_List(db.raw_loan_input_list).loan_list, -# downpayment_max = db.customer_preference['downpayment_max'], # 60006 is a number to show effect -# expected_payback= db.customer_preference['expected_payback'], -# req_dscr = db.req_dscr, -# first_year_noi = db.next_year_income['noi'], -# first_year_cash = 50000, -# savings = 15000, -# )) - -# from bpfin.tests.testdata import sample_data as db -# req_dscr = { -# 'req_noi_dscr': 1.15, -# 'req_cash_dscr': 1.05, -# 'req_saving_dscr': 1.10 -# } -# test cases -# print('\n Base Case:') -# print(cal_max_budget( -# loan_list=Loan_List(db.loan_input_list).loan_list, -# downpayment_max=90000, -# expected_payback=120, -# req_dscr=req_dscr, -# first_year_noi=10000, -# first_year_cash=10000, -# savings=15000, -# is_loan_first=1)) - -# print('\n loan_list=None') -# print(cal_max_budget( -# loan_list=None, -# downpayment_max=90000, -# expected_payback=120, -# req_dscr=req_dscr, -# first_year_noi=10000, -# first_year_cash=10000, -# savings=15000, -# is_loan_first=1)) - -# print('\n loan_list = downpayment_max = None,') -# print(cal_max_budget( -# loan_list=None, -# downpayment_max=None, -# expected_payback=120, -# req_dscr=req_dscr, -# first_year_noi=10000, -# first_year_cash=10000, -# savings=15000, -# is_loan_first=1)) - -# print('\n expected_payback = None') -# print(cal_max_budget( -# loan_list=Loan_List(db.loan_input_list).loan_list, -# downpayment_max=90000, -# expected_payback=None, -# req_dscr=req_dscr, -# first_year_noi=10000, -# first_year_cash=10000, -# savings=15000, -# is_loan_first=1)) - -# print('\n expected_payback = None, is_loan_first=0') -# print(cal_max_budget( -# loan_list=Loan_List(db.loan_input_list).loan_list, -# downpayment_max=90000, -# expected_payback=None, -# req_dscr=req_dscr, -# first_year_noi=10000, -# first_year_cash=10000, -# savings=15000, -# is_loan_first=0)) - -# print('\n expected_payback = 0') -# print(cal_max_budget( -# loan_list=Loan_List(db.loan_input_list).loan_list, -# downpayment_max=90000, -# expected_payback=0, -# req_dscr=req_dscr, -# first_year_noi=10000, -# first_year_cash=10000, -# savings=15000, -# is_loan_first=1)) - -# print('\n req_noi_dscr = None, req_cash_dscr = None') -# print(cal_max_budget( -# loan_list=Loan_List(db.loan_input_list).loan_list, -# downpayment_max=90000, -# expected_payback=120, -# req_dscr={'req_noi_dscr': None, 'req_cash_dscr': None, 'req_saving_dscr': 1.10}, -# first_year_noi=10000, -# first_year_cash=10000, -# savings=15000, -# is_loan_first=1)) - -# print('\n req_saving_dscr = None') -# print(cal_max_budget( -# loan_list=Loan_List(db.loan_input_list).loan_list, -# downpayment_max=90000, -# expected_payback=120, -# req_dscr={'req_noi_dscr': 1.15, 'req_cash_dscr': 1.05, 'req_saving_dscr': None}, -# first_year_noi=10000, -# first_year_cash=10000, -# savings=15000, -# is_loan_first=1)) - -# print('\n req_noi_dscr = None, req_cash_dscr=0, req_saving_dscr = None') -# print(cal_max_budget( -# loan_list=Loan_List(db.loan_input_list).loan_list, -# downpayment_max=90000, -# expected_payback=120, -# req_dscr={'req_noi_dscr': None, 'req_cash_dscr': 0, 'req_saving_dscr': None}, -# first_year_noi=10000, -# first_year_cash=10000, -# savings=15000, -# is_loan_first=1)) - -# print('\n first_year_noi=None') -# print(cal_max_budget( -# loan_list=Loan_List(db.loan_input_list).loan_list, -# downpayment_max=90000, -# expected_payback=120, -# req_dscr={'req_noi_dscr': 1.15, 'req_cash_dscr': 1.05, 'req_saving_dscr': 1.10}, -# first_year_noi=None, -# first_year_cash=10000, -# savings=15000, -# is_loan_first=1)) - -# print('\n first_year_noi=0') -# print(cal_max_budget( -# loan_list=Loan_List(db.loan_input_list).loan_list, -# downpayment_max=90000, -# expected_payback=120, -# req_dscr={'req_noi_dscr': 1.15, 'req_cash_dscr': 1.05, 'req_saving_dscr': 1.10}, -# first_year_noi=0, -# first_year_cash=10000, -# savings=15000, -# is_loan_first=1)) - -# print('\n first_year_noi=0, req_noi_dscr: 0') -# print(cal_max_budget( -# loan_list=Loan_List(db.loan_input_list).loan_list, -# downpayment_max=90000, -# expected_payback=120, -# req_dscr={'req_noi_dscr': 0, 'req_cash_dscr': 1.05, 'req_saving_dscr': 1.10}, -# first_year_noi=0, -# first_year_cash=10000, -# savings=15000, -# is_loan_first=1)) - -# print('\n savings=None') -# print(cal_max_budget( -# loan_list=Loan_List(db.loan_input_list).loan_list, -# downpayment_max=90000, -# expected_payback=120, -# req_dscr={'req_noi_dscr': 1.15, 'req_cash_dscr': 1.05, 'req_saving_dscr': 1.10}, -# first_year_noi=10000, -# first_year_cash=10000, -# savings=None, -# is_loan_first=1)) - -# print('\n savings=0') -# print(cal_max_budget( -# loan_list=Loan_List(db.loan_input_list).loan_list, -# downpayment_max=90000, -# expected_payback=120, -# req_dscr={'req_noi_dscr': 1.15, 'req_cash_dscr': 1.05, 'req_saving_dscr': 1.10}, -# first_year_noi=10000, -# first_year_cash=10000, -# savings=0, -# is_loan_first=1)) - -# print('\n savings=0 , req_saving_dscr =0' ) -# print(cal_max_budget( -# loan_list=Loan_List(db.loan_input_list).loan_list, -# downpayment_max=90000, -# expected_payback=120, -# req_dscr={'req_noi_dscr': 1.15, 'req_cash_dscr': 1.05, 'req_saving_dscr': 0}, -# first_year_noi=10000, -# first_year_cash=10000, -# savings=0, -# is_loan_first=1)) - -# print('\n first_year_noi=None, first_year_cash=None, savings=None,' ) -# print(cal_max_budget( -# loan_list=Loan_List(db.loan_input_list).loan_list, -# downpayment_max=90000, -# expected_payback=120, -# req_dscr=req_dscr, -# first_year_noi=None, -# first_year_cash=None, -# savings=None, -# is_loan_first=1)) - - # !!!! next step: write some warning message. Learn to run warning message diff --git a/bpfin/tests/test_financials/test_financial_budget.py b/bpfin/tests/test_financials/test_financial_budget.py index b34b38e..0cc339f 100644 --- a/bpfin/tests/test_financials/test_financial_budget.py +++ b/bpfin/tests/test_financials/test_financial_budget.py @@ -43,7 +43,7 @@ def test_form_max_financing_1(): raw_loan_input_list = [loan_term_1, loan_term_2, loan_term_3] req_dscr = { - 'req_saving_dscr': 1.10 + 'req_saving_dscr': 1.10, 'req_noi_dscr': 1.15, 'req_cash_dscr': 1.15, } @@ -62,7 +62,7 @@ def test_form_max_financing_1(): first_year_cash = 50000, savings = 15000, ) - print(result) + # print(result) expected_outcome = { 'loan_only': [74405.68811718613, 0.0, 50000.0, 24405.68811718613, 0.0], 'loan_first': [120057.86211718613, 0.0, 50000.0, 24405.68811718613, 45652.174000000006], @@ -70,3 +70,207 @@ def test_form_max_financing_1(): 'sf_max': [124405.68811718613, 0.0, 50000.0, 24405.68811718613, 50000.0] } assert result == expected_outcome + + + +# **** ugly test **** +# from bpfin.tests.testdata import feature_data as db +# from bpfin.financials.loan import Loan_List + +# import pprint +# pp = pprint.PrettyPrinter(width=120, indent=4, compact=True) + +# print('\n Feature data cases:') +# pp.pprint(form_max_financing( +# loan_list=Loan_List(db.raw_loan_input_list).loan_list, +# downpayment_max = db.customer_preference['downpayment_max'], # 60006 is a number to show effect +# expected_payback= db.customer_preference['expected_payback'], +# req_dscr = db.req_dscr, +# first_year_noi = db.next_year_income['noi'], +# first_year_cash = 50000, +# savings = 15000, +# )) + +# from bpfin.tests.testdata import sample_data as db +# req_dscr = { +# 'req_noi_dscr': 1.15, +# 'req_cash_dscr': 1.05, +# 'req_saving_dscr': 1.10 +# } +# test cases +# print('\n Base Case:') +# print(cal_max_budget( +# loan_list=Loan_List(db.loan_input_list).loan_list, +# downpayment_max=90000, +# expected_payback=120, +# req_dscr=req_dscr, +# first_year_noi=10000, +# first_year_cash=10000, +# savings=15000, +# is_loan_first=1)) + +# print('\n loan_list=None') +# print(cal_max_budget( +# loan_list=None, +# downpayment_max=90000, +# expected_payback=120, +# req_dscr=req_dscr, +# first_year_noi=10000, +# first_year_cash=10000, +# savings=15000, +# is_loan_first=1)) + +# print('\n loan_list = downpayment_max = None,') +# print(cal_max_budget( +# loan_list=None, +# downpayment_max=None, +# expected_payback=120, +# req_dscr=req_dscr, +# first_year_noi=10000, +# first_year_cash=10000, +# savings=15000, +# is_loan_first=1)) + +# print('\n expected_payback = None') +# print(cal_max_budget( +# loan_list=Loan_List(db.loan_input_list).loan_list, +# downpayment_max=90000, +# expected_payback=None, +# req_dscr=req_dscr, +# first_year_noi=10000, +# first_year_cash=10000, +# savings=15000, +# is_loan_first=1)) + +# print('\n expected_payback = None, is_loan_first=0') +# print(cal_max_budget( +# loan_list=Loan_List(db.loan_input_list).loan_list, +# downpayment_max=90000, +# expected_payback=None, +# req_dscr=req_dscr, +# first_year_noi=10000, +# first_year_cash=10000, +# savings=15000, +# is_loan_first=0)) + +# print('\n expected_payback = 0') +# print(cal_max_budget( +# loan_list=Loan_List(db.loan_input_list).loan_list, +# downpayment_max=90000, +# expected_payback=0, +# req_dscr=req_dscr, +# first_year_noi=10000, +# first_year_cash=10000, +# savings=15000, +# is_loan_first=1)) + +# print('\n req_noi_dscr = None, req_cash_dscr = None') +# print(cal_max_budget( +# loan_list=Loan_List(db.loan_input_list).loan_list, +# downpayment_max=90000, +# expected_payback=120, +# req_dscr={'req_noi_dscr': None, 'req_cash_dscr': None, 'req_saving_dscr': 1.10}, +# first_year_noi=10000, +# first_year_cash=10000, +# savings=15000, +# is_loan_first=1)) + +# print('\n req_saving_dscr = None') +# print(cal_max_budget( +# loan_list=Loan_List(db.loan_input_list).loan_list, +# downpayment_max=90000, +# expected_payback=120, +# req_dscr={'req_noi_dscr': 1.15, 'req_cash_dscr': 1.05, 'req_saving_dscr': None}, +# first_year_noi=10000, +# first_year_cash=10000, +# savings=15000, +# is_loan_first=1)) + +# print('\n req_noi_dscr = None, req_cash_dscr=0, req_saving_dscr = None') +# print(cal_max_budget( +# loan_list=Loan_List(db.loan_input_list).loan_list, +# downpayment_max=90000, +# expected_payback=120, +# req_dscr={'req_noi_dscr': None, 'req_cash_dscr': 0, 'req_saving_dscr': None}, +# first_year_noi=10000, +# first_year_cash=10000, +# savings=15000, +# is_loan_first=1)) + +# print('\n first_year_noi=None') +# print(cal_max_budget( +# loan_list=Loan_List(db.loan_input_list).loan_list, +# downpayment_max=90000, +# expected_payback=120, +# req_dscr={'req_noi_dscr': 1.15, 'req_cash_dscr': 1.05, 'req_saving_dscr': 1.10}, +# first_year_noi=None, +# first_year_cash=10000, +# savings=15000, +# is_loan_first=1)) + +# print('\n first_year_noi=0') +# print(cal_max_budget( +# loan_list=Loan_List(db.loan_input_list).loan_list, +# downpayment_max=90000, +# expected_payback=120, +# req_dscr={'req_noi_dscr': 1.15, 'req_cash_dscr': 1.05, 'req_saving_dscr': 1.10}, +# first_year_noi=0, +# first_year_cash=10000, +# savings=15000, +# is_loan_first=1)) + +# print('\n first_year_noi=0, req_noi_dscr: 0') +# print(cal_max_budget( +# loan_list=Loan_List(db.loan_input_list).loan_list, +# downpayment_max=90000, +# expected_payback=120, +# req_dscr={'req_noi_dscr': 0, 'req_cash_dscr': 1.05, 'req_saving_dscr': 1.10}, +# first_year_noi=0, +# first_year_cash=10000, +# savings=15000, +# is_loan_first=1)) + +# print('\n savings=None') +# print(cal_max_budget( +# loan_list=Loan_List(db.loan_input_list).loan_list, +# downpayment_max=90000, +# expected_payback=120, +# req_dscr={'req_noi_dscr': 1.15, 'req_cash_dscr': 1.05, 'req_saving_dscr': 1.10}, +# first_year_noi=10000, +# first_year_cash=10000, +# savings=None, +# is_loan_first=1)) + +# print('\n savings=0') +# print(cal_max_budget( +# loan_list=Loan_List(db.loan_input_list).loan_list, +# downpayment_max=90000, +# expected_payback=120, +# req_dscr={'req_noi_dscr': 1.15, 'req_cash_dscr': 1.05, 'req_saving_dscr': 1.10}, +# first_year_noi=10000, +# first_year_cash=10000, +# savings=0, +# is_loan_first=1)) + +# print('\n savings=0 , req_saving_dscr =0' ) +# print(cal_max_budget( +# loan_list=Loan_List(db.loan_input_list).loan_list, +# downpayment_max=90000, +# expected_payback=120, +# req_dscr={'req_noi_dscr': 1.15, 'req_cash_dscr': 1.05, 'req_saving_dscr': 0}, +# first_year_noi=10000, +# first_year_cash=10000, +# savings=0, +# is_loan_first=1)) + +# print('\n first_year_noi=None, first_year_cash=None, savings=None,' ) +# print(cal_max_budget( +# loan_list=Loan_List(db.loan_input_list).loan_list, +# downpayment_max=90000, +# expected_payback=120, +# req_dscr=req_dscr, +# first_year_noi=None, +# first_year_cash=None, +# savings=None, +# is_loan_first=1)) + -- GitLab