Exemplo n.º 1
0
    def test_reverse_mortgage(self):
        cf = ReverseMortgage(home_value=200000,
                             value_date=self.today,
                             start_date=self.retirement,
                             end_date=self.death)

        # Make sure we can use the calculator as of today
        self.assertEqual(cf.on(self.today), 0)

        # Make sure before start_date is zero
        self.assertEqual(cf.on(self.retirement - relativedelta(days=1)), 0)

        # Make sure it starts on start date, and was inflated correctly
        ret_val = cf.on(self.retirement)
        payments = months_between(self.retirement, self.death)
        self.assertAlmostEqual(
            ret_val,
            200000 * 1.001**months_between(self.today, self.retirement) /
            payments * 0.9, 4)

        # Make sure we can get end date and it is the same payment
        self.assertAlmostEqual(cf.on(self.death), ret_val, 4)

        # Make sure after end date it returns zero
        self.assertEqual(cf.on(self.death + relativedelta(days=1)), 0)

        # Make sure backwards dates raise a value error
        with self.assertRaises(ValueError):
            cf.on(self.retirement)

        # Make sure a reset allows previous dates again, and we get the same result
        cf.reset()
        self.assertEqual(ret_val, cf.on(self.retirement))
        time_series = self.get_cash_flow(cf)
        self.assertTrue(isinstance(time_series, pd.DataFrame))
Exemplo n.º 2
0
    def test_inflated_cash_flow(self):
        cf = InflatedCashFlow(amount=116,
                              today=self.today,
                              start_date=self.retirement,
                              end_date=self.dob + relativedelta(years=85))

        # Make sure we can use the calculator as of today
        self.assertEqual(cf.on(self.today), 0)

        # Make sure before start_date is zero
        self.assertEqual(cf.on(self.retirement - relativedelta(days=1)), 0)

        # Make sure it starts on start date, and was inflated correctly
        ret_val = cf.on(self.retirement)
        self.assertAlmostEqual(
            ret_val, 116 * 1.001**months_between(self.today, self.retirement),
            4)

        # Make sure we can get end date and it is inflated correctly
        self.assertAlmostEqual(
            cf.on(self.dob + relativedelta(years=85)), 116 * 1.001**
            months_between(self.today, self.dob + relativedelta(years=85)), 4)

        # Make sure after end date it returns zero
        self.assertEqual(cf.on(self.dob + relativedelta(years=85, days=1)), 0)

        # Make sure backwards dates raise a value error
        with self.assertRaises(ValueError):
            cf.on(self.retirement)

        # Make sure a reset allows previous dates again, and we get the same result
        cf.reset()
        self.assertEqual(ret_val, cf.on(self.retirement))
        time_series = self.get_cash_flow(cf)
        self.assertTrue(isinstance(time_series, pd.DataFrame))
Exemplo n.º 3
0
    def test_tax_paid_account(self):
        ac = TaxPaidAccount(name="Test Account",
                            today=self.today,
                            opening_balance=50000,
                            growth=0.05,
                            retirement_date=self.retirement,
                            end_date=self.death,
                            contributions=400)

        # Make sure we can use the calculator as of today, but attempted withdrawals fail until retirement date
        self.assertEqual(ac.balance(self.today), 50000)
        self.assertEqual(ac.withdraw(self.today, 1000), 0)
        self.assertEqual(ac.balance(self.today), 50000)

        # Make sure withdrawal before start_date is zero, but balance is inflated correctly
        r_minus_1 = self.retirement - relativedelta(days=1)

        def get_pred(months):
            pred = 50000 * (((1.05**(1 / 12)) + 0.001)**months)
            for m in range(1, months + 1):
                pred += (400 *
                         (1.001**m)) * ((1.05**(1 / 12)) + 0.001)**(months - m)
            return pred

        predicted = get_pred(months_between(self.today, r_minus_1))

        self.assertAlmostEqual(ac.balance(r_minus_1), predicted, 6)
        self.assertEqual(ac.withdraw(r_minus_1, 1000), 0)
        # Make sure the withdrawal didn't actually withdraw.
        self.assertAlmostEqual(ac.balance(r_minus_1), predicted, 6)

        # Make sure withdrawal can happen on start date, and withdrawal actually happens.
        predicted = get_pred(months_between(self.today, self.retirement))
        self.assertAlmostEqual(ac.balance(self.retirement), predicted, 6)
        self.assertEqual(ac.withdraw(self.retirement, 1000), 1000)
        self.assertAlmostEqual(ac.balance(self.retirement), predicted - 1000,
                               6)

        # Make sure we can get end date
        self.assertEqual(ac.withdraw(self.death, 1000), 1000)

        # Make sure after end date it returns zero
        self.assertEqual(ac.withdraw(self.death + relativedelta(days=1), 1000),
                         0)

        # Make sure backwards dates raise a value error
        with self.assertRaises(ValueError):
            ac.balance(self.retirement)

        # Make sure a reset allows previous dates again, and we get the same result
        ac.reset()
        self.assertAlmostEqual(ac.balance(self.retirement), predicted, 6)
        time_series = self.get_balances(ac)
        self.assertTrue(isinstance(time_series, pd.DataFrame))
