def setUp_decimal(self):
        """ Set up stock variables with Decimal inputs. """
        self.initial_year = 2000
        # Live on $24000/yr while working and $12000/yr in retirement:
        self.working = LivingExpensesStrategy(
            LivingExpensesStrategy.strategy_const_living_expenses,
            base_amount=Decimal(24000))
        self.retirement = LivingExpensesStrategy(
            LivingExpensesStrategy.strategy_const_living_expenses,
            base_amount=Decimal(12000))
        self.strategy = LivingExpensesStrategySchedule(self.working,
                                                       self.retirement)

        # Simple tax treatment: 50% tax rate across the board.
        tax = Tax(tax_brackets={self.initial_year: {Decimal(0): Decimal(0.5)}})
        # Set up a person with $50000 gross income, $2000 net income:
        self.person1 = Person(
            initial_year=self.initial_year,
            name="Test 1",
            birth_date="1 January 1980",
            retirement_date="31 December 2001",  # next year
            gross_income=Decimal(50000),
            tax_treatment=tax,
            payment_timing=Timing(frequency="BW"))
        self.people = {self.person1}
    def test_strategy_princ_pct_ret_inf(self):
        """ Test inflation-adjustment when living on principal. """
        # Live off of 50% of the principal balance at retirement,
        # adjusted to inflation:
        method = LivingExpensesStrategy.strategy_principal_percent_ret
        strategy = LivingExpensesStrategy(
            strategy=method,
            rate=0.5,
            inflation_adjust=self.variable_inflation)

        # Retire in this year and advance to next year:
        retirement_year = self.initial_year
        year = retirement_year + 1
        for person in self.people:
            person.next_year()

        # Determine the inflation between retirement_year and
        # the current year (since all figs. are in nominal terms)
        inflation_adjustment = self.variable_inflation(
            year, base_year=retirement_year)
        principal = self.account1.balance + self.account2.balance

        self.assertEqual(
            strategy(people=self.people,
                     year=year,
                     retirement_year=retirement_year),
            strategy.rate * principal * inflation_adjustment)
 def setUp(self):
     """ Builds stock variables to test with. """
     self.initial_year = 2000
     # Simple tax treatment: 50% tax rate across the board.
     tax = Tax(tax_brackets={self.initial_year: {0: 0.5}})
     # A person who is paid $200 gross ($100 net) every 2 weeks:
     timing = Timing(frequency='BW')
     self.person1 = Person(initial_year=self.initial_year,
                           name="Test 1",
                           birth_date="1 January 1980",
                           retirement_date="31 December 2045",
                           gross_income=5200,
                           tax_treatment=tax,
                           payment_timing=timing)
     # A person who is paid $100 gross ($50 net) every 2 weeks:
     self.person2 = Person(initial_year=self.initial_year,
                           name="Test 2",
                           birth_date="1 January 1982",
                           retirement_date="31 December 2047",
                           gross_income=2600,
                           tax_treatment=tax,
                           payment_timing=timing)
     # Track inflows from employment:
     self.available = {0.5 + i / 26: 150 for i in range(26)}
     self.total_available = sum(self.available.values())
     # Contribute 50% of net income (i.e. $3900):
     self.strategy = LivingExpensesStrategy(
         strategy=LivingExpensesStrategy.strategy_gross_percent, rate=0.5)
     self.forecast = LivingExpensesForecast(
         initial_year=self.initial_year,
         people={self.person1, self.person2},
         living_expenses_strategy=self.strategy)
