3 class tax_collector(object):
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
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
20 def record_taxes_paid_and_reset_for_next_year(self,
22 assert taxes_paid >= 0, "You can't pay negative taxes"
23 self.total_tax_bill += taxes_paid
24 self.total_aggregate_income += self.get_total_income()
25 assert self.total_aggregate_income >= 0, "Accumulator should be >= 0"
26 self.ordinary_income = 0
27 self.short_term_gains = 0
28 self.dividends_and_long_term_gains = 0
31 def record_ordinary_income(self, amount):
32 assert amount >= 0, "Income should be non-negative"
33 self.ordinary_income += amount
34 self.total_ordinary_income += amount
36 def record_short_term_gain(self, amount):
37 assert amount >= 0, "Income should be non-negative"
38 self.short_term_gains += amount
39 self.total_short_term_gains += amount
41 def record_dividend_or_long_term_gain(self, amount):
42 assert amount >= 0, "Income should be non-negative"
43 self.dividends_and_long_term_gains += amount
44 self.total_dividends_and_long_term_gains += amount
46 def record_roth_income(self, amount):
47 assert amount >= 0, "Income should be non-negative"
48 self.roth_income += amount
49 self.total_roth_income += amount
51 def approximate_taxes(self,
53 ordinary_income_tax_brackets,
54 dividends_and_long_term_gains_brackets):
55 assert standard_deduction >= 0, "Standard deduction should be non-negative"
58 # Handle ordinary income:
59 ordinary_income = (self.ordinary_income +
60 self.short_term_gains -
62 if ordinary_income < 0:
64 taxes_due += ordinary_income_tax_brackets.compute_taxes_for_income(
67 # Handle dividends and long term gains:
68 taxes_due += dividends_and_long_term_gains_brackets.compute_taxes_for_income(
69 self.dividends_and_long_term_gains)
71 # Assume Roth money is still available tax free in the future.
72 assert taxes_due >= 0, "Computed negative taxes?!"
75 def how_many_more_dollars_can_we_earn_without_changing_tax_rate(
77 federal_ordinary_income_tax_brackets):
78 """Return number of ordinary income dollars we can make without
79 changing this year's tax rate. Note: this may return None
80 which actually indicates something more like 'infinite since
81 you're already at the top tax bracket.'"""
82 income = self.ordinary_income
83 if income <= 1: income = 2
84 b = federal_ordinary_income_tax_brackets.get_bracket_above_income(
91 def get_total_income(self):
92 return (self.ordinary_income +
93 self.short_term_gains +
94 self.dividends_and_long_term_gains +
97 def dump_final_report(self):
98 print " Taxes and income:"
99 print " {:<50}: {:>14}".format("Total aggregate income",
100 utils.format_money(self.total_aggregate_income))
101 print " ...{:<47}: {:>14}".format("Ordinary income",
102 utils.format_money(self.total_ordinary_income))
103 print " ...{:<47}: {:>14}".format("Income from short term gains",
104 utils.format_money(self.total_short_term_gains))
105 print " ...{:<47}: {:>14}".format("Income from dividends and long term gains",
106 utils.format_money(self.total_dividends_and_long_term_gains))
107 print " ...{:<47}: {:>14}".format("Roth income",
108 utils.format_money(self.total_roth_income))
109 print " {:<50}: {:>14}".format("Total taxes paid",
110 utils.format_money(self.total_tax_bill))
111 overall_tax_rate = float(self.total_tax_bill) / float(self.total_aggregate_income)
112 print " {:<50}: {:>14}".format("Effective tax rate",
113 utils.format_rate(overall_tax_rate))