コード例 #1
0
    def test_len(self):
        """ Tests `Scenario.__len__`. """

        # Some variables that we'll use multiple times:
        num_years = 100
        initial_year = 2000

        # Test a constant scenario
        scenario = Scenario(inflation=0,
                            stock_return=0,
                            bond_return=0,
                            other_return=0,
                            management_fees=0,
                            initial_year=initial_year,
                            num_years=num_years)
        self.assertEqual(len(scenario), num_years)

        # Test a scenario built from lists/constants
        scenario = Scenario(initial_year=initial_year,
                            num_years=num_years,
                            inflation=[0 for _ in range(0, num_years)],
                            stock_return=[0 for _ in range(0, num_years)],
                            bond_return=[0 for _ in range(0, num_years)])
        self.assertEqual(len(scenario), num_years)

        # Test a scenario built from dicts:
        num_years = 100
        scenario = Scenario(
            initial_year=initial_year,
            num_years=num_years,
            inflation={
                year: 0
                for year in range(initial_year, initial_year + num_years)
            },
            stock_return={
                year: 0
                for year in range(initial_year, initial_year + num_years - 1)
            },
            bond_return=0,
            other_return=0,
            management_fees=0)
        self.assertEqual(len(scenario), num_years)

        # Test a scenario built from dicts and (longer) lists:
        num_years = 100
        scenario = Scenario(
            initial_year=initial_year,
            num_years=num_years,
            inflation={
                year: 0
                for year in range(initial_year, initial_year + num_years)
            },
            stock_return={
                year: 0
                for year in range(initial_year, initial_year + num_years - 1)
            },
            bond_return=[0 for _ in range(0, num_years)],
            other_return=0,
            management_fees=0)
        self.assertEqual(len(scenario), num_years)
コード例 #2
0
    def setUpClass(cls):
        """ Set up default values for tests """
        cls.initial_year = 2000
        # Set up a simple `Scenario` with constant values
        cls.constant_initial_year = cls.initial_year
        cls.constant_inflation = 0.02
        cls.constant_stock_return = 0.07
        cls.constant_bond_return = 0.04
        cls.constant_other_return = 0.03
        cls.constant_management_fees = 0.01
        cls.constant_num_years = 100
        cls.constant_scenario = Scenario(
            inflation=cls.constant_inflation,
            stock_return=cls.constant_stock_return,
            bond_return=cls.constant_bond_return,
            other_return=cls.constant_other_return,
            management_fees=cls.constant_management_fees,
            initial_year=cls.constant_initial_year,
            num_years=100)

        # Set up a `Scenario` with varying elements,
        # including at least one 0 in each list
        cls.varying_initial_year = cls.initial_year
        cls.varying_num_years = 100
        cls.varying_inflation = [0]
        cls.varying_stock_return = [0]
        cls.varying_bond_return = [0]
        cls.varying_other_return = [0]
        cls.varying_management_fees = [0]
        # Values will jump around, but will generally increase in magnitude
        for i in range(cls.varying_num_years - 1):
            cls.varying_inflation.append(0.0025 * i)
            cls.varying_stock_return.append(pow(-1, i) * 0.01 * i)
            cls.varying_bond_return.append(pow(-1, i + 1) * 0.005 * i)
            cls.varying_other_return.append(pow(-1, i) * 0.001 * i)
            cls.varying_management_fees.append(0.0002 * i)
        cls.varying_scenario = Scenario(
            inflation=cls.varying_inflation,
            stock_return=cls.varying_stock_return,
            bond_return=cls.varying_bond_return,
            other_return=cls.varying_other_return,
            management_fees=cls.varying_management_fees,
            initial_year=cls.varying_initial_year,
            num_years=cls.varying_num_years)

        cls.scenarios = [cls.constant_scenario, cls.varying_scenario]
        # Add a scenario of all 0 values
        cls.scenarios.append(
            Scenario(inflation=0,
                     stock_return=0,
                     bond_return=0,
                     other_return=0,
                     management_fees=0,
                     initial_year=cls.constant_initial_year,
                     num_years=10))
        for _ in range(10):  # add some random scenarios to the test set
            cls.scenarios.append(cls.get_random_scenario())
コード例 #3
0
    def setUp(self):
        """ Builds a default Person for testing of complex objects. """

        # Build inputs to Person:
        self.settings = Settings()  # default settings object
        self.initial_year = self.settings.initial_year  # convenience
        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.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)

        # Build a Person object to test against later:
        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)
