コード例 #1
0
    def setUp(self):
        """ Sets up class to use Canadian default values. """
        # Override settings/forecaster types to use Canadian subclasses.
        # (This is conditional so that subclasses can assign their own
        # objects before calling super().setUp())
        if not hasattr(self, 'settings'):
            self.settings = SettingsCanada()
        if not hasattr(self, 'forecaster_type'):
            self.forecaster_type = ForecasterCanada
        # Let the superclass handle setup:
        super().setUp()

        self.constants = constants.ConstantsCanada()

        # Override tax_treatment to use TaxCanada object:
        self.tax_treatment = TaxCanada(
            inflation_adjust=self.scenario.inflation_adjust,
            province=self.settings.tax_province, constants=self.constants)
        # The AccountTransactionStrategy settings for ForecasterCanada
        # don't include an Account object; replace it with an
        # otherwise-identical TaxableAccount, which is represented in
        # the settings.
        self.account = TaxableAccount(
            owner=self.person,
            balance=self.account.balance,
            rate=self.account.rate,
            nper=self.account.nper)
コード例 #2
0
ファイル: test_strategy.py プロジェクト: dxcv/forecaster
    def setUp(self):
        """ Sets up variables for testing. """
        # Vars for building accounts:
        initial_year = 2000
        person = Person(
            initial_year, 'Testy McTesterson', 1980, retirement_date=2045)

        # Set up some accounts for the tests.
        self.rrsp = RRSP(
            person,
            balance=Money(200), rate=0, contribution_room=Money(200))
        self.rrsp2 = RRSP(person, balance=Money(100), rate=0)
        self.tfsa = TFSA(
            person,
            balance=Money(100), rate=0, contribution_room=Money(100))
        self.taxable_account = TaxableAccount(
            person, balance=Money(1000), rate=0)
        self.accounts = {
            self.rrsp, self.rrsp2, self.tfsa, self.taxable_account
        }

        # Define a simple timing for transactions:
        self.timing = {Decimal(0.5): 1}

        # Build strategy for testing (in non-init tests):
        self.weights = {
            'RRSP': Decimal('0.4'),
            'TFSA': Decimal('0.3'),
            'TaxableAccount': Decimal('0.3')
        }
        self.strategy = TransactionStrategy(
            TransactionStrategy.strategy_weighted, self.weights)
コード例 #3
0
ファイル: test_strategy.py プロジェクト: dxcv/forecaster
    def setUp(self):
        """ Sets up variables for testing. """
        # Different groups of tests use different groups of variables.
        # We could split this class up into multiple classes (perhaps
        # one for ordered strategies and one for weighted strategies?),
        # but for now this project's practice is one test case for each
        # custom class.
        # pylint: disable=too-many-instance-attributes

        initial_year = 2000
        person = Person(
            initial_year, 'Testy McTesterson', 1980, retirement_date=2045)

        # Set up some accounts for the tests.
        self.rrsp = RRSP(
            person,
            balance=Money(200), rate=0, contribution_room=Money(200))
        self.tfsa = TFSA(
            person,
            balance=Money(100), rate=0, contribution_room=Money(100))
        self.taxable_account = TaxableAccount(
            person, balance=Money(1000), rate=0)
        self.accounts = {self.rrsp, self.tfsa, self.taxable_account}

        # Define a simple timing for transactions:
        self.timing = {Decimal(0.5): 1}

        # Build strategy for testing (in non-init tests):
        self.strategy = TransactionStrategy(
            TransactionStrategy.strategy_ordered, {
                'RRSP': 1,
                'TFSA': 2,
                'TaxableAccount': 3
            })
