The ProductBase Space#

Base projection logic for all products

The ProductBase space serves as the base space for concrete product spaces defined in the Run space.

This space defines main projection logic that is common for all products.

Projection parameters#

fixed_params()

Fixed parameters

proj_len()

Projection length in months

scen_index()

asmp_id()

Assumption ID

date_id()

Date ID

Model point data#

model_point()

Target model points

model_point_index()

Index for model points

model_point_table_ext()

Extended model point table

age(t)

The attained age at time t.

sex()

The sex of the model points

age_at_entry()

The age at entry of the model points

av_pp_init()

Initial account value per policy

commission_rate()

Commission rate

duration(t)

Duration of model points at t in years

duration_mth(t)

Duration of model points at t in months

duration_mth_init()

Initial duration in month

has_gmab()

Whether GMAB is attached

has_gmdb()

Whether GMDB is attached

has_surr_charge()

Whether surrender charge applies

is_wl()

Whether the model point is whole life

maint_fee_rate()

Maintenance fee per account value

policy_term()

The policy term of the model points.

premium_type()

Type of premium payment

sum_assured()

The sum assured of the model points

surr_charge_id()

ID of surrender charge pattern

Assumptions#

base_lapse_rate(t)

Base lapse rate

is_lapse_dynamic()

Whether the lapse assumption is dynamic

dyn_lapse_param()

Dynamic lapse parameters

dyn_lapse_factor(t)

Dynamic lapse factor

lapse_rate_key(t)

Index keys to retrieve lapse rates for time t

lapse_rate(t)

Lapse rate

disc_factors(t)

Discount factors.

disc_rate(t)

Discount rate to be applied at time t

disc_rate_mth(t)

Monthly discount rate

expense_acq()

Acquisition expense per policy

expense_maint()

Annual maintenance expense per policy

inflation_rate()

Inflation rate

inflation_factor(t)

The inflation factor at time t

mort_last_age()

The last age of mortality tables

base_mort_rate(t)

Base mortality rate to be applied at time t

mort_rate(t)

Mortality rates for time t

mort_rate_key(t)

Index keys to retrieve mortality rates for time t

mort_rate_mth(t)

Monthly mortality rate to be applied at time t

mort_table_id()

Mortality table IDs

Policy values#

claim_net_pp(t, kind)

Per policy claim in excess of account value

claim_pp(t, kind)

Claim per policy

coi_pp(t)

Cost of insurance charges per policy

coi_rate(t)

Cost of insurance rate per account value

premium_pp(t)

Premium amount per policy

surr_charge_key(t)

Index keys to retrieve surrender charge rates at time t

surr_charge_rate(t)

Surrender charge rate

Policy decrement#

pols_if(t)

Number of policies in-force

pols_if_at(t, timing)

Number of policies in-force

pols_if_init()

Initial number of policies in-force

pols_lapse(t)

Number of lapse

pols_death(t)

Number of death

pols_maturity(t)

Number of maturing policies

pols_new_biz(t)

Number of new business policies

Account Value#

inv_income(t)

Investment income on account value

inv_income_pp(t)

Investment income on account value per policy

inv_return_mth(t)

Rate of investment return

av_at(t, timing)

Account value in-force

av_change(t)

Change in account value

av_pp_at(t, timing)

Account value per policy

csv_pp(t)

Cash surrender value per policy

coi(t)

Cost of insurance charges

maint_fee(t)

Maintenance fee deducted from account value

maint_fee_pp(t)

Maintenance fee per policy

net_amt_at_risk(t)

Net amount at risk per policy

prem_to_av(t)

Premium portion put in account value

prem_to_av_pp(t)

Per-policy premium portion put in the account value

Cashflows#

claims(t[, kind])

Claims

claims_from_av(t, kind)

Account value taken out to pay claim

claims_over_av(t, kind)

Claim in excess of account value

commissions(t)

Commissions

expenses(t)

Expenses

surr_charge(t)

Surrender charge

net_cf(t)

Net cashflow

Margin Analysis#

margin_expense(t)

Expense margin

margin_guarantee(t)

Mortality margin

Present values#

pv_av_change()

Present value of change in account value

pv_claims([kind])

Present value of claims

pv_claims_from_av([kind])

Present value of claims

pv_claims_over_av([kind])

Present value of claims

pv_commissions()

Present value of commissions

pv_expenses()

Present value of expenses

pv_inv_income()

Present value of investment income

