def plot(n_click, principal, payment, rate, ext_pay): if ext_pay is None: loan = Loan.Loan(principal=principal, rate=rate, payment=payment, extra_payment=0) else: loan = Loan.Loan(principal=principal, rate=rate, payment=payment, extra_payment=ext_pay) loan.check_loan_parameters() loan.compute_schedule() payment_number, applied_ext, applied_principal, applied_interest, end_principal = [], [], [], [], [] for pay in loan.schedule.values(): payment_number.append(pay[0]) applied_ext.append(pay[3]) applied_principal.append(pay[4]) applied_interest.append(pay[5]) end_principal.append(pay[6]) ind = np.arange(1, len(payment_number) + 1) fig = go.Figure(data=[ go.Bar(name="Principal", x=ind, y=applied_principal, hovertemplate="Principal:%{y:$.2f}", marker_color="#92A8D1"), go.Bar(name="Extra Payment", x=ind, y=applied_ext, hovertemplate="Extra Payment:%{y:$.2f}", marker_color="#8FBC8F"), go.Bar(name="Interest", x=ind, y=applied_interest, hovertemplate="Interest:%{y:$.2f}", marker_color="#DEB887") ]) fig.update_layout(barmode='stack', yaxis=dict(title='$ USD', titlefont_size=16, tickfont_size=14), xaxis=dict(title='Payment Period')) fig.update_layout(barmode='stack', yaxis=dict(title='$ USD', titlefont_size=16, tickfont_size=14), xaxis=dict(title='Payment Period')) return dcc.Graph(figure=fig)
def test_status_validation(self): LOAN1 = Loan(None, None, None) for txt in ("Bad", "FOO", "Invalid", "approved", None): LOAN1.loan_status = txt with self.assertRaises(InvalidLoanStatusError) as context: LOAN1.validate_loan_status()
def compute_schedule(principal, rate, payment, extra_payment): loan = None try: loan = Loan(principal=principal, rate=rate, payment=payment, extra_payment=extra_payment) loan.check_loan_parameters() loan.compute_schedule() except ValueError as ex: print(ex) loans.add_loan(loan) Helper.plot(loan) Helper.print(loan) Helper.getimg(loan) print(round(loan.total_principal_paid, 2), round(loan.total_interest_paid, 2), round(loan.time_to_loan_termination, 0)) if loans.get_loan_count() == 3: loans.aggregate() Helper.plot(loans) Helper.print(loans)
def test_to_jsonable(self): LOAN1 = Loan("123-45-6789", 12345, 67890, 987) LOAN1.loan_status = "New" # just making sure this executes, don't need to check that json package works encode_me = LOAN1.to_jsonable() self.assertTrue(len(encode_me) > 0,"JSON encoding should exist")
def main(): os.chdir('D:\Documents - HDD') wb = openpyxl.load_workbook('Loan_Spreadsheet.xlsx') type(wb) # changing the sheet to the "List" sheets where the loans are wb.active = 1 sheet = wb.active loanList = [] # creates the "Loan" object and appends to a list for x in range(sheet.max_row): name = sheet.cell(x + 1, 1) t = sheet.cell(x + 1, 2) amt = sheet.cell(x + 1, 3) interest = sheet.cell(x + 1, 4) dateBorrowed = sheet.cell(x + 1, 5) print(name.value, " | ", t.value, " | ", amt.value, " | ", interest.value, " | ", dateBorrowed.value) l = Loan(name, t, amt, interest, dateBorrowed) loanList.append(l) print("\n") loanCal(loanList)
def book_car(self, car, name, age, licence, email, date, period, pickup, dropoff): customer = Customer(name, age, email, licence) loan = Loan(car, customer, date, period, pickup, dropoff) self._loans.append(loan) print(loan)
def test_property_value_validation(self): LOAN1 = Loan(None, None, None) for amt in (0, -10, None): LOAN1.prop_value = amt with self.assertRaises(InvalidPropertyValueError) as context: LOAN1.validate_prop_value()
def test_loan_value_validation(self): LOAN1 = Loan(None, None, None) for amt in (0, -10, None): LOAN1.loan_value = amt with self.assertRaises(InvalidLoanValueError) as context: LOAN1.validate_loan_value()
def test_loan_with_extra_payment(principal, rate, payment, extra_payment, total_principal_paid, total_interest_paid, time_to_loan_termination): tolerance_for_cash = 5.0 tolerance_for_time = 1.0 loan = None try: loan = Loan(principal=principal, rate=rate, payment=payment, extra_payment=extra_payment) loan.check_loan_parameters() loan.compute_schedule() except ValueError as ex: print(ex) loans.add_loan(loan) Helper.plot(loan) print(round(loan.total_principal_paid, 2), round(loan.total_interest_paid, 2), round(loan.time_to_loan_termination, 0)) assert abs(loan.total_principal_paid - total_principal_paid) <= tolerance_for_cash assert abs(loan.total_interest_paid - total_interest_paid) <= tolerance_for_cash assert abs(loan.time_to_loan_termination - time_to_loan_termination) <= tolerance_for_time if loans.get_loan_count() == 2: loans.aggregate() Helper.plot(loans)
def test_ltv_validation(self): LOAN1 = Loan(None, None, None) LOAN1.prop_value = 5000 # 100% loan amount, too high! # LOAN1.loan_value = LOAN1.prop_value with self.assertRaises(ExcessLoanToValueError) as context: LOAN1.validate_ltv() # 50% loan amount, still too much # LOAN1.loan_value = LOAN1.prop_value * 0.5 with self.assertRaises(ExcessLoanToValueError) as context: LOAN1.validate_ltv() # 40% loan amount is the cap # LOAN1.loan_value = LOAN1.prop_value * 0.4 LOAN1.validate_ltv() # And lower is OK, too # LOAN1.loan_value = LOAN1.prop_value * 0.1 LOAN1.validate_ltv()
def test_db_load(self): LOAN1 = Loan("123-45-6789", 12345, 67890) db = sqlite3.connect(TEST_DB) LOAN1.loan_status = "Awesome" LOAN1.save(db) LOAN2 = Loan(None, None, None, LOAN1.loan_id) self.assertTrue(LOAN2.loan_id == LOAN1.loan_id, "Loan id issue") LOAN2.load(db) self.assertTrue(LOAN2.payer_ssn == LOAN1.payer_ssn, "SSN issue") self.assertTrue(LOAN2.prop_value == LOAN1.prop_value, "Property value issue") self.assertTrue(LOAN1.loan_value == LOAN1.loan_value, "Loan value issue") self.assertTrue(LOAN2.loan_status == LOAN1.loan_status, "Loan status issue") db.close()
def compute_schedule(principal, rate, payment, extra_payment): loan = None try: loan = Loan(principal, rate, payment, extra_payment) loan.check_loan_parameters() loan.compute_schedule() except ValueError as ex: print(ex) return loan
def test_creates(self): LOAN1 = Loan("123-45-6789", 12345, 67890) self.assertTrue("123-45-6789" == LOAN1.payer_ssn, "SSN issue") self.assertTrue(12345 == LOAN1.prop_value, "Property value issue") self.assertTrue(67890 == LOAN1.loan_value, "Loan value issue") self.assertIsNone(LOAN1.loan_status, "Loan should not have a status") self.assertIsNone(LOAN1.loan_id, "Loan should not have an id") # LOAN2 = Loan("012-34-5678", 300, 400, "abc-def-ghijkl") self.assertTrue("012-34-5678" == LOAN2.payer_ssn, "SSN issue") self.assertTrue(300 == LOAN2.prop_value, "Property value issue") self.assertTrue(400 == LOAN2.loan_value, "Loan value issue") self.assertIsNone(LOAN2.loan_status, "Loan should not have a status") self.assertTrue("abc-def-ghijkl" == LOAN2.loan_id, "Loan should have an id")
def create_table(n_click, principal, payment, rate, ext_pay): loans = LoanPortfolio.LoanPortfolio() if ext_pay is None: loan = Loan.Loan(principal=principal, rate=rate, payment=payment, extra_payment=0) else: loan = Loan.Loan(principal=principal, rate=rate, payment=payment, extra_payment=ext_pay) loan.check_loan_parameters() loan.compute_schedule() loans.add_loan(loan) helper = Helper.Helper() table = helper.print_df(loan) if loans.get_loan_count() == 3: loans.aggregate() helper = Helper.Helper() table = helper.print_df(loans) temp = dash_table.DataTable(data=table.to_dict("records"), columns=[{ 'id': c, 'name': c } for c in table.columns], style_cell={'textAlign': 'center'}, style_as_list_view=True, style_header={ 'backgroundColor': '#E9DADA', 'fontWeight': 'bold' }, style_table={ 'height': '400px', 'overflowY': 'auto' }) return temp
def compute_schedule(principal, rate, payment, extra_payment): loans.schedule = {} loan = None try: loan = Loan(principal=principal, rate=rate, payment=payment, extra_payment=extra_payment) loan.check_loan_parameters() loan.compute_schedule() except ValueError as ex: print(ex) #Add loans to portfolio and start aggregation loans.add_loan(loan) loans.aggregate()
def end_date(principal, payment, rate, ext_pay, date_value): loans = LoanPortfolio.LoanPortfolio() if ext_pay is None: loan = Loan.Loan(principal=principal, rate=rate, payment=payment, extra_payment=0) else: loan = Loan.Loan(principal=principal, rate=rate, payment=payment, extra_payment=ext_pay) loan.check_loan_parameters() loan.compute_schedule() loans.add_loan(loan) helper = Helper.Helper() table = helper.print_df(loan) if loans.get_loan_count() == 3: loans.aggregate() helper = Helper.Helper() table = helper.print_df(loans) period = table.shape[0] year = int(date_value[:4]) month = int(date_value[5:7]) for i in range(period): if month == 12: year += 1 month = 1 else: month += 1 month = calendar.month_name[month] end_date = "Your estimated loan end date is {},{}".format(month, year) return end_date
def table_figure2(loan_amount, interest_rate, payment, extra1, extra2, extra3, start_date1): y = int( list(start_date1)[0] + list(start_date1)[1] + list(start_date1)[2] + list(start_date1)[3]) m = int(list(start_date1)[5] + list(start_date1)[6]) d = min(int(list(start_date1)[8] + list(start_date1)[9]), 28) start_date = date(y, m, d) if loan_amount != None and payment != None and interest_rate != None: ex1 = disting(extra1) ex2 = disting(extra2) ex3 = disting(extra3) loan = Loan(loan_amount, interest_rate, payment, ex1 + ex2 + ex3) a, b, c = compute_schedule_loan(loan_amount, interest_rate, payment, ex1 + ex2 + ex3) loan_noextra = Loan(loan_amount, interest_rate, payment, 0) df = date_trans(to_df(loan), start_date) df_noextra = date_trans(to_df(loan_noextra), start_date) new_df = pd.concat([ df_noextra['Month'], df_noextra['End Principal'], df['End Principal'] ], axis=1) new_df.columns = ['Month', 'No extra', 'Extra all'] new_df = new_df.append( { 'Month': start_date, 'No extra': loan_amount, 'Extra all': loan_amount }, ignore_index=True).sort_values(by='Month') return df.to_dict('record'), a, b, c, new_df.to_dict('record') else: df = pd.DataFrame(columns=[ 'Month', 'Begin Principal', 'Payment', 'Extra Payment', 'Applied Principal', 'Applied Interest', 'End Principal' ]) return df.to_dict('record'), 0, 0, 0, []
def test_ssn_validation(self): LOAN1 = Loan(None, None, None) # SSN should look like AAA-GG-SSSS where A/G/S are 0-9... # for ssn in ("1234", "foo", "123456789", "329487240948372039487231", None): LOAN1.payer_ssn = ssn with self.assertRaises(FormatSSNError) as context: LOAN1.validate_payer_ssn() # ...except A cannot be 000, 666, or any 9xx # for ssn in ("000-12-3456","666-77-8888","900-12-6473","999-12-6473"): LOAN1.payer_ssn = ssn with self.assertRaises(InvalidSSNError) as context: LOAN1.validate_payer_ssn()
def test_db_save(self): LOAN1 = Loan("123-45-6789", 12345, 67890) db = sqlite3.connect(TEST_DB) self.assertIsNone(LOAN1.loan_id, "Loan should not have an id") LOAN1.save(db) self.assertIsNotNone(LOAN1.loan_id, "Loan should have an id after saving") # with the id stored, a different branch is executed # # just validating that it doesn't fail in this test, load test checks values LOAN1.save(db) db.close()
def main(): parser = argparse.ArgumentParser() parser.add_argument('-p','--principal', help='Principal amount on loan', required=True, type=float, metavar='P') parser.add_argument('-n','--name', help='Name for specific Loan. (car, student, house)', required=False, type=str, metavar='N', default='') parser.add_argument('-i','--interest', help=r'''Interest rate on loan in terms of decimal. If it's 5.00%% enter .05''', required=True, type=float, metavar='I') parser.add_argument('-m','--monthly', help='Monthly payment on loan', required=True, type=float, metavar='M') args = parser.parse_args() loan1 = Loan.Loan(args.principal, args.interest) months = 0 monthly_pay = args.monthly while(not loan1.is_zero()): months += 1 loan1.pay(monthly_pay) message = 'Time to pay off {}loan: {} years and {} months'.format(args.name+' ', months//12, months % 12) print(message) message = 'Total interest paid over time: ${:,.2f}'.format(loan1.interest_paid) print(message)
def compute_schedule_loan(principal, rate, payment, extra_payment): loan = Loan(principal=principal, rate=rate, payment=payment, extra_payment=extra_payment) loan.check_loan_parameters() loan.compute_schedule() return round(loan.total_principal_paid, 2) + round(loan.total_interest_paid, 2), round(loan.total_interest_paid, 2), round(loan.time_to_loan_termination, 0)
"Num of Lenders")) for i in range(0, len(data)): print("{:<10} {:<15} {:<15} {:<10} {:<15} {:<5}".format( data[i].id, data[i].loan_amount, data[i].country_name, data[i].status, data[i].time_to_raise, data[i].num_lenders_total)) with open('data.csv') as csv_file: csv_reader = csv.reader(csv_file, delimiter=',') line_count = 0 for row in csv_reader: if line_count == 0: line_count += 1 continue # print(row[1]) data.append(Loan(row[0], row[1], row[2], row[3], row[4], row[5])) line_count += 1 def find_total_amount(data): sum = 0 for i in range(0, 25): # data samples = 25 sum += int(data[i].loan_amount) return sum def find_average_amount(data): sum = 0 for i in range(0, 25): # data samples = 25 sum += int(data[i].loan_amount) return sum / 25
def update_output_div(principal, payment, rate, extra_payment, c1, c2, c3, btn1, btn2, bt3): global loans changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0] if 'btn-nclicks-1' in changed_id: loan = None try: loan = Loan(principal=float(principal), rate=float(rate), payment=float(payment), extra_payment=float(extra_payment)) loan.check_loan_parameters() loan.compute_schedule() except ValueError as ex: print(ex) loans.add_loan(loan) msg = 'add loan success' loans.aggregate() # msg = re.sub('\r\n', '<br>', str(Helper.print(loans))) return html.Div([ html.H5('Current loan: '), html.Table([ html.Thead( html.Tr([ html.Th(col) for col in [ 'Payment Number', 'Begin Principal', 'Payment', 'Extra Payment', 'Applied Principal', 'Applied Interest', 'End Principal' ] ])), html.Tbody([ html.Tr([ html.Td(Helper.display(float(pay[i]))) for i in range(7) ]) for pay in loan.schedule.values() ]) ]), dcc.Graph(figure=Helper.getimg(loan)), html.H5('ALL loans: '), html.Table([ html.Thead( html.Tr([ html.Th(col) for col in [ 'Payment Number', 'Begin Principal', 'Payment', 'Extra Payment', 'Applied Principal', 'Applied Interest', 'End Principal' ] ])), html.Tbody([ html.Tr([ html.Td(Helper.display(float(pay[i]))) for i in range(7) ]) for pay in loans.schedule.values() ]) ]), dcc.Graph(figure=Helper.getimg(loans)) ]) elif 'btn-nclicks-2' in changed_id: loans = LoanPortfolio() msg = 'clear success' elif 'btn-nclicks-3' in changed_id: loan_impacts = LoanImpacts( principal=float(principal), rate=float(rate), payment=float(payment), extra_payment=float(extra_payment), contributions=[float(c1), float(c2), float(c3)]) impdata = loan_impacts.compute_impacts() return html.Div([ html.H5('Loan impact: '), html.Table([ html.Thead( html.Tr([ html.Th(col) for col in [ 'Index', 'InterestPaid', 'Duration', 'MIInterest', 'MIDuration' ] ])), html.Tbody([ html.Tr([html.Td(pay[i]) for i in range(5)]) for pay in impdata ]) ]) ]) else: msg = 'None of the buttons have been clicked yet' return 'Output: {}'.format(msg)