Beispiel #1
0
 def test_toml_input_retiree_info(self):
     toml_file_name = 't.toml'
     tf = working_toml_file(toml_file_name)
     taxinfo = tif.taxinfo()
     S = tomldata.Data(taxinfo)
     S.load_toml_file(toml_file_name)
     S.process_toml_info()
Beispiel #2
0
 def test_toml_input_load_rmd_needed(self):
     toml_file_name = 't.toml'
     tf = working_toml_file(toml_file_name)
     taxinfo = tif.taxinfo()
     S = tomldata.Data(taxinfo)
     #S = tomldata.Data()
     S.load_toml_file(toml_file_name)
     S.process_toml_info()
     # toml has age 56, retire 58, through 72 primary so ageAtStart 58 (retire age)
     retiree1 = 'will'
     retiree2 = 'spouse'  # toml has age 54, retire 60, through 75 secondary so ageAtStart 56
     retireeNot = 'joe'
     rmd = S.rmd_needed(69 - 58, retiree1)
     self.assertEqual(
         rmd, 0, msg='At age 69 there should be no RMD (i.e., zero)')
     rmd = S.rmd_needed(70 - 58, retiree1)
     self.assertGreater(
         rmd, 0, msg='At age 70, RMD should be the IRS life expectancy')
     rmd = S.rmd_needed(69 - 56, retiree2)
     self.assertEqual(
         rmd, 0, msg='At age 69 there should be no RMD (i.e., zero)')
     rmd = S.rmd_needed(70 - 56, retiree2)
     self.assertGreater(
         rmd, 0, msg='At age 70, RMD should be the IRS life expectancy')
     rmd = S.rmd_needed(69 - 56, retireeNot)
     self.assertEqual(
         rmd, 0, msg='Non-valid Retiree should alway return rmd 0')
Beispiel #3
0
 def lp_constraint_model_load_default_toml(self):
     toml_file_name = 'self_temp_toml.toml'
     tf = working_toml_file(toml_file_name)
     self.taxinfo = tif.taxinfo()
     S = tomldata.Data(self.taxinfo)
     #S = tomldata.Data()
     S.load_toml_file(toml_file_name)
     S.process_toml_info()
     return S
Beispiel #4
0
 def test_toml_input_load_load_toml_file_to_match_crator_string(self):
     toml_file_name = 't.toml'
     tf = working_toml_file(toml_file_name)
     taxinfo = tif.taxinfo()
     S = tomldata.Data(taxinfo)
     S.load_toml_file(toml_file_name)
     s1 = tf.tomls.lstrip().rstrip()
     s2 = toml.dumps(S.toml_dict).rstrip()
     self.assertEqual(s1, s2)
Beispiel #5
0
 def test_toml_input_load_update_dictionary(self):
     toml_file_name = 't.toml'
     skipfilewrite = True
     tf = working_toml_file(toml_file_name, skipfilewrite)
     dict =tf.toml_dict()
     dict['retirement_type'] = 'single'
     tf.toml_dict(dict) # update tf.tomls
     tf.write_working_toml_file(tf.tomls)
     taxinfo = tif.taxinfo()
     S = tomldata.Data(taxinfo)
     S.load_toml_file(toml_file_name)
     S.process_toml_info()
     self.assertEqual(S.retirement_type, 'single', msg='Explicitly setting retirement_type to single so it should match')
Beispiel #6
0
 def test_toml_input_load_missing_toml_file_will_fail(self):
     toml_file_name = 't.toml'
     # Since the next two lines stops the toml file from 
     # being written in the background it must be explicitly
     # written or will not exist as in this test.
     skipfilewrite = True
     tf = working_toml_file(toml_file_name, skipfilewrite)
     taxinfo = tif.taxinfo()
     S = tomldata.Data(taxinfo)
     expect_exception = FileNotFoundError(2,'No such file or directory: \'t.toml\'')
     with self.assertRaises(OSError) as cm:
         S.load_toml_file(toml_file_name) #This should fail
     self.assertEqual(str(cm.exception), str(expect_exception))
