예제 #1
0
    def _split_s1s2s3(
        self, target: IDataProviderTarget
    ) -> Tuple[IDataProviderTarget, Optional[IDataProviderTarget]]:
        """
        If there is a s1s2s3 scope, split it into two targets with s1s2 and s3

        :param target: The input target
        :return The split targets or the original target and None
        """
        if target.scope == EScope.S1S2S3:
            s1s2, s3 = target.copy(), None
            if (not pd.isnull(target.base_year_ghg_s1) and not pd.isnull(target.base_year_ghg_s1)) or \
                    target.coverage_s1 == target.coverage_s2:
                s1s2.scope = EScope.S1S2
                if not pd.isnull(target.base_year_ghg_s1) and not pd.isnull(target.base_year_ghg_s2) and \
                        target.base_year_ghg_s1 + target.base_year_ghg_s2 != 0:
                    coverage_percentage = (s1s2.coverage_s1 * s1s2.base_year_ghg_s1 +
                                           s1s2.coverage_s2 * s1s2.base_year_ghg_s2) / \
                                          (s1s2.base_year_ghg_s1 + s1s2.base_year_ghg_s2)
                    s1s2.coverage_s1 = coverage_percentage
                    s1s2.coverage_s2 = coverage_percentage

            if not pd.isnull(target.coverage_s3):
                s3 = target.copy()
                s3.scope = EScope.S3
            return s1s2, s3
        else:
            return target, None
예제 #2
0
    def _boundary_coverage(self,
                           target: IDataProviderTarget) -> IDataProviderTarget:
        """
        Test on boundary coverage:

        Option 1: minimal coverage threshold
        For S1+S2 targets: coverage% must be at or above 95%, for S3 targets coverage must be above 67%

        Option 2: weighted coverage
        Thresholds are still 95% and 67%, target is always valid. Below threshold ambition is scaled.*
        New target ambition = input target ambition * coverage
        *either here or in tem score module

        Option 3: default coverage
        Target is always valid, % uncovered is given default score in temperature score module.

        :param target: The input target
        :return: The original target with a weighted reduction ambition, if so required
        """
        if target.scope == EScope.S1S2:
            if target.coverage_s1 < 0.95:
                target.reduction_ambition = target.reduction_ambition * target.coverage_s1
        elif target.scope == EScope.S3:
            if target.coverage_s3 < 0.67:
                target.reduction_ambition = target.reduction_ambition * target.coverage_s3
        return target
예제 #3
0
    def _combine_s1_s2(self, target: IDataProviderTarget):
        """
        Check if there is an S2 target that matches this target exactly (if this is a S1 target) and combine them into one target.

        :param target: The input target
        :return: The combined target (or the original if no combining was required)
        """
        if target.scope == EScope.S1 and not pd.isnull(
                target.base_year_ghg_s1):
            matches = [
                t for t in self.s2_targets
                if t.company_id == target.company_id and t.base_year == target.
                base_year and t.start_year == target.start_year and t.end_year
                == target.end_year and t.target_type == target.target_type
                and t.intensity_metric == target.intensity_metric
            ]
            if len(matches) > 0:
                matches.sort(key=lambda t: t.coverage_s2, reverse=True)
                s2 = matches[0]
                combined_coverage = (target.coverage_s1 * target.base_year_ghg_s1 +
                                     s2.coverage_s2 * s2.base_year_ghg_s2) / \
                                    (target.base_year_ghg_s1 + s2.base_year_ghg_s2)
                target.reduction_ambition = target.reduction_ambition * target.coverage_s1 * target.base_year_ghg_s1 + \
                                            s2.reduction_ambition * s2.coverage_s1 * s2.base_year_ghg_s2 / \
                                            (target.base_year_ghg_s1 + s2.base_year_ghg_s1) / combined_coverage
                target.coverage_s1 = combined_coverage
                target.coverage_s2 = combined_coverage
                # We don't need to delete the S2 target as it'll be definition have a lower coverage than the combined
                # target, therefore it won't be picked for our 9-box grid
        return target
예제 #4
0
    def _time_frame(self, target: IDataProviderTarget) -> IDataProviderTarget:
        """
        Time frame is forward looking: target year - current year. Less than 5y = short, between 5 and 15 is mid, 15 to 30 is long

        :param target: The input target
        :return: The original target with the time_frame field filled out (if so required)
        """
        now = datetime.datetime.now()
        time_frame = target.end_year - now.year
        if time_frame <= 4:
            target.time_frame = ETimeFrames.SHORT
        elif time_frame <= 15:
            target.time_frame = ETimeFrames.MID
        elif time_frame <= 30:
            target.time_frame = ETimeFrames.LONG

        return target
