def create_aggregate_cash_flows(analysis_results_name, cash_flow_results, discount_rate):
    loan_df = pd.read_pickle(analysis_results_name + '_loans.pk')
    cash_flow_df = pd.read_pickle(analysis_results_name + '_cash_flows.pk')
    analysis_portfolio = LoanPortfolio(
        discount_rate=discount_rate, loan_df=loan_df, cash_flow_df=cash_flow_df
    )
    aggregate_cash_flow_df = analysis_portfolio.cash_flows_aggregate_for_portfolio()
    analysis_portfolio.cash_flows_df.to_pickle(analysis_results_name + '_aggregate_flows.pk')
    cash_flow_results.aggregated = True
    cash_flow_results.save()
    return aggregate_cash_flow_df
def create_aggregate_cash_flows(analysis_results_name, cash_flow_results,
                                discount_rate):
    loan_df = pd.read_pickle(analysis_results_name + '_loans.pk')
    cash_flow_df = pd.read_pickle(analysis_results_name + '_cash_flows.pk')
    analysis_portfolio = LoanPortfolio(discount_rate=discount_rate,
                                       loan_df=loan_df,
                                       cash_flow_df=cash_flow_df)
    aggregate_cash_flow_df = analysis_portfolio.cash_flows_aggregate_for_portfolio(
    )
    analysis_portfolio.cash_flows_df.to_pickle(analysis_results_name +
                                               '_aggregate_flows.pk')
    cash_flow_results.aggregated = True
    cash_flow_results.save()
    return aggregate_cash_flow_df
    def post(self, request):
        """ Conducts new analysis on portfolio, scenario combinations.

        If cash_flow_results do not exist with the same scenario_id, portfolio_id and analysis_results_name,
        a new cash flow is generated.

        Args:
            request: Request

        Returns: Status and message indicating if there it is a new analysis.

        """
        request_dict = request.POST.dict()

        scenario_id = request_dict['scenario_id']
        portfolio_id = request_dict['portfolio_id']
        discount_rate = float(request_dict['discount_rate']) / 100

        analysis_results_name = "scenario_{}_portfolio_{}_discount_{}_analysis".format(
            scenario_id, portfolio_id, discount_rate)
        cash_flow_results = self.model.objects.filter(
            scenario_id=scenario_id,
            portfolio_id=portfolio_id,
            analysis_results_name=analysis_results_name,
            discount_rate=discount_rate)

        if not cash_flow_results.exists():
            loan_df = generate_adjusted_assumptions(portfolio_id, scenario_id)

            loan_df.to_pickle(analysis_results_name + '_loans.pk')

            analysis_portfolio = LoanPortfolio(discount_rate=discount_rate,
                                               loan_df=loan_df)

            analysis_portfolio.cash_flows_df.to_pickle(analysis_results_name +
                                                       '_cash_flows.pk')

            analysis_results = self.model.objects.create(
                discount_rate=discount_rate,
                scenario_id=scenario_id,
                portfolio_id=portfolio_id,
                analysis_results_name=analysis_results_name)
            analysis_results.save()

            message = 'New Analysis has been run.'
        else:
            message = 'Analysis has already been run.'
        return JsonResponse({'status': 'PASS', 'message': message})
    def get(self, request):
        request_dict = request.GET.dict()

        scenario_id = request_dict['scenario_id']
        portfolio_id = request_dict['portfolio_id']
        discount_rate = float(request_dict['discount_rate']) / 100

        analysis_results_name = "scenario_{}_portfolio_{}_discount_{}_analysis".format(
            scenario_id, portfolio_id, discount_rate
        )

        cash_flow_results = self.model.objects.filter(
            scenario_id=scenario_id,
            portfolio_id=portfolio_id,
            discount_rate=discount_rate,
            analysis_results_name=analysis_results_name
        )

        if cash_flow_results.exists():
            cash_flow_results = cash_flow_results[0]
            loan_df = pd.read_pickle(analysis_results_name + '_loans.pk')
            cash_flow_df = pd.read_pickle(analysis_results_name + '_cash_flows.pk')

            if cash_flow_results.aggregated:
                aggregate_flows_df = pd.read_pickle(analysis_results_name + '_aggregate_flows.pk')
            else:
                aggregate_flows_df = create_aggregate_cash_flows(
                    analysis_results_name, cash_flow_results, discount_rate
                )

            analysis_portfolio = LoanPortfolio(
                discount_rate=discount_rate,
                loan_df=loan_df,
                cash_flow_df=cash_flow_df,
                aggregate_flows_df=aggregate_flows_df
            )

            remaining_balance = analysis_portfolio.current_balance_aggregate_for_portfolio()
            npv = analysis_portfolio.net_present_value_aggregate_for_portfolio()
            current_balance = analysis_portfolio.current_balance_aggregate_for_portfolio()
            price = npv / current_balance * 100
            yield_irr = float(analysis_portfolio.internal_rate_of_return_aggregate_for_portfolio()) * 100
            weighted_average_life = analysis_portfolio.weighted_average_life_for_portfolio()
            original_cdr = float(cash_flow_results.scenario.assumption_profile.constant_default_rate)
            original_cpr = float(cash_flow_results.scenario.assumption_profile.constant_prepayment_rate)
            original_recovery_percentage = float(cash_flow_results.scenario.assumption_profile.recovery_percentage)
            weighted_average_cdr = analysis_portfolio.weighted_average_cdr_for_portfolio()
            weighted_average_cpr = analysis_portfolio.weighted_average_cpr_for_portfolio()
            weighted_average_recovery = float(analysis_portfolio.weighted_average_recovery_for_portfolio()) * 100

            return JsonResponse(dict(
                portfolio_balance='$ {:,.2f}'.format(remaining_balance),
                npv='$ {:,.2f}'.format(npv),
                price='$ {:,.2f}'.format(price),
                yield_irr='{:.2%}'.format(yield_irr),
                weighted_average_life='{:,.2f}'.format(weighted_average_life),
                original_cdr='{:.2%}'.format(original_cdr),
                original_cpr='{:.2%}'.format(original_cpr),
                original_recovery='{:.2%}'.format(original_recovery_percentage),
                weighted_average_cdr='{:.2%}'.format(weighted_average_cdr),
                weighted_average_cpr='{:.2%}'.format(weighted_average_cpr),
                weighted_average_recovery='{:.2%}'.format(weighted_average_recovery)
            ))
    def get(self, request):
        request_dict = request.GET.dict()

        scenario_id = request_dict['scenario_id']
        portfolio_id = request_dict['portfolio_id']
        discount_rate = float(request_dict['discount_rate']) / 100

        analysis_results_name = "scenario_{}_portfolio_{}_discount_{}_analysis".format(
            scenario_id, portfolio_id, discount_rate)

        cash_flow_results = self.model.objects.filter(
            scenario_id=scenario_id,
            portfolio_id=portfolio_id,
            discount_rate=discount_rate,
            analysis_results_name=analysis_results_name)

        if cash_flow_results.exists():
            cash_flow_results = cash_flow_results[0]
            loan_df = pd.read_pickle(analysis_results_name + '_loans.pk')
            cash_flow_df = pd.read_pickle(analysis_results_name +
                                          '_cash_flows.pk')

            if cash_flow_results.aggregated:
                aggregate_flows_df = pd.read_pickle(analysis_results_name +
                                                    '_aggregate_flows.pk')
            else:
                aggregate_flows_df = create_aggregate_cash_flows(
                    analysis_results_name, cash_flow_results, discount_rate)

            analysis_portfolio = LoanPortfolio(
                discount_rate=discount_rate,
                loan_df=loan_df,
                cash_flow_df=cash_flow_df,
                aggregate_flows_df=aggregate_flows_df)

            remaining_balance = analysis_portfolio.current_balance_aggregate_for_portfolio(
            )
            npv = analysis_portfolio.net_present_value_aggregate_for_portfolio(
            )
            current_balance = analysis_portfolio.current_balance_aggregate_for_portfolio(
            )
            price = npv / current_balance * 100
            yield_irr = float(
                analysis_portfolio.
                internal_rate_of_return_aggregate_for_portfolio()) * 100
            weighted_average_life = analysis_portfolio.weighted_average_life_for_portfolio(
            )
            original_cdr = float(cash_flow_results.scenario.assumption_profile.
                                 constant_default_rate)
            original_cpr = float(cash_flow_results.scenario.assumption_profile.
                                 constant_prepayment_rate)
            original_recovery_percentage = float(
                cash_flow_results.scenario.assumption_profile.
                recovery_percentage)
            weighted_average_cdr = analysis_portfolio.weighted_average_cdr_for_portfolio(
            )
            weighted_average_cpr = analysis_portfolio.weighted_average_cpr_for_portfolio(
            )
            weighted_average_recovery = float(
                analysis_portfolio.weighted_average_recovery_for_portfolio(
                )) * 100

            return JsonResponse(
                dict(
                    portfolio_balance='$ {:,.2f}'.format(remaining_balance),
                    npv='$ {:,.2f}'.format(npv),
                    price='$ {:,.2f}'.format(price),
                    yield_irr='{:.2%}'.format(yield_irr),
                    weighted_average_life='{:,.2f}'.format(
                        weighted_average_life),
                    original_cdr='{:.2%}'.format(original_cdr),
                    original_cpr='{:.2%}'.format(original_cpr),
                    original_recovery='{:.2%}'.format(
                        original_recovery_percentage),
                    weighted_average_cdr='{:.2%}'.format(weighted_average_cdr),
                    weighted_average_cpr='{:.2%}'.format(weighted_average_cpr),
                    weighted_average_recovery='{:.2%}'.format(
                        weighted_average_recovery)))