Beispiel #7
0
 def test_toml_input_account_owner_age(self):
     toml_file_name = 't.toml'
     tf = working_toml_file(toml_file_name)
     taxinfo = tif.taxinfo()
     S = tomldata.Data(taxinfo)
     #S = tomldata.Data()
     S.load_toml_file(toml_file_name)
     S.process_toml_info()
     for account in S.accounttable:
         if account['acctype'] != 'aftertax':
             year = 59 - 58  # age - start of plan age for will
             if account['mykey'] != 'will':
                 year = 59 - 56  # age - start of plan age for spouse
             a = S.account_owner_age(year, account)
             self.assertEqual(
                 a, 59, msg='At age 59 account_owner_age() should be 59')
Beispiel #8
0
 def test_toml_input_do_ss_details(self):
     toml_file_name = 't.toml'
     tf = working_toml_file(toml_file_name)
     taxinfo = tif.taxinfo()
     S = tomldata.Data(taxinfo)
     S.load_toml_file(toml_file_name)
     S.process_toml_info()
     # [iam.will] primary = true, age = 56, retire = 58, through = 72
     # [SocialSecurity.will] amount = 31000 FRA = 67 age = "68-"
     # [iam.spouse] primary = false, age = 54, retire = 60, through = 75
     # [SocialSecurity.spouse] amount = 21000 FRA = 67 age = "70-"
     # => let's check the SS when spouse is 70 and will is 72 ->SS[72-58]
     willcontrib = (31000 * (1.08**(68 - 67))) * 1.025**(72 - 56)
     spousecontrib = (21000 * (1.08**(70 - 67))) * 1.025**(70 - 54)
     expect = willcontrib + spousecontrib
     self.assertEqual(S.SS[72 - 58], expect)
Beispiel #9
0
 def test_toml_input_match_retiree(self):
     toml_file_name = 't.toml'
     tf = working_toml_file(toml_file_name)
     taxinfo = tif.taxinfo()
     S = tomldata.Data(taxinfo)
     #S = tomldata.Data()
     S.load_toml_file(toml_file_name)
     S.process_toml_info()
     retiree1 = 'will'
     retiree2 = 'spouse'
     retireeNot = 'joe'
     v = S.match_retiree(retiree1)
     self.assertEqual(v['mykey'], retiree1)
     v = S.match_retiree(retiree2)
     self.assertEqual(v['mykey'], retiree2)
     v = S.match_retiree(retireeNot)
     self.assertEqual(v, None)
Beispiel #10
0
 def test_toml_input_start_amount(self):
     S = tomldata.Data(None)
     amount = 12000
     fra = 67
     start = 62
     a = S.startamount(amount, fra, start)
     b = amount / (1.067**(fra - start))
     self.assertEqual(a, b)
     start = 70
     a = S.startamount(amount, fra, start)
     b = amount * (1.08**(start - fra))
     self.assertEqual(a, b)
     start = fra
     a = S.startamount(amount, fra, start)
     self.assertEqual(a, amount)
     start = 61  # test 61 and should fail too young
     a = S.startamount(amount, fra, start)
     # will not go to 61, 62 is lower bound
     b = amount / (1.067**(fra - 62))
     self.assertEqual(a, b)
Beispiel #11
0
 def test_toml_input_do_details(self):
     toml_file_name = 't.toml'
     tf = working_toml_file(toml_file_name)
     taxinfo = tif.taxinfo()
     S = tomldata.Data(taxinfo)
     S.load_toml_file(toml_file_name)
     S.process_toml_info()
     #[income.mytaxfree] amount = 3000 age = "56-" inflation = false tax = false
     #[income.rental_1] amount = 36000 age = "67-" inflation = true tax = true
     #[income.rental_2] amount = 2400 age = "67-" inflation = true tax = true
     # => let's check the INC when will is 65->INC[65-58] and 68->INC[68-58]
     self.assertEqual(
         S.income[65 - 58], 3300, msg='No Inflation so should equal configured amount')
     self.assertEqual(
         S.taxed[65 - 58], 300, msg='income.mytaxfree is not taxed but stopgap is so 300')
     expect = 3300 + (36000 + 2400) * 1.025**(68 - 56)
     taxexpect = expect - 3000
     self.assertEqual(
         S.income[68 - 58], expect, msg='Sum of mytaxfree and inflation adjusted rental_1 and rental_2')
     self.assertEqual(
         S.taxed[68 - 58], taxexpect, msg='Same as income minus mytaxfee')
