Generating 100K model points#
This notebook generates the sample model points ued by the “3. Memory-Optimized Mutiprocess Example” notebook. A DataFrame of 100,000 model points is generated and saved to an Excel file named model_point_table_100K.xlsx in the current directory. The generated model point file can be loaded back by calling pandas’ read_excel
function with index_col=0
. The DataFrame can be used with CashValue_ME
by setting it to model_point_table
in the Projection
space.
Index and Columns:
point_id
(Index): Model point identifierspec_id
: Character identifier (‘A’,’B’,’C’ and ‘D’) representing the product specs of the model point.product_spec_table
inCashValue_ME.Projection
defines the product specs for each identifier.age_at_entry
: Issue age. The samples are distributed uniformly from 20 to 59.sex
: “M” or “F” to indicate policy holder’s sex.policy_term
: Policy term in years. The samples are evenly distriubted among 10, 15 and 20.policy_count
: The number of policies. Uniformly distributed from 0 to 100.sum_assured
: Sum assured. The samples are uniformly distributed from 10,000 to 1,000,000.duration_mth
: Months elapsed from the issue til t=0. New business is assumed so 0 for all model points.premium_pp
: Premium per policy.av_pp_init
: Initial account value per policy for existing policies. 0 for all model points.
Number of model points:
100,000
Click the badge below to run this notebook online on Google Colab. You need a Google account and need to be logged in to it to run this notebook on Google Colab.
The next code cell below is relevant only when you run this notebook on Google Colab. It installs lifelib and creates a copy of the library for this notebook.
[1]:
import sys, os
if 'google.colab' in sys.modules:
lib = 'savings'; lib_dir = '/content/'+ lib
if not os.path.exists(lib_dir):
!pip install lifelib
import lifelib; lifelib.create(lib, lib_dir)
%cd $lib_dir
[2]:
import numpy as np
from numpy.random import default_rng # Requires NumPy 1.17 or newer
rng = default_rng(12345)
# Number of Model Points
MPCount = 100000
# Issue Age (Integer): 20 - 59 year old
age_at_entry = rng.integers(low=20, high=60, size=MPCount)
# Sex (Char)
Sex = ["M", "F"]
sex = np.fromiter(map(lambda i: Sex[i], rng.integers(low=0, high=len(Sex), size=MPCount)), np.dtype('<U1'))
# Policy Term (Integer, modified later for whole life): 10, 15, 20
policy_term = rng.integers(low=0, high=3, size=MPCount) * 5 + 10
# Sum Assured (Float): 10,000 - 1,000,000
sum_assured = np.round((1_000_000 - 10_000) * rng.random(size=MPCount) + 10_000, -3)
# Policy Count (Integer): 1
policy_count = np.rint(100 * rng.random(size=MPCount)).astype(int)
[3]:
import pandas as pd
attrs = [
"age_at_entry",
"sex",
"policy_term",
"policy_count",
"sum_assured"
]
data = [
age_at_entry,
sex,
policy_term,
policy_count,
sum_assured
]
model_point_table = pd.DataFrame(dict(zip(attrs, data)), index=range(1, MPCount+1))
model_point_table.index.name = "policy_id"
[4]:
# Spec ID
SpedIDs = "ABCD"
spec_ids = np.fromiter(map(lambda i: SpedIDs[i], rng.integers(low=0, high=len(SpedIDs), size=MPCount)), np.dtype('<U1'))
model_point_table.insert(0, 'spec_id', spec_ids)
whole_life = (model_point_table['spec_id'] == 'C') | (model_point_table['spec_id'] == 'D')
# Modify Policy Term
model_point_table['policy_term'].mask(whole_life, 9999, inplace=True)
# Set Duration to 0
model_point_table['duration_mth'] = 0
# Premium per Plicy (by adjusting size between single premium(A and B) and level premium(C and D) policies)
premium_pp = np.ceil(model_point_table['sum_assured'] / (80 - model_point_table['age_at_entry']) / 12 / 100) * 100
model_point_table.insert(len(model_point_table.columns), 'premium_pp', model_point_table['sum_assured'])
model_point_table['premium_pp'].mask(whole_life, premium_pp, inplace=True)
# Ininital Account Value per Policy
model_point_table['av_pp_init'] = 0
[5]:
model_point_table
[5]:
spec_id | age_at_entry | sex | policy_term | policy_count | sum_assured | duration_mth | premium_pp | av_pp_init | |
---|---|---|---|---|---|---|---|---|---|
policy_id | |||||||||
1 | A | 47 | M | 20 | 22 | 804000.0 | 0 | 804000.0 | 0 |
2 | C | 29 | F | 9999 | 75 | 519000.0 | 0 | 900.0 | 0 |
3 | A | 51 | F | 10 | 5 | 409000.0 | 0 | 409000.0 | 0 |
4 | B | 32 | M | 15 | 60 | 128000.0 | 0 | 128000.0 | 0 |
5 | D | 28 | M | 9999 | 45 | 698000.0 | 0 | 1200.0 | 0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
99996 | A | 21 | M | 10 | 34 | 152000.0 | 0 | 152000.0 | 0 |
99997 | D | 24 | F | 9999 | 53 | 928000.0 | 0 | 1400.0 | 0 |
99998 | B | 46 | F | 15 | 72 | 662000.0 | 0 | 662000.0 | 0 |
99999 | A | 46 | M | 15 | 36 | 583000.0 | 0 | 583000.0 | 0 |
100000 | B | 35 | M | 15 | 3 | 638000.0 | 0 | 638000.0 | 0 |
100000 rows × 9 columns
[6]:
model_point_table.to_excel('model_point_table_100K.xlsx')