Reputation: 163
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
Upvotes: 0
Views: 77
Reputation: 1301
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)
Upvotes: 1