示例#1
0
def test_life_table__axn_due(life_table):
    lxs = life_table.get_lxs()
    expected = (
        1
        + discount_factor(0.07) * (lxs[1] / lxs[0])
        + (discount_factor(0.07) ** 2) * (lxs[2] / lxs[0])
    )
    actual = life_table.axn_due(0, 0.07, 3)
    assert round(expected, 7) == round(actual, 7)
示例#2
0
def test_life_table__Nx_and_Dx_as_annuity_due_pv(life_table):
    lxs = life_table.get_lxs()
    expected = (
        1
        + discount_factor(0.07) * (lxs[1] / lxs[0])
        + (discount_factor(0.07) ** 2) * (lxs[2] / lxs[0])
    )
    actual = (life_table.Nx(0, 0.07) - life_table.Nx(3, 0.07)) / life_table.Dx(0, 0.07)
    assert round(expected, 7) == round(actual, 7)
示例#3
0
def test_life_table__Axn(life_table):
    expected = (
        (life_table.qx(0) * discount_factor(0.07))
        + (life_table.qx(1) * life_table.px(0) * discount_factor(0.07) ** (2))
        + (
            life_table.qx(2)
            * life_table.px(1)
            * life_table.px(0)
            * discount_factor(0.07) ** 3
        )
    )
    actual = life_table.Axn(0, 0.07, 3)
    assert round(expected, 7) == round(actual, 7)
示例#4
0
def test_life_table__Mx_and_Dx_as_term_insurance_pv(life_table):
    expected = (
        (life_table.qx(0) * discount_factor(0.07))
        + (life_table.qx(1) * life_table.px(0) * discount_factor(0.07) ** (2))
        + (
            life_table.qx(2)
            * life_table.px(1)
            * life_table.px(0)
            * discount_factor(0.07) ** 3
        )
    )
    actual = (life_table.Mx(0, 0.07) - life_table.Mx(3, 0.07)) / life_table.Dx(0, 0.07)
    assert round(expected, 7) == round(actual, 7)
示例#5
0
def test_life_table__Dx_as_annuity_pv(life_table):
    lxs = life_table.get_lxs()
    expected = (
        discount_factor(0.07) * (lxs[1] / lxs[0])
        + (discount_factor(0.07) ** 2) * (lxs[2] / lxs[0])
        + (discount_factor(0.07) ** 3) * (lxs[3] / lxs[0])
    )
    actual = (
        (life_table.Dx(1, 0.07) / life_table.Dx(0, 0.07))
        + (life_table.Dx(2, 0.07) / life_table.Dx(0, 0.07))
        + (life_table.Dx(3, 0.07) / life_table.Dx(0, 0.07))
    )
    assert expected == actual
示例#6
0
    def Cx(self, x: int, i: float) -> float:
        """
        Actuarial commutation function Cx

        Args:
            x: start age
            i: interest rate
        Returns:
            Failures between x and x + 1 discounted for x years
        """
        return (self.lx(x) - self.lx(x + 1)) * discount_factor(i) ** (x + 1)
示例#7
0
    def Dx(self, x: int, i: float) -> float:
        """
        Actuarial commutation function Dx

        Args:
            x: start age
            i: interest rate
        Returns:
            Population at age x discounted for x years
        """
        return self.lx(x) * discount_factor(i) ** x
示例#8
0
def test_discount_factor(interest_rates, expected):
    assert np.allclose(ann.discount_factor(interest_rates), expected, atol=1e-03)
示例#9
0
def expected_present_value(
    cash_flows: Union[Iterable, np.ndarray],
    probabilities: Union[Iterable, np.ndarray],
    interest_rates: Union[Iterable, np.ndarray],
) -> Union[float, np.ndarray]:
    """
    This function is useful for calculating variable streams of cash flows,
    interest rates, and probabilities.

    Args:
        cash_flows: payouts from time 0 to n, where time n is the last
        possible payout, e.g., (cf0, cf1, cf2, ..., cfn-1, cfn)
        probabilities: probability of a cash flow occuring from time
                       0 to n, e.g., (1p0, 2p1, 3p2, ..., npn-1)
        interest_rates: collection of interest rates to use for
                        discounting, where each interest rate is for one
                        period, e.g., (i0to1, i1to2, ..., in-1ton)

    Returns:
        The expected present value

    Example:
        Given the probabilities: 1p0 = 0.98, 2p1=0.94, 3p2=0.91

        annuity(x=0, i=0.07, n=3)

        expected_present_value((1, 1, 1), (0.98, 0.94, 0.91), (0.07, 0.07, 0.07))

        The two methods of calculating the present value of an annuity are the same

        Additionally a two-dimensional arrays of inputs can be provided to perform
        multiple expected present values at once.  The work flows below produce the
        same results:

        expected_present_value((1, 1, 1), (0.98, 0.94, 0.91), (0.07, 0.07, 0.07))

        expected_present_value((1, 1, 1), (0.88, 0.84, 0.81), (0.06, 0.06, 0.06))

        expected_present_value((1, 1, 1), (0.78, 0.74, 0.71), (0.05, 0.05, 0.05))

        expected_present_value(
            np.array([
                [1, 1, 1],
                [1, 1, 1],
                [1, 1, 1]
            ]),
            np.array([
                [0.98, 0.96, 0.91],
                [0.88, 0.86, 0.81],
                [0.78, 0.76, 0.71]
            ]),
            np.array([
                [0.07, 0.07, 0.07],
                [0.06, 0.06, 0.06],
                [0.05, 0.05, 0.05]
            ])
        )
    """
    cash_flows = np.array(cash_flows)
    probabilities = np.array(probabilities)
    interest_rates = np.array(interest_rates)

    if not cash_flows.size == probabilities.size == interest_rates.size:
        raise InvalidEPVInputs(
            "The shape of the inputs do not match! The cash "
            f"flow shape is {cash_flows.shape}, the probability "
            f"shape is {probabilities.shape}, "
            f"the interest rate shape is {interest_rates.shape}!"
        )
    if cash_flows.ndim > 2 or probabilities.ndim > 2 or interest_rates.ndim > 2:
        raise InvalidEPVInputs(
            "The dimensions of the inputs are too high! The cash "
            f"flow number of dimensions is {cash_flows.ndim}, the probability "
            f"number of dimensions is {probabilities.ndim}, "
            f"the interest rate number of dimensions is {interest_rates.ndim}! "
            "The number of dimensions for each input must be less than 3."
        )

    discount_factors = discount_factor(interest_rates)
    if interest_rates.ndim == 1:
        cumulative_product = np.nancumprod(discount_factors)
        epv = np.nansum(
            np.multiply(np.multiply(cash_flows, probabilities), cumulative_product)
        )
    else:
        cumulative_product = np.apply_along_axis(np.nancumprod, 1, discount_factors)
        epv = np.apply_along_axis(
            np.nansum,
            1,
            np.multiply(np.multiply(cash_flows, probabilities), cumulative_product),
        )
    return epv