Actuarial present value of a payment stream under mortality
Source:R/apv_life_flow.R
apv_life_flow.RdComputes the actuarial present value (APV) of a cash-flow stream contingent on survival. The life table is supplied as the first argument (pipe-friendly). Payments may be specified by numeric times or by calendar dates.
Usage
apv_life_flow(
lt,
ages,
t = NULL,
date = NULL,
date0 = NULL,
cf,
i,
i_type = "effective",
m = 1L,
status = c("single", "first", "last", "reversionary"),
alpha = NULL,
plot = FALSE
)Arguments
- lt
A life table data frame with column
xand at least one oflx,px, orqx.- ages
Integer vector of actuarial ages. Use length 1 for a single life and length 2 or more for multiple lives.
- t
Numeric vector of payment times in years, measured from time 0. Provide either
tordate.- date
Optional vector of
Datepayment dates. Provide eithertordate.- date0
Optional
Dateused as time 0 whendateis provided. If missing, the minimum ofdateis used.- cf
Numeric vector of cash flows. Must have the same length as
tordate.- i
Numeric scalar. Annual interest-rate input.
- i_type
Character string indicating the interest-rate type. Allowed values are
"effective","nominal_interest","nominal_discount", and"force".- m
Positive integer. Conversion frequency for nominal rates. Ignored for
i_type = "effective"andi_type = "force".- status
Survival status:
"single","first","last", or"reversionary".- alpha
Reversionary fraction for
status = "reversionary". While all lives are alive, full benefit is paid; while at least one but not all are alive,alphatimes the benefit is paid.- plot
Logical. If
TRUE, attaches a ggplot object inattr(result, "plot")showing cumulative APV over time.
Value
A tibble with one row per payment and columns:
t, cf, surv_prob, discount,
expected_cf, pv, and pv_cum. If date was
provided, a date column is included. The total APV is stored as
attr(result, "apv").
The contingency attribute identifies "survival" or "weighted"
(reversionary benefit fraction) for plot_contingent_cash_flow().
Details
Multiple lives are supported under an independence assumption, through
common statuses: single-life, first-death (all alive), last-survivor
(any alive), and reversionary (joint-and-survivor) with fraction
alpha.
This function follows the compact actuarial notation used throughout
tidyactuarial: t denotes payment time, cf denotes cash
flows, i denotes the interest rate, i_type denotes the
interest-rate type, and m denotes the conversion frequency for nominal
rates.
For each payment at time \(t\), the APV contribution is $$PV(t) = C(t) v^t P(\text{status alive at } t).$$
The survival probability depends on the status:
"single": \({}_t p_x\) for a single life."first": \({}_t p_{x_1} \cdot {}_t p_{x_2} \cdots\), so all lives must be alive."last": \(1 - \prod_j (1 - {}_t p_{x_j})\), so at least one life must be alive."reversionary": full benefit while all lives are alive, and fraction \(\alpha\) while at least one but not all lives are alive.
Fractional-year survival is computed under UDD within each year. Discounting uses the log accumulation rate from the original interest specification. A displayed discount factor may be zero or infinite even when its monetary APV contribution is representable.
Unknown mortality intervals produce missing contributions, unless survival
has already reached zero. Missing numeric payment times and cash flows are
retained as missing rows. Cumulative APV follows input row order and remains
missing after a missing contribution. For compatibility, the apv attribute
is the sum of nonmissing contributions (zero if none are known), so it is a
subtotal when any contribution is missing, not a complete contract valuation.
Calendar times use actual elapsed days divided by 365.25; all dates must be
finite and nonmissing. Payments at the same time remain separate rows.
Examples
lt <- data.frame(
x = 40:100,
lx = seq(100000, 0, length.out = 61)
)
apv_life_flow(
lt = lt,
ages = 40,
t = c(1, 2, 3),
cf = c(100, 100, 100),
i = 0.05
)
#> # A tibble: 3 × 7
#> t cf surv_prob discount expected_cf pv pv_cum
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1 100 0.983 0.952 98.3 93.7 93.7
#> 2 2 100 0.967 0.907 96.7 87.7 181.
#> 3 3 100 0.95 0.864 95 82.1 263.
apv_life_flow(
lt = lt,
ages = c(60, 58),
t = c(1, 2, 3),
cf = c(100, 100, 100),
i = 0.05,
status = "first"
)
#> # A tibble: 3 × 7
#> t cf surv_prob discount expected_cf pv pv_cum
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1 100 0.952 0.952 95.2 90.6 90.6
#> 2 2 100 0.905 0.907 90.5 82.1 173.
#> 3 3 100 0.859 0.864 85.9 74.2 247.