Beispiel #12
0
 def test_toml_input_account_info(self):
     toml_file_name = 't.toml'
     tf = working_toml_file(toml_file_name)
     taxinfo = tif.taxinfo()
     S = tomldata.Data(taxinfo)
     #S = tomldata.Data()
     S.load_toml_file(toml_file_name)
     S.process_toml_info()
     # tmol Accounts
     # IRA.will    bal=2,000,000 contrib=100 inflation=true period=56-65 {inflation applies to contrib}
     # IRA.spouse  bal=200,000   contrib=0   inflation=false period=
     # Roth.spouse bal=100,000   contrib=0   inflation=false period=
     # aftertax    bal=700,000   contrib=10  inflation=false period=56-65
     # Plan period 58-73, age will 56 age spouse 54
     for acc in S.accounttable:
         origbal = acc['origbal']
         bal = acc['bal']
         mykey = acc['mykey']
         acctype = acc['acctype']
         if (acctype == 'IRA' or acctype == 'roth') and mykey == 'spouse':
             self.assertEqual(bal, origbal * S.r_rate**(58 - 56),
                              msg='Rate of return till plan start, no contributions')
         elif mykey == 'will' or mykey == 'nokey':
             calcb = origbal * S.r_rate**(58 - 56)
             contrib = acc['contrib']
             p = contrib * (S.r_rate**(58 - 56) - 1) * \
                 (1 + (1 / (S.r_rate - 1)))
             pwicontrib = (contrib * (1 - (S.r_rate * S.i_rate) **
                                      (60 - 58)) / (1 - S.r_rate * S.i_rate)) * (S.r_rate)
             age60contrib = acc['contributions'][60 - 58]
             if acc['inflation'] == False:
                 self.assertEqual(
                     bal, calcb + p, msg='Rate of return and contributions till plan start')
                 self.assertEqual(
                     contrib, age60contrib, msg='No inflation so all contrib values should match')
             else:
                 self.assertEqual(round(bal, 0), round(
                     calcb + pwicontrib, 0), msg='Rate of return and inflating contributions till plan start')
                 self.assertEqual(contrib * S.i_rate**(60 - 56), age60contrib,
                                  msg='Inflation so contrib values should increase each year with inflation')
Beispiel #13
0
    def test_input_through_solver_joint_first_year_spinding(self):
        toml_file_name = 't.toml'
        skipfilewrite = True
        tf = working_toml_file(toml_file_name, skipfilewrite)
        dict =tf.toml_dict()
        dict['retirement_type'] = 'joint'
        tf.toml_dict(dict) # update tf.tomls
        tf.write_working_toml_file(tf.tomls)
        taxinfo = tif.taxinfo()
        S = tomldata.Data(taxinfo)
        S.load_toml_file(toml_file_name)
        S.process_toml_info()

        years = S.numyr
        taxbins = len(taxinfo.taxtable)
        cgbins = len(taxinfo.capgainstable)
        accounts = len(S.accounttable)
        verbose = False
        disallowdeposits = False
        vindx = v.vector_var_index(years, taxbins, cgbins, accounts, S.accmap)
        lp = lpclass.lp_constraint_model(S, vindx, taxinfo.taxtable,
                                        taxinfo.capgainstable,
                                        taxinfo.penalty, 
                                        taxinfo.stded,
                                        taxinfo.SS_taxable, 
                                        verbose, 
                                        disallowdeposits)
        c, A, b = lp.build_model()

        res = scipy.optimize.linprog(c, A_ub=A, b_ub=b,
                                     options={"disp": verbose,
                                              #"bland": True,
                                              "tol": 1.0e-7,
                                              "maxiter": 3000})
        self.assertTrue(res.success, msg='res.success indicates solver failed')
        # If we get this far test the output
        year = 0
        verifiedSolverResult = 220896.0970
        latestSolverResult = res.x[vindx.s(year)]
        self.assertEqual(round(latestSolverResult,3), round(verifiedSolverResult,3), msg='Verified solver result is ${:0_.3f} but here we got ${:0_.3f}'.format(verifiedSolverResult, latestSolverResult))
