I have two issues that need resolving. I have created a class object LoanInstance. The object should create a list of numbers (int or float) that show different aspects of a personal loan repayment balance. There are 2 main parts to the object.
Part 1: Read in data from a data frame (I’ve created an example data frame below)
df = {'amount':[7000], 'term':[36], 'apr':[0.145], 'product':['standard'], 'score':[750], 'customer_type':[Home], 'Channel':[trad]}
Part 2: Generate the repayment profiles for the loan
Part 1 is working fine. However, part 2 is not working as I expect.
These are the steps:
Step 1: create a loan object
loans = LoanInstance()
Step 2: read in data from pandas dataframe (this works fine)
loans.get_loan(df,1)
Step 3:generating the balance profiles
balance profiles are generated with the following method applied to the loan object.
loans.repayment_profiles()
Issue 1!
This produces the error: TypeError: ‘int’ object is not callable.
It is being caused by the expression below:
monthly_repayment = self.amount/(12(1 - (1 + (self.apr/12))**-n*12))
What’s going wrong here?
Issue 2
When I bypass issue 1 by replacing the problematic expression with a number (i.e 200) I can get the code to run.
loans.repayment_profiles()
However, when I try to print any of the balance profile attributes they come up as an empty list [ ].
i.e running the code below comes out as an empty list [ ]
loans.balance_profile_start
Why is this happening ? I expected a list of numbers represented the repayment balance for the loan taken into the object in step 1.
Thanks for your help in advance!
Full class code is here:
class LoanInstance: def __init__(self, amount=0, term=0, apr=0, product=0, score=0, customer_type=0, channel=0, balance_profile_end =[], balance_profile_start=[], interest_profile=[], recieved_interest=[], recieved_capital=[] ): self.amount = amount self.term = term self.apr = apr self.product = product self.score = score self.customer_type = customer_type self.channel = channel self.balance_profile_start = balance_profile_start # Starting balance profile over loan term self.balance_profile_end = balance_profile_end # End balance profile over loan term self.interest_profile = interest_profile # Interest accrued over loan term self.recieved_interest = recieved_interest # Recieved interest profile self.recieved_capital = recieved_capital # Recieved capital profile # Read in loan attributes from pandas dataframe def get_loan(self, df, row): self.amount = df.at[row, 'amount'] self.term = df.at[row, 'term'] self.apr = df.at[row, 'apr'] self.product = df.at[row, 'product'] self.score = df.at[row, 'score'] self.customer_type = df.at[row, 'customer_type'] self.channel = df.at[row, 'Channel'] # Generate contractual balance profiles def repayment_profiles(self): n = self.term/12 # Repayment term in years nominal_interest = (((self.apr + 1)**(1/12))-1)*12 # Nominal interest rate: APR excluding other fees monthly_rate = nominal_interest/12 # Monthly customer rate monthly_repayment = self.amount/(12(1 - (1 + (self.apr/12))**-n*12)) # Fixed monthly repayment return print(nominal_interest) # Generate contractual repayment over the term of the loan for month in range(0, self.term + 1): # Set special case for month 0 if month == 0: interest = recieved_int = 0 recieved_capital = 0 balance_start = 0 # Gives a starting balance profile of 0 at month 0 balance_end = self.amount self.interest_profile.append(interest) # Append interest to interest profile self.balance_profile_end.append(balance_end) # Append balance to balance profile end self.balance_profile_start.append(balance_start) # Append balance to balance profile start self.recieved_interest.append(recieved_int) # Append recieved interest self.recieved_capital.append(recieved_capital) # Append recieved capital elif month == 1: # set special case for month 1 balance_start = self.amount self.balance_profile_start.append(balance_start) interest = recieved_int = monthly_rate*self.balance_profile_start[1] self.interest_profile.append(interest) self.recieved_interest.append(recieved_int) balance_end = self.balance_profile_start[1] + self.interest_profile[1] - monthly_repayment self.balance_profile_end.append(balance_end) recieved_capital = monthly_payment - self.interest_profile[1] self.recieved_capital.append(recieved_capital) else: balance_start = self.balance_profile_end[month] self.balance_profile_start.append(balance_start) interest = recieved_int = monthly_rate*self.balance_profile_start[month] self.interest_profile.append(interest) self.recieved_interest.append(recieved_int) balance_end = self.balance_profile_start[month] + self.interest_profile[month] - monthly_repayment self.balance_profile_end.append(balance_end) recieved_capital = monthly_payment - self.interest_profile[month] self.recieved_capital.append(recieved_capital) return self.balance_profile_start, self.balance_profile_end, self.interest_profile, self.recieved_interest, self.recieved_capital
Advertisement
Answer
For the first issue,
Multiplication operator (*
) is used to perform multiplication. In your case, self.amount/12(...)
note the missing *
operator between 12
and (
. Because of the missing operator, it treats 12
as a callable (function). But 12
is an int and not a callable, hence the error.
So insert the *
if you mean multiplication.
Also, I would suggest properly insert the brackets to avoid ambiguity. For example, in the case of **-n*12
, you can change it to **(-n*12)
. If this is what it means.
For the second issue,
Note the return statement, return print(nominal_interest)
. A return statement is used to end the function right there and return the value where the function was called. Meaning, the function stops executing at this line, and all the further instruction are skipped. And since, by default balance_profile_start
is []
, it displays an empty list. You probably only want to print nominal_interest
, instead of returning it. So the line becomes just: print(nominal_interest)