def generate_oasis_structures(self): ''' Create the Oasis structures - FM Programmes, FM Profiles and FM Policy TCs - that represent the resinsurance structure. The algorithm to create the stucture has three steps: Step 1 - Build a tree representation of the insurance program, depening on the reinsurance risk level. Step 2 - Overlay the reinsurance structure. Each resinsuarnce contact is a seperate layer. Step 3 - Iterate over the tree and write out the Oasis structure. ''' fmprogrammes_list = list() fmprofiles_list = list() fm_policytcs_list = list() profile_id = 1 nolossprofile_id = profile_id fmprofiles_list.append(oed.get_no_loss_profile(nolossprofile_id)) profile_id = profile_id + 1 passthroughprofile_id = profile_id fmprofiles_list.append( oed.get_pass_through_profile(passthroughprofile_id)) node_layer_profile_map = {} self.logger.debug(fmprofiles_list) # # Step 1 - Build a tree representation of the insurance program, depening on the reinsurance risk level. # program_node = self._get_tree() if self.logger: self.logger.debug('program_node tree: "{}"'.format(self.name)) self.logger.debug(anytree.RenderTree(program_node)) # Plot tree to image (graphviz) # from anytree.dotexport import RenderTreeGraph # RenderTreeGraph(program_node).to_picture( # "/tmp/Init_{}.png".format(self.name)) # # Step 2 - Overlay the reinsurance structure. Each resinsuarnce contact is a seperate layer. # layer_id = 1 # Current layer ID overlay_loop = 0 # Overlays multiple rules in same layer prev_reins_number = 1 for _, ri_info_row in self.ri_info.iterrows(): overlay_loop += 1 scope_rows = self.ri_scope[ (self.ri_scope.ReinsNumber == ri_info_row.ReinsNumber) & (self.ri_scope.RiskLevel == self.risk_level)] # Three rules for layers # 1. if FAC, don't increment the layer number # 2. Otherwise, only increment inline with the reins_number if ri_info_row.ReinsType in ['FAC']: pass elif prev_reins_number < ri_info_row.ReinsNumber: layer_id += 1 prev_reins_number = ri_info_row.ReinsNumber if self.logger: pd.set_option('display.width', 1000) self.logger.debug('ri_scope: "{}"'.format(self.name)) self.logger.debug(scope_rows) if scope_rows.shape[0] == 0: continue add_profiles_args = self.add_profiles_args( program_node, ri_info_row, scope_rows, overlay_loop, layer_id, node_layer_profile_map, fmprofiles_list, nolossprofile_id, passthroughprofile_id) # Add pass through nodes at all levels so that the risks # not explicitly covered are unaffected for node in anytree.iterators.LevelOrderIter( add_profiles_args.program_node): add_profiles_args.node_layer_profile_map[( node.name, add_profiles_args.layer_id, add_profiles_args.overlay_loop )] = add_profiles_args.nolossprofile_id add_profiles_args.node_layer_profile_map[( add_profiles_args.program_node.name, add_profiles_args.layer_id, add_profiles_args.overlay_loop )] = add_profiles_args.passthroughprofile_id if ri_info_row.ReinsType == oed.REINS_TYPE_FAC: self._add_fac_profiles(add_profiles_args) elif ri_info_row.ReinsType == oed.REINS_TYPE_PER_RISK: self._add_per_risk_profiles(add_profiles_args) elif ri_info_row.ReinsType == oed.REINS_TYPE_QUOTA_SHARE: self._add_quota_share_profiles(add_profiles_args) elif ri_info_row.ReinsType == oed.REINS_TYPE_SURPLUS_SHARE: self._add_surplus_share_profiles(add_profiles_args) elif ri_info_row.ReinsType == oed.REINS_TYPE_CAT_XL: self._add_cat_xl_profiles(add_profiles_args) else: raise Exception("ReinsType not supported yet: {}".format( ri_info_row.ReinsType)) # # Step 3 - Iterate over the tree and write out the Oasis structure. # for node in anytree.iterators.LevelOrderIter(program_node): if node.parent is not None: fmprogrammes_list.append( oed.FmProgramme(from_agg_id=node.agg_id, level_id=node.level_id, to_agg_id=node.parent.agg_id)) # Note: Pending confirmation from Joh that ReinsLayerNumber is being used correctly for layer in range(1, layer_id + 1): for node in anytree.iterators.LevelOrderIter(program_node): if node.level_id > 1: profiles_ids = [] # The `overlay_rule` replaces using each resinsuarnce contact in a seperate layer # Collect overlaping unique combinations of (layer_id, level_id, agg_id) and combine into # a single layer for overlay_rule in range(1, overlay_loop + 1): try: profiles_ids.append( node_layer_profile_map[(node.name, layer, overlay_rule)]) except: profiles_ids.append(1) pass fm_policytcs_list.append( oed.FmPolicyTc(layer_id=layer, level_id=node.level_id - 1, agg_id=node.agg_id, profile_id=max(profiles_ids))) self.fmprogrammes = pd.DataFrame(fmprogrammes_list) self.fmprofiles = pd.DataFrame(fmprofiles_list) self.fm_policytcs = pd.DataFrame(fm_policytcs_list) self.fm_xrefs['layer_id'] = pd.Series(layer_id, range(len(self.fm_xrefs.index))) # Log Reinsurance structures if self.logger: self.logger.debug('policytc_map: "{}"'.format(self.name)) policytc_map = dict() for k in add_profiles_args.node_layer_profile_map.keys(): profile_id = add_profiles_args.node_layer_profile_map[k] policytc_map["(Name=%s, layer_id=%s, overlay_loop=%s)" % k] = profile_id self.logger.debug(json.dumps(policytc_map, indent=4)) self.logger.debug('fm_policytcs: "{}"'.format(self.name)) self.logger.debug(self.fm_policytcs) self.logger.debug('fm_profile: "{}"'.format(self.name)) self.logger.debug(self.fmprofiles)
def generate_oasis_structures(self): coverage_id = 0 item_id = 0 group_id = 0 policy_agg_id = 0 profile_id = 0 coverages_list = list() items_list = list() fmprogrammes_list = list() fmprofiles_list = list() fm_policytcs_list = list() fm_xrefs_list = list() xref_descriptions_list = list() site_agg_id = 0 for policy_index, policy in self.accounts.iterrows(): policy_agg_id = policy_agg_id + 1 profile_id = profile_id + 1 fmprofiles_list.append( oed.get_profile(profile_id, deductible=policy.AccDed6All, limit=policy.AccLimit6All)) fm_policytcs_list.append( oed.FmPolicyTc(layer_id=1, level_id=2, agg_id=policy_agg_id, profile_id=profile_id)) for location_index, location in self.locations.loc[ self.locations["AccNumber"] == policy.AccNumber].iterrows(): group_id = group_id + 1 site_agg_id = site_agg_id + 1 profile_id = profile_id + 1 fmprofiles_list.append( oed.get_profile(profile_id=profile_id, deductible=location.LocDed6All, limit=location.LocLimit6All)) fm_policytcs_list.append( oed.FmPolicyTc(layer_id=1, level_id=1, agg_id=site_agg_id, profile_id=profile_id)) fmprogrammes_list.append( oed.FmProgramme(from_agg_id=site_agg_id, level_id=2, to_agg_id=policy_agg_id)) for coverage_type_id in oed.COVERAGE_TYPES: tiv = self._get_location_tiv(location, coverage_type_id) if tiv > 0: coverage_id = coverage_id + 1 self.item_id_dict[coverage_id] = location coverages_list.append( oed.Coverage( coverage_id=coverage_id, tiv=tiv, )) for peril in oed.PERILS: item_id = item_id + 1 self.item_ids.append(item_id) self.item_tivs.append(tiv) items_list.append( oed.Item(item_id=item_id, coverage_id=coverage_id, areaperil_id=-1, vulnerability_id=-1, group_id=group_id)) fmprogrammes_list.append( oed.FmProgramme(from_agg_id=item_id, level_id=1, to_agg_id=site_agg_id)) fm_xrefs_list.append( oed.FmXref(output_id=item_id, agg_id=item_id, layer_id=1)) xref_descriptions_list.append( oed.XrefDescription( xref_id=item_id, account_number=location.AccNumber, location_number=location.LocNumber, coverage_type_id=coverage_type_id, peril_id=peril, policy_number=policy.PolNumber, #portfolio_number=policy.PortNumber, tiv=tiv)) self.coverages = pd.DataFrame(coverages_list) self.items = pd.DataFrame(items_list) self.fmprogrammes = pd.DataFrame(fmprogrammes_list) self.fmprofiles = pd.DataFrame(fmprofiles_list) self.fm_policytcs = pd.DataFrame(fm_policytcs_list) self.fm_xrefs = pd.DataFrame(fm_xrefs_list) self.xref_descriptions = pd.DataFrame(xref_descriptions_list)
def generate_oasis_structures(self): ''' Create the Oasis structures - FM Programmes, FM Profiles and FM Policy TCs - that represent the reinsurance structure. The algorithm to create the stucture has three steps: Step 1 - Build a tree representation of the insurance program, depending on the reinsurance risk level. Step 2 - Overlay the reinsurance structure. Each reinsurance contact is a seperate layer. Step 3 - Iterate over the tree and write out the Oasis structure. ''' fmprogrammes_list = list() fmprofiles_list = list() fm_policytcs_list = list() profile_id = 1 nolossprofile_id = profile_id fmprofiles_list.append(oed.get_no_loss_profile(nolossprofile_id)) profile_id = profile_id + 1 passthroughprofile_id = profile_id fmprofiles_list.append( oed.get_pass_through_profile(passthroughprofile_id)) node_layer_profile_map = {} self.logger.debug(fmprofiles_list) # # Step 1 - Build a tree representation of the insurance program, depening on the reinsurance risk level. # program_node = self._get_tree() self._log_tree(program_node) # # Step 2 - Overlay the reinsurance structure. Each reinsurance contact is a seperate layer. # layer_id = 1 # Current layer ID overlay_loop = 0 # Overlays multiple rules in same layer prev_reins_number = 1 for _, ri_info_row in self.ri_info.iterrows(): overlay_loop += 1 scope_rows = self.ri_scope[ (self.ri_scope.ReinsNumber == ri_info_row.ReinsNumber) & (self.ri_scope.RiskLevel == self.risk_level)] # If FAC, don't increment the layer number # Else, only increment inline with the reins_number if ri_info_row.ReinsType in ['FAC']: pass elif prev_reins_number < ri_info_row.ReinsNumber: layer_id += 1 prev_reins_number = ri_info_row.ReinsNumber if self.logger: pd.set_option('display.width', 1000) self.logger.debug('ri_scope: "{}"'.format(self.name)) self.logger.debug(scope_rows) if scope_rows.shape[0] == 0: continue add_profiles_args = self.add_profiles_args( program_node, ri_info_row, scope_rows, overlay_loop, layer_id, node_layer_profile_map, fmprofiles_list, nolossprofile_id, passthroughprofile_id) # Add pass through nodes at all levels so that the risks not explicitly covered are unaffected for node in anytree.iterators.LevelOrderIter( add_profiles_args.program_node): if self.risk_level == oed.REINS_RISK_LEVEL_LOCATION: add_profiles_args.node_layer_profile_map[( node.name, add_profiles_args.layer_id, add_profiles_args.overlay_loop )] = add_profiles_args.nolossprofile_id else: if node.level_id == self._get_risk_level_id(): add_profiles_args.node_layer_profile_map[( node.name, add_profiles_args.layer_id, add_profiles_args.overlay_loop )] = add_profiles_args.nolossprofile_id elif node.level_id == self._get_filter_level_id(): add_profiles_args.node_layer_profile_map[( node.name, add_profiles_args.layer_id, add_profiles_args.overlay_loop )] = add_profiles_args.nolossprofile_id else: add_profiles_args.node_layer_profile_map[( node.name, add_profiles_args.layer_id, add_profiles_args.overlay_loop )] = add_profiles_args.passthroughprofile_id add_profiles_args.node_layer_profile_map[( add_profiles_args.program_node.name, add_profiles_args.layer_id, add_profiles_args.overlay_loop )] = add_profiles_args.passthroughprofile_id if ri_info_row.ReinsType == oed.REINS_TYPE_FAC: self._add_fac_profiles(add_profiles_args) elif ri_info_row.ReinsType == oed.REINS_TYPE_PER_RISK: self._add_per_risk_profiles(add_profiles_args) elif ri_info_row.ReinsType == oed.REINS_TYPE_QUOTA_SHARE: self._add_quota_share_profiles(add_profiles_args) elif ri_info_row.ReinsType == oed.REINS_TYPE_SURPLUS_SHARE: self._add_surplus_share_profiles(add_profiles_args) elif ri_info_row.ReinsType == oed.REINS_TYPE_CAT_XL: self._add_cat_xl_profiles(add_profiles_args) else: raise Exception("ReinsType not supported yet: {}".format( ri_info_row.ReinsType)) # # Step 3 - Iterate over the tree and write out the Oasis structure. # for node in anytree.iterators.LevelOrderIter(program_node): if node.parent is not None: fmprogrammes_list.append( oed.FmProgramme(from_agg_id=node.agg_id, level_id=node.level_id, to_agg_id=node.parent.agg_id)) for layer in range(1, layer_id + 1): for node in anytree.iterators.LevelOrderIter(program_node): if node.level_id > 1: profiles_ids = [] # Collect over-lapping unique combinations of (layer_id, level_id, agg_id) # and combine into a single layer for overlay_rule in range(1, overlay_loop + 1): try: profiles_ids.append( node_layer_profile_map[(node.name, layer, overlay_rule)]) except: profiles_ids.append(1) pass fm_policytcs_list.append( oed.FmPolicyTc(layer_id=layer, level_id=node.level_id - 1, agg_id=node.agg_id, profile_id=max(profiles_ids))) self.fmprogrammes = pd.DataFrame(fmprogrammes_list) self.fmprofiles = pd.DataFrame(fmprofiles_list) self.fm_policytcs = pd.DataFrame(fm_policytcs_list) self.fm_xrefs['layer_id'] = pd.Series(layer_id, range(len(self.fm_xrefs.index))) self._log_reinsurance_structure(add_profiles_args)