Skip to content

Commit

Permalink
issue #104 - added some more payoff methods; complete unit test cover…
Browse files Browse the repository at this point in the history
…age for current interest module
  • Loading branch information
jantman committed Aug 16, 2017
1 parent 184fab0 commit 596f358
Show file tree
Hide file tree
Showing 2 changed files with 340 additions and 25 deletions.
104 changes: 102 additions & 2 deletions biweeklybudget/interest.py
Expand Up @@ -623,7 +623,7 @@ class HighestBalanceFirstMethod(_PayoffMethod):
"""

description = 'Highest to Lowest Balance'
show_in_ui = False
show_in_ui = True

def __init__(self, max_total_payment):
"""
Expand Down Expand Up @@ -667,14 +667,64 @@ def find_payments(self, statements):
return res


class HighestInterestRateFirstMethod(_PayoffMethod):
"""
Pay statements off from highest to lowest interest rate.
"""

description = 'Highest to Lowest Interest Rate'
show_in_ui = True

def __init__(self, max_total_payment):
"""
:param max_total_payment: maximum total payment for all statements
:type max_total_payment: decimal.Decimal
"""
super(HighestInterestRateFirstMethod, self).__init__()
self._max_total = max_total_payment

def find_payments(self, statements):
"""
Given a list of statements, return a list of payment amounts to make
on each of the statements.
:param statements: statements to pay, list of :py:class:`~.CCStatement`
:type statements: list
:return: list of payment amounts to make, same order as ``statements``
:rtype: list
"""
min_sum = sum([s.minimum_payment for s in statements])
if min_sum > self._max_total:
raise TypeError(
'ERROR: Max total payment of %s is less than sum of minimum '
'payments (%s)' % (self._max_total, min_sum)
)
max_apr = Decimal('0.00')
max_idx = None
for idx, stmt in enumerate(statements):
if stmt.apr > max_apr:
max_apr = stmt.apr
max_idx = idx
res = [None for _ in statements]
max_pay = self._max_total - (
min_sum - statements[max_idx].minimum_payment
)
for idx, stmt in enumerate(statements):
if idx == max_idx:
res[idx] = max_pay
else:
res[idx] = statements[idx].minimum_payment
return res


class LowestBalanceFirstMethod(_PayoffMethod):
"""
Pay statements off from lowest to highest balance, a.k.a. the "snowball"
method.
"""

description = 'Lowest to Highest Balance (a.k.a. Snowball Method)'
show_in_ui = False
show_in_ui = True

def __init__(self, max_total_payment):
"""
Expand Down Expand Up @@ -718,6 +768,56 @@ def find_payments(self, statements):
return res


class LowestInterestRateFirstMethod(_PayoffMethod):
"""
Pay statements off from lowest to highest interest rate.
"""

description = 'Lowest to Highest Interest Rate'
show_in_ui = True

def __init__(self, max_total_payment):
"""
:param max_total_payment: maximum total payment for all statements
:type max_total_payment: decimal.Decimal
"""
super(LowestInterestRateFirstMethod, self).__init__()
self._max_total = max_total_payment

def find_payments(self, statements):
"""
Given a list of statements, return a list of payment amounts to make
on each of the statements.
:param statements: statements to pay, list of :py:class:`~.CCStatement`
:type statements: list
:return: list of payment amounts to make, same order as ``statements``
:rtype: list
"""
min_sum = sum([s.minimum_payment for s in statements])
if min_sum > self._max_total:
raise TypeError(
'ERROR: Max total payment of %s is less than sum of minimum '
'payments (%s)' % (self._max_total, min_sum)
)
min_apr = Decimal('+Infinity')
min_idx = None
for idx, stmt in enumerate(statements):
if stmt.apr < min_apr:
min_apr = stmt.apr
min_idx = idx
res = [None for _ in statements]
min_pay = self._max_total - (
min_sum - statements[min_idx].minimum_payment
)
for idx, stmt in enumerate(statements):
if idx == min_idx:
res[idx] = min_pay
else:
res[idx] = statements[idx].minimum_payment
return res


def calculate_payoffs(payment_method, statements):
"""
Calculate the amount of time (in years) and total amount of money required
Expand Down

0 comments on commit 596f358

Please sign in to comment.