pv_maint_fee()

Present value of maintenance fees

pv_net_cf()

Present value of net cashflows.

pv_pols_if()

Present value of policies in-force

pv_premiums()

Present value of premiums

Results and output#

result_pv()

Result table of present value of cashflows

result_cf()

Result table of cashflows

result_pols()

Result table of policy decrement

result_sample([point_id, scen])

Sample projection result for a specific model point and scenario

excel_sample([point_id, scen])

Output sample cashflows to Excel

Validation#

check_av_roll_fwd()

Check account value roll-forward

check_margin()

Check consistency between net cashflow and margins

check_pv_net_cf()

Check present value summation

Cells Descriptions#

fixed_params()[source]#

Fixed parameters

proj_len()[source]#

Projection length in months

proj_len() returns how many months the projection for each model point should be carried out for all the model point. Defined as:

np.maximum(12 * policy_term() - duration_mth(0) + 1, 0)

Since this model carries out projections for all the model points simultaneously, the projections are actually carried out from 0 to max_proj_len for all the model points.

See also

scen_index()[source]#
asmp_id()[source]#

Assumption ID

date_id()[source]#

Date ID

model_point()[source]#

Target model points

Returns as a DataFrame the model points to be in the scope of calculation. By default, this Cells returns the entire model_point_table_ext() without change. model_point_table_ext() is the extended model point table, which extends model_point_table by joining the columns in product_spec_table. Do not directly refer to model_point_table in this formula. To select model points, change this formula so that this Cells returns a DataFrame that contains only the selected model points.

Examples

To select only the model point 1:

def model_point():
    return model_point_table_ext().loc[1:1]

To select model points whose ages at entry are 40 or greater:

def model_point():
    return model_point_table[model_point_table_ext()["age_at_entry"] >= 40]

Note that the shape of the returned DataFrame must be the same as the original DataFrame, i.e. model_point_table_ext().

When selecting only one model point, make sure the returned object is a DataFrame, not a Series, as seen in the example above where model_point_table_ext().loc[1:1] is specified instead of model_point_table_ext().loc[1].

Be careful not to accidentally change the original table held in model_point_table_ext().

model_point_index()[source]#

Index for model points

model_point_table_ext()[source]#

Extended model point table

Returns an extended model_point_table by joining product_spec_table on the spec_id column.

See also

  • model_point_table

  • product_spec_table

age(t)[source]#

The attained age at time t.

Defined as:

age_at_entry() + duration(t)
sex()[source]#

The sex of the model points

Note

This cells is not used by default.

The sex column of the DataFrame returned by model_point().

age_at_entry()[source]#

The age at entry of the model points

The age_at_entry column of the DataFrame returned by model_point().

av_pp_init()[source]#

Initial account value per policy

For existing business at time 0, returns initial per-policy accout value read from the av_pp_init column in model_point(). For new business, 0 should be entered in the column.

commission_rate()[source]#

Commission rate

duration(t)[source]#

Duration of model points at t in years

See also

duration_mth()

duration_mth(t)[source]#

Duration of model points at t in months

Indicates how many months the policies have been in-force at t. The initial values at time 0 are read from the duration_mth column in model_point_table through model_point(). Increments by 1 as t increments. Negative values of duration_mth() indicate future new business policies. For example, If the duration_mth() is -15 at time 0, the model point is issued at t=15.

See also

model_point()

duration_mth_init()[source]#

Initial duration in month

has_gmab()[source]#

Whether GMAB is attached

has_gmdb()[source]#

Whether GMDB is attached

has_surr_charge()[source]#

Whether surrender charge applies

True if surrender charge on account value applies upon lapse, False if other wise. By default, the value is read from the has_surr_charge column in model_point().

See also

is_wl()[source]#

Whether the model point is whole life

True if the model point is whole life, False if other wise. By default, the value is read from the is_wl column in model_point(). This attribute is used to determin policy_term(). If True, policy_term() is defined as mort_table_last_age() minus age_at_entry(). If False, policy_term() is read from model_point().

See also

maint_fee_rate()[source]#

Maintenance fee per account value

The rate of maintenance fee on account value each month. Set to 0.01 / 12 by default.

See also

policy_term()[source]#

The policy term of the model points.

The policy_term column of the DataFrame returned by model_point().

premium_type()[source]#

Type of premium payment

Returns a string indicating the payment type, which is either "LEVEL" if level payment, or "SINGLE" if single payment.