コード例 #4
0
    def setUp(self):
        """ Sets up variables for testing. """

        # Vars for building accounts:
        initial_year = 2000
        person = Person(initial_year,
                        'Testy McTesterson',
                        1980,
                        retirement_date=2045)

        # Set up some accounts for the tests.
        self.rrsp = RRSP(person, balance=200, rate=0, contribution_room=200)
        self.tfsa = TFSA(person, balance=100, rate=0, contribution_room=100)
        self.taxable_account = TaxableAccount(person, balance=1000, rate=0)
        self.accounts = {self.rrsp, self.tfsa, self.taxable_account}

        # Define a simple timing for transactions:
        self.timing = {0.5: 1}

        self.max_outflow = sum(
            sum(account.max_outflows(timing=self.timing).values())
            for account in self.accounts)
        self.max_inflows = sum(
            sum(account.max_inflows(timing=self.timing).values())
            for account in self.accounts)

        # Build strategy for testing (in non-init tests):
        self.weights = {'RRSP': 0.4, 'TFSA': 0.3, 'TaxableAccount': 0.3}
        self.strategy = TransactionStrategy(
            TransactionStrategy.strategy_weighted, self.weights)
コード例 #5
0
 def setUp_decimal(self):
     """ Sets up variables based on Decimal inputs. """
     self.initial_year = 2000
     self.person = Person(self.initial_year,
                          "Test",
                          "1 January 1980",
                          retirement_date="1 January 2030",
                          high_precision=Decimal)
     # An RRSP with a $1000 balance and $100 in contribution room:
     self.rrsp = RRSP(initial_year=self.initial_year,
                      owner=self.person,
                      balance=Decimal(1000),
                      contribution_room=Decimal(100),
                      high_precision=Decimal)
     # Another RRSP, linked to the first one:
     # (For testing LinkedLimitAccount nodes)
     self.rrsp2 = RRSP(initial_year=self.initial_year,
                       owner=self.person,
                       high_precision=Decimal)
     # A TFSA with a $100 balance and $1000 in contribution room:
     self.tfsa = TFSA(initial_year=self.initial_year,
                      owner=self.person,
                      balance=Decimal(100),
                      contribution_room=Decimal(1000),
                      high_precision=Decimal)
     # Another TFSA, linked to the first one:
     self.tfsa2 = TFSA(initial_year=self.initial_year,
                       owner=self.person,
                       high_precision=Decimal)
     # A taxable account with $0 balance (and no contribution limit)
     self.taxable_account = TaxableAccount(initial_year=self.initial_year,
                                           owner=self.person,
                                           balance=Decimal(0),
                                           high_precision=Decimal)
     # A $100 debt with no interest and a $10 min. payment:
     self.debt = Debt(initial_year=self.initial_year,
                      owner=self.person,
                      balance=Decimal(100),
                      minimum_payment=Decimal(10),
                      high_precision=Decimal)
     # Contribute to RRSP, then TFSA, then taxable
     self.priority_ordered = [self.rrsp, self.tfsa, self.taxable_account]
     # Contribute 50% to RRSP, 25% to TFSA, and 25% to taxable
     self.priority_weighted = {
         self.rrsp: Decimal(0.5),
         self.tfsa: Decimal(0.25),
         self.taxable_account: Decimal(0.25)
     }
     # Contribute to RRSP and TFSA (50-50) until both are full, with
     # the remainder to taxable accounts.
     self.priority_nested = [{
         self.rrsp: Decimal(0.5),
         self.tfsa: Decimal(0.5)
     }, self.taxable_account]