コード例 #4
0
    def test_decimal(self):
        """ Tests a Forecast with Decimal inputs. """
        # Convert values to Decimal:
        self.setUp_decimal()

        # This test is based on test_multi_year:
        # Build a two-year forecast. Should contribute $360 each year.
        # No tax refunds or withdrawals.
        self.scenario = Scenario(self.initial_year, 2)
        self.tax_forecast_dummy.tax_adjustment = Decimal(0)
        forecast = Forecast(
            income_forecast=self.income_forecast_dummy,
            living_expenses_forecast=self.living_expenses_forecast_dummy,
            # NOTE: Saving forecast is not a dummy because we
            # want to actually contribute to savings accounts:
            saving_forecast=self.saving_forecast,
            withdrawal_forecast=self.null_forecast,
            tax_forecast=self.tax_forecast_dummy,
            scenario=self.scenario,
            high_precision=Decimal)
        results = [
            # pylint: disable=no-member
            # Pylint has trouble with attributes added via metaclass
            forecast.principal_history[self.initial_year],
            forecast.principal_history[self.initial_year + 1],
            self.account.balance_at_time('end')
        ]
        target = [Decimal(0), Decimal(360), Decimal(720)]
        for first, second in zip(results, target):
            self.assertAlmostEqual(first, second, places=2)
コード例 #5
0
 def test_multi_year(self):
     """ Tests a multi-year forecast. """
     # Build a two-year forecast. Should contribute $360 each year.
     # No tax refunds or withdrawals.
     self.scenario = Scenario(self.initial_year, 2)
     self.tax_forecast_dummy.tax_adjustment = 0
     forecast = Forecast(
         income_forecast=self.income_forecast_dummy,
         living_expenses_forecast=self.living_expenses_forecast_dummy,
         # NOTE: Saving forecast is not a dummy because we
         # want to actually contribute to savings accounts:
         saving_forecast=self.saving_forecast,
         withdrawal_forecast=self.null_forecast,
         tax_forecast=self.tax_forecast_dummy,
         scenario=self.scenario)
     results = [
         # pylint: disable=no-member
         # Pylint has trouble with attributes added via metaclass
         forecast.principal_history[self.initial_year],
         forecast.principal_history[self.initial_year + 1],
         self.account.balance_at_time('end')
     ]
     target = [0, 360, 720]
     for first, second in zip(results, target):
         self.assertAlmostEqual(first, second, places=2)
コード例 #6
0
ファイル: test_base.py プロジェクト: ChrisCScott/forecaster
    def setUp_decimal(self):
        """ Sets up variables based on Decimal inputs. """
        # We use caps because this is a type.
        # pylint: disable=invalid-name
        self.AccountType = Account
        # pylint: enable=invalid-name

        # It's important to synchronize the initial years of related
        # objects, so store it here:
        self.initial_year = 2000
        # Every init requires an owner, so store that here:
        self.scenario = Scenario(inflation=Decimal(0),
                                 stock_return=Decimal(1),
                                 bond_return=Decimal(0.5),
                                 other_return=Decimal(0),
                                 management_fees=Decimal(0.03125),
                                 initial_year=self.initial_year,
                                 num_years=100)
        self.allocation_strategy = AllocationStrategy(
            strategy=AllocationStrategy.strategy_n_minus_age,
            min_equity=Decimal(0.5),
            max_equity=Decimal(0.5),
            target=Decimal(0.5),
            standard_retirement_age=65,
            risk_transition_period=20,
            adjust_for_retirement_plan=False)
        self.owner = Person(
            self.initial_year,
            "test",
            2000,
            raise_rate={year: Decimal(1)
                        for year in range(2000, 2066)},
            retirement_date=2065)

        # We'll also need a timing value for various tests.
        # Use two inflows, at the start and end, evenly weighted:
        self.timing = {Decimal(0): Decimal(1), Decimal(1): Decimal(1)}

        # Inheriting classes should assign to self.account with an
        # instance of an appropriate subclass of Account.
        self.account = Account(self.owner,
                               balance=Decimal(100),
                               rate=Decimal(1.0),
                               high_precision=Decimal)
