adjusted_lynn_annual_social_security_dollars = (
self.params.get_initial_social_security_benefit(constants.LYNN))
-# try:
- for self.year in xrange(2020, 2080):
- self.scott_age = self.year - 1974
- self.lynn_age = self.year - 1964
- self.alex_age = self.year - 2005
-
- # Computed money needed this year based on inflated budget.
- money_needed = adjusted_annual_expenses
-
- # When Alex is in college, we need $50K more per year.
- if self.alex_age > 18 and self.alex_age <= 22:
- money_needed += 50000
-
- self.dump_annual_header(money_needed)
-
- # Now, figure out how to find money to pay for this year
- # and how much of it is taxable.
- total_income = 0
-
- # When we reach a certain age we have to take RMDs from
- # some accounts. Handle that here.
- rmds = self.do_rmd_withdrawals(taxes)
- if rmds > 0:
- print "## Satisfied %s of RMDs from age-restricted accounts." % utils.format_money(rmds)
- total_income += rmds
- money_needed -= rmds
-
- # When we reach a certain age we are eligible for SS
- # payments.
- ss = self.get_social_security(adjusted_scott_annual_social_security_dollars,
- adjusted_lynn_annual_social_security_dollars,
- taxes)
- if ss > 0:
- print "## Social security paid %s" % utils.format_money(ss)
- total_income += ss
- money_needed -= ss
-
- # If we still need money, try to go find it.
- if money_needed > 0:
- self.go_find_money(money_needed, taxes)
- total_income += money_needed
- money_needed = 0
-
- look_for_conversions = True
- while True:
- # Maybe do some opportunistic Roth conversions.
- taxes_due = taxes.approximate_taxes(
- self.params.get_federal_standard_deduction(),
- self.params.get_federal_ordinary_income_tax_brackets(),
- self.params.get_federal_dividends_and_long_term_gains_income_tax_brackets())
- total_income = taxes.get_total_income()
- tax_rate = float(taxes_due) / float(total_income)
- print "INCOME: %s, TAXES: %s\n" % (utils.format_money(total_income), utils.format_money(taxes_due))
-
- if (look_for_conversions and
- tax_rate <= 0.14 and
- taxes_due < 20000 and
- self.year <= 2035):
-
- look_for_conversions = self.do_opportunistic_roth_conversions(taxes)
- # because these conversions affect taxes, spin
- # once more in the loop and recompute taxes
- # due and tax rate.
+ try:
+ for self.year in xrange(2020, 2080):
+ self.scott_age = self.year - 1974
+ self.lynn_age = self.year - 1964
+ self.alex_age = self.year - 2005
+
+ # Computed money needed this year based on inflated budget.
+ money_needed = adjusted_annual_expenses
+
+ # When Alex is in college, we need $50K more per year.
+ if self.alex_age > 18 and self.alex_age <= 22:
+ money_needed += 50000
+
+ self.dump_annual_header(money_needed)
+
+ # Now, figure out how to find money to pay for this year
+ # and how much of it is taxable.
+ total_income = 0
+
+ # When we reach a certain age we have to take RMDs from
+ # some accounts. Handle that here.
+ rmds = self.do_rmd_withdrawals(taxes)
+ if rmds > 0:
+ print "## Satisfied %s of RMDs from age-restricted accounts." % utils.format_money(rmds)
+ total_income += rmds
+ money_needed -= rmds
+
+ # When we reach a certain age we are eligible for SS
+ # payments.
+ ss = self.get_social_security(adjusted_scott_annual_social_security_dollars,
+ adjusted_lynn_annual_social_security_dollars,
+ taxes)
+ if ss > 0:
+ print "## Social security paid %s" % utils.format_money(ss)
+ total_income += ss
+ money_needed -= ss
+
+ # If we still need money, try to go find it.
+ if money_needed > 0:
+ self.go_find_money(money_needed, taxes)
+ total_income += money_needed
+ money_needed = 0
+
+ look_for_conversions = True
+ while True:
+ # Maybe do some opportunistic Roth conversions.
+ taxes_due = taxes.approximate_taxes(
+ self.params.get_federal_standard_deduction(),
+ self.params.get_federal_ordinary_income_tax_brackets(),
+ self.params.get_federal_dividends_and_long_term_gains_income_tax_brackets())
+ total_income = taxes.get_total_income()
+ tax_rate = float(taxes_due) / float(total_income)
+ print "INCOME: %s, TAXES: %s\n" % (utils.format_money(total_income), utils.format_money(taxes_due))
+
+ if (look_for_conversions and
+ tax_rate <= 0.14 and
+ taxes_due < 20000 and
+ self.year <= 2035):
+
+ look_for_conversions = self.do_opportunistic_roth_conversions(taxes)
+ # because these conversions affect taxes, spin
+ # once more in the loop and recompute taxes
+ # due and tax rate.
+ else:
+ break
+
+ # Pay taxes_due by going to find more money. This is a
+ # bit hacky since withdrawing more money to cover taxes
+ # will, in turn, cause taxable income. But I think taxes
+ # are low enough and this simulation is rough enough that
+ # we can ignore this.
+ if taxes_due > 0:
+ print "## Estimated federal tax due: %s (this year's tax rate=%s)" % (
+ utils.format_money(taxes_due),
+ utils.format_rate(tax_rate))
+ self.go_find_money(taxes_due, taxes)
else:
- break
-
- # Pay taxes_due by going to find more money. This is a
- # bit hacky since withdrawing more money to cover taxes
- # will, in turn, cause taxable income. But I think taxes
- # are low enough and this simulation is rough enough that
- # we can ignore this.
- if taxes_due > 0:
- print "## Estimated federal tax due: %s (this year's tax rate=%s)" % (
- utils.format_money(taxes_due),
- utils.format_rate(tax_rate))
- self.go_find_money(taxes_due, taxes)
- else:
- print "## No federal taxes due this year!"
- taxes.record_taxes_paid_and_reset_for_next_year(taxes_due)
-
- # Inflation and appreciation:
- # * Cost of living increases
- # * Social security benefits increase
- # * Tax brackets are adjusted for inflation
- inflation_multiplier = self.params.get_average_inflation_multiplier()
- adjusted_annual_expenses *= inflation_multiplier
- for x in self.accounts:
- x.appreciate(self.params.get_average_investment_return_multiplier())
- if self.scott_age >= self.params.get_initial_social_security_age(constants.SCOTT):
- adjusted_scott_annual_social_security_dollars *= self.params.get_average_social_security_multiplier()
- if self.lynn_age >= self.params.get_initial_social_security_age(constants.LYNN):
- adjusted_lynn_annual_social_security_dollars *= self.params.get_average_social_security_multiplier()
-
- self.params.get_federal_ordinary_income_tax_brackets().adjust_with_multiplier(inflation_multiplier)
- self.params.get_federal_dividends_and_long_term_gains_income_tax_brackets().adjust_with_multiplier(inflation_multiplier)
-# except:
-# print "Ran out of money!!!"
-# pass
-
-# finally:
- self.dump_final_report(taxes)
+ print "## No federal taxes due this year!"
+ taxes.record_taxes_paid_and_reset_for_next_year(taxes_due)
+
+ # Inflation and appreciation:
+ # * Cost of living increases
+ # * Social security benefits increase
+ # * Tax brackets are adjusted for inflation
+ inflation_multiplier = self.params.get_average_inflation_multiplier()
+ adjusted_annual_expenses *= inflation_multiplier
+ for x in self.accounts:
+ x.appreciate(self.params.get_average_investment_return_multiplier())
+ if self.scott_age >= self.params.get_initial_social_security_age(constants.SCOTT):
+ adjusted_scott_annual_social_security_dollars *= self.params.get_average_social_security_multiplier()
+ if self.lynn_age >= self.params.get_initial_social_security_age(constants.LYNN):
+ adjusted_lynn_annual_social_security_dollars *= self.params.get_average_social_security_multiplier()
+
+ self.params.get_federal_ordinary_income_tax_brackets().adjust_with_multiplier(inflation_multiplier)
+ self.params.get_federal_dividends_and_long_term_gains_income_tax_brackets().adjust_with_multiplier(inflation_multiplier)
+ except:
+ print "Ran out of money!!!"
+ pass
+
+ finally:
+ self.dump_final_report(taxes)
# main
params = parameters().with_default_values()
def record_taxes_paid_and_reset_for_next_year(self,
taxes_paid):
+ assert taxes_paid >= 0, "You can't pay negative taxes"
self.total_tax_bill += taxes_paid
self.total_aggregate_income += self.get_total_income()
+ assert self.total_aggregate_income >= 0, "Accumulator should be >= 0"
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):
+ assert amount >= 0, "Income should be non-negative"
self.ordinary_income += amount
self.total_ordinary_income += amount
def record_short_term_gain(self, amount):
+ assert amount >= 0, "Income should be non-negative"
self.short_term_gains += amount
self.total_short_term_gains += amount
def record_dividend_or_long_term_gain(self, amount):
+ assert amount >= 0, "Income should be non-negative"
self.dividends_and_long_term_gains += amount
self.total_dividends_and_long_term_gains += amount
def record_roth_income(self, amount):
+ assert amount >= 0, "Income should be non-negative"
self.roth_income += amount
self.total_roth_income += amount
standard_deduction,
ordinary_income_tax_brackets,
dividends_and_long_term_gains_brackets):
+ assert standard_deduction >= 0, "Standard deduction should be non-negative"
taxes_due = 0
# Handle ordinary income:
self.dividends_and_long_term_gains)
# Assume Roth money is still available tax free in the future.
+ assert taxes_due >= 0, "Computed negative taxes?!"
return taxes_due
def how_many_more_dollars_can_we_earn_without_changing_tax_rate(