Fix a couple of bugs. Make the simulation run 100x and halt if
authorScott Gasch <[email protected]>
Mon, 20 Jan 2020 01:07:28 +0000 (17:07 -0800)
committerScott Gasch <[email protected]>
Mon, 20 Jan 2020 01:07:28 +0000 (17:07 -0800)
it ever finds a scenario that causes it to run out of money.  Also
keep track of max net worth and display it in the final report.

accounts.py
retire.py
secrets.py
tax_brackets.py

index 0e53e045949ecd3708e00a8ac24054e48a113690..2ff804da8c30de0a29f15729c91d45f4b6045914 100644 (file)
@@ -120,7 +120,7 @@ class age_restricted_tax_deferred_account(account):
             taxes.record_ordinary_income(pretax_part)
 
     def deposit(self, amount):
-        self.pretax_part += amount
+        self.pretax += amount
 
     def appreciate(self, multiplier):
         old_pretax = self.pretax
index 578869b402e55b04ccfec4e1e7e1e72b20cf9265..fc68655dcd63e8b1c96187090317b152472483a6 100755 (executable)
--- a/retire.py
+++ b/retire.py
@@ -1,6 +1,7 @@
 #!/usr/local/bin/python
 
 import sys
+import traceback
 
 from accounts import *
 import constants
@@ -20,6 +21,7 @@ class simulation(object):
         self.scott_age = 0
         self.alex_age = 0
         self.year = 0
+        self.max_net_worth = 0
 
     def do_rmd_withdrawals(self, taxes):
         """Determine if any account that has RMDs will require someone to
@@ -129,12 +131,20 @@ class simulation(object):
             total += x.get_balance()
             print "{:<50}: {:>14}".format(x.get_name(), x.get_balance())
         print "{:<50}: {:>14}\n".format("TOTAL", total)
+        if self.max_net_worth < total:
+            self.max_net_worth = total
 
     def dump_final_report(self, taxes):
         print "\nAGGREGATE STATS FINAL REPORT:"
+        total = money(0)
         for x in self.accounts:
             x.dump_final_report()
+            total += x.get_balance()
         taxes.dump_final_report()
+        print "    {:<50}: {:>14}".format("Max net worth achieved",
+                                          self.max_net_worth)
+        print "==> {:<50}: {:>14}".format("Final net worth of simulation",
+                                          total)
 
     def run(self):
         """Run the simulation!"""
@@ -147,6 +157,7 @@ class simulation(object):
         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
@@ -201,7 +212,9 @@ class simulation(object):
                         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)
+                    tax_rate = 0.0
+                    if total_income > 0:
+                        tax_rate = float(taxes_due) / float(total_income)
 
                     if (look_for_conversions and
                         tax_rate <= 0.14 and
@@ -244,16 +257,31 @@ class simulation(object):
                     adjusted_lynn_annual_social_security_dollars *= ss_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)
+            succeeded = True
         except Exception as e:
             print "Exception: %s" % e
+            print traceback.print_exc(e)
             print "Ran out of money!?!"
+            succeeded = False
 
         finally:
             self.dump_final_report(taxes)
+            return succeeded
 
 # main
 #params = mutable_default_parameters()
-params = mutable_dynamic_historical_parameters()
-accounts = secrets.accounts
-s = simulation(params, accounts)
-s.run()
+
+params = None
+accounts = None
+s = None
+for x in xrange(1, 100):
+    del params
+    del accounts
+    del s
+    params = mutable_dynamic_historical_parameters()
+    accounts = secrets.get_starting_account_list()
+    s = simulation(params, accounts)
+    print "====================== Simulation %d ======================" % x
+    if s.run() == False:
+        print "This simulation failed!"
+        sys.exit(0)
index dba25241a6afc0b6651294bd4ba6e74eed943159..cedeec59c3479bb6fb28ab81af5cf704b2d725ed 100644 (file)
@@ -1,2 +1,4 @@
+import accounts
 
-accounts = [ <<< your accounts >>> ]
+def get_starting_account_list:
+    return [ <<< your accounts >>> ]
index e0a46607fcfa8e524945acc7d98f03c393c003c6..b2bd4a788298f58617bc83ae68ec27cc34b6a041 100644 (file)
@@ -1,3 +1,4 @@
+import copy
 import utils
 from money import money
 
@@ -5,7 +6,7 @@ class tax_brackets:
     """A class to represent tax brackets and some operations on them."""
 
     def __init__(self, brackets):
-        self.brackets = brackets
+        self.brackets = copy.deepcopy(brackets)
 
     def compute_taxes_for_income(self, income):
         """Compute the tax bill for income given our brackets."""