Skip to content

Latest commit

 

History

History
270 lines (214 loc) · 11.9 KB

Documentation.md

File metadata and controls

270 lines (214 loc) · 11.9 KB

Documentation

Check out a notebook tutorial here

Classes

  1. Loan: Object for a single loan
  2. Multiloan: Object for handling multiple loans
  3. Payrange: Analyze how the total payment towards a loan changes with varying recurring payment amounts

How it works

  1. Compounding interest
  2. Multiple loan payments

Classes

Loan

Parameters

The Loan class is used for storing data and making calculations for a single loan.

Assumed we have a loan with the following parameters

Principal: $10,000
Annual rate: 5%
Number of compounding events in compound period: 365 (compounding daily)
Payment frequency: 1/12 (once a month)
Reucrring payment amount: $200

We can represent this loan using multiloan:

from multiloan.loans import Loan
principal = 1e4
rate = .05
n = 365
t = 1/12
payment = 200

# Create `loan` object
loan = Loan(principal, rate, payment, n, t)
print(loan)
Original principal: $10,000.00
Current balance: $10,000.00
Payment amount: $200.00
Total amount paid: $0.00
Number of payments: 0

Note that the default values for n and t are 365 and 1/12, respectively, so the same object can be created with:

loan = Loan(principal, rate, payment)

In summary:

Parameters
----------
principal: Loan balance
rate: Interest rate for payment period
payment: Amount of recurring payment
n: Number of times interest compounds in pay period
t: Payment period within rate compounding period
stop: Stop criteria to avoid infinite calculation (default 1 million)

Functions and properties

Once a Loan object is created, payments can be simulated all at once or one at a time.

Functions
-------
pay_remaining(amount): Pay the remaining balance on loan, using `payment` as default or provide a custom `amount`
pay_one(amount): Make a single payment using `payment` as default or provide a custom `amount`
reset(): Reset payment history

Properties
----------
payments: A list of payments made on this loan
balances: A list of balances after accruing interest and applying payments for each pay period
totalpay: The total amount paid on this loan (ie. sum(payments))
n_payments: The number of payments on this loan (ie. len(payments) - 1, to account for initial empty payment)
df: A pandas DataFrame of payments and balances
from multiloan.loans import Loan
principal = 1e4
rate = .05
payment = 1000

# Create loan
loan = Loan(principal, rate, payment)

# Simulate paying off entire loan with monthly payments of $200
loan.pay_remaining()
print(loan)

# We can also extract a list of balances, payments themselves, the total amount paid, and the number of payments
balances = loan.balances
payments = loan.payments
totalpaid = loan.totalpay
n_payments = loan.n_payments

print()
for name, value in zip(['Balances', 'Payments', 'Total', '#Payments'], [balances, payments, totalpaid, n_payments]):
    print(f'{name}: {value}')
Original principal: $10,000.00
Current balance: $0.00
Payment amount: $1,000.00
Total amount paid: $10,236.44
Number of payments: 11

Balances: [10000.0, 9041.750727376013, 8079.500694338067, 7113.233197420429, 6142.93146341918, 5168.578649101054, 4190.157840911064, 3207.652054678899, 2221.0442353240996, 1230.317256560008, 235.45392059647202, 0.0]
Payments: [0, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 236.4369578413157]
Total: 10236.436957841315
#Payments: 11

This data can also be viewed in a DataFrame with one row per payment using: loan.df

If you want to reset the payment history on a loan, you can use loan.reset(). Additionally, you can make single payments with loan.pay_one()

Notes

  • If you're loan balance reached $1,000,000, you will receive an error. This amount can be changed with the stop argument or by increasing your payment

Multiloan

Parameters

The Mutliloan class is used for storing data and making calculations towards multiple loans. Each loan will likely have a different rate, principal, and minimum payment - while you may choose a different t for each loan, it may make results hard to interpret.

Parameters
----------
Loans: an array of Loan objects
payment: Payment to contribute to all loans per pay period
filepath: Path to CSV file containing the principal, rate, and payment for each loan, one loan per line.
    By default, it is assumed that the column names are 'principal', 'rate', and 'payment' respectively.
    *Make sure there are NO STRING CHARACTERS in this file (ex. no '$' or ',')
    *Rates must be provided as DECIMALS, not percents (ex. 5% must be provided as .05)
{principal, rate, payment}_col: Name of column in file at `filepath` indicating each loan feature
load_kwargs: A dict of keyword arguments to pass to `pd.read_csv()`, which is used to read in `filepath`

A multiloan object can be created from either a list of Loan objects OR by providing a filepath to a CSV file containing loan data properties like the one here. If providing a filepath, it is most convenient to have your columns named principal, rate, and payment - if this is not the case you can specify the corresponding name of each column by providing it to {principal, rate, payment}_col.

For a multiloan, the payment is the amount you would like to put towards all loans in a given payment period. This amount must exceed the sum of the minimum payments for each loan

from multiloan.loans import Loan, MultiLoan

# Create some loans
loans = [Loan(p, r, pay) for p, r, pay in zip([1000, 13000, 900], [.05, .03, .04], [50, 50, 70])]
# Create a multiloan object from list of loans
ml1 = MultiLoan(loans, payment=500)

