def index(self): """return a dataframe, keep API the same after introducing .indices, which is a list ot ts""" result = pd.concat([x.data for x in self.indices], join='outer', axis=1) result.columns = self.index_names result = ip.IndexProvider(result) return result
def asset_return(self, _prev_date): # reorder the inv index to be consistent with asset names if needed. # if the investment index is of a single asset: use that asset for all accounts -> dangerous # TODO: more strict asset setting: crediting index must have the same asset name as self._asset_names return_index = self._inv_index if self._inv_index.n_assets == 1 else \ ip.IndexProvider(self._inv_index.data[self._asset_names]) return inv_return(_prev_date, self._date, self._asset_values, return_index)
# 1/ create a fixed rate bond b = AssBondFixRate(face=100, coupon_rate=0.05, frequency=4, issue_date=dt.date(2014, 4, 15), expiration_date=dt.date(2016, 4, 15), dcf=dcf_act_act, pricing_model=None, name='Sample Bond 1', ) # or a "float rate bond" but provided with a scenario generator gives you flat rate init_df = pd.TimeSeries(data=[[0.0]], index=pd.date_range(start=dt.date(2014, 4, 15), periods=1, freq='D').date, name=['LIBOR_3M']) ir_index = ip.IndexProvider(init_df, 'LIBOR_3M') sim_engine = FixRateEngine(0.05) scen_gen = ScenarioGenerator([ir_index], sim_engine, **{'max_time_step': 5. / 252}) # a LIBOR 3M +50 bps floater b = AssBondFloater(rate_index_name='LIBOR_3M', spread=0.005) # 1.5/ print coupon rate at any fixing date print(b.coupon_rate(dt.date(2014, 6, 12))) # 2/ create bond iterator it = b.bond_iterator() # 3/ print essentials at initial step print(it)
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
def test_variable_credit_rate(self): # TODO: bear in mind that the fund info fee is not implemented yet init_df = [pd.TimeSeries(data=np.exp(np.random.randn(10)), index=pd.date_range(start=dt.date(2014, 1, 1), periods=10, freq='D').date, name='stock A'), pd.TimeSeries(data=np.exp(np.random.randn(10)), index=pd.date_range(start=dt.date(2014, 1, 1), periods=10, freq='D').date, name='stock B'), ] eq_index = [ip.IndexProvider(init_df[0], 'stock A'), ip.IndexProvider(init_df[1], 'stock B')] sim_engine = EqBSEngine(np.array([0.02, 0.02]), np.array([0.2, 0.25]), 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(dt.date(2014, 1, 1)) 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 mix_weight = 0.4 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', }, 'Fund C': { 'Allocations': { 'stock A': mix_weight, 'stock B': 1-mix_weight, }, 'Management Fee': 0.01, 'Description': 'blah blah', }, } ic = InsCreditRateMutualFunds(fund_info=fund_info) index = ic.inv_index(dt.date(2014, 1, 10), periods=360, step_per_year=12) # since Fund A is 100% stock A, the return should be equal self.assertEqual(np.array(abs(eq_index[0].data - index.data['Fund A'])).max(),0.0) # since Fund B is 100% stock B, the return should be equal self.assertEqual(np.array(abs(eq_index[1].data - index.data['Fund B'])).max(),0.0) # Fund C is 50% 50% mix of stock A and B self.assertEqual(np.array(abs(mix_weight * eq_index[0].data + (1-mix_weight) * eq_index[1].data) - index.data['Fund C']).max(), 0.0)
def main(): # # Test single asset # init_df = pd.DataFrame(data=np.exp(np.random.randn(10)), # index=pd.date_range(start=dt.date(2014, 1, 1), periods=10, freq='D').date, # columns=['stock A']) # eq_index = ip.IndexProvider(init_df) # print(eq_index.data) # sim_engine = EqBSEngine(np.array([0.02]), # np.array([0.2])) # simulator = ScenarioGenerator(eq_index, sim_engine, **{'max_time_step': 5./BDAYS_PER_YEAR}) # simulator.next(dt.date(2014, 3, 1)) # print(eq_index.data) # # Test Multiple asset case # init_df = pd.DataFrame(data=np.exp(np.random.randn(10, 2)), # index=pd.date_range(start=dt.date(2014, 1, 1), periods=10, freq='D').date, # columns=['stock A', 'stock B']) # eq_index = ip.IndexProvider(init_df) # print(eq_index.data) # sim_engine = EqBSEngine(np.array([0.02, 0.02]), np.array([0.2, 0.25]), corr=np.array([[1., 0.3], [0.3, 1.]])) # simulator = ScenarioGenerator(eq_index, sim_engine, **{'max_time_step': 5./BDAYS_PER_YEAR}) # simulator.next(dt.date(2014, 3, 1)) # print(eq_index.data) # Test Term Structure data = [ pd.TimeSeries(data=np.exp(np.random.randn(10)), index=pd.date_range(start=dt.date(2014, 1, 1), periods=10, freq='D').date), pd.TimeSeries(data=np.exp(np.random.randn(10)), index=pd.date_range(start=dt.date(2014, 1, 1), periods=10, freq='D').date) ] vol_term = pd.TimeSeries(data=np.array([0.2, 0.25, 0.3, 0.32, 0.35, 0.4]), index=[ dt.date(2014, 1, 1), dt.date(2014, 7, 1), dt.date(2015, 1, 1), dt.date(2016, 1, 1), dt.date(2019, 1, 1), dt.date(2024, 1, 1) ]) eq_indices = [ ip.IndexProvider(data[0], 'index A'), ip.IndexProvider(data[1], 'index B') ] print(eq_indices[0].index_name) print(eq_indices[0].data) print(eq_indices[1].index_name) print(eq_indices[1].data) sim_engine = EqBSTermEngine(np.array([0.02]), np.array([ip.IndexProvider(vol_term)])) simulator = ScenarioGenerator( eq_indices, sim_engine, **{ 'max_time_step': 5. / BDAYS_PER_YEAR, 'initial_date': dt.date(2014, 1, 1) }) simulator.next(dt.date(2020, 12, 31)) print(eq_indices[0].index_name) print(eq_indices[0].data) print(eq_indices[1].index_name) print(eq_indices[1].data)