Пример #4
0
    def test_run_forecast_basic(self):
        """ Test Forecaster.run_forecast with simple arguments. """
        # Run a simple forecast with $10,000 income, $500 in annual
        # contributions, and $1000 in starting balances with no growth:
        self.forecaster = Forecaster(
            living_expenses_strategy=LivingExpensesStrategy(
                strategy=LivingExpensesStrategy.strategy_const_contribution,
                base_amount=500,
                inflation_adjust=None),
            settings=self.settings)
        forecast = self.forecaster.run_forecast(people={self.person},
                                                accounts={self.account},
                                                debts={})

        # Test that it starts and ends in the right place and that
        # income and total balance (principal) are correct
        self.assertEqual(forecast.scenario, self.scenario)
        # Pylint has trouble with attributes added by metaclass
        # pylint: disable=no-member
        self.assertEqual(len(forecast.principal_history),
                         self.scenario.num_years)
        # pylint: enable=no-member

        # Test that the $500 in contributions have been added to the
        # initial $1000 principal by the start of year 2:
        self.assertAlmostEqual(forecast.principal, 1500, places=2)
        # Gross income should be unchanged at $10,000:
        self.assertAlmostEqual(forecast.income_forecast.gross_income,
                               10000,
                               places=2)
 def test_insufficient_income(self):
     """ Test a lower net income than the contribution rate. """
     # Try to contribute more than net income:
     method = LivingExpensesStrategy.strategy_const_contribution
     strategy = LivingExpensesStrategy(method, 2001)
     # Living expenses are $0 in this case, not -$1:
     self.assertEqual(strategy(people=self.people), 0)
Пример #6
0
    def test_const_contrib_inf(self):
        """ Test inflation-adjusted constant contributions. """
        # Contribute $500/yr, leaving $1500/yr for living.
        method = LivingExpensesStrategy.strategy_const_contribution
        strategy = LivingExpensesStrategy(method,
                                          base_amount=Money(500),
                                          inflation_adjust=lambda year: {
                                              2000: Decimal(0.5),
                                              2001: Decimal(1),
                                              2002: Decimal(2)
                                          }[year])

        # Test different inflation_adjustments for different years.
        # 2000: the adjustment is 50% so $500 contribution is reduced
        # to $250, leaving $1750 for living expenses.
        self.assertEqual(strategy(people=self.people, year=2000),
                         Money('1750'))
        # 2001: the adjustment is 100% so $500 contribution is
        # unchanged, leaving $1500 for living expenses.
        self.assertEqual(strategy(people=self.people, year=2001),
                         Money('1500'))
        # 2002: the adjustment is 200% so $500 contribution is
        # increased to $1000, leaving $1000 for living expenses.
        self.assertEqual(strategy(people=self.people, year=2002),
                         Money('1000'))
    def test_decimal_inputs(self):
        """ Test LivingExpensesStrategy with Decimal inputs. """
        # This is based on test_const_contrib_inf, with inputs
        # converted to Decimal.

        # Convert values to Decimal:
        self.setUp_decimal()

        # Contribute $250/yr in the first year and double it each year:
        method = LivingExpensesStrategy.strategy_const_contribution
        inflation_schedule = {
            2000: Decimal(0.5),
            2001: Decimal(1),
            2002: Decimal(2)
        }
        strategy = LivingExpensesStrategy(
            method,
            base_amount=Decimal(500),
            inflation_adjust=lambda year: inflation_schedule[year])

        # In 2000, contribute $250, leaving $1750 for living expenses.
        self.assertEqual(strategy(people=self.people, year=2000),
                         Decimal(1750))
        # 2001: the adjustment is 100% so $500 contribution is
        # unchanged, leaving $1500 for living expenses.
        self.assertEqual(strategy(people=self.people, year=2001),
                         Decimal(1500))
        # 2002: the adjustment is 200% so $500 contribution is
        # increased to $1000, leaving $1000 for living expenses.
        self.assertEqual(strategy(people=self.people, year=2002),
                         Decimal(1000))
    def test_strategy_gross_pct_ret_inf(self):
        """ Test inflation-adjustment when living on gross income. """
        # Live off of 50% of gross income at retirement,
        # adjusted to inflation:
        method = LivingExpensesStrategy.strategy_gross_percent_ret
        strategy = LivingExpensesStrategy(
            strategy=method,
            rate=0.5,
            inflation_adjust=self.variable_inflation)

        # Retire in this year, advance to next year, set income to $0
        # (record income first, since this is the year that matters):
        gross_income = sum(person.gross_income for person in self.people)
        retirement_year = self.initial_year
        year = retirement_year + 1
        for person in self.people:
            person.next_year()
            person.gross_income = 0
            person.net_income = 0

        # Determine the inflation between retirement_year and
        # the current year (since all figs. are in nominal terms)
        inflation_adjustment = self.variable_inflation(
            year, base_year=retirement_year)

        self.assertEqual(
            strategy(people=self.people,
                     year=year,
                     retirement_year=retirement_year),
            strategy.rate * gross_income * inflation_adjustment)
 def test_minimum(self):
     """ Test minimum living expenses. """
     self.strategy.minimum = LivingExpensesStrategy(
         LivingExpensesStrategy.strategy_const_living_expenses,
         base_amount=18000)
     self.assertEqual(
         self.strategy(year=2001, retirement_year=2000, people=self.people),
         18000)
 def test_init_default(self):
     """ Test LivingExpensesStrategy.__init__ with default args."""
     # Test default init:
     method = "Constant contribution"
     strategy = LivingExpensesStrategy(method)
     self.assertEqual(strategy.strategy, method)
     self.assertEqual(strategy.base_amount, 0)
     self.assertEqual(strategy.rate, 0)
 def test_strategy_gross_percent(self):
     """ Test living off percentage of gross income. """
     # Live on 50% of gross income:
     method = LivingExpensesStrategy.strategy_gross_percent
     strategy = LivingExpensesStrategy(method, rate=0.5)
     gross_income = sum(person.gross_income for person in self.people)
     self.assertEqual(strategy(people=self.people),
                      gross_income * strategy.rate)
 def test_strategy_net_percent(self):
     """ Test LivingExpensesStrategy.strategy_net_percent. """
     # Live on 50% of net income:
     method = LivingExpensesStrategy.strategy_net_percent
     strategy = LivingExpensesStrategy(method, rate=0.5)
     net_income = sum(person.net_income for person in self.people)
     self.assertEqual(strategy(people=self.people),
                      net_income * strategy.rate)
 def test_strategy_earnings_percent(self):
     """ Test living off of percentage of earnings over a base amount. """
     # Live off the first $1000 plus 50% of amounts above that:
     method = LivingExpensesStrategy.strategy_percent_over_base
     strategy = LivingExpensesStrategy(method, base_amount=1000, rate=0.5)
     # The test people earn $2000 net. They spend $1000 plus
     # another $500 for a total of $1500.
     self.assertEqual(strategy(people=self.people), 1500)
    def test_strategy_const_living_exp(self):
        """ Test LivingExpensesStrategy.strategy_const_living_expenses. """
        # Rather than hardcode the key, let's look it up here.
        method = LivingExpensesStrategy.strategy_const_living_expenses

        # Contribute $1000 annually, regardless of income:
        strategy = LivingExpensesStrategy(method, base_amount=1000)
        # This method requires net_income
        self.assertEqual(strategy(people=self.people), 1000)
    def test_strategy_const_contrib(self):
        """ Test LivingExpensesStrategy.strategy_const_contribution. """
        # Rather than hardcode the key, let's look it up here.
        method = LivingExpensesStrategy.strategy_const_contribution

        # Default strategy. Set to $1 constant contributions.
        strategy = LivingExpensesStrategy(method, base_amount=1)
        # Test all default parameters (no inflation adjustments here)
        self.assertAlmostEqual(
            strategy(people=self.people),
            sum(person.net_income
                for person in self.people) - strategy.base_amount)