コード例 #7
0
    def get_random_scenario(initial_year=None, length=None):
        """ Returns a random `Scenario`.

        The `Scenario` has length `length` and starts in `initial_year`.
        Each parameter is randomized if not provided.
        """
        rand = Random()
        # If inputs aren't given, randomly choose reasonable values.
        if initial_year is None:
            initial_year = rand.randint(2000, 2100)
        if length is None:
            length = rand.randint(2, 200)
        # Initialize empty lists
        inflation = []
        stock_return = []
        bond_return = []
        other_return = []
        management_fees = []
        # Build lists for each variable using a reasonable range.
        #   inflation:          [0, 30%]
        #   stock_return:       [-50%, 50%]
        #   bond_return:        [-25%, 25%]
        #   other_return:       [-10%, 10%]
        #   management_fees:    [0.15%, 2%]
        for _ in range(length):
            inflation.append(rand.random() * 0.3)
            stock_return.append(rand.random() - 0.5)
            bond_return.append(rand.random() * 0.5 - 0.5)
            other_return.append(rand.random() * 0.2 - 0.1)
            management_fees.append(rand.random() * 0.0185 + 0.0015)
        return Scenario(initial_year=initial_year,
                        num_years=length,
                        inflation=inflation,
                        stock_return=stock_return,
                        bond_return=bond_return,
                        other_return=other_return,
                        management_fees=management_fees)
コード例 #8
0
    def test_init(self):
        """ Tests `Scenario.__init__()` and basic properties.

        Also tests `inflation()`, `stock_return()`, and `bond_return()`
        """
        # Test initialization with scalar values.
        scenario = Scenario(inflation=0,
                            stock_return=0,
                            bond_return=0,
                            other_return=0,
                            management_fees=0,
                            initial_year=2000,
                            num_years=100)
        # Confirm we can pull 100 (identical) years from the scenario
        for i in range(100):
            year = i + 2000
            self.assertEqual(scenario.inflation[year], 0)
            self.assertEqual(scenario.stock_return[year], 0)
            self.assertEqual(scenario.bond_return[year], 0)
            self.assertEqual(scenario.other_return[year], 0)
            self.assertEqual(scenario.management_fees[year], 0)
        self.assertEqual(scenario.initial_year, 2000)

        # Test the varying scenario next, using list inputs
        scenario = Scenario(self.varying_initial_year,
                            self.varying_num_years,
                            inflation=self.varying_inflation,
                            stock_return=self.varying_stock_return,
                            bond_return=self.varying_bond_return,
                            other_return=self.varying_other_return,
                            management_fees=self.varying_management_fees)

        # Do an elementwise comparison to confirm initialization worked
        for i in range(self.varying_num_years):
            year = i + self.varying_initial_year
            self.assertEqual(scenario.inflation[year],
                             self.varying_inflation[i])
            self.assertEqual(scenario.stock_return[year],
                             self.varying_stock_return[i])
            self.assertEqual(scenario.bond_return[year],
                             self.varying_bond_return[i])
            self.assertEqual(scenario.other_return[year],
                             self.varying_other_return[i])
            self.assertEqual(scenario.management_fees[year],
                             self.varying_management_fees[i])
        self.assertEqual(scenario.initial_year, self.varying_initial_year)

        # Construct a varying scenario from dicts instead of lists
        years = list(
            range(self.varying_initial_year,
                  self.varying_initial_year + len(self.varying_inflation)))
        inflation = dict(zip(years, self.varying_inflation))
        stock_return = dict(zip(years, self.varying_stock_return))
        bond_return = dict(zip(years, self.varying_bond_return))
        other_return = dict(zip(years, self.varying_other_return))
        management_fees = dict(zip(years, self.varying_management_fees))

        # Do an elementwise comparison to confirm initialization worked
        for year in years:
            self.assertEqual(scenario.inflation[year], inflation[year])
            self.assertEqual(scenario.stock_return[year], stock_return[year])
            self.assertEqual(scenario.bond_return[year], bond_return[year])
            self.assertEqual(scenario.other_return[year], other_return[year])
            self.assertEqual(scenario.management_fees[year],
                             management_fees[year])
        self.assertEqual(scenario.initial_year, self.varying_initial_year)

        # Mix constant, list, and dict inputs
        scenario = Scenario(initial_year=self.initial_year,
                            num_years=len(self.varying_stock_return),
                            inflation=0.02,
                            stock_return=self.varying_stock_return,
                            bond_return=bond_return,
                            other_return=Decimal(0.03),
                            management_fees=self.varying_management_fees)

        for i in range(scenario.num_years):
            year = i + scenario.initial_year
            self.assertEqual(scenario.inflation[year], 0.02)
            self.assertEqual(scenario.stock_return[year],
                             self.varying_stock_return[i])
            self.assertEqual(scenario.bond_return[year], bond_return[year])
            self.assertEqual(scenario.other_return[year], Decimal(0.03))
            self.assertEqual(scenario.management_fees[year],
                             self.varying_management_fees[i])
        self.assertEqual(scenario.initial_year, self.initial_year)