Exemplo n.º 4
0
    def test_employment_income(self):
        cf = EmploymentIncome(income=150000,
                              growth=0.01,
                              today=self.today,
                              end_date=self.retirement)

        # Make sure we can use the calculator as of today
        self.assertEqual(cf.on(self.today), 150000)

        # Make sure we can get it on the end date and it is inflated correctly
        predicted = 150000 * (
            (1 + (0.01 / 12))**months_between(self.today, self.retirement))
        self.assertAlmostEqual(cf.on(self.retirement), predicted, 4)

        # Make sure after end date it returns zero
        self.assertEqual(cf.on(self.death + relativedelta(days=1)), 0)

        # Make sure backwards dates raise a value error
        with self.assertRaises(ValueError):
            cf.on(self.retirement)

        # Make sure a reset allows previous dates again, and we get the same result
        cf.reset()
        self.assertAlmostEqual(predicted, cf.on(self.retirement), 4)
        time_series = self.get_cash_flow(cf)
        self.assertTrue(isinstance(time_series, pd.DataFrame))
Exemplo n.º 5
0
 def __init__(self, home_value: float, value_date: datetime.date,
              start_date: datetime.date, end_date: datetime.date):
     """
     Initialises a reverse mortgage calculator
     :param home_value:
     :param value_date: The date the home was valued. Must be <= start_date
     :param start_date: The day the reverse mortgage should start paying (Usually the retirement date)
     :param end_date: The day the reverse mortgage should end (Usually the death of the last family member)
     """
     self.start_date = start_date
     self.end_date = end_date
     home_value_at_start_date = home_value * (
         1 + Inflation.between(value_date, start_date))
     self.monthly_payment = home_value_at_start_date * 0.9 / months_between(
         start_date, end_date)
Exemplo n.º 6
0
 def cumulative(cls):
     """
     :return: A dictionary from (year, month) => cumulative total inflation (1-based) from beginning of records till that time
     """
     data = getattr(cls, '_cum_data', None)
     if not data:
         data = cache.get(redis.Keys.INFLATION)
     if not data:
         data = {}
         vals = list(cls.objects.all().values_list('year', 'month', 'value'))
         if vals:
             f_d = date(vals[0][0], vals[0][1], 1)
             l_d = date(vals[-1][0], vals[-1][1], 1)
             if (months_between(f_d, l_d) + 1) > len(vals):
                 raise Exception("Holes exist in the inflation forecast figures, cannot proceed.")
             isum = 1
             # Add the entry for the start of the series.
             data[((f_d - timedelta(days=1)).month, (f_d - timedelta(days=1)).year)] = isum
             for val in vals:
                 isum *= 1 + val[2]
                 data[(val[0], val[1])] = isum
             cache.set(redis.Keys.INFLATION, data, timeout=60 * 60 * 24)
     cls._cum_data = data
     return data