コード例 #6
0
    def setUp_decimal(self):
        """ Sets up variables for testing. """
        # 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
        initial_year = 2000
        person = Person(initial_year,
                        'Testy McTesterson',
                        1980,
                        retirement_date=2045,
                        high_precision=Decimal)

        # Set up some accounts for the tests.
        self.rrsp = RRSP(person,
                         balance=Decimal(200),
                         rate=Decimal(0),
                         contribution_room=Decimal(200),
                         high_precision=Decimal)
        self.rrsp2 = RRSP(person,
                          balance=Decimal(100),
                          rate=Decimal(0),
                          high_precision=Decimal)
        self.tfsa = TFSA(person,
                         balance=Decimal(100),
                         rate=Decimal(0),
                         contribution_room=Decimal(100),
                         high_precision=Decimal)
        self.taxable_account = TaxableAccount(person,
                                              balance=Decimal(1000),
                                              rate=Decimal(0),
                                              high_precision=Decimal)
        self.accounts = {
            self.rrsp, self.rrsp2, self.tfsa, self.taxable_account
        }

        # Define a simple timing for transactions:
        self.timing = {Decimal(0.5): Decimal(1)}

        self.max_outflow = sum(
            sum(account.max_outflows(timing=self.timing).values())
            for account in self.accounts)
        self.max_inflows = sum(
            sum(account.max_inflows(timing=self.timing).values())
            for account in self.accounts)

        # Build strategies for testing (in non-init tests):
        self.strategy = TransactionStrategy(
            TransactionStrategy.strategy_ordered, {
                'RRSP': Decimal(1),
                'TFSA': Decimal(2),
                'TaxableAccount': Decimal(3)
            },
            high_precision=Decimal)
コード例 #7
0
    def setUp_decimal(self):
        """ Sets up variables based on Decimal inputs. """
        # 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

        # Vars for building accounts:
        initial_year = 2000
        person = Person(initial_year,
                        'Testy McTesterson',
                        1980,
                        retirement_date=2045,
                        high_precision=Decimal)

        # Set up some accounts for the tests.
        self.rrsp = RRSP(person,
                         balance=Decimal(200),
                         rate=Decimal(0),
                         contribution_room=Decimal(200),
                         high_precision=Decimal)
        self.rrsp2 = RRSP(person,
                          balance=Decimal(100),
                          rate=Decimal(0),
                          high_precision=Decimal)
        self.tfsa = TFSA(person,
                         balance=Decimal(100),
                         rate=Decimal(0),
                         contribution_room=Decimal(100),
                         high_precision=Decimal)
        self.taxable_account = TaxableAccount(person,
                                              balance=Decimal(1000),
                                              rate=Decimal(0),
                                              high_precision=Decimal)
        self.accounts = {
            self.rrsp, self.rrsp2, self.tfsa, self.taxable_account
        }

        # Define a simple timing for transactions:
        self.timing = {Decimal(0.5): Decimal(1)}

        # Build strategy for testing (in non-init tests):
        self.weights = {
            'RRSP': Decimal(0.4),
            'TFSA': Decimal(0.3),
            'TaxableAccount': Decimal(0.3)
        }
        self.strategy = TransactionStrategy(
            TransactionStrategy.strategy_weighted,
            self.weights,
            high_precision=Decimal)
コード例 #8
0
    def setUp_decimal(self):
        """ Sets up variables based on Decimal inputs. """
        # 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

        # Different groups of tests use different groups of variables.
        # We could split this class up into multiple classes (perhaps
        # one for ordered strategies and one for weighted strategies?),
        # but for now this project's practice is one test case for each
        # custom class.
        # pylint: disable=too-many-instance-attributes

        initial_year = 2000
        person = Person(initial_year,
                        'Testy McTesterson',
                        1980,
                        retirement_date=2045,
                        high_precision=Decimal)

        # Set up some accounts for the tests.
        self.rrsp = RRSP(person,
                         balance=Decimal(200),
                         rate=Decimal(0),
                         contribution_room=Decimal(200),
                         high_precision=Decimal)
        self.tfsa = TFSA(person,
                         balance=Decimal(100),
                         rate=Decimal(0),
                         contribution_room=Decimal(100),
                         high_precision=Decimal)
        self.taxable_account = TaxableAccount(person,
                                              balance=Decimal(1000),
                                              rate=Decimal(0),
                                              high_precision=Decimal)
        self.accounts = {self.rrsp, self.tfsa, self.taxable_account}

        # Define a simple timing for transactions:
        self.timing = {Decimal(0.5): Decimal(1)}

        # Build strategy for testing (in non-init tests):
        self.strategy = TransactionStrategy(
            TransactionStrategy.strategy_ordered, {
                'RRSP': 1,
                'TFSA': 2,
                'TaxableAccount': 3
            },
            high_precision=Decimal)
