Search code examples
javabigdecimalfinance

Attempting to calculate monthly repayments with BigDecimal calculations


I am a beginner attempting to create a small program in Java that allows a user to input their loan term, interest rate etc. and will hopefully spit out an estimate for monthly repayments. When i am doing this, however, it gives me a completely different number to what i've calculated manually.

I been told to use the BigDecimal math system as the primitive double data type is not accurate enough for financial calculations.

The steps i am doing are attempting to mimic this formula : M = P [i(1+i)^n/ 1-(1+i)^n]

BigDecimal iRateInput = BigDecimal.valueOf(iRate);
BigDecimal twelve = new BigDecimal("12"); 
BigDecimal iRateMonthly = iRateInput.divide(twelve); 
BigDecimal one = new BigDecimal ("1"); 
BigDecimal iRateTemp = iRateMonthly.add(one);
BigDecimal loanTermBD = BigDecimal.valueOf(loanTerm);
loanTermBD = loanTermBD.multiply(twelve); 
BigDecimal iRatePower = iRateTemp.pow(loanTerm); 
BigDecimal iRateTop = iRateMonthly.multiply(iRatePower);
BigDecimal iRateBottom = iRatePower.subtract(one);
BigDecimal iRateTotal = iRateTop.divide(iRateBottom, BigDecimal.ROUND_UP);
BigDecimal borrowAmountBD = BigDecimal.valueOf(borrowAmount);
BigDecimal repayments = borrowAmountBD.multiply(iRateTotal);

I have been testing this code with:

P = 100,000

n = 15 years (*12)

r = 0.06p/a

According to my calculations, the monthly repayment should be 843.86 but I am getting 6936.43

Help would be appreciated! <3


Solution

  • I do not see why you need to use BigDecimal here

    private static double calculateRatePower(double rate, int period) {
      return Math.pow(1.0 + rate/12.0, period * 12.0);
    }
    
    public static void main(String[] args) throws IOException {
      double iRate = 0.06;
      double borrowAmount = 100000.0;
      int loanTerm = 15;
    
      double top = (iRate / 12.0) * calculateRatePower(iRate, loanTerm);
      double bottom = 1 - calculateRatePower(iRate, loanTerm);
    
      double repayments = borrowAmount * (top/bottom);
      System.out.println(repayments);
    }
    

    running this yields

    -843.8568280484624

    If you still want to use BigDecimal I suggest doing some stuff in separate methods for a more readable code

    private static BigDecimal ratePerMonth(double rate) {
      return BigDecimal.valueOf(rate).divide(BigDecimal.valueOf(12), 20, RoundingMode.DOWN);
    }
    
    private static BigDecimal calculateRatePower(double rate, int period) {
      BigDecimal onePlus = BigDecimal.ONE.add(ratePerMonth(rate));
      return onePlus.pow(period * 12);
    }
    
    public static void main(String[] args) throws IOException {
      double iRate = 0.06;
      double borrowAmount = 100000.0;
      int loanTerm = 15;
    
      BigDecimal top = ratePerMonth(iRate).multiply(calculateRatePower(iRate, loanTerm));
      BigDecimal bottom = BigDecimal.ONE.subtract(calculateRatePower(iRate, loanTerm));
      BigDecimal ratio = top.divide(bottom, 20, RoundingMode.DOWN);
    
      BigDecimal repayments = BigDecimal.valueOf(borrowAmount).multiply(ratio);
      System.out.println(repayments);
    }
    

    which yields

    -843.856828048451310000000