Процентная ставка для нескольких кредиторов - PullRequest
0 голосов
/ 29 апреля 2018

Я хочу создать Калькулятор амортизации , чтобы получить цитату из числа N кредиторов на кредиты сроком на 36 месяцев, где у каждого кредитора разные процентные ставки. Цель состоит в том, чтобы обеспечить максимально возможную ставку low и указать ежемесячную сумму погашения и общую сумму погашения. Результат моего кода близок, но не точен .

Я использую формулу formula

вычисление i (процентная ставка) как total amount lended / requested amount, где общая сумма округленных денежных сумм, умноженная на каждого кредитора, умножается на ставку кредитора.

    BigDecimal requestedAmountP = new BigDecimal("" + requestedAmount);
    BigDecimal minLendersRate = calculateRate(requestedAmount, lenders);

    // https://en.wikipedia.org/wiki/Mortgage_calculator#Monthly_payment_formula
    // r*P/(1 - (1+r)^(-N))         if r != 0
    // P/N                          if r == 0
    BigDecimal monthlyRepayment;
    if (minLendersRate.compareTo(BigDecimal.ZERO) == 0) {
        monthlyRepayment = requestedAmountP.divide(DURATION_MONTHS, MathContext.DECIMAL128);
    } else {
        BigDecimal r = calculateEffectiveInterestInMonths(minLendersRate);
        BigDecimal tmp = r.add(BigDecimal.ONE).pow(-DURATION_MONTHS.intValue(), MathContext.DECIMAL128);
        BigDecimal dividend = BigDecimal.ONE.subtract(tmp);
        monthlyRepayment = r.multiply(requestedAmountP).divide(dividend, MathContext.DECIMAL128);
    }
    BigDecimal totalRepayment = monthlyRepayment.multiply(DURATION_MONTHS);

Для расчета ставки:

private BigDecimal calculateRate(double requestedAmount, List<Lender> lenders) {
    List<Lender> sortedLenders = lenders.stream().sorted(Comparator.comparing(Lender::getRate)).collect(toList());
    List<BigDecimal> moneyLended = moneyLended(requestedAmount, sortedLenders);

    BigDecimal totalMoneyLended = IntStream.range(0, moneyLended.size())
            .mapToObj(index -> moneyLended.get(index).multiply(sortedLenders.get(index).getRate()))
            .reduce(BigDecimal.ZERO, BigDecimal::add);

    return totalMoneyLended.divide(new BigDecimal("" + requestedAmount), MathContext.DECIMAL128);
}

private List<BigDecimal> moneyLended(double requestedAmount, List<Lender> sortedLenders) {
    List<BigDecimal> moneyLended = new ArrayList<>(sortedLenders.size());

    int i = 0;
    Double remaining = requestedAmount;
    while (remaining > 0) {
        if (remaining - sortedLenders.get(i).getAvailable().doubleValue() >= 0) {
            remaining = remaining - sortedLenders.get(i).getAvailable().doubleValue();

        } else {
            remaining = 0d;
        }
        moneyLended.add(sortedLenders.get(i).getAvailable());
        i++;
    }
    return moneyLended;
}

Для расчета Эффективный процент в месяцах

private BigDecimal calculateEffectiveInterestInMonths(BigDecimal nominalInterest) {
    // Formula: ((1+nominalInterest)^(1/12))-1
    BigDecimal exp = BigDecimal.ONE.divide(new BigDecimal("12"), MathContext.DECIMAL128);
    return BigDecimalMath.pow(BigDecimal.ONE.add(nominalInterest), exp, MathContext.DECIMAL128)
            .subtract(BigDecimal.ONE);
}

Кажется, есть проблема с десятичными операциями, но я не могу определить, где.

...