コード例 #9
0
ファイル: test_tax.py プロジェクト: dxcv/forecaster
    def setUp(self):
        """ Sets up mutable variables for each test call. """
        # Set to default province:
        self.province = 'BC'
        self.tax = TaxCanada(self.inflation_adjustments, province='BC')

        # Set up some people to test on:
        # Person1 makes $100,000/yr, has a taxable account with $500,000
        # taxable income, and an RRSP with $500,000 in taxable income.
        self.person1 = Person(
            self.initial_year, "Tester 1", self.initial_year - 20,
            retirement_date=self.initial_year + 45, gross_income=100000)
        self.taxable_account1 = TaxableAccount(
            owner=self.person1,
            acb=0, balance=Money(1000000), rate=Decimal('0.05'), nper=1)
        self.taxable_account1.add_transaction(-Money(1000000), when='start')
        # NOTE: by using an RRSP here, a pension income tax credit will
        # be applied by TaxCanadaJurisdiction. Be aware of this if you
        # want to test this output against a generic Tax object with
        # Canadian brackets.
        self.rrsp = RRSP(
            self.person1,
            inflation_adjust=self.inflation_adjustments,
            contribution_room=0,
            balance=Money(500000), rate=Decimal('0.05'), nper=1)
        self.rrsp.add_transaction(-Money(500000), when='start')

        # Person2 makes $50,000/yr and has a taxable account with
        # $5000 taxable income.
        self.person2 = Person(
            self.initial_year, "Tester 2", self.initial_year - 18,
            retirement_date=self.initial_year + 47, gross_income=50000)
        self.taxable_account2 = TaxableAccount(
            owner=self.person2,
            acb=0, balance=Money(10000), rate=Decimal('0.05'), nper=1)
        self.taxable_account2.add_transaction(-Money(10000), when='start')
コード例 #10
0
ファイル: test_strategy.py プロジェクト: dxcv/forecaster
    def setUp(self):
        """ Sets up variables for testing. """
        initial_year = 2000
        person = Person(
            initial_year, 'Testy McTesterson', 1980, retirement_date=2045)

        # Set up some accounts for the tests.
        self.rrsp = RRSP(
            person,
            balance=Money(200), rate=0, contribution_room=Money(200))
        self.rrsp2 = RRSP(person, balance=Money(100), rate=0)
        self.tfsa = TFSA(
            person,
            balance=Money(100), rate=0, contribution_room=Money(100))
        self.taxable_account = TaxableAccount(
            person, balance=Money(1000), rate=0)
        self.accounts = {
            self.rrsp, self.rrsp2, self.tfsa, self.taxable_account
        }

        # Define a simple timing for transactions:
        self.timing = {Decimal(0.5): 1}

        self.max_outflow = sum(
            sum(account.max_outflows(timing=self.timing).values())
            for account in self.accounts)
        self.max_inflows = sum(
            sum(account.max_inflows(timing=self.timing).values())
            for account in self.accounts)

        # Build strategies for testing (in non-init tests):
        self.strategy = TransactionStrategy(
            TransactionStrategy.strategy_ordered, {
                'RRSP': 1,
                'TFSA': 2,
                'TaxableAccount': 3
            })
コード例 #11
0
    def setUp_decimal(self):
        """ Sets up class to use Canadian default values. """
        # This handles almost everything:
        super().setUp_decimal()

        self.settings = SettingsCanada(high_precision=Decimal)
        self.constants = constants.ConstantsCanada(high_precision=Decimal)

        # Override tax_treatment to use TaxCanada object:
        self.tax_treatment = TaxCanada(
            inflation_adjust=self.scenario.inflation_adjust,
            province=self.settings.tax_province,
            high_precision=Decimal,
            constants=self.constants)
        # The AccountTransactionStrategy settings for ForecasterCanada
        # don't include an Account object; replace it with an
        # otherwise-identical TaxableAccount, which is represented in
        # the settings.
        self.account = TaxableAccount(
            owner=self.person,
            balance=self.account.balance,
            rate=self.account.rate,
            nper=self.account.nper,
            high_precision=Decimal)