sum_assured()[source]#

The sum assured of the model points

The sum_assured column of the DataFrame returned by model_point().

surr_charge_id()[source]#

ID of surrender charge pattern

A string to indicate the ID of the surrender charge pattern. The ID should be one of the column names in surr_charge_table if has_surr_charge() is True.

See also

base_lapse_rate(t)[source]#

Base lapse rate

By default, the lapse rate assumption is defined by duration as:

max(0.1 - 0.01 * duration(t), 0.02)

See also

duration()

is_lapse_dynamic()[source]#

Whether the lapse assumption is dynamic

dyn_lapse_param()[source]#

Dynamic lapse parameters

dyn_lapse_factor(t)[source]#

Dynamic lapse factor

lapse_rate_key(t)[source]#

Index keys to retrieve lapse rates for time t

lapse_rate(t)[source]#

Lapse rate

disc_factors(t)[source]#

Discount factors.

Vector of the discount factors as a Numpy array. Used for calculating the present values of cashflows.

See also

disc_rate_mth()

disc_rate(t)[source]#

Discount rate to be applied at time t

disc_rate_mth(t)[source]#

Monthly discount rate

Nummpy array of monthly discount rates from time 0 to max_proj_len() - 1 defined as:

(1 + disc_rate_ann)**(1/12) - 1

See also

disc_rate_ann()

expense_acq()[source]#

Acquisition expense per policy

expense_maint()[source]#

Annual maintenance expense per policy

inflation_rate()[source]#

Inflation rate

The inflation rate to be applied to the expense assumption. By defualt it is set to 0.01.

inflation_factor(t)[source]#

The inflation factor at time t

See also

mort_last_age()[source]#

The last age of mortality tables

base_mort_rate(t)[source]#

Base mortality rate to be applied at time t

Returns a Series of the mortality rates to be applied at time t. The index of the Series is point_id, copied from model_point().

See also

mort_rate(t)[source]#

Mortality rates for time t

mort_rate_key(t)[source]#

Index keys to retrieve mortality rates for time t

mort_rate_mth(t)[source]#

Monthly mortality rate to be applied at time t

See also

mort_table_id()[source]#

Mortality table IDs

claim_net_pp(t, kind)[source]#

Per policy claim in excess of account value

claim_pp(t, kind)[source]#

Claim per policy

The claim amount per policy. The second parameter is to indicate the type of the claim, and it takes a string, which is either "DEATH", "LAPSE" or "MATURITY".

The death benefit as denoted by "DEATH", is the greater of sum_assured() and mid-month account value (av_pp_at(t, "MID_MTH")).

The surrender benefit as denoted by "LAPSE" and the maturity benefit as denoted by "MATURITY" are equal to the mid-month account value.

coi_pp(t)[source]#

Cost of insurance charges per policy

The cost of insurance charges per policy. Defined as the coi charge rate times net amount at risk per policy.

coi_rate(t)[source]#

Cost of insurance rate per account value

The cost of insuranc rate per account value per month. By default, it is set to 1.1 times the monthly mortality rate.

premium_pp(t)[source]#

Premium amount per policy

Single premium amount if premium_type() is "SINGLE", monthly premium amount if premium_type() is "LEVEL".

surr_charge_key(t)[source]#

Index keys to retrieve surrender charge rates at time t

surr_charge_rate(t)[source]#

Surrender charge rate

Surrender charge rate to be applied for lapsed policies

See also

pols_if(t)[source]#

Number of policies in-force

pols_if(t) is an alias for pols_if_at(t, "BEF_MAT").

See also

pols_if_at(t, timing)[source]#

Number of policies in-force

pols_if_at(t, timing) calculates the number of policies in-force at time t. The second parameter timing takes a string value to indicate the timing of in-force, which is either "BEF_MAT", "BEF_NB" or "BEF_DECR".

BEF_MAT

The number of policies in-force before maturity after lapse and death. At time 0, the value is read from pols_if_init(). For time > 0, defined as:

pols_if_at(t-1, "BEF_DECR") - pols_lapse(t-1) - pols_death(t-1)

BEF_NB

The number of policies in-force before new business after maturity. Defined as:

pols_if_at(t, "BEF_MAT") - pols_maturity(t)

BEF_DECR

The number of policies in-force before lapse and death after new business. Defined as:

pols_if_at(t, "BEF_NB") + pols_new_biz(t)
pols_if_init()[source]#

Initial number of policies in-force