Пример #16
0
    def test_init(self):
        """ Test LivingExpensesStrategy.__init__ """
        # Test default init:
        method = "Constant contribution"
        strategy = LivingExpensesStrategy(method)

        self.assertEqual(strategy.strategy, method)
        self.assertEqual(strategy.base_amount, Money(0))
        self.assertEqual(strategy.rate, Decimal(0))

        # Test explicit init:
        method = 'Constant contribution'
        base_amount = Money('1000')
        rate = Decimal('0.5')
        inflation_adjust = self.variable_inflation
        strategy = LivingExpensesStrategy(strategy=method,
                                          base_amount=base_amount,
                                          rate=rate,
                                          inflation_adjust=inflation_adjust)
        self.assertEqual(strategy.strategy, method)
        self.assertEqual(strategy.base_amount, base_amount)
        self.assertEqual(strategy.rate, rate)
        self.assertEqual(strategy.inflation_adjust, inflation_adjust)

        # Test invalid strategies
        with self.assertRaises(ValueError):
            strategy = LivingExpensesStrategy(strategy='Not a strategy')
        with self.assertRaises(TypeError):
            strategy = LivingExpensesStrategy(strategy=1)
        # Test invalid base_amount
        with self.assertRaises(decimal.InvalidOperation):
            strategy = LivingExpensesStrategy(strategy=method, base_amount='a')
        # Test invalid rate
        with self.assertRaises(decimal.InvalidOperation):
            strategy = LivingExpensesStrategy(strategy=method, rate='a')
 def test_gross_percent_inf(self):
     """ Test inflation-adjusted gross-percent living expenses. """
     # Live on 50% of gross income, and also provide inflation-adjust:
     method = LivingExpensesStrategy.strategy_gross_percent
     strategy = LivingExpensesStrategy(
         strategy=method,
         rate=0.5,
         inflation_adjust=self.variable_inflation)
     # Since gross_income is nominal, inflation should have no effect:
     gross_income = sum(person.gross_income for person in self.people)
     self.assertEqual(strategy(people=self.people, year=2000),
                      gross_income * strategy.rate)
     self.assertEqual(strategy(people=self.people, year=2002),
                      gross_income * strategy.rate)
 def test_const_living_exp_inf(self):
     """ Test inflation-adjusted constant living expenses. """
     # Contribute $1000 every year, adjusted to inflation:
     method = LivingExpensesStrategy.strategy_const_living_expenses
     strategy = LivingExpensesStrategy(
         strategy=method,
         inflation_adjust=self.variable_inflation,
         base_amount=1000)
     self.assertEqual(strategy(year=2000),
                      strategy.base_amount * self.variable_inflation(2000))
     self.assertEqual(strategy(year=2001),
                      strategy.base_amount * self.variable_inflation(2001))
     self.assertEqual(strategy(year=2002),
                      strategy.base_amount * self.variable_inflation(2002))