Beispiel #14
0
 def test_toml_input_check_record(self):
     taxinfo = tif.taxinfo()
     S = tomldata.Data(taxinfo)
     #S = tomldata.Data()
     orig = {'aftertax': {'bal': 700000, 'basis': 400000,
                          'contrib': 10, 'period': '56-65'}}
     to = {'aftertax': {'nokey': {'bal': 700000,
                                  'basis': 400000, 'contrib': 10, 'period': '56-65'}}}
     d = json.loads(json.dumps(orig))  # thread safe deep copy
     S.check_record(d, 'aftertax', ('bal', 'rate', 'contrib',
                                    'inflation', 'period', 'basis'))
     # Do a deep compare:
     self.assertEqual(pickle.dumps(to), pickle.dumps(
         d), msg='dictionary should be transformed')
     orig = {}
     to = {}
     d = json.loads(json.dumps(orig))  # thread safe deep copy
     S.check_record(d, 'aftertax', ('bal', 'rate', 'contrib',
                                    'inflation', 'period', 'basis'))
     # Do a deep compare:
     self.assertEqual(pickle.dumps(to), pickle.dumps(
         d), msg='{} dictionary should remain {}')
Beispiel #15
0
 def test_toml_input_maxcontribution(self):
     toml_file_name = 't.toml'
     tf = working_toml_file(toml_file_name)
     taxinfo = tif.taxinfo()
     S = tomldata.Data(taxinfo)
     #S = tomldata.Data()
     S.load_toml_file(toml_file_name)
     S.process_toml_info()
     # toml has age 56, retire 58, through 72 primary so ageAtStart 58 (retire age)
     retiree1 = 'will'
     retiree2 = 'spouse'  # toml has age 54, retire 60, through 75 secondary so ageAtStart 56
     retireeNot = 'joe'
     retireeNone = None
     year = 1
     m = S.maxContribution(year, retiree1)
     self.assertEqual(m, (taxinfo.contribspecs['TDRA'] + taxinfo.contribspecs['TDRACatchup'])
                      * S.i_rate**year, msg='TDRA+RothRA contribution plus catchup')
     m = S.maxContribution(year, retireeNot)
     self.assertEqual(m, 0, msg='zero if non-existant retiree')
     m = S.maxContribution(year, retireeNone)
     self.assertEqual(m, 2 * (taxinfo.contribspecs['TDRA'] + taxinfo.contribspecs['TDRACatchup'])
                      * S.i_rate**year, msg='TDRA+RothRA contribution plus catchup for both Retirees')
Beispiel #16
0
 def test_toml_input_apply_early_penalty(self):
     toml_file_name = 't.toml'
     tf = working_toml_file(toml_file_name)
     taxinfo = tif.taxinfo()
     S = tomldata.Data(taxinfo)
     #S = tomldata.Data()
     S.load_toml_file(toml_file_name)
     S.process_toml_info()
     # toml has age 56, retire 58, through 72 primary so ageAtStart 58 (retire age)
     retiree1 = 'will'
     retiree2 = 'spouse'  # toml has age 54, retire 60, through 75 secondary so ageAtStart 56
     retireeNot = 'joe'
     p = S.apply_early_penalty(59 - 58, retiree1)
     self.assertTrue(
         p, msg='At age 59 an early penalty is require, unless...')
     p = S.apply_early_penalty(60 - 58, retiree1)
     self.assertFalse(p, msg='At age 60 no early penalty is require')
     p = S.apply_early_penalty(59 - 56, retiree2)
     self.assertTrue(
         p, msg='At age 59 an early penalty is require, unless...')
     p = S.apply_early_penalty(60 - 56, retiree2)
     self.assertFalse(p, msg='At age 60 no early penalty is require')
     p = S.apply_early_penalty(59 - 56, retireeNot)
     self.assertFalse(p, msg='A non-existant retiree should return false')
Beispiel #17
0
                        help='Require configuration input toml file')
    args = parser.parse_args()

    if args.alltables:
        args.verboseaccounttrans = True
        args.verboseincome = True
        args.verbosetax = True
        args.verbosetaxbrackets = True

    csv_file_name = None
    if args.csv != '':
        csv_file_name = args.csv
    ao = app_out.app_output(csv_file_name)

    taxinfo = tif.taxinfo()
    S = tomldata.Data(taxinfo)
    S.load_toml_file(args.conffile)
    S.process_toml_info()

    #print("\naccounttable: ", S.accounttable)

    if S.accmap['IRA'] + S.accmap['roth'] + S.accmap['aftertax'] == 0:
        print(
            'Error: This app optimizes the withdrawals from your retirement account(s); you must have at least one specified in the input toml file.'
        )
        exit(0)

    if args.verbosewga:
        print("accounttable: ", S.accounttable)

    non_binding_only = True