Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
    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)