/// <summary>
    /// Calculate the loan request.
    /// </summary>
    /// <param name="request">The request to calculate</param>
    /// <returns>A completed AmortizationResponse</returns>
    /// <exception cref="ArgumentNullException">Throws when request is null.</exception>
    public AmortizationResponse Calculate(AmortizationRequest request)
    {
        if (request is null)
        {
            throw new ArgumentNullException(nameof(request), "Calculator request cannot be null.");
        }

        var ratePerPeriod   = request.RatePerPeriod;
        var numberOfPeriods = request.NumberOfPeriods;
        var totalPrincipal  = request.TotalPrincipal;

        var schedule = new AmortizationPeriod[numberOfPeriods];

        Parallel.For(1, numberOfPeriods + 1, periodNumber =>
        {
            var principalPayment = _financial.PrincipalPayment(ratePerPeriod, periodNumber, numberOfPeriods, -totalPrincipal);

            var interestPayment = _financial.InterestPayment(ratePerPeriod, periodNumber, numberOfPeriods, -totalPrincipal);

            var balanceLeft = ratePerPeriod == 0 ?
                              totalPrincipal - (principalPayment * periodNumber) :
                              _financial.InterestPayment(ratePerPeriod, periodNumber + 1, numberOfPeriods, -totalPrincipal) / ratePerPeriod;

            schedule[periodNumber - 1] = new AmortizationPeriod(periodNumber, interestPayment, principalPayment, balanceLeft);
        });

        var paymentPerPeriod  = _financial.Payment(ratePerPeriod, numberOfPeriods, -totalPrincipal);
        var totalInterestPaid = schedule.Sum(p => p.InterestPayment);
        var totalPaid         = totalPrincipal + totalInterestPaid;

        return(new AmortizationResponse(paymentPerPeriod, totalInterestPaid, totalPaid, schedule, request));
    }
Example #2
0
    public void InterestPaymentNoFvAtEnd()
    {
        var answer = _financial.InterestPayment(.05m, 2, 60, -35);

        Assert.Equal(1.75m, decimal.Round(answer, 2));
    }