Skip to content

Commit

Permalink
feat: Update Kids model and calculate cost of kids
Browse files Browse the repository at this point in the history
- Update `Kids` model in `config.py` to include `fraction_of_spending` and `years_of_support` properties.
- Add new function `_calc_cost_of_kids` in `state_change.py` to calculate the cost of children based on the current date, spending, and `Kids` configuration.
- Implement tests in `test_state_change.py` to validate the calculation of the cost of kids.
- Add new field "Kids" in the `Results` class in `simulator.py` to display the cost of children in the simulation results.
- Update the sample configuration file `full_config.yml` to reflect the changes in the `Kids` model.
  • Loading branch information
chriskelly committed Oct 22, 2023
1 parent 690c5c6 commit 44a39a1
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 12 deletions.
3 changes: 2 additions & 1 deletion app/models/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,8 @@ class Kids(BaseModel):
birth_years (list[float])
"""

cost_of_kid: float
fraction_of_spending: float
years_of_support: int
birth_years: list[float]


Expand Down
41 changes: 33 additions & 8 deletions app/models/financial/state_change.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import numpy as np
from app import util
from app.data.constants import INTERVALS_PER_YEAR
from app.models.config import Spending
from app.models.config import Kids, Spending
from app.models.financial.state import State
from app.models.controllers import Controllers

Expand Down Expand Up @@ -37,8 +37,8 @@ def __float__(self):

@dataclass
class _Costs(util.FloatRepr):
spending: float = -1
kids: float = -1
spending: float
kids: float
income_tax: float = -1
medicare_tax: float = -1
ss_tax: float = -1
Expand All @@ -64,6 +64,27 @@ def _calc_spending(state: State, config: Spending, is_working: bool) -> float:
return base_amount


def _calc_cost_of_kids(current_date: float, spending: float, config: Kids) -> float:
"""Calculate the cost of children
Args:
current_date (float): date of state
spending (float): base spending in current state
config (Kids)
Returns:
float: cost of children for this interval
"""
if config is None:
return 0
current_kids = [
year
for year in config.birth_years
if current_date - config.years_of_support < year <= current_date
]
return len(current_kids) * spending * config.fraction_of_spending


@dataclass
class _NetTransactions(util.FloatRepr):
income: _Income
Expand Down Expand Up @@ -97,12 +118,16 @@ def __init__(self, state: State, controllers: Controllers):
)

income = _Income(state, controllers)
spending = _calc_spending(
state=state,
config=state.user.spending,
is_working=(controllers.job_income.is_working(state.interval_idx)),
)
costs = _Costs(
spending=_calc_spending(
state=state,
config=state.user.spending,
is_working=(controllers.job_income.is_working(state.interval_idx)),
)
spending=spending,
kids=_calc_cost_of_kids(
current_date=state.date, spending=spending, config=state.user.kids
),
)
annuity = controllers.annuity.make_annuity_transaction(
state=state,
Expand Down
2 changes: 2 additions & 0 deletions app/models/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ def as_dataframes(self) -> list[pd.DataFrame]:
"Pension",
"Total Income",
"Spending",
"Kids",
"Total Costs",
"Portfolio Return",
"Annuity",
Expand All @@ -142,6 +143,7 @@ def as_dataframes(self) -> list[pd.DataFrame]:
interval.state_change_components.net_transactions.income.pension,
interval.state_change_components.net_transactions.income,
interval.state_change_components.net_transactions.costs.spending,
interval.state_change_components.net_transactions.costs.kids,
interval.state_change_components.net_transactions.costs,
interval.state_change_components.net_transactions.portfolio_return,
interval.state_change_components.net_transactions.annuity,
Expand Down
52 changes: 50 additions & 2 deletions tests/models/financial/test_state_change.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

import pytest
from app.data.constants import INTERVALS_PER_YEAR
from app.models.config import Spending
from app.models.config import Kids, Spending
from app.models.financial.state import State
from app.models.financial.state_change import _calc_spending
from app.models.financial.state_change import _calc_cost_of_kids, _calc_spending


class TestCalcSpending:
Expand Down Expand Up @@ -40,3 +40,51 @@ def test_after_working(self, first_state: State):
* self.inflation
* (1 + self.retirement_change)
)


class TestCalcCostOfKids:
spending = -100
cost_of_each_kid = -20
current_date = 2020
years_of_support = 18
birth_years = None
config = None

def calc_cost(self):
"""Helper function to calculate the cost of kids"""
config = Kids(
fraction_of_spending=self.cost_of_each_kid / self.spending,
birth_years=self.birth_years,
years_of_support=self.years_of_support,
)
return _calc_cost_of_kids(
current_date=self.current_date,
spending=self.spending,
config=config,
)

def test_one_kid(self):
"""Test that the cost of one kid is calculated correctly"""
self.birth_years = [2018]
cost_of_kid = self.calc_cost()
assert cost_of_kid == pytest.approx(self.cost_of_each_kid)

def test_multiple_kids(self):
"""Test that the cost of multiple kids is calculated correctly"""
self.birth_years = [2018, 2019]
cost_of_kids = self.calc_cost()
assert cost_of_kids == pytest.approx(
len(self.birth_years) * self.cost_of_each_kid
)

def test_kid_not_born_yet(self):
"""Test that the cost of a kid not born yet is zero"""
self.birth_years = [self.current_date + 1]
cost_of_kids = self.calc_cost()
assert cost_of_kids == pytest.approx(0)

def test_kid_too_old(self):
"""Test that the cost of a kid that is older than `years_of_support` is zero"""
self.birth_years = [self.current_date - (self.years_of_support + 1)]
cost_of_kids = self.calc_cost()
assert cost_of_kids == pytest.approx(0)
3 changes: 2 additions & 1 deletion tests/sample_configs/full_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ spending:
state: California

kids:
cost_of_kid: 0.12
fraction_of_spending: 0.12
years_of_support: 18
birth_years:
- 2021
- 2026
Expand Down

0 comments on commit 44a39a1

Please sign in to comment.