Пример #19
0
    def test_living_const_contrib(self):
        """ Test living expenses based on constant contribution. """
        # Contribute $100 and live off the rest:
        self.strategy = LivingExpensesStrategy(
            strategy=LivingExpensesStrategy.strategy_const_contribution,
            base_amount=100)
        self.forecast.living_expenses_strategy = self.strategy

        # It _is_ necessary to record inflows from employment
        # for this strategy:
        self.forecast(self.available)

        # Calculate manually and compare results:
        living_expenses = self.total_available - 100
        self.assertEqual(living_expenses, self.forecast.living_expenses)
Пример #20
0
    def test_living_gross_percent(self):
        """ Test living expenses based on percent of gross income. """
        # Contribute 50% of gross income:
        self.strategy = LivingExpensesStrategy(
            strategy=LivingExpensesStrategy.strategy_gross_percent, rate=0.5)
        self.forecast.living_expenses_strategy = self.strategy

        # It's not necessary to record inflows from employment,
        # but since this is usually how it'll be called we do
        # so here:
        self.forecast(self.available)

        # Calculate manually and compare results:
        living_expenses = (self.person1.gross_income +
                           self.person2.gross_income) / 2
        self.assertEqual(living_expenses, self.forecast.living_expenses)
Пример #21
0
    def test_living_const_living(self):
        """ Test living expenses based on constant living expenses. """
        # Live off of $1200/yr:
        self.strategy = LivingExpensesStrategy(
            strategy=LivingExpensesStrategy.strategy_const_living_expenses,
            base_amount=Money(1200))
        self.forecast.living_expenses_strategy = self.strategy

        # It's not necessary to record inflows from employment,
        # but since this is usually how it'll be called we do
        # so here:
        self.forecast(self.available)

        # Calculate manually and compare results:
        living_expenses = Money(1200)
        self.assertEqual(living_expenses, self.forecast.living_expenses)