コード例 #12
0
ファイル: test_tax.py プロジェクト: ChrisCScott/forecaster
    def setUp(self):
        self.initial_year = 2000
        # Build 100 years of inflation adjustments with steadily growing
        # adjustment factors. First, pick a nice number (ideally a power
        # of 2 to avoid float precision issues); inflation_adjustment
        # will grow by adding the inverse (1/n) of this number annually
        growth_factor = 32
        year_range = range(self.initial_year, self.initial_year + 100)
        self.inflation_adjustments = {
            year: 1 + (year - self.initial_year) / growth_factor
            for year in year_range
        }
        # For convenience, store the year where inflation has doubled
        # the nominal value of money
        self.double_year = self.initial_year + growth_factor
        # Build some brackets with nice round numbers:
        self.tax_brackets = {self.initial_year: {0: 0.1, 100: 0.2, 10000: 0.3}}
        # For convenience, build a sorted, type-converted array of
        # each of the tax bracket thresholds:
        self.brackets = sorted({
            key: self.tax_brackets[self.initial_year][key]
            for key in self.tax_brackets[self.initial_year].keys()
        })
        # For convenience in testing, build an accum dict that
        # corresponds to the tax brackets above.
        self.accum = {self.initial_year: {0: 0, 100: 10, 10000: 1990}}
        self.personal_deduction = {self.initial_year: 100}
        self.credit_rate = {self.initial_year: 0.1}

        self.tax = Tax(self.tax_brackets,
                       inflation_adjust=self.inflation_adjustments,
                       personal_deduction=self.personal_deduction,
                       credit_rate=self.credit_rate)

        # Set up a simple person with no account-derived taxable income
        self.person = Person(self.initial_year,
                             "Tester",
                             self.initial_year - 25,
                             retirement_date=self.initial_year + 40,
                             gross_income=0)

        # Set up two people, spouses, on which to do more complex tests
        self.person1 = Person(self.initial_year,
                              "Tester 1",
                              self.initial_year - 20,
                              retirement_date=self.initial_year + 45,
                              gross_income=100000)
        self.person2 = Person(self.initial_year,
                              "Tester 2",
                              self.initial_year - 22,
                              retirement_date=self.initial_year + 43,
                              gross_income=50000)

        # Give the first person two accounts, one taxable and one
        # tax-deferred. Withdraw the entirety from the taxable account,
        # so that we don't need to worry about tax on unrealized growth:
        self.taxable_account1 = TaxableAccount(owner=self.person1,
                                               acb=0,
                                               balance=50000,
                                               rate=0.05,
                                               nper=1)
        self.taxable_account1.add_transaction(-50000, when='start')
        self.rrsp = RRSP(owner=self.person1,
                         inflation_adjust=self.inflation_adjustments,
                         contribution_room=0,
                         balance=10000,
                         rate=0.05,
                         nper=1)
        # Employment income is fully taxable, and only half of capital
        # gains (the income from the taxable account) is taxable:
        self.person1_taxable_income = (self.person1.gross_income +
                                       self.taxable_account1.balance / 2)

        # Give the second person two accounts, one taxable and one
        # non-taxable. Withdraw the entirety from the taxable account,
        # so that we don't need to worry about tax on unrealized growth,
        # and withdraw a bit from the non-taxable account (which should
        # have no effect on taxable income):
        self.taxable_account2 = TaxableAccount(owner=self.person2,
                                               acb=0,
                                               balance=20000,
                                               rate=0.05,
                                               nper=1)
        self.taxable_account2.add_transaction(-20000, when='start')
        self.tfsa = TFSA(owner=self.person2, balance=50000, rate=0.05, nper=1)
        self.tfsa.add_transaction(-20000, when='start')
        # Employment income is fully taxable, and only half of capital
        # gains (the income from the taxable account) is taxable:
        self.person2_taxable_income = (self.person2.gross_income +
                                       self.taxable_account2.balance / 2)
