Change the filespec for ignored changes and the mode of retire.py
[retire.git] / tax_collector.py
1 import utils
2
3 class tax_collector(object):
4     def __init__(self):
5         # These four accumulate and then clear every year (i.e. every call
6         # to record_taxes_paid_and_reset_for_next_year)
7         self.ordinary_income = 0
8         self.short_term_gains = 0
9         self.dividends_and_long_term_gains = 0
10         self.roth_income = 0
11
12         # The rest of these aggregate and are used as part of the final stats.
13         self.total_tax_bill = 0
14         self.total_ordinary_income = 0
15         self.total_short_term_gains = 0
16         self.total_dividends_and_long_term_gains = 0
17         self.total_roth_income = 0
18         self.total_aggregate_income = 0
19
20     def record_taxes_paid_and_reset_for_next_year(self,
21                                                   taxes_paid):
22         self.total_tax_bill += taxes_paid
23         self.total_aggregate_income += self.get_total_income()
24         self.ordinary_income = 0
25         self.short_term_gains = 0
26         self.dividends_and_long_term_gains = 0
27         self.roth_income = 0
28
29     def record_ordinary_income(self, amount):
30         self.ordinary_income += amount
31         self.total_ordinary_income += amount
32
33     def record_short_term_gain(self, amount):
34         self.short_term_gains += amount
35         self.total_short_term_gains += amount
36
37     def record_dividend_or_long_term_gain(self, amount):
38         self.dividends_and_long_term_gains += amount
39         self.total_dividends_and_long_term_gains += amount
40
41     def record_roth_income(self, amount):
42         self.roth_income += amount
43         self.total_roth_income += amount
44
45     def approximate_taxes(self,
46                           standard_deduction,
47                           ordinary_income_tax_brackets,
48                           dividends_and_long_term_gains_brackets):
49         taxes_due = 0
50
51         # Handle ordinary income:
52         ordinary_income = (self.ordinary_income +
53                            self.short_term_gains -
54                            standard_deduction)
55         if ordinary_income < 0:
56             ordinary_income = 0
57         taxes_due += ordinary_income_tax_brackets.compute_taxes_for_income(
58             ordinary_income)
59
60         # Handle dividends and long term gains:
61         taxes_due += dividends_and_long_term_gains_brackets.compute_taxes_for_income(
62             self.dividends_and_long_term_gains)
63
64         # Assume Roth money is still available tax free in the future.
65         return taxes_due
66
67     def how_many_more_dollars_can_we_earn_without_changing_tax_rate(
68             self,
69             federal_ordinary_income_tax_brackets):
70         """Return number of ordinary income dollars we can make without
71            changing this year's tax rate.  Note: this may return None
72            which actually indicates something more like 'infinite since
73            you're already at the top tax bracket.'"""
74         income = self.ordinary_income
75         if income <= 1: income = 2
76         b = federal_ordinary_income_tax_brackets.get_bracket_above_income(
77             income)
78         if b[0] is not None:
79             delta = b[0] - income
80             return delta
81         return 0
82
83     def get_total_income(self):
84         return (self.ordinary_income +
85                 self.short_term_gains +
86                 self.dividends_and_long_term_gains +
87                 self.roth_income)
88
89     def dump_final_report(self):
90         print "  Taxes and income:"
91         print "    {:<50}: {:>14}".format("Total aggregate income",
92                                           utils.format_money(self.total_aggregate_income))
93         print "    ...{:<47}: {:>14}".format("Ordinary income",
94                                              utils.format_money(self.total_ordinary_income))
95         print "    ...{:<47}: {:>14}".format("Income from short term gains",
96                                              utils.format_money(self.total_short_term_gains))
97         print "    ...{:<47}: {:>14}".format("Income from dividends and long term gains",
98                                              utils.format_money(self.total_dividends_and_long_term_gains))
99         print "    ...{:<47}: {:>14}".format("Roth income",
100                                              utils.format_money(self.total_roth_income))
101         print "    {:<50}: {:>14}".format("Total taxes paid",
102                                           utils.format_money(self.total_tax_bill))
103         overall_tax_rate = float(self.total_tax_bill) / float(self.total_aggregate_income)
104         print "    {:<50}: {:>14}".format("Effective tax rate",
105                                           utils.format_rate(overall_tax_rate))