Пример #22
0
    def test_living_earnings_pct(self):
        """ Test living expenses based on percentage of raises. """
        # Live off of $1200/yr:
        self.strategy = LivingExpensesStrategy(
            strategy=LivingExpensesStrategy.strategy_percent_over_base,
            base_amount=1200)
        self.forecast.living_expenses_strategy = self.strategy

        # It's not necessary to record inflows from employment,
        # but since this is usually how it'll be called we do
        # so here:
        self.forecast(self.available)

        # Calculate manually and compare results:
        living_expenses = 1200
        self.assertEqual(living_expenses, self.forecast.living_expenses)
    def test_init_decimal(self):
        """ Tests init with Decimal inputs. """
        method = 'Constant contribution'
        base_amount = Decimal(1000)
        rate = Decimal(0.5)

        def inflation_adjust(year, base_year=self.year_1):
            return Decimal(self.variable_inflation(year, base_year=base_year))

        strategy = LivingExpensesStrategy(strategy=method,
                                          base_amount=base_amount,
                                          rate=rate,
                                          inflation_adjust=inflation_adjust)
        self.assertEqual(strategy.strategy, method)
        self.assertEqual(strategy.base_amount, base_amount)
        self.assertEqual(strategy.rate, rate)
        self.assertEqual(strategy.inflation_adjust, inflation_adjust)
    def test_strategy_principal_pct_ret(self):
        """ Test living off of percentage of principal at retirement. """
        # Live off of 50% of the principal balance at retirement:
        method = LivingExpensesStrategy.strategy_principal_percent_ret
        strategy = LivingExpensesStrategy(strategy=method, rate=0.5)

        # Retire in this year and advance to next year:
        retirement_year = self.initial_year
        year = retirement_year + 1
        for person in self.people:
            person.next_year()

        principal = self.account1.balance + self.account2.balance
        self.assertEqual(
            strategy(people=self.people,
                     year=year,
                     retirement_year=retirement_year),
            strategy.rate * principal)
 def test_earnings_percent_inf(self):
     """ Test inflation-adjusted earnings-percent living expenses. """
     # Live off the first $1000 plus 50% of amounts above that:
     method = LivingExpensesStrategy.strategy_percent_over_base
     strategy = LivingExpensesStrategy(
         strategy=method,
         base_amount=1000,
         rate=0.5,
         inflation_adjust=self.variable_inflation)
     # 1999: Adjustment is 50%, so live on $500 plus 50% of
     # remaining $1500 (i.e. $750) for a total of $1250:
     self.assertAlmostEqual(
         strategy(people=self.people, year=self.year_half), 1250)
     # 2000: Adjustment is 100%; should yield the usual $1500:
     self.assertAlmostEqual(strategy(people=self.people, year=self.year_1),
                            1500)
     # 2001: Adjustment is 200%, so live on $2000. That's all
     # of the net income, so the 50% rate doesn't apply:
     self.assertAlmostEqual(strategy(people=self.people, year=self.year_2),
                            2000)
    def test_strategy_gross_pct_ret(self):
        """ Test living off of gross income at retirement. """
        # Live off of 50% of gross income at retirement:
        method = LivingExpensesStrategy.strategy_gross_percent_ret
        strategy = LivingExpensesStrategy(strategy=method, rate=0.5)

        # Retire in this year, advance to next year, set income to $0
        # (record income first, since this is the year that matters):
        gross_income = sum(person.gross_income for person in self.people)
        retirement_year = self.initial_year
        year = retirement_year + 1
        for person in self.people:
            person.next_year()
            person.gross_income = 0
            person.net_income = 0

        self.assertEqual(
            strategy(people=self.people,
                     year=year,
                     retirement_year=retirement_year),
            strategy.rate * gross_income)
Пример #27
0
 def setUp_decimal(self):
     """ Builds stock variables to test with. """
     # pylint: disable=invalid-name
     # Pylint doesn't like `setUp_decimal`, but it's not our naming
     # convention, so don't complain to us!
     # pylint: enable=invalid-name
     self.initial_year = 2000
     # Simple tax treatment: 50% tax rate across the board.
     tax = Tax(tax_brackets={self.initial_year: {Decimal(0): Decimal(0.5)}})
     # A person who is paid $200 gross ($100 net) every 2 weeks:
     timing = Timing(frequency='BW', high_precision=Decimal)
     self.person1 = Person(initial_year=self.initial_year,
                           name="Test 1",
                           birth_date="1 January 1980",
                           retirement_date="31 December 2045",
                           gross_income=Decimal(5200),
                           tax_treatment=tax,
                           payment_timing=timing)
     # A person who is paid $100 gross ($50 net) every 2 weeks:
     self.person2 = Person(initial_year=self.initial_year,
                           name="Test 2",
                           birth_date="1 January 1982",
                           retirement_date="31 December 2047",
                           gross_income=Decimal(2600),
                           tax_treatment=tax,
                           payment_timing=timing)
     # Track inflows from employment:
     self.available = {
         Decimal(0.5 + i) / 26: Decimal(150)
         for i in range(26)
     }
     self.total_available = sum(self.available.values())
     # Contribute 50% of net income (i.e. $3900):
     self.strategy = LivingExpensesStrategy(
         strategy=LivingExpensesStrategy.strategy_gross_percent,
         rate=Decimal(0.5))
     self.forecast = LivingExpensesForecast(
         initial_year=self.initial_year,
         people={self.person1, self.person2},
         living_expenses_strategy=self.strategy)