Number of in-force policies at time 0 referenced from pols_if_at(0, "BEF_MAT").

pols_lapse(t)[source]#

Number of lapse

Number of policies decreased by lapse during t and t+1.

pols_death(t)[source]#

Number of death

Number of policies decreased by death between t and t+1

pols_maturity(t)[source]#

Number of maturing policies

The policy maturity occurs when duration_mth() equals 12 times policy_term(). The amount is equal to pols_if_at(t, "BEF_MAT").

otherwise 0.

pols_new_biz(t)[source]#

Number of new business policies

The number of new business policies. The value duration_mth(0) for the selected model point is read from the policy_count column in model_point(). If the value is 0 or negative, the model point is new business at t=0 or at t when duration_mth(t) is 0, and the pols_new_biz(t) is read from the policy_count in model_point().

See also

inv_income(t)[source]#

Investment income on account value

Investment income earned on account value during each period. For the plicies decreased by lapse and death, half the investment income is credited.

inv_income_pp(t)[source]#

Investment income on account value per policy

Investment income on account value defined as:

inv_return_mth(t) * av_pp_at(t, "BEF_INV")
inv_return_mth(t)[source]#

Rate of investment return

Rate of monthly investment return for scen_id and t read from inv_return_table()

See also

  • inv_return_table()

  • scen_id

av_at(t, timing)[source]#

Account value in-force

av_at(t, timing) calculates the total amount of account value at time t for the policies represented by a model point.

At each t, the events that change the account value balance occur in the following order:

  • Maturity

  • New business and premium payment

  • Fee deduction

The second parameter timing takes a string to indicate the timing of the account value, which is either "BEF_MAT", "BEF_NB" or "BEF_FEE".

BEF_MAT

The amount of account value before maturity, defined as:

av_pp_at(t, "BEF_PREM") * pols_if_at(t, "BEF_MAT")

BEF_NB

The amount of account value before new business after maturity, defined as:

av_pp_at(t, "BEF_PREM") * pols_if_at(t, "BEF_NB")

BEF_FEE

The amount of account value before lapse and death after new business, defined as:

av_pp_at(t, "BEF_FEE") * pols_if_at(t, "BEF_DECR")
av_change(t)[source]#

Change in account value

Change in account value during each period, defined as:

av_at(t+1, 'BEF_MAT') - av_at(t, 'BEF_MAT')

See also

av_pp_at(t, timing)[source]#

Account value per policy

av_at(t, timing) calculates the total amount of account value at time t for the policies in-force.

At each t, the events that change the account value balance occur in the following order:

  • Premium payment

  • Fee deduction

Investment income is assumed to be earned throughout each month, so at the middle of the month when death and lapse occur, half the investment income for the month is credited.

The second parameter timing takes a string to indicate the timing of the account value, which is either "BEF_PREM", "BEF_FEE", "BEF_INV" or "MID_MTH".

BEF_PREM

Account value before premium payment. At the start of the projection (i.e. when t=0), the account value is set to av_pp_init().

BEF_FEE

Account value after premium payment before fee deduction

BEF_INV

Account value after fee deduction before crediting investemnt return

MID_MTH

Account value at middle of month (t+0.5) when half the investment retun for the month is credited

csv_pp(t)[source]#

Cash surrender value per policy

coi(t)[source]#

Cost of insurance charges

The cost of insurance charges deducted from acccount values each period.

maint_fee(t)[source]#

Maintenance fee deducted from account value

See also

maint_fee_pp(t)[source]#

Maintenance fee per policy

net_amt_at_risk(t)[source]#

Net amount at risk per policy

Return sum assured net of account value per policy.

prem_to_av(t)[source]#

Premium portion put in account value

The amount of premiums net of loadings, which is put in the accoutn value.

See also

prem_to_av_pp(t)[source]#

Per-policy premium portion put in the account value

The amount of premium per policy net of loading, which is put in the accoutn value.

See also

claims(t, kind=None)[source]#

Claims

The claim amount during the period from t to t+1. The optional second parameter is for indicating the type of the claim, and it takes a string, which is either "DEATH", "LAPSE" or "MATURITY", or defaults to None to indicate the total of all the types of claims during the period.

The death benefit as denoted by "DEATH" is defined as:

claim_pp(t) * pols_death(t)

The surrender benefit as denoted by "LAPSE" is defined as:

claims_from_av(t, "LAPSE") - surr_charge(t)

