-
Notifications
You must be signed in to change notification settings - Fork 0
/
ruleset.py
84 lines (68 loc) · 3.79 KB
/
ruleset.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
"""
Helper functions for building a ruleset.
"""
import natural_rules
import model
def get_career_rules(salary_rule, spending_rule, savings_rule, rrsp_interest_rate: float, tfsa_interest_rate: float):
"""
Takes assumption-driven rules as input and returns a full career ruleset including 'natural' rules, correctly ordered.
:param salary_rule: Rule setting the gross salary.
:param spending_rule: Rule setting the amount of spending.
:param savings_rule: Rule dividing the available savings between RRSP and TFSA.
:param rrsp_interest_rate: Interest rate on the RRSP account.
:type rrsp_interest_rate: float
:param tfsa_interest_rate: Interest rate on the TFSA account.
:type tfsa_interest_rate: float
:return: A full career ruleset.
"""
return [
# No current-year dependencies
natural_rules.apply_tax_refund,
natural_rules.get_calculate_investment_interest(rrsp_interest_rate, tfsa_interest_rate),
# Assume no current-year dependencies
salary_rule,
#Depends on deltas.gross_salary (ie salary_rule)
natural_rules.apply_tax,
# May depend on salary and tax
spending_rule,
# Depends on pretty much everything else
savings_rule
]
def get_retirement_rules(retirement_income: float, savings_rule, rrsp_interest_rate: float, tfsa_interest_rate: float):
"""
Returns a retirement ruleset including 'natural' rules, correctly ordered.
:param retirement_income: Yearly 'income' or expenditure during retirement, assumed to be constant.
:type retirement_income: float
:param savings_rule: Rule governing the distribution of deductions between RRSP and TFSA accounts.
:param rrsp_interest_rate: Interest rate on the RRSP account.
:type rrsp_interest_rate: float
:param tfsa_interest_rate: Interest rate on the TFSA account.
:type tfsa_interest_rate: float
:return: The retirement ruleset.
"""
def retirement_spending(deltas: model.deltas_state, previous_funds: model.funds_state, previous_deltas: model.deltas_state):
return deltas.update_spending(retirement_income)
return [
retirement_spending, # Spend
# Skip tax on employment salary since we're not employed
natural_rules.apply_tax_refund, # Pay tax on previous year's RRSP deductions and investment interest
savings_rule, # Deduct spending from RRSP/TFSA according to rule
natural_rules.get_calculate_investment_interest(rrsp_interest_rate, tfsa_interest_rate) # Earn interest on remaining savings
]
def get_couple_ruleset(partner1_salary_rule, partner2_salary_rule, spending_rule, savings_rule, rrsp_interest_rate: float, tfsa_interest_rate: float):
def ruleset(current_year : int, is_partner1_retired : bool, is_partner2_retired : bool):
for i in range(1, 3):
# These rules don't have dependencies and apply both pre- and post-retirement
# (Tax 'refund' can have either sign and is actually a payment when deducting from the RRSP)
yield model.get_couple_rule_from_single_rule(natural_rules.apply_tax_refund, i)
yield model.get_couple_rule_from_single_rule(natural_rules.get_calculate_investment_interest(rrsp_interest_rate, tfsa_interest_rate), i)
# Those who are working earn income and pay tax
if (not is_partner1_retired):
yield model.get_couple_rule_from_single_rule(partner1_salary_rule, 1)
yield model.get_couple_rule_from_single_rule(natural_rules.apply_tax, 1)
if (not is_partner2_retired):
yield model.get_couple_rule_from_single_rule(partner2_salary_rule, 2)
yield model.get_couple_rule_from_single_rule(natural_rules.apply_tax, 2)
yield spending_rule
yield savings_rule
return ruleset