Пример #28
0
    def setUp(self):
        """ Builds default strategies, persons, etc. """
        # Use a default settings object:
        # (This is conditional so that subclasses can assign their own
        # settings object before calling super().setUp())
        if not hasattr(self, 'settings'):
            self.settings = Settings()

        # To simplify tests, modify Settings so that forecasts are
        # just 2 years with easy-to-predict contributions ($1000/yr)
        self.settings.num_years = 2
        self.settings.living_expenses_strategy = (
            LivingExpensesStrategy.strategy_const_contribution)
        self.settings.living_expenses_base_amount = 1000

        # Allow subclasses to use subclasses of Forecaster by assigning
        # to forecaster_type
        if not hasattr(self, 'forecaster_type'):
            self.forecaster_type = Forecaster

        # Build default `SubForecast` inputs based on `settings`:
        self.initial_year = self.settings.initial_year
        self.scenario = Scenario(inflation=self.settings.inflation,
                                 stock_return=self.settings.stock_return,
                                 bond_return=self.settings.bond_return,
                                 other_return=self.settings.other_return,
                                 management_fees=self.settings.management_fees,
                                 initial_year=self.settings.initial_year,
                                 num_years=self.settings.num_years)
        self.living_expenses_strategy = LivingExpensesStrategy(
            strategy=self.settings.living_expenses_strategy,
            base_amount=self.settings.living_expenses_base_amount,
            rate=self.settings.living_expenses_rate,
            inflation_adjust=self.scenario.inflation_adjust)
        self.saving_strategy = TransactionStrategy(
            strategy=self.settings.saving_strategy,
            weights=self.settings.saving_weights)
        self.withdrawal_strategy = TransactionStrategy(
            strategy=self.settings.withdrawal_strategy,
            weights=self.settings.withdrawal_weights)
        self.allocation_strategy = AllocationStrategy(
            strategy=self.settings.allocation_strategy,
            min_equity=self.settings.allocation_min_equity,
            max_equity=self.settings.allocation_max_equity,
            target=self.settings.allocation_target,
            standard_retirement_age=(
                self.settings.allocation_std_retirement_age),
            risk_transition_period=self.settings.allocation_risk_trans_period,
            adjust_for_retirement_plan=(
                self.settings.allocation_adjust_retirement))
        self.debt_payment_strategy = DebtPaymentStrategy(
            strategy=self.settings.debt_payment_strategy)
        self.tax_treatment = Tax(
            tax_brackets=self.settings.tax_brackets,
            personal_deduction=self.settings.tax_personal_deduction,
            credit_rate=self.settings.tax_credit_rate,
            inflation_adjust=self.scenario.inflation_adjust)

        # Now build some Ledger objects to test against:
        # A person making $10,000/yr
        self.person = Person(initial_year=self.initial_year,
                             name="Test 1",
                             birth_date="1 January 1980",
                             retirement_date="31 December 2040",
                             gross_income=10000,
                             raise_rate=0,
                             spouse=None,
                             tax_treatment=self.tax_treatment)
        # An account with $1000 in it (and no interest)
        self.account = Account(owner=self.person, balance=1000)
        # A debt with a $100 balance (and no interest)
        self.debt = Debt(owner=self.person, balance=100)

        # Init a Forecaster object here for convenience:
        self.forecaster = self.forecaster_type(settings=self.settings)