The maturity benefit as denoted by "MATURITY" is defined as:

claims_from_av(t, "MATURITY")
claims_from_av(t, kind)[source]#

Account value taken out to pay claim

The part of the claim amount that is paid from account value. The second parameter takes a string indicating the type of the claim, which is either "DEATH", "LAPSE" or "MATURITY".

Death benefit is denoted by "DEATH", is defined as:

av_pp_at(t, "MID_MTH") * pols_death(t)

When the account value is greater than the death benefit, the death benefit equates to the account value.

Surrender benefit as denoted by "LAPSE" is defined as:

av_pp_at(t, "MID_MTH") * pols_lapse(t)

As the surrender benefit is defined as account value less surrender charge, when there is no surrender charge the surrender benefit equates to the account value.

Maturity benefit as denoted by "MATURITY" is defined as:

av_pp_at(t, "BEF_PREM") * pols_maturity(t)

By default, the maturity benefit equates to the account value of maturing policies.

claims_over_av(t, kind)[source]#

Claim in excess of account value

The amount of death benefits in excess of account value. coi() net of this amount represents mortality margin.

See also

  • margin_mortality()

  • coi()

commissions(t)[source]#

Commissions

By default, 100% premiums for the first year, 0 otherwise.

See also

expenses(t)[source]#

Expenses

Expenses during the period from t to t+1 defined as the sum of acquisition expenses and maintenance expenses. The acquisition expenses are modeled as expense_acq() times pols_new_biz(). The maintenance expenses are modeled as expense_maint() times inflation_factor() times pols_if_at() before decrement.

surr_charge(t)[source]#

Surrender charge

Surrender charge rate times account values of lapsed policies

net_cf(t)[source]#

Net cashflow

Net cashflow for the period from t to t+1 defined as:

premiums(t) - claims(t) - expenses(t) - commissions(t)

See also

margin_expense(t)[source]#

Expense margin

Expense margin is defined as the sum of premium loading, surrender charge and maintenance fees net of commissions and expenses.

The sum of the expense margin and mortality margin add up to the net cashflow.

margin_guarantee(t)[source]#

Mortality margin

Mortality margin is defined coi() net of claims_over_av().

The sum of the expense margin and mortality margin add up to the net cashflow.

pv_av_change()[source]#

Present value of change in account value

pv_claims(kind=None)[source]#

Present value of claims

See claims() for the parameter kind.

pv_claims_from_av(kind=None)[source]#

Present value of claims

See claims() for the parameter kind.

pv_claims_over_av(kind=None)[source]#

Present value of claims

See claims() for the parameter kind.

pv_commissions()[source]#

Present value of commissions

pv_expenses()[source]#

Present value of expenses

pv_inv_income()[source]#

Present value of investment income

The discounted sum of monthly investment income.

pv_maint_fee()[source]#

Present value of maintenance fees

pv_net_cf()[source]#

Present value of net cashflows.

Defined as:

pv_premiums() + pv_inv_income()
- pv_claims() - pv_expenses() - pv_commissions() - pv_av_change()
pv_pols_if()[source]#

Present value of policies in-force

Note

This cells is not used by default.

The discounted sum of the number of in-force policies at each month. It is used as the annuity factor for calculating net_premium_pp().

pv_premiums()[source]#

Present value of premiums

See also

result_pv()[source]#

Result table of present value of cashflows

result_cf()[source]#

Result table of cashflows

result_pols()[source]#

Result table of policy decrement

result_sample(point_id=1, scen=1)[source]#

Sample projection result for a specific model point and scenario

excel_sample(point_id=1, scen=1)[source]#

Output sample cashflows to Excel

check_av_roll_fwd()[source]#

Check account value roll-forward

Returns Ture if av_at(t+1, "BEF_NB") equates to the following expression for all t, otherwise returns False:

av_at(t, "BEF_MAT")
      + prem_to_av(t)
      - maint_fee(t)
      - coi(t)
      + inv_income(t)
      - claims_from_av(t, "DEATH")
      - claims_from_av(t, "LAPSE")
      - claims_from_av(t, "MATURITY"))
check_margin()[source]#

Check consistency between net cashflow and margins

Returns True if net_cf() equates to the sum of margin_expense() and margin_mortality() for all t, otherwise, returns False.

See also

check_pv_net_cf()[source]#

Check present value summation

Check if the present value of net_cf() matches the sum of the present values of each cashflow. Returns the check result as True or False.