コード例 #9
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)
コード例 #10
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)
コード例 #11
0
    def setUp(self):
        """ Builds stock variables to test with. """
        self.initial_year = 2000
        # We will occasionally need to swap out subforecasts when
        # we want them to have no effect (e.g. no withdrawals because
        # we're not yet retired). Use null_forecast for that:
        self.null_forecast = DummyForecast(self.initial_year)
        # Paid $100 at the start of each month
        self.income_forecast_dummy = DummyForecast(
            self.initial_year, {when / 12: 100
                                for when in range(12)})
        self.income_forecast_dummy.people = None
        # Spend $70 on living expenses at the start of each month
        self.living_expenses_forecast_dummy = DummyForecast(
            self.initial_year, {when / 12: -70
                                for when in range(12)})
        # Contribute the balance ($30/mo, $360/yr):
        self.saving_forecast_dummy = DummyForecast(
            self.initial_year, {when + 1 / 12: -30
                                for when in range(12)})
        # Withdraw $300 at the start and middle of the year:
        self.withdrawal_forecast_dummy = DummyForecast(self.initial_year, {
            0: 300,
            0.5: 300
        })
        # Refund for $100 next year:
        self.tax_forecast_dummy = DummyForecast(self.initial_year)
        self.tax_forecast_dummy.tax_adjustment = 100
        self.tax_forecast_dummy.tax_refund_timing = Timing('start')

        # Also build a real ContributionForecast so that we can
        # test cash flows into accounts according to the overall
        # Forecast:
        # Simple tax rate: 50% on all income:
        tax = Tax(tax_brackets={self.initial_year: {0: 0.5}})
        # One person, to own the account:
        timing = Timing(frequency='BW')
        self.person = Person(initial_year=self.initial_year,
                             name="Test",
                             birth_date="1 January 1980",
                             retirement_date="31 December 2045",
                             gross_income=5200,
                             tax_treatment=tax,
                             payment_timing=timing)
        # An account for savings to go to:
        self.account = Account(owner=self.person)
        # A strategy is required, but since there's only
        # one account the result will always be the same:
        self.strategy = TransactionTraversal(priority=[self.account])
        self.saving_forecast = SavingForecast(
            initial_year=self.initial_year,
            retirement_accounts={self.account},
            debt_accounts=set(),
            transaction_strategy=self.strategy)

        # Now assign `people`, `accounts`, and `debts` attrs to
        # appropriate subforecasts so that Forecast can retrieve
        # them:
        self.income_forecast_dummy.people = {self.person}
        self.saving_forecast_dummy.debt_accounts = set()
        self.withdrawal_forecast_dummy.accounts = {self.account}
        # Also add these to the null forecast, since it could be
        # substituted for any of the above dummy forecasts:
        self.null_forecast.people = self.income_forecast_dummy.people
        self.null_forecast.accounts = self.withdrawal_forecast_dummy.accounts
        self.null_forecast.debt_accounts = (
            self.saving_forecast_dummy.debt_accounts)
        # Forecast depends on SubForecasts having certain properties,
        # so add those here:
        self.income_forecast_dummy.net_income = (sum(
            self.income_forecast_dummy.transactions.values()))
        self.living_expenses_forecast_dummy.living_expenses = (sum(
            self.living_expenses_forecast_dummy.transactions.values()))
        self.withdrawal_forecast_dummy.gross_withdrawals = (sum(
            self.withdrawal_forecast_dummy.transactions.values()))
        self.tax_forecast_dummy.tax_owing = 600
        # Add the same properties to the null forecast, since it
        # could be substituted for any of the above:
        self.null_forecast.net_income = self.income_forecast_dummy.net_income
        self.null_forecast.living_expenses = (
            self.living_expenses_forecast_dummy.living_expenses)
        self.null_forecast.gross_withdrawals = (
            self.withdrawal_forecast_dummy.gross_withdrawals)
        self.null_forecast.tax_owing = self.tax_forecast_dummy.tax_owing

        # Finally, we need a Scenario to build a Forecast.
        # This is the simplest possible: 1 year, no growth.
        self.scenario = Scenario(self.initial_year, num_years=1)