예제 #5
0
파일: csv.py 프로젝트: dlinderyd/SBTi
    def get_targets(self, company_ids: list) -> List[IDataProviderTarget]:
        """
        Get all relevant targets for a list of company ids (ISIN). This method should return a list of
        IDataProviderTarget instances.

        :param company_ids: A list of company IDs (ISINs)
        :return: A list containing the targets
        """
        targets = self.data_targets.to_dict(orient="records")
        model_targets: List[IDataProviderTarget] = [
            IDataProviderTarget.parse_obj(target) for target in targets
        ]
        model_targets = [
            target for target in model_targets
            if target.company_id in company_ids
        ]
        return model_targets
예제 #6
0
파일: csv.py 프로젝트: sarah-jallot/SBTi
    def _target_df_to_model(self, df_targets):
        """
        transforms target Dataframe into list of IDataProviderTarget instances

        :param df_targets: pandas Dataframe with targets
        :return: A list containing the targets
        """
        logger = logging.getLogger(__name__)
        targets = df_targets.to_dict(orient="records")
        model_targets: List[IDataProviderTarget] = []
        for target in targets:
            try:
                model_targets.append(IDataProviderTarget.parse_obj(target))
            except ValidationError as e:
                logger.warning(
                    "(one of) the target(s) of company %s is invalid and will be skipped"
                    % target[self.c.COMPANY_NAME])
                pass
        return model_targets
예제 #7
0
    def setUp(self):
        company_id = "BaseCompany"
        self.BASE_COMP_SCORE = 0.43
        self.company_base = IDataProviderCompany(company_name=company_id,
                                                 company_id=company_id,
                                                 ghg_s1s2=100,
                                                 ghg_s3=0,
                                                 company_revenue=100,
                                                 company_market_cap=100,
                                                 company_enterprise_value=100,
                                                 company_total_assets=100,
                                                 company_cash_equivalents=100,
                                                 isic='A12')
        # define targets
        self.target_base = IDataProviderTarget(
            company_id=company_id,
            target_type="abs",
            scope=EScope.S1S2,
            coverage_s1=0.95,
            coverage_s2=0.95,
            coverage_s3=0,
            reduction_ambition=0.8,
            base_year=2019,
            base_year_ghg_s1=100,
            base_year_ghg_s2=0,
            base_year_ghg_s3=0,
            end_year=2030,
        )

        # pf
        self.pf_base = PortfolioCompany(
            company_name=company_id,
            company_id=company_id,
            investment_value=100,
            company_isin=company_id,
        )
예제 #8
0
    def validate(self, target: IDataProviderTarget) -> bool:
        """
        Validate a target, meaning it should:

        * Have a valid type
        * Not be finished
        * A valid end year

        :param target: The target to validate
        :return: True if it's a valid target, false if it isn't
        """
        # Only absolute targets or intensity targets with a valid intensity metric are allowed.
        target_type = "abs" in target.target_type.lower() or \
                      ("int" in target.target_type.lower() and
                       target.intensity_metric is not None and
                       target.intensity_metric.lower() != "other")
        # The target should not have achieved it's reduction yet.
        target_process = pd.isnull(target.achieved_reduction) or \
                         target.achieved_reduction is None or \
                         target.achieved_reduction < 1

        # The end year should be greater than the start year.
        if target.start_year is None or pd.isnull(target.start_year):
            target.start_year = target.base_year

        target_end_year = target.end_year > target.start_year
        # Delete all S1 or S2 targets we can't combine
        s1 = target.scope != EScope.S1 or (
            not pd.isnull(target.coverage_s1)
            and not pd.isnull(target.base_year_ghg_s1)
            and not pd.isnull(target.base_year_ghg_s2))
        s2 = target.scope != EScope.S2 or (
            not pd.isnull(target.coverage_s2)
            and not pd.isnull(target.base_year_ghg_s1)
            and not pd.isnull(target.base_year_ghg_s2))
        return target_type and target_process and target_end_year and s1 and s2
예제 #9
0
    def _convert_s1_s2(self, target: IDataProviderTarget):
        """
        Convert a S1 or S2 target into a S1+S2 target.

        :param target: The input target
        :return: The converted target (or the original if no conversion was required)
        """
        # In both cases the base_year_ghg s1 + s2 should not be zero
        if target.base_year_ghg_s1 + target.base_year_ghg_s2 != 0:
            if target.scope == EScope.S1:
                coverage = target.coverage_s1 * target.base_year_ghg_s1 / (
                    target.base_year_ghg_s1 + target.base_year_ghg_s2)
                target.coverage_s1 = coverage
                target.coverage_s2 = coverage
                target.scope = EScope.S1S2
            elif target.scope == EScope.S2:
                coverage = target.coverage_s2 * target.base_year_ghg_s2 / (
                    target.base_year_ghg_s1 + target.base_year_ghg_s2)
                target.coverage_s1 = coverage
                target.coverage_s2 = coverage
                target.scope = EScope.S1S2
        return target