Code cleanups and one more place to use money class.
[retire.git] / tax_brackets.py
1 import utils
2 from money import money
3
4 class tax_brackets:
5     """A class to represent tax brackets and some operations on them."""
6
7     def __init__(self, brackets):
8         self.brackets = brackets
9
10     def compute_taxes_for_income(self, income):
11         """Compute the tax bill for income given our brackets."""
12         taxes_due = money(0)
13         while income > 1:
14             (threshold, rate) = self.get_bracket_for_income(income)
15             taxes_due += (income - threshold) * rate
16             income = threshold
17         assert taxes_due >= 0, "Somehow computed negative tax bill?!"
18         return taxes_due
19
20     def get_bracket_for_income(self, income):
21         """Return the bracket that the last dollar of income was in."""
22         assert income > 0, "Income should be >0 to be taxed"
23         rate = 0.0
24         threshold = 0
25         for bracket in self.brackets:
26             # Bracket is a tuple of (monetary_threshold,
27             # tax_rate).  So bracket[0] is a dollar amount and
28             # bracket[1] is a tax rate.  e.g. ( 250000, 0.20 )
29             # indicates that every dollar you earn over 250K is
30             # taxed at 20%.
31             if (income > bracket[0] and rate < bracket[1]):
32                 threshold = bracket[0]
33                 rate = bracket[1]
34         return (threshold, rate)
35
36     def get_bracket_above_income(self, income):
37         """Return the next bracket above the one activated by income."""
38         assert income > 0, "Income should be >0 to be taxed"
39         rate = 1.0
40         threshold = None
41
42         # Walk the income tax brackets and look for the one just above
43         # the one this year's income is activating.
44         for bracket in self.brackets:
45             if (bracket[0] > income and bracket[1] < rate):
46                 threshold = bracket[0]
47                 rate = bracket[1]
48
49         # Note: this can return (None, 1.0) iff the income is already
50         # in the top tax bracket.
51         return (threshold, rate)
52
53     def get_bracket_below_income(self, income):
54         """Return the next bracket below the one activated by income."""
55         assert income > 0, "Income should be >0 to be taxed"
56         bracket = self.get_bracket_for_income(income)
57         income = bracket[0]
58         return self.get_bracket_for_income(income)
59
60     def get_effective_tax_rate_for_income(self, income):
61         """Compute and return the effective tax rate for an income."""
62         if income <= 0: return 0
63         tax_bill = self.compute_taxes_for_income(income)
64         return float(tax_bill) / income
65
66     def adjust_with_multiplier(self, multiplier):
67         """Every year the IRS adjusts the income tax brackets for inflation."""
68         for bracket in self.brackets:
69             if bracket[0] != 1:
70                 bracket[0] *= multiplier
71
72     def dump(self):
73         """Print out the tax brackets we're using in here."""
74         for x in self.brackets:
75             print "{:<20} -> {:<3}".format(x[0], utils.format_rate(x[1]))