import utils class tax_collector(object): def __init__(self): # These four accumulate and then clear every year (i.e. every call # to record_taxes_paid_and_reset_for_next_year) self.ordinary_income = 0 self.short_term_gains = 0 self.dividends_and_long_term_gains = 0 self.roth_income = 0 # The rest of these aggregate and are used as part of the final stats. self.total_tax_bill = 0 self.total_ordinary_income = 0 self.total_short_term_gains = 0 self.total_dividends_and_long_term_gains = 0 self.total_roth_income = 0 self.total_aggregate_income = 0 def record_taxes_paid_and_reset_for_next_year(self, taxes_paid): self.total_tax_bill += taxes_paid self.total_aggregate_income += self.get_total_income() self.ordinary_income = 0 self.short_term_gains = 0 self.dividends_and_long_term_gains = 0 self.roth_income = 0 def record_ordinary_income(self, amount): self.ordinary_income += amount self.total_ordinary_income += amount def record_short_term_gain(self, amount): self.short_term_gains += amount self.total_short_term_gains += amount def record_dividend_or_long_term_gain(self, amount): self.dividends_and_long_term_gains += amount self.total_dividends_and_long_term_gains += amount def record_roth_income(self, amount): self.roth_income += amount self.total_roth_income += amount def approximate_taxes(self, standard_deduction, ordinary_income_tax_brackets, dividends_and_long_term_gains_brackets): taxes_due = 0 # Handle ordinary income: ordinary_income = (self.ordinary_income + self.short_term_gains - standard_deduction) if ordinary_income < 0: ordinary_income = 0 taxes_due += ordinary_income_tax_brackets.compute_taxes_for_income( ordinary_income) # Handle dividends and long term gains: taxes_due += dividends_and_long_term_gains_brackets.compute_taxes_for_income( self.dividends_and_long_term_gains) # Assume Roth money is still available tax free in the future. return taxes_due def how_many_more_dollars_can_we_earn_without_changing_tax_rate( self, federal_ordinary_income_tax_brackets): """Return number of ordinary income dollars we can make without changing this year's tax rate. Note: this may return None which actually indicates something more like 'infinite since you're already at the top tax bracket.'""" income = self.ordinary_income if income <= 1: income = 2 b = federal_ordinary_income_tax_brackets.get_bracket_above_income( income) if b[0] is not None: delta = b[0] - income return delta return 0 def get_total_income(self): return (self.ordinary_income + self.short_term_gains + self.dividends_and_long_term_gains + self.roth_income) def dump_final_report(self): print " Taxes and income:" print " {:<50}: {:>14}".format("Total aggregate income", utils.format_money(self.total_aggregate_income)) print " ...{:<47}: {:>14}".format("Ordinary income", utils.format_money(self.total_ordinary_income)) print " ...{:<47}: {:>14}".format("Income from short term gains", utils.format_money(self.total_short_term_gains)) print " ...{:<47}: {:>14}".format("Income from dividends and long term gains", utils.format_money(self.total_dividends_and_long_term_gains)) print " ...{:<47}: {:>14}".format("Roth income", utils.format_money(self.total_roth_income)) print " {:<50}: {:>14}".format("Total taxes paid", utils.format_money(self.total_tax_bill)) overall_tax_rate = float(self.total_tax_bill) / float(self.total_aggregate_income) print " {:<50}: {:>14}".format("Effective tax rate", utils.format_rate(overall_tax_rate))