2 from money import money
4 class tax_collector(object):
6 # These four accumulate and then clear every year (i.e. every call
7 # to record_taxes_paid_and_reset_for_next_year)
8 self.ordinary_income = money(0)
9 self.short_term_gains = money(0)
10 self.dividends_and_long_term_gains = money(0)
11 self.roth_income = money(0)
13 # The rest of these aggregate and are used as part of the final stats.
14 self.total_tax_bill = money(0)
15 self.total_ordinary_income = money(0)
16 self.total_short_term_gains = money(0)
17 self.total_dividends_and_long_term_gains = money(0)
18 self.total_roth_income = money(0)
19 self.total_aggregate_income = money(0)
21 def record_taxes_paid_and_reset_for_next_year(self,
23 assert taxes_paid >= 0, "You can't pay negative taxes"
24 self.total_tax_bill += taxes_paid
25 self.total_aggregate_income += self.get_total_income()
26 assert self.total_aggregate_income >= 0, "Accumulator should be >= 0"
27 self.ordinary_income = money(0)
28 self.short_term_gains = money(0)
29 self.dividends_and_long_term_gains = money(0)
30 self.roth_income = money(0)
32 def record_ordinary_income(self, amount):
33 assert amount >= 0, "Income should be non-negative"
34 self.ordinary_income += amount
35 self.total_ordinary_income += amount
37 def record_short_term_gain(self, amount):
38 assert amount >= 0, "Income should be non-negative"
39 self.short_term_gains += amount
40 self.total_short_term_gains += amount
42 def record_dividend_or_long_term_gain(self, amount):
43 assert amount >= 0, "Income should be non-negative"
44 self.dividends_and_long_term_gains += amount
45 self.total_dividends_and_long_term_gains += amount
47 def record_roth_income(self, amount):
48 assert amount >= 0, "Income should be non-negative"
49 self.roth_income += amount
50 self.total_roth_income += amount
52 def approximate_taxes(self,
54 ordinary_income_tax_brackets,
55 dividends_and_long_term_gains_brackets):
56 assert standard_deduction >= 0, "Standard deduction should be non-negative"
59 # Handle ordinary income:
60 ordinary_income = (self.ordinary_income +
61 self.short_term_gains -
63 if ordinary_income < 0:
64 ordinary_income = money(0)
65 taxes_due += ordinary_income_tax_brackets.compute_taxes_for_income(
68 # Handle dividends and long term gains:
69 taxes_due += dividends_and_long_term_gains_brackets.compute_taxes_for_income(
70 self.dividends_and_long_term_gains)
72 # Assume Roth money is still available tax free in the future.
73 assert taxes_due >= 0, "Computed negative taxes?!"
76 def how_many_more_dollars_can_we_earn_without_changing_tax_rate(
78 federal_ordinary_income_tax_brackets):
79 """Return number of ordinary income dollars we can make without
80 changing this year's tax rate. Note: this may return None
81 which actually indicates something more like 'infinite since
82 you're already at the top tax bracket.'"""
83 income = self.ordinary_income
84 if income <= 1: income = 2
85 b = federal_ordinary_income_tax_brackets.get_bracket_above_income(
92 def get_total_income(self):
93 return (self.ordinary_income +
94 self.short_term_gains +
95 self.dividends_and_long_term_gains +
98 def dump_final_report(self):
99 print " Taxes and income:"
100 print " {:<50}: {:>14}".format("Total aggregate income",
101 self.total_aggregate_income)
102 print " ...{:<47}: {:>14}".format("Ordinary income",
103 self.total_ordinary_income)
104 print " ...{:<47}: {:>14}".format("Income from short term gains",
105 self.total_short_term_gains)
106 print " ...{:<47}: {:>14}".format("Income from dividends and long term gains",
107 self.total_dividends_and_long_term_gains)
108 print " ...{:<47}: {:>14}".format("Roth income",
109 self.total_roth_income)
110 print " {:<50}: {:>14}".format("Total taxes paid",
112 overall_tax_rate = float(self.total_tax_bill) / float(self.total_aggregate_income)
113 print " {:<50}: {:>14}".format("Effective tax rate",
114 utils.format_rate(overall_tax_rate))