コード例 #13
0
    def setUp_decimal(self):  # pylint: disable=invalid-name
        """ Sets up mutable variables for each test call. """
        # Set up constants:
        self.initial_year = 2000
        self.constants = constants.ConstantsCanada(high_precision=Decimal)

        # Modify constants to make math easier:
        # Build some brackets with nice round numbers:
        self.constants.TAX_BRACKETS = {
            'Federal': {
                self.initial_year: {
                    Decimal(0): Decimal('0.1'),
                    Decimal(100): Decimal('0.2'),
                    Decimal(10000): Decimal('0.3')
                }
            },
            'BC': {
                self.initial_year: {
                    Decimal(0): Decimal('0.25'),
                    Decimal(1000): Decimal('0.5'),
                    Decimal(100000): Decimal('0.75')
                }
            }
        }
        self.constants.TAX_PERSONAL_DEDUCTION = {
            'Federal': {
                self.initial_year: Decimal('100')
            },
            'BC': {
                self.initial_year: Decimal('1000')
            }
        }
        self.constants.TAX_CREDIT_RATE = {
            'Federal': {
                self.initial_year: Decimal('0.1')
            },
            'BC': {
                self.initial_year: Decimal('0.25')
            }
        }
        self.constants.TAX_PENSION_CREDIT = {
            'Federal': {
                self.initial_year: Decimal('100')
            },
            'BC': {
                self.initial_year: Decimal('1000')
            }
        }
        # It's convenient (and accurate!) to use the same values
        # for the spousal amount and the personal deduction:
        self.constants.TAX_SPOUSAL_AMOUNT = (
            self.constants.TAX_PERSONAL_DEDUCTION)

        # Build 100 years of inflation adjustments.
        growth_factor = Decimal(32)
        year_range = range(self.initial_year, self.initial_year + 100)
        self.inflation_adjustments = {
            year: 1 + (year - self.initial_year) / growth_factor
            for year in year_range
        }

        # Set to default province:
        self.province = 'BC'
        self.tax = TaxCanada(self.inflation_adjustments,
                             province='BC',
                             constants=self.constants)

        # Set up some people to test on:
        # Person1 makes $100,000/yr, has a taxable account with $500,000
        # taxable income, and an RRSP with $500,000 in taxable income.
        self.person1 = Person(self.initial_year,
                              "Tester 1",
                              self.initial_year - 20,
                              retirement_date=self.initial_year + 45,
                              gross_income=100000)
        self.taxable_account1 = TaxableAccount(owner=self.person1,
                                               acb=0,
                                               balance=Decimal(1000000),
                                               rate=Decimal('0.05'),
                                               nper=1)
        self.taxable_account1.add_transaction(-Decimal(1000000), when='start')
        # NOTE: by using an RRSP here, a pension income tax credit will
        # be applied by TaxCanadaJurisdiction. Be aware of this if you
        # want to test this output against a generic Tax object with
        # Canadian brackets.
        self.rrsp = RRSP(self.person1,
                         inflation_adjust=self.inflation_adjustments,
                         contribution_room=0,
                         balance=Decimal(500000),
                         rate=Decimal('0.05'),
                         nper=1,
                         constants=self.constants)
        self.rrsp.add_transaction(-Decimal(500000), when='start')

        # Person2 makes $50,000/yr and has a taxable account with
        # $5000 taxable income.
        self.person2 = Person(self.initial_year,
                              "Tester 2",
                              self.initial_year - 18,
                              retirement_date=self.initial_year + 47,
                              gross_income=50000)
        self.taxable_account2 = TaxableAccount(owner=self.person2,
                                               acb=0,
                                               balance=Decimal(10000),
                                               rate=Decimal('0.05'),
                                               nper=1)
        self.taxable_account2.add_transaction(-Decimal(10000), when='start')