Пример #29
0
    def setUp_decimal(self):
        """ Builds default strategies/persons/etc. with Decimal inputs. """
        # pylint: disable=invalid-name
        # This name is based on `setUp`, which doesn't follow Pylint's rules
        # pylint: enable=invalid-name

        # Use a default settings object:
        # (This is conditional so that subclasses can assign their own
        # settings object before calling super().setUp())
        if not hasattr(self, 'settings'):
            self.settings = Settings()

        # To simplify tests, modify Settings so that forecasts are
        # just 2 years with easy-to-predict contributions ($1000/yr)
        self.settings.num_years = 2
        self.settings.living_expenses_strategy = (
            LivingExpensesStrategy.strategy_const_contribution)
        self.settings.living_expenses_base_amount = Decimal(1000)

        # Allow subclasses to use subclasses of Forecaster by assigning
        # to forecaster_type
        if not hasattr(self, 'forecaster_type'):
            self.forecaster_type = Forecaster

        # Build default `SubForecast` inputs based on `settings`:
        self.initial_year = self.settings.initial_year
        self.scenario = Scenario(
            inflation=Decimal(self.settings.inflation),
            stock_return=Decimal(self.settings.stock_return),
            bond_return=Decimal(self.settings.bond_return),
            other_return=Decimal(self.settings.other_return),
            management_fees=Decimal(self.settings.management_fees),
            initial_year=self.settings.initial_year,
            num_years=self.settings.num_years)
        self.living_expenses_strategy = LivingExpensesStrategy(
            strategy=self.settings.living_expenses_strategy,
            base_amount=Decimal(self.settings.living_expenses_base_amount),
            rate=Decimal(self.settings.living_expenses_rate),
            inflation_adjust=self.scenario.inflation_adjust)
        self.saving_strategy = TransactionStrategy(
            strategy=self.settings.saving_strategy,
            weights={
                year: Decimal(val)
                for (year, val) in self.settings.saving_weights.items()
            })
        self.withdrawal_strategy = TransactionStrategy(
            strategy=self.settings.withdrawal_strategy,
            weights={
                year: Decimal(val)
                for (year, val) in self.settings.withdrawal_weights.items()
            })
        self.allocation_strategy = AllocationStrategy(
            strategy=self.settings.allocation_strategy,
            min_equity=Decimal(self.settings.allocation_min_equity),
            max_equity=Decimal(self.settings.allocation_max_equity),
            target=Decimal(self.settings.allocation_target),
            standard_retirement_age=(
                self.settings.allocation_std_retirement_age),
            risk_transition_period=self.settings.allocation_risk_trans_period,
            adjust_for_retirement_plan=(
                self.settings.allocation_adjust_retirement))
        self.debt_payment_strategy = DebtPaymentStrategy(
            strategy=self.settings.debt_payment_strategy,
            high_precision=Decimal)
        self.tax_treatment = Tax(
            tax_brackets={
                year: {
                    Decimal(lower): Decimal(upper)
                }
                for (year, vals) in self.settings.tax_brackets.items()
                for (lower, upper) in vals.items()
            },
            personal_deduction={
                year: Decimal(val)
                for (year,
                     val) in self.settings.tax_personal_deduction.items()
            },
            credit_rate={
                year: Decimal(val)
                for (year, val) in self.settings.tax_credit_rate.items()
            },
            inflation_adjust=self.scenario.inflation_adjust,
            high_precision=Decimal)

        # Now build some Ledger objects to test against:
        # A person making $10,000/yr
        self.person = Person(initial_year=self.initial_year,
                             name="Test 1",
                             birth_date="1 January 1980",
                             retirement_date="31 December 2040",
                             gross_income=Decimal(10000),
                             raise_rate=Decimal(0),
                             spouse=None,
                             tax_treatment=self.tax_treatment,
                             high_precision=Decimal)
        # An account with $1000 in it (and no interest)
        self.account = Account(owner=self.person,
                               balance=Decimal(1000),
                               high_precision=Decimal)
        # A debt with a $100 balance (and no interest)
        self.debt = Debt(owner=self.person,
                         balance=Decimal(100),
                         high_precision=Decimal)

        # Init a Forecaster object here for convenience:
        self.forecaster = self.forecaster_type(settings=self.settings,
                                               high_precision=Decimal)
 def test_invalid_strategies(self):
     """ Tests invalid strategies. """
     with self.assertRaises(ValueError):
         _ = LivingExpensesStrategy(strategy='Not a strategy')
     with self.assertRaises(TypeError):
         _ = LivingExpensesStrategy(strategy=1)