### OR ###

# Create multiloan object from CSV
ml2 = MultiLoan(filepath='data/tutorial_data.csv', payment=500)

Functions and properties

The Multiloan class shares all of the functions and properties as the Loan class, with the ability to examine the balance over all loans and for each loan independently.

Functions
-------
pay_remaining(amount): Pay the remaining balance on loan, using `payment` as default or provide a custom `amount`
pay_one(amount): Make a single payment using `payment` as default or provide a custom `amount`
reset(): Reset payment history

Properties
----------
payments: A list of payments made on this loan
balances: A list of balances after accruing interest and applying payments for each pay period
totalpay: The total amount paid on this loan (ie. sum(payments))
n_payments: The number of payments on this loan (ie. len(payments) - 1, to account for initial empty payment)
loan_{balances, payments, totals}: A nested list of dimensions [loans X n_payments] containing that loan's {balance,
    payment, total payment} history
df: A pandas DataFrame of the payment and balance history for each loan, including the "total" payments and
balances. Each row represents one payment from one loan.

A list of total payments and balances can be accessed with the payments and balances properties. Matrices of the dimensions [number of loans x number of payments] can be accessed with loan_payments and loan_balances. A longform dataframe of all of this data, per loan and in summed, is available with df.

The dataframe can be particularly useful for visualization:

import matplotlib.pyplot as plt
import seaborn as sns
from multiloan.loans import MultiLoan

# Create multiloan with $500 monthly payment
"""Generate data"""
# Create multiloan with $500 monthly payment
ml = MultiLoan(filepath='data/tutorial_data.csv', payment=500)

# Pay off all loans
ml.pay_remaining()

"""Visualize"""
# Plot the balance for each loan at each payment period
sns.lineplot('payment', 'balance', 'loan', data=ml.df)
plt.show()

payment_sched

Payrange

Payrange allows you to see how varying your routine payments changes the total amount paid for a loan.

Parameters

Parameters
----------
loan: Either a single Loan or a MultiLoan
payrange: A list of payment amounts (default = 100 to 1000 by increments of 100)

Here is an example of how to make a Payrange object

from multiloan.loans import MultiLoan, Payrange

# Create a multiloan
ml = MultiLoan(filepath='data/tutorial_data.csv')

# Create a payrange with that multiloan to examine the total cost from monthly payments of 100->1000
r = range(100, 1100, 100)
pr = Payrange(ml, r)

# Create a Payrange for just a single loan
## (The data for this loan is also returned in `pr`, this is just to illustrate that you can generate a Payrange
## with a single loan)
single_loan = ml.Loans[0]
pr2 = Payrange(single_loan, r)

Note: Only payment amounts that satisfy the stop criteria will be returned when creating a Payrange.

Properties

Properties
----------
amounts: List of amount of recurring payments assessed 
(Same as 'payrange' excluding payment amounts that don't satisfy stop criteria)
totals: A list of total amount paid at each level of `payrange`
payments: A list of the number of payments at each level of `payrange`
pct_change: A list of first difference percent change in `totals`
loan_totals: A matrix of dimensions [number of payranges X number of loans] with the total amount of each loan
for each payrange (only if a Mutliloan is provided)
loan_amounts: A matrix of dimensions [#payranges X #loans X max(# of payments)] (only if a Multiloan is provided)
df: A Pandas DataFrame of the above data. Each row contains the data for paying off one loan, with one recurring
payment value. If a Multiloan is provided, data for the 'total' will also be included (df[df.loan.eq('total')]).

Here is an example of visualizing a Payrange from 100 to 1000 by 100 for loans described by this data. Notice that the payment amounts start at 200 - this is because 100 was insufficient for paying off this loan according to the stopping criteria.

from multiloan.loans import MultiLoan, Payrange
import matplotlib.pyplot as plt
import seaborn as sns
# Create multiloan
ml = MultiLoan(filepath='data/tutorial_data.csv')
# Create payrange
pr = Payrange(ml)
# Visualize payrange using dataframe (pr.df)
sns.lineplot('amount', 'total', 'loan', data=pr.df, marker='o')
plt.legend(bbox_to_anchor=(1, 1))
plt.savefig('data/figures/payrange_sns.png')
plt.show()

payrange seaborn

How it works

Compounding interest

This code assumes that each loan compounds in interest with the user-specified frequency of n within the compounding period. By default n=365, anticipating that rate you provide is for a year, hence n=365 since under these conditions the loan will compound 365 times/year. The formula for compound interest is:

For an initial principal Pi-1, interest rate r, number of times interest compounds in period n, a time elapsed t, and the balance following compounding, Pi. Therefore, a single loan payment is applied by compounding interest over the user-specified time period, t (which is 1/12 by default to indicate monthly payments) and then subtracting the payment amount from the new balance.

Multiple loan payments

The "avalanche method" of multiple loan repayment minimizes the total amount spent by paying off the loans in order of interest rate from high to low. You allot a certain amount you wish to apply to all loans with Multiloan(..., payment=some_amount) and for each payment period first the minimum payments are made to each loan and then the remainder is contributed to the reamaining loans with the highest interest rate.