3 from tax_brackets import tax_brackets
4 from money import money
5 from numpy import random
7 class parameters(object):
8 def get_initial_annual_expenses(self):
11 def get_average_inflation_multiplier(self):
14 def get_average_social_security_multiplier(self):
17 def get_average_investment_return_multiplier(self):
20 def get_initial_social_security_age(self, person):
23 def get_initial_social_security_benefit(self, person):
26 def get_federal_standard_deduction(self):
29 def get_federal_ordinary_income_tax_brackets(self):
32 def get_federal_dividends_and_long_term_gains_income_tax_brackets(self):
38 def report_year(self, year):
41 class mutable_default_parameters(parameters):
42 """A container to hold the initial states of several simulation
43 parameters. Play with them as you see fit and see what happens."""
46 self.with_default_values()
48 def with_default_values(self):
49 # Annual expenses in USD at the start of the simulation. This
50 # will be adjusted upwards with inflation_multiplier every year.
51 self.initial_annual_expenses = money(144300)
53 # The average US inflation rate during the simulation. The
54 # Fed's target rate is 2.0% as of 2020. The long term observed
55 # average historical inflation rate in the US is 2.1%.
57 # Note this is a multiplier... so 1.0 would be no inflation,
58 # 1.21 is 2.1% inflation, 0.9 is deflation, etc...
59 self.inflation_multiplier = 1.03
61 # We want to be able to model social security payments not
62 # keeping pace with inflation. Like the inflation_multiplier
63 # above, this is a multiplier. It affect the magnitide of
64 # social security payments year over year.
65 self.social_security_multiplier = 1.02
67 # This is the average investment return rate. Asset allocation has
68 # a large effect on this as does the overall economy. That said,
69 # the US stock market has returned 10%/year over a large enough
70 # time window. Our investments at Fidelity have returned 6.91%
71 # in the lifetime they have been there. The expected return of a
72 # 50/50 stock/bond investment mix based on historical data is 8.3%.
73 self.investment_multiplier = 1.04
75 # The age at which each person will take social security
76 # benefits in this simulation and how much she will get the
77 # first year. Note, this benefit size increases year over
78 # year at social_security_multiplier. This is what the social
79 # security website estimates if we both earn $0 from 2020 on:
81 # Lynn's benefits: Scott's benefits:
82 # age 62 - $21,120 age 62 - $21,420
83 # age 67 - $30,000 age 67 - $30,420
84 # age 70 - $37,200 age 70 - $37,728
87 self.social_security_age = [0, 62, 62 ]
88 self.initial_social_security_dollars = [0, money(21000), money(21000) ]
90 # Tax details... the standard deduction amount and tax
91 # brackets for ordinary income and long term capital gains.
92 self.federal_standard_deduction_dollars = 24800
93 self.federal_ordinary_income_tax_brackets = tax_brackets(
94 constants.PESSIMISTIC_FEDERAL_INCOME_TAX_BRACKETS)
95 self.federal_dividends_and_long_term_gains_brackets = tax_brackets(
96 constants.CURRENT_LONG_TERM_GAIN_FEDERAL_TAX_BRACKETS)
99 def set_initial_annual_expenses(self, expenses):
100 assert expenses >= 0, "You can't have negative expenses"
101 self.initial_annual_expenses = expenses
104 def get_initial_annual_expenses(self):
105 return self.initial_annual_expenses
107 def set_average_inflation_multiplier(self, multiplier):
108 self.inflation_multiplier = multiplier
111 def get_average_inflation_multiplier(self):
112 return self.inflation_multiplier
114 def set_average_social_security_multiplier(self, multiplier):
115 self.social_security_multiplier = multiplier
118 def get_average_social_security_multiplier(self):
119 return self.social_security_multiplier
121 def set_average_investment_return_multiplier(self, multiplier):
122 self.investment_multiplier = multiplier
125 def get_average_investment_return_multiplier(self):
126 return self.investment_multiplier
128 def set_initial_social_security_age_and_benefits(self,
132 assert age >= 60 and age <= 70, "age should be between 60 and 70"
133 self.social_security_age[person] = age
134 assert amount >= 0, "Social security won't pay negative dollars"
135 self.initial_social_security_dollars[person] = amount
138 def get_initial_social_security_age(self, person):
139 return self.social_security_age[person]
141 def get_initial_social_security_benefit(self, person):
142 return self.initial_social_security_dollars[person]
144 def set_federal_standard_deduction(self, deduction):
145 assert deduction >= 0, "Standard deduction should be non-negative"
146 self.federal_standard_deduction_dollars = deduction
149 def get_federal_standard_deduction(self):
150 return self.federal_standard_deduction_dollars
152 def set_federal_ordinary_income_tax_brackets(self, brackets):
153 self.federal_ordinary_income_tax_brackets = brackets
156 def get_federal_ordinary_income_tax_brackets(self):
157 return self.federal_ordinary_income_tax_brackets
159 def set_federal_dividends_and_long_term_gains_income_tax_brackets(self,
161 self.federal_dividends_and_long_term_gains_brackets = brackets;
164 def get_federal_dividends_and_long_term_gains_income_tax_brackets(self):
165 return self.federal_dividends_and_long_term_gains_brackets
168 print "SIMULATION PARAMETERS"
169 print " {:<50}: {:>14}".format("Initial year annual expenses",
170 self.initial_annual_expenses)
171 print " {:<50}: {:>14}".format("Annual inflation rate",
172 utils.format_rate(self.inflation_multiplier))
173 print " {:<50}: {:>14}".format("Average annual investment return rate",
174 utils.format_rate(self.investment_multiplier))
175 print " {:<50}: {:>14}".format("Annual social security benefit increase rate",
176 utils.format_rate(self.social_security_multiplier))
177 print " {:<50}: {:>14}".format("Age at which Lynn takes social security",
178 self.social_security_age[constants.LYNN])
179 print " {:<50}: {:>14}".format("Lynn's first year social security benefit",
180 self.initial_social_security_dollars[constants.LYNN])
181 print " {:<50}: {:>14}".format("Age at which Scott takes social security",
182 self.social_security_age[constants.SCOTT])
183 print " {:<50}: {:>14}".format("Scott's first year social security benefit",
184 self.initial_social_security_dollars[constants.SCOTT])
185 print " Federal tax brackets ["
186 self.federal_ordinary_income_tax_brackets.dump()
189 print " Federal dividend and long term gain brackets ["
190 self.federal_dividends_and_long_term_gains_brackets.dump()
192 print " We assume Roth money continues to be available tax-free."
194 class mutable_dynamic_historical_parameters(mutable_default_parameters):
196 self.selection_index = None
197 self.selection_duration = 0
198 self.historical_tuples = [
199 # year stock infl bond
200 (2020, 3.14, 1.90, 1.54),
201 (2019, 31.49, 1.70, 2.15),
202 (2018, -4.38, 2.40, 2.33),
203 (2017, 21.83, 2.10, 1.19),
204 (2016, 11.96, 1.30, 0.61),
205 (2015, 1.38, 0.10, 0.32),
206 (2014, 13.69, 1.60, 0.12),
207 (2013, 32.39, 1.50, 0.13),
208 (2012, 16.00, 2.10, 0.17),
209 (2011, 2.11, 3.20, 0.18),
210 (2010, 15.06, 1.60, 0.32),
211 (2009, 26.46, -0.40, 0.47),
212 (2008,-37.00, 3.80, 1.83),
213 (2007, 5.49, 2.80, 4.53),
214 (2006, 15.79, 3.20, 4.94),
215 (2005, 4.91, 3.40, 3.62),
216 (2004, 10.88, 2.70, 1.89),
217 (2003, 28.68, 2.30, 1.24),
218 (2002,-22.10, 1.60, 2.00),
219 (2001,-11.89, 2.80, 3.49),
220 (2000, -9.10, 3.40, 6.11),
221 (1999, 21.04, 2.20, 5.08),
222 (1998, 28.58, 1.50, 5.05),
223 (1997, 33.36, 2.30, 5.63),
224 (1996, 22.96, 3.00, 5.52),
225 (1995, 37.58, 2.80, 5.94),
226 (1994, 1.32, 2.60, 5.32),
227 (1993, 10.08, 3.00, 3.43),
228 (1992, 7.62, 3.00, 3.89),
229 (1991, 30.47, 4.20, 5.86),
230 (1990, -3.10, 5.40, 7.89),
231 (1989, 31.69, 4.82, 8.54),
232 (1988, 16.61, 4.14, 7.65),
233 (1987, 15.25, 3.65, 6.77),
234 (1986, 18.67, 0.86, 6.45),
235 (1985, 31.73, 3.56, 8.42),
236 (1984, 6.27, 4.32, 10.91),
237 (1983, 22.56, 3.21, 9.58),
238 (1982, 21.55, 6.16, 12.27),
239 (1981, -4.91, 10.32, 14.80),
240 (1980, 32.42, 13.50, 12.00),
241 (1979, 18.44, 11.35, 10.65),
242 (1978, 6.65, 7.59, 7.00),
243 (1977, -7.18, 6.50, 6.08),
244 (1976, 23.84, 5.76, 5.88),
245 (1975, 37.20, 9.13, 6.78),
246 (1974,-26.47, 11.04, 8.20),
247 (1973,-14.66, 6.22, 7.32),
248 (1972, 18.90, 3.21, 4.95),
249 (1971, 14.31, 4.38, 4.89),
250 (1970, 14.01, 5.72, 6.90),
251 (1969, -8.50, 5.46, 7.12),
252 (1968, 11.06, 4.19, 5.69),
253 (1967, 23.98, 3.09, 4.88),
254 (1966,-10.06, 2.86, 5.20),
255 (1965, 12.45, 1.61, 4.15),
256 (1964, 16.48, 1.31, 3.85),
257 (1963, 22.80, 1.32, 3.36),
258 (1962, -8.73, 1.00, 2.90),
259 (1961, 26.89, 1.01, 2.60),
260 (1960, 0.47, 1.72, 3.24),
261 (1959, 11.96, 0.69, 3.83),
262 (1958, 43.36, 2.85, 3.5),
263 (1957,-10.78, 3.31, 3.6),
264 (1956, 6.56, 1.49, 2.9),
265 (1955, 31.56, -0.37, 2.5),
266 (1954, 52.62, 0.75, 2.37),
267 (1953, -0.99, 0.75, 2.71),
268 (1952, 18.37, 1.92, 2.19),
269 (1951, 24.02, 7.88, 2.00),
270 (1950, 31.71, 1.26, 1.98),
271 (1949, 18.79, -1.24, 2.21),
272 (1948, 5.50, 8.07, 2.40),
273 (1947, 5.71, 14.36, 2.01),
274 (1946, -8.07, 8.33, 1.64),
275 (1945, 36.44, 2.27, 1.67),
276 (1944, 19.75, 1.73, 1.86),
277 (1943, 25.90, 6.13, 2.05),
278 (1942, 20.34, 10.88, 2.36),
279 (1941,-11.59, 5.00, 2.10),
280 (1940, -9.78, 0.72, 2.76),
281 (1939, -0.41, -1.42, 2.76),
282 (1938, 31.12, -2.08, 2.94),
283 (1937,-35.03, 3.60, 2.76),
284 (1936, 33.92, 1.46, 3.39),
285 (1935, 47.67, 2.24, 2.76),
286 (1934, -1.44, 3.08, 2.76),
287 (1933, 53.99, -5.11, 4.71),
288 (1932, -8.19, -9.87, 4.71),
289 (1931,-43.34, -8.90, 3.99),
290 (1930,-24.90, -2.34, 4.71),
291 (1929, -8.42, 0.00, 4.27) ]
292 mutable_default_parameters.__init__(self)
294 def report_year(self, year):
295 if self.selection_index is None:
296 self.selection_index = random.randint(0,
297 len(self.historical_tuples) - 1)
298 self.selection_duration = 1
300 t = self.historical_tuples[self.selection_index]
306 print "## REPLAY YEAR %d" % sim_year
307 inflation_multiplier = utils.convert_rate_to_multiplier(inflation)
308 self.set_average_inflation_multiplier(inflation_multiplier)
309 print "## INFLATION is %s (%f)" % (
310 utils.format_rate(inflation_multiplier),
311 inflation_multiplier)
312 ss_multiplier = inflation_multiplier
313 if ss_multiplier >= 1.0:
315 ss_multiplier *= 0.6666
317 self.set_average_social_security_multiplier(ss_multiplier)
318 print "## SS is %s (%f)" % (
319 utils.format_rate(self.get_average_social_security_multiplier()),
322 # Assumes 50/50 Stocks/Bonds portfolio
323 our_return = (stock_return * 0.5 +
325 self.set_average_investment_return_multiplier(utils.convert_rate_to_multiplier(our_return))
326 print "## 50/50 INVESTMENTS RETURN is %s" % utils.format_rate(self.get_average_investment_return_multiplier())
327 self.selection_duration += 1
328 self.selection_index -= 1
329 if self.selection_index < 0 or random.randint(1, 100) < 20:
330 self.selection_index = None
331 self.selection_duration = None