Active Lives - Deterministic¶
Valuation Model¶
Documentation¶
-
class
ActiveLivesValEMD
(*, extract_base: pandas.core.frame.DataFrame, extract_riders: pandas.core.frame.DataFrame, valuation_dt: pandas._libs.tslibs.timestamps.Timestamp, assumption_set: str, net_benefit_method: str, modifier_ctr: float = 1.0, modifier_incidence=1.0, modifier_interest: float = 1.0, modifier_lapse=1.0, modifier_mortality=1.0)¶ Active lives deterministic valuation extract model.
This model takes an extract of policies and runs them through the respective Policy Models based on the COVERAGE_ID column (i.e., whether it is base policy or rider).
Parameters
- extract_baseDataFrame
The active lives base extract.
- extract_ridersDataFrame
The active lives rider extract.
- valuation_dtTimestamp
The valuation date which reserves are based.
- assumption_setstr
The assumption set to use for running the model. Options are :
stat
gaap
best-estimate
- net_benefit_methodstr
The net benefit method. Options are :
NLP = Net level premium
PT1 = 1 year preliminary term
PT2 = 2 year preliminary term
Sensitivities
- modifier_ctrfloat
Modifier for CTR.
- modifier_incidence
The incidence rate modifier.
- modifier_interestfloat
Interest rate modifier.
- modifier_lapse
The withdraw rate modifier
- modifier_mortality
The withdraw rate modifier
Meta
- model_versionstr
The model version generated by versioneer.
- last_commitstr
The last git commit.
- run_date_timeTimestamp
The run date and time.
Intermediates
- recordsdict
The extract transformed to records.
Returns
- projectedDataFrame
The projected reserves for the policyholders.
- time_0DataFrame
The time 0 reserve for the policyholders
- errorslist
Any errors captured.
Steps
Create Records from Extract - Turn extract into a list of records for each row in extract.
Run Records with Policy Models - Foreach record run through respective policy model based on COVERAGE_ID value.
Get Time0 Values - Filter projected reserves frame down to time_0 reserve for each record.
Usage¶
import pandas as pd
from footings_idi_model.models import ActiveLivesValEMD
extract_base = pd.read_csv(
"active-lives-sample-base.csv",
parse_dates=["BIRTH_DT", "POLICY_START_DT", "PREMIUM_PAY_TO_DT", "POLICY_END_DT"]
)
extract_base
POLICY_ID | BIRTH_DT | GENDER | TOBACCO_USAGE | COVERAGE_ID | POLICY_START_DT | PREMIUM_PAY_TO_DT | POLICY_END_DT | ELIMINATION_PERIOD | GROSS_PREMIUM | GROSS_PREMIUM_FREQ | BENEFIT_AMOUNT | IDI_OCCUPATION_CLASS | IDI_CONTRACT | IDI_BENEFIT_PERIOD | IDI_MARKET | COLA_PERCENT | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | M1 | 1978-08-01 | F | N | BASE | 2018-03-06 | 2048-07-31 | 2048-07-31 | 360 | 10 | MONTH | 100 | M | AS | TO70 | INDV | 0.02 |
1 | M1 | 1978-08-01 | F | N | ROP | 2018-03-06 | 2048-07-31 | 2048-07-31 | 360 | 10 | MONTH | 100 | M | AS | TO70 | INDV | 0.02 |
2 | M2 | 1967-11-03 | M | N | BASE | 2018-01-19 | 2032-11-02 | 2032-11-02 | 14 | 10 | MONTH | 100 | 4 | AS | 18M | INDV | 0.00 |
3 | M3 | 1982-06-17 | M | N | BASE | 2007-06-19 | 2047-06-16 | 2047-06-16 | 180 | 10 | MONTH | 100 | M | AS | TO65 | INDV | 0.03 |
4 | M3 | 1982-06-17 | M | N | ROP | 2007-06-19 | 2047-06-16 | 2047-06-16 | 180 | 10 | MONTH | 100 | M | AS | TO65 | INDV | 0.03 |
5 | M4 | 1974-03-08 | F | Y | BASE | 2009-10-06 | 2041-03-07 | 2041-03-07 | 90 | 10 | MONTH | 100 | 1 | AS | TO67 | INDV | 0.03 |
6 | M4 | 1974-03-08 | F | Y | ROP | 2009-10-06 | 2041-03-07 | 2041-03-07 | 90 | 10 | MONTH | 100 | 1 | AS | TO67 | INDV | 0.03 |
7 | M5 | 1972-12-10 | F | Y | BASE | 2003-01-29 | 2037-12-09 | 2037-12-09 | 90 | 10 | MONTH | 100 | 2 | AO | TO65 | INDV | 0.03 |
8 | M5 | 1972-12-10 | F | Y | ROP | 2003-01-29 | 2037-12-09 | 2037-12-09 | 90 | 10 | MONTH | 100 | 2 | AO | TO65 | INDV | 0.03 |
extract_riders = pd.read_csv("active-lives-sample-riders.csv")
extract_riders
POLICY_ID | COVERAGE_ID | RIDER_ATTRIBUTE | VALUE | |
---|---|---|---|---|
0 | M1 | ROP | rop_return_freq | 10.0 |
1 | M1 | ROP | rop_return_percent | 0.8 |
2 | M1 | ROP | rop_claims_paid | 0.0 |
3 | M3 | ROP | rop_return_freq | 7.0 |
4 | M3 | ROP | rop_return_percent | 0.5 |
5 | M3 | ROP | rop_claims_paid | 0.0 |
6 | M4 | ROP | rop_return_freq | 10.0 |
7 | M4 | ROP | rop_return_percent | 0.5 |
8 | M4 | ROP | rop_claims_paid | 1000.0 |
9 | M5 | ROP | rop_return_freq | 7.0 |
10 | M5 | ROP | rop_return_percent | 0.8 |
11 | M5 | ROP | rop_claims_paid | 0.0 |
model = ActiveLivesValEMD(
extract_base=extract_base,
extract_riders=extract_riders,
valuation_dt=pd.Timestamp("2020-03-31"),
assumption_set="STAT",
net_benefit_method="NLP",
)
To run the model call the run
method which returns -
the projected reserve for each policy in the extract (
projected
),the reserve as of the valuation date for each policy (
time0
), andpolicies that error out when the model runs (
run
).
projected, time0, errors = model.run()
/home/runner/work/footings-idi-model/footings-idi-model/.venv/lib/python3.8/site-packages/pandas/core/series.py:726: RuntimeWarning: divide by zero encountered in log
result = getattr(ufunc, method)(*inputs, **kwargs)
/home/runner/work/footings-idi-model/footings-idi-model/.venv/lib/python3.8/site-packages/pandas/core/series.py:726: RuntimeWarning: divide by zero encountered in log
result = getattr(ufunc, method)(*inputs, **kwargs)
/home/runner/work/footings-idi-model/footings-idi-model/.venv/lib/python3.8/site-packages/pandas/core/series.py:726: RuntimeWarning: divide by zero encountered in log
result = getattr(ufunc, method)(*inputs, **kwargs)
/home/runner/work/footings-idi-model/footings-idi-model/.venv/lib/python3.8/site-packages/pandas/core/series.py:726: RuntimeWarning: divide by zero encountered in log
result = getattr(ufunc, method)(*inputs, **kwargs)
/home/runner/work/footings-idi-model/footings-idi-model/.venv/lib/python3.8/site-packages/pandas/core/series.py:726: RuntimeWarning: divide by zero encountered in log
result = getattr(ufunc, method)(*inputs, **kwargs)
/home/runner/work/footings-idi-model/footings-idi-model/.venv/lib/python3.8/site-packages/pandas/core/series.py:726: RuntimeWarning: divide by zero encountered in log
result = getattr(ufunc, method)(*inputs, **kwargs)
/home/runner/work/footings-idi-model/footings-idi-model/.venv/lib/python3.8/site-packages/pandas/core/series.py:726: RuntimeWarning: divide by zero encountered in log
result = getattr(ufunc, method)(*inputs, **kwargs)
/home/runner/work/footings-idi-model/footings-idi-model/.venv/lib/python3.8/site-packages/pandas/core/series.py:726: RuntimeWarning: divide by zero encountered in log
result = getattr(ufunc, method)(*inputs, **kwargs)
/home/runner/work/footings-idi-model/footings-idi-model/.venv/lib/python3.8/site-packages/pandas/core/series.py:726: RuntimeWarning: divide by zero encountered in log
result = getattr(ufunc, method)(*inputs, **kwargs)
/home/runner/work/footings-idi-model/footings-idi-model/.venv/lib/python3.8/site-packages/pandas/core/series.py:726: RuntimeWarning: divide by zero encountered in log
result = getattr(ufunc, method)(*inputs, **kwargs)
Note the time0
and projected
have the same columns with time0
being a subset of the projected
frame.
projected.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 207 entries, 2 to 34
Data columns (total 24 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 MODEL_VERSION 207 non-null object
1 LAST_COMMIT 207 non-null object
2 RUN_DATE_TIME 207 non-null datetime64[ns]
3 SOURCE 207 non-null object
4 POLICY_ID 207 non-null object
5 COVERAGE_ID 207 non-null object
6 DATE_BD 207 non-null datetime64[ns]
7 DATE_ED 207 non-null datetime64[ns]
8 DURATION_YEAR 207 non-null Int64
9 LIVES_BD 207 non-null float64
10 LIVES_MD 207 non-null float64
11 LIVES_ED 207 non-null float64
12 DISCOUNT_BD 207 non-null float64
13 DISCOUNT_MD 207 non-null float64
14 DISCOUNT_ED 207 non-null float64
15 BENEFIT_AMOUNT 207 non-null int64
16 INCIDENCE_RATE 207 non-null float64
17 BENEFIT_COST 206 non-null float64
18 PVFB 207 non-null float64
19 PVFNB 207 non-null float64
20 ALR_BD 207 non-null float64
21 ALR_ED 207 non-null float64
22 ALR_DATE 207 non-null datetime64[ns]
23 ALR 207 non-null float64
dtypes: Int64(1), datetime64[ns](4), float64(13), int64(1), object(5)
memory usage: 40.6+ KB
projected
MODEL_VERSION | LAST_COMMIT | RUN_DATE_TIME | SOURCE | POLICY_ID | COVERAGE_ID | DATE_BD | DATE_ED | DURATION_YEAR | LIVES_BD | ... | DISCOUNT_ED | BENEFIT_AMOUNT | INCIDENCE_RATE | BENEFIT_COST | PVFB | PVFNB | ALR_BD | ALR_ED | ALR_DATE | ALR | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2 | 0.6.0 | 5d026f4756f03f9cb797de5a8f0c3c6d2b349ccb | 2021-03-25 11:27:59.453717 | AValBasePMD | M1 | BASE | 2020-03-06 | 2021-03-06 | 3 | 0.997402 | ... | 0.915142 | 100 | 0.002228 | 30.688392 | 773.833863 | 746.848211 | 28.703659 | 41.720113 | 2020-03-31 | 29.45 |
3 | 0.6.0 | 5d026f4756f03f9cb797de5a8f0c3c6d2b349ccb | 2021-03-25 11:27:59.453717 | AValBasePMD | M1 | BASE | 2021-03-06 | 2022-03-06 | 4 | 0.995975 | ... | 0.888487 | 100 | 0.002365 | 32.215403 | 745.408331 | 707.382176 | 41.720113 | 53.600038 | 2021-03-31 | 42.44 |
4 | 0.6.0 | 5d026f4756f03f9cb797de5a8f0c3c6d2b349ccb | 2021-03-25 11:27:59.453717 | AValBasePMD | M1 | BASE | 2022-03-06 | 2023-03-06 | 5 | 0.994452 | ... | 0.862609 | 100 | 0.002525 | 33.930135 | 716.479136 | 669.120430 | 53.600038 | 64.120353 | 2022-03-31 | 54.26 |
5 | 0.6.0 | 5d026f4756f03f9cb797de5a8f0c3c6d2b349ccb | 2021-03-25 11:27:59.453717 | AValBasePMD | M1 | BASE | 2023-03-06 | 2024-03-06 | 6 | 0.992811 | ... | 0.837484 | 100 | 0.002684 | 35.552118 | 686.943074 | 632.029939 | 64.120353 | 73.336151 | 2023-03-31 | 64.71 |
6 | 0.6.0 | 5d026f4756f03f9cb797de5a8f0c3c6d2b349ccb | 2021-03-25 11:27:59.453717 | AValBasePMD | M1 | BASE | 2024-03-06 | 2025-03-06 | 7 | 0.991034 | ... | 0.813092 | 100 | 0.002875 | 37.431773 | 656.946344 | 596.079170 | 73.336151 | 80.948847 | 2024-03-31 | 73.83 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
30 | 0.6.0 | 5d026f4756f03f9cb797de5a8f0c3c6d2b349ccb | 2021-03-25 11:27:59.453717 | AValRopRPMD | M5 | ROP | 2033-01-29 | 2034-01-29 | 31 | 0.921102 | ... | 0.399987 | 100 | 0.000000 | 0.000000 | 214.558780 | 150.518335 | 168.757613 | 264.151963 | 2033-03-31 | 182.07 |
31 | 0.6.0 | 5d026f4756f03f9cb797de5a8f0c3c6d2b349ccb | 2021-03-25 11:27:59.453717 | AValRopRPMD | M5 | ROP | 2034-01-29 | 2035-01-29 | 32 | 0.913448 | ... | 0.388337 | 100 | 0.000000 | 0.000000 | 214.558780 | 118.046290 | 264.151963 | 363.484402 | 2034-03-31 | 278.83 |
32 | 0.6.0 | 5d026f4756f03f9cb797de5a8f0c3c6d2b349ccb | 2021-03-25 11:27:59.453717 | AValRopRPMD | M5 | ROP | 2035-01-29 | 2036-01-29 | 33 | 0.905227 | ... | 0.377026 | 100 | 0.000000 | 0.000000 | 214.558780 | 86.782017 | 363.484402 | 467.074761 | 2035-03-31 | 379.26 |
33 | 0.6.0 | 5d026f4756f03f9cb797de5a8f0c3c6d2b349ccb | 2021-03-25 11:27:59.453717 | AValRopRPMD | M5 | ROP | 2036-01-29 | 2037-01-29 | 34 | 0.896410 | ... | 0.366045 | 100 | 0.000000 | 0.000000 | 214.558780 | 56.701535 | 467.074761 | 575.287050 | 2036-03-31 | 483.86 |
34 | 0.6.0 | 5d026f4756f03f9cb797de5a8f0c3c6d2b349ccb | 2021-03-25 11:27:59.453717 | AValRopRPMD | M5 | ROP | 2037-01-29 | 2038-01-29 | 35 | 0.886962 | ... | 0.355383 | 100 | 0.000000 | 672.000000 | 214.558780 | 27.781635 | 575.287050 | 0.000000 | 2037-03-31 | 0.00 |
207 rows × 24 columns
time0
MODEL_VERSION | LAST_COMMIT | RUN_DATE_TIME | SOURCE | POLICY_ID | COVERAGE_ID | ALR_DATE | ALR | |
---|---|---|---|---|---|---|---|---|
2 | 0.6.0 | 5d026f4756f03f9cb797de5a8f0c3c6d2b349ccb | 2021-03-25 11:27:59.453717 | AValBasePMD | M1 | BASE | 2020-03-31 | 29.45 |
2 | 0.6.0 | 5d026f4756f03f9cb797de5a8f0c3c6d2b349ccb | 2021-03-25 11:27:59.453717 | AValRopRPMD | M1 | ROP | 2020-03-31 | 174.05 |
2 | 0.6.0 | 5d026f4756f03f9cb797de5a8f0c3c6d2b349ccb | 2021-03-25 11:27:59.453717 | AValBasePMD | M2 | BASE | 2020-03-31 | 26.68 |
12 | 0.6.0 | 5d026f4756f03f9cb797de5a8f0c3c6d2b349ccb | 2021-03-25 11:27:59.453717 | AValBasePMD | M3 | BASE | 2020-03-31 | 188.23 |
12 | 0.6.0 | 5d026f4756f03f9cb797de5a8f0c3c6d2b349ccb | 2021-03-25 11:27:59.453717 | AValRopRPMD | M3 | ROP | 2020-03-31 | 339.68 |
10 | 0.6.0 | 5d026f4756f03f9cb797de5a8f0c3c6d2b349ccb | 2021-03-25 11:27:59.453717 | AValBasePMD | M4 | BASE | 2020-03-31 | 77.36 |
10 | 0.6.0 | 5d026f4756f03f9cb797de5a8f0c3c6d2b349ccb | 2021-03-25 11:27:59.453717 | AValRopRPMD | M4 | ROP | 2020-03-31 | 0.00 |
17 | 0.6.0 | 5d026f4756f03f9cb797de5a8f0c3c6d2b349ccb | 2021-03-25 11:27:59.453717 | AValBasePMD | M5 | BASE | 2020-03-31 | 0.00 |
17 | 0.6.0 | 5d026f4756f03f9cb797de5a8f0c3c6d2b349ccb | 2021-03-25 11:27:59.453717 | AValRopRPMD | M5 | ROP | 2020-03-31 | 277.58 |
errors
[]
An audit of the model is ran by calling the audit
method as shown below.
model.audit("Audit-ActiveLivesValEMD.xlsx")
/home/runner/work/footings-idi-model/footings-idi-model/.venv/lib/python3.8/site-packages/pandas/core/series.py:726: RuntimeWarning: divide by zero encountered in log
result = getattr(ufunc, method)(*inputs, **kwargs)
/home/runner/work/footings-idi-model/footings-idi-model/.venv/lib/python3.8/site-packages/pandas/core/series.py:726: RuntimeWarning: divide by zero encountered in log
result = getattr(ufunc, method)(*inputs, **kwargs)
/home/runner/work/footings-idi-model/footings-idi-model/.venv/lib/python3.8/site-packages/pandas/core/series.py:726: RuntimeWarning: divide by zero encountered in log
result = getattr(ufunc, method)(*inputs, **kwargs)
/home/runner/work/footings-idi-model/footings-idi-model/.venv/lib/python3.8/site-packages/pandas/core/series.py:726: RuntimeWarning: divide by zero encountered in log
result = getattr(ufunc, method)(*inputs, **kwargs)
/home/runner/work/footings-idi-model/footings-idi-model/.venv/lib/python3.8/site-packages/pandas/core/series.py:726: RuntimeWarning: divide by zero encountered in log
result = getattr(ufunc, method)(*inputs, **kwargs)
/home/runner/work/footings-idi-model/footings-idi-model/.venv/lib/python3.8/site-packages/pandas/core/series.py:726: RuntimeWarning: divide by zero encountered in log
result = getattr(ufunc, method)(*inputs, **kwargs)
/home/runner/work/footings-idi-model/footings-idi-model/.venv/lib/python3.8/site-packages/pandas/core/series.py:726: RuntimeWarning: divide by zero encountered in log
result = getattr(ufunc, method)(*inputs, **kwargs)
/home/runner/work/footings-idi-model/footings-idi-model/.venv/lib/python3.8/site-packages/pandas/core/series.py:726: RuntimeWarning: divide by zero encountered in log
result = getattr(ufunc, method)(*inputs, **kwargs)
/home/runner/work/footings-idi-model/footings-idi-model/.venv/lib/python3.8/site-packages/pandas/core/series.py:726: RuntimeWarning: divide by zero encountered in log
result = getattr(ufunc, method)(*inputs, **kwargs)
The audit file can be downloaded here.