def set_rel_time(self, init_date, freq, days_per_year): self._t_0 = init_date self._var_funcs = [ InsStepFunc( vol_crv.index_time_rel_from(init_date, freq=freq, days_per_year=days_per_year), np.insert(np.power(vol_crv.data.values, 2), 0, 0.)) for vol_crv in self._vol ]
def test_prob_mono(self): """ Test the probability is monotonic w.r.t year_frac. """ x = np.array(range(0, 90)) y = np.array(range(0, 90)) * 0.01 y = np.insert(y, y.size, float('inf')) mort_func = InsStepFunc(x, y) mort_model = InsMortModel(mort_func) _probs = np.array([ mort_model.prob( namedtuple('mock_iter', ['attained_age', 'year_frac'])(0, year_frac)) for year_frac in range(0, 90) ]) self.assertTrue(all((_probs[1:] - _probs[:-1]) >= 0.0))
def test_prob_range(self): """ Test the probability is between 0 and 1. """ x = np.random.uniform(0, 90, 10) x.sort() y = np.random.uniform(0, 4, 10) y = np.insert(y, y.size, float('inf')) mort_func = InsStepFunc(x, y) mort_model = InsMortModel(mort_func) for age, year_frac in zip(np.random.uniform(0, 90, 100), np.random.uniform(0, 1, 100)): _prob = mort_model.prob( namedtuple('mock_iter', ['attained_age', 'year_frac'])(age, year_frac)) self.assertTrue(0.0 <= _prob <= 1.0)
def test_prob_limit(self): """ Test the limit case: 1. When duration is zero, the prob is zero 2. When duration is over the upper limit of age, prob is 1 """ x = np.array(range(0, 90)) y = np.array(range(0, 90)) * 0.01 y = np.insert(y, y.size, float('inf')) mort_func = InsStepFunc(x, y) mort_model = InsMortModel(mort_func) for age in range(0, 100): _prob = mort_model.prob( namedtuple('mock_iter', ['attained_age', 'year_frac'])(age, 0.0)) self.assertAlmostEqual(_prob, 0.0, 10) _prob = mort_model.prob( namedtuple('mock_iter', ['attained_age', 'year_frac'])(age, 100 - age)) self.assertAlmostEqual(_prob, 1.0, 10)
class InsMortModel(object): """ This is the mortality model. """ def __init__(self, mort_func): """ The mortality model is initialized by the mort_func, which provides the aggregate mortality intensity """ self._mort_func = mort_func def prob(self, model_iter): return 1.0 - np.exp(-1 * self._mort_func.integral( model_iter.attained_age, model_iter.year_frac)) if __name__ == '__main__': from lib.insurance import InsStepFunc from collections import namedtuple x = np.array(range(0, 90)) y = np.array(range(0, 90)) * 0.01 y = np.insert(y, y.size, float('inf')) mort_func = InsStepFunc(x, y) mort_model = InsMortModel(mort_func) for age in range(0, 90): _prob = mort_model.prob( namedtuple('mock_iter', ['attained_age', 'year_frac'])(age, 100 - age)) print(_prob)
def run_va_model(self): raw_input = {"Acct Value": 1344581.6, "Attained Age": 52.8, "ID": "000001", "Issue Age": 45.1, "Issue Date": dt.date(2005, 6, 22), "Initial Date": dt.date(2013, 2, 1), "Maturity Age": 90, "Population": 1, "Riders": dict({}), "ROP Amount": 1038872.0, "Gender": "F", "RPB": 1038872.0, "Free Withdrawal Rate": 0.1, "Asset Names": ["Fund A", "Fund B"], "Asset Values": [1344581.6/2, 1344581.6/2]} # For now, we assume the init_date is month begin step_per_year = 12 periods = 360 init_date = dt.date(2013, 2, 1) pricing_date = init_date # Set up the investment index #credit_rider = isr.InsCreditRateFixed(credit_rate) # set up the mutual fund return index init_df = [ pd.TimeSeries(data=[100], index=[init_date], name='stock A'), pd.TimeSeries(data=[100], index=[init_date], name='stock B') ] eq_index = [ip.IndexProvider(init_df[0], 'stock A'), ip.IndexProvider(init_df[1], 'stock B')] # no vol, otherwise randomness will break my test sim_engine = EqBSEngine(np.array([0.02, 0.02]), np.array([0.0, 0.0]), corr=np.array([[1., 0.3], [0.3, 1.]])) simulator = ScenarioGenerator(eq_index, sim_engine, **{'max_time_step': 5. / BDAYS_PER_YEAR}) MARKET_DATA_MANAGER.reset() MARKET_DATA_MANAGER.setup(init_date) MARKET_DATA_MANAGER.index_table[ 'stock A'] = eq_index[0] MARKET_DATA_MANAGER.index_table[ 'stock B'] = eq_index[1] MARKET_DATA_MANAGER.scen_gen_table['stock A']=simulator MARKET_DATA_MANAGER.scen_gen_table['stock B']=simulator fund_info = {'Fund A': { 'Allocations': { 'stock A': 1, 'stock B': 0, }, 'Management Fee': 0.01, 'Description': 'blah blah', }, 'Fund B': { 'Allocations': { 'stock A': 0, 'stock B': 1, }, 'Management Fee': 0.01, 'Description': 'blah blah', }, } credit_rider = isr.InsCreditRateMutualFunds(fund_info=fund_info) # Set up non-rider fees annual_fee_rate = 0.01 annual_booking_fee = 100 mgmt_fee = mif.InsFeeProp(annual_fee_rate, fee_name="Mgmt Fee") booking_fee = mif.InsFeeConst(annual_booking_fee, fee_name="Booking Fee") fees = [mgmt_fee, booking_fee] # Set up rider db_rider_fee_rate = 0.005 db_rider = mir.InsRiderDB(extract_strict(raw_input, "ROP Amount"), db_rider_fee_rate, rider_name="UWL") riders = [db_rider] # Setup investment index inv_index = credit_rider.inv_index(init_date, periods, step_per_year) # Setup iteration product = InsProduct(riders, fees, inv_index) acct = InsAcct(raw_input, product) acct_iter = acct.acct_iterator() # Setup lapse function and lapse model xs = [0] ys = [0.0, 0.1] shock_func = linear_comp_bounded(1, 0, floor=0.5, cap=1.5) lapse_model = LapseDynamic(InsStepFunc(xs, ys), shock_func, rider_name='UWL') # Setup surrender charge xs = [0] ys = [100, 100] fixed_charge_func = InsStepFunc(xs, ys) xs = [0, 1, 2] ys = [0.0, 0.3, 0.2, 0.0] pct_charge_func = InsStepFunc(xs, ys) surrender_charge = SurrenderCharge(fixed_charge_func, pct_charge_func) # Setup mortality function and mortality model xs = [x for x in range(0, 100)] ys = [0.01] * 100 ys.append(float('inf')) mort_model = InsMortModel(InsStepFunc(xs, ys)) # Setup VA Model model = InsModelVA(acct, lapse_model, mort_model, surrender_charge) model_iter = model.create_iterator(pricing_date) # model iterator to evolve the model_iter to move forward metrics = ['Account Value', 'Active Population', 'Benefit Base.UWL', 'Rider Fee.UWL', 'Benefit.UWL', 'Fee.Mgmt Fee', 'Fee.Booking Fee', 'Date', 'Attained Age', 'Anniv Flag', 'Death', 'Lapse', 'Paid Benefit.UWL', 'Surrender Charge', ] crv_aggregator = create_curve_aggregator(metrics) params = {'pricing date': init_date, 'periods': 60, 'frequency': 'MS'} proj_mgr = ProjectionManager(crv_aggregator, model_iter, **params) proj_mgr.run() df = crv_aggregator.to_dataframe() # df[['Rider Fee.UWL', 'Fee.Mgmt Fee', 'Fee.Booking Fee', 'Surrender Charge']].plot(kind='bar', stacked=True) return df
riders = [db_rider] # Setup investment index inv_index = credit_rider.inv_index(init_date, periods, step_per_year) # Setup iteration product = InsProduct(riders, fees, inv_index) acct = InsAcct(raw_input, product) acct_iter = acct.acct_iterator() # Setup lapse function and lapse model xs = [0] ys = [0.0, 0.1] shock_func = linear_comp_bounded(1, 0, floor=0.5, cap=1.5) # lapse_model = LapseStatic(InsStepFunc(xs, ys)) lapse_model = LapseDynamic(InsStepFunc(xs, ys), shock_func, rider_name='UWL') # Setup surrender charge xs = [0] ys = [100, 100] fixed_charge_func = InsStepFunc(xs, ys) xs = [0, 1, 2] ys = [0.0, 0.3, 0.2, 0.0] pct_charge_func = InsStepFunc(xs, ys) surrender_charge = SurrenderCharge(fixed_charge_func, pct_charge_func) # Setup mortality function and mortality model xs = [x for x in range(0, 100)] ys = [0.01] * 100
from Models.InsMortModel import InsMortModel from Models.InsLapseModel import SurrenderCharge, LapseDynamic from lib.insurance import InsStepFunc, linear_comp_bounded from utils.database import pickle_save #TODO: Technically, all the assumptions can be saved or generate on the fly or interact with user input #TODO: But pickel it is not working now due to the use of decorator I believe. # Setup lapse function and lapse model xs = [0] ys = [0.0, 0.1] shock_func = linear_comp_bounded(1, 0, floor=0.5, cap=1.5) lapse_model = LapseDynamic(InsStepFunc(xs, ys), shock_func, rider_name='UWL') # pickle_save(lapse_model, 'lapse_model_sample_1') # Setup surrender charge xs = [0] ys = [100, 100] fixed_charge_func = InsStepFunc(xs, ys) xs = [0, 1, 2] ys = [0.0, 0.3, 0.2, 0.0] pct_charge_func = InsStepFunc(xs, ys) surrender_charge = SurrenderCharge(fixed_charge_func, pct_charge_func) # pickle_save(surrender_charge, 'surrender_charge_sample_1') # Setup mortality function and mortality model xs = [x for x in range(0, 100)] ys = [0.01] * 100 ys.append(float('inf')) mort_model = InsMortModel(InsStepFunc(xs, ys)) # pickle_save(mort_model, 'mort_model_sample_1')
def run_fa_model(self): raw_input = { "Acct Value": 1344581.6, "Attained Age": 52.8, "ID": "000001", "Issue Age": 45.1, "Issue Date": dt.date(2005, 6, 22), "Initial Date": dt.date(2013, 2, 1), "Maturity Age": 90, "Population": 1, "Riders": dict({}), "ROP Amount": 1038872.0, "Gender": "F", "RPB": 1038872.0, "Free Withdrawal Rate": 0.1, "Asset Names": ["Credit Account"], "Asset Values": [1344581.6] } # For now, we assume the init_date is month begin step_per_year = 12 credit_rate = 0.03 periods = 360 init_date = dt.date(2013, 2, 1) pricing_date = init_date # Set up the investment index credit_rider = isr.InsCreditRateFixed(credit_rate) # Set up non-rider fees annual_fee_rate = 0.01 annual_booking_fee = 100 mgmt_fee = mif.InsFeeProp(annual_fee_rate, fee_name="Mgmt Fee") booking_fee = mif.InsFeeConst(annual_booking_fee, fee_name="Booking Fee") fees = [mgmt_fee, booking_fee] # Set up rider db_rider_fee_rate = 0.005 db_rider = mir.InsRiderDB(extract_strict(raw_input, "ROP Amount"), db_rider_fee_rate, rider_name="UWL") riders = [db_rider] # Setup investment index inv_index = credit_rider.inv_index(init_date, periods, step_per_year) # Setup iteration product = InsProduct(riders, fees, inv_index) acct = InsAcct(raw_input, product) # Setup lapse function and lapse model xs = [0] ys = [0.0, 0.1] lapse_model = LapseStatic(InsStepFunc(xs, ys)) # Setup surrender charge xs = [0] ys = [100, 100] fixed_charge_func = InsStepFunc(xs, ys) xs = [0, 1, 2] ys = [0.0, 0.3, 0.2, 0.0] pct_charge_func = InsStepFunc(xs, ys) surrender_charge = SurrenderCharge(fixed_charge_func, pct_charge_func) # Setup mortality function and mortality model xs = [x for x in range(0, 100)] ys = [0.01] * 100 ys.append(float('inf')) mort_model = InsMortModel(InsStepFunc(xs, ys)) # Setup FA Model model = InsModelFA(acct, lapse_model, mort_model, surrender_charge) model_iter = model.create_iterator(pricing_date) # model iterator to evolve the model_iter to move forward metrics = [ 'Account Value', 'Active Population', 'Benefit Base.UWL', 'Rider Fee.UWL', 'Benefit.UWL', 'Fee.Mgmt Fee', 'Fee.Booking Fee', 'Date', 'Attained Age', 'Anniv Flag', 'Death', 'Lapse', 'Paid Benefit.UWL', 'Surrender Charge', ] crv_aggregator = create_curve_aggregator(metrics) time_line = pd.date_range(init_date, periods=60, freq='MS').date prev_date = init_date for d in time_line: if d != init_date: year_frac = (d - prev_date).days / DAYS_PER_YEAR model_iter.next(d, year_frac) crv_aggregator.collect_element(model_iter) prev_date = d df = crv_aggregator.to_dataframe() return df