private decimal CalculateExtraPayments(MortgageInformation mortgage, int i) { var extraPayment = 0m; if (mortgage.ExtraPayments != null && mortgage.ExtraPayments.ExtraPaymentInterval > 0 && mortgage.ExtraPayments.ExtraPaymentAmount > 0) { if (i % mortgage.ExtraPayments.ExtraPaymentInterval == 0) { extraPayment = mortgage.ExtraPayments.ExtraPaymentAmount; } } return extraPayment; }
private decimal CalculateInterestDue(MortgageInformation mortgageInformation, decimal intrestRate, decimal currentBalance) { var cp = (decimal)mortgageInformation.CompoundPeriod; var value = 1 + intrestRate / cp; var pf = (decimal)mortgageInformation.PaymentFrequency; var power = cp / pf; var result = (Math.Pow((double)value, (double)power) - 1) * (double)currentBalance; return (decimal)((Math.Round(result, 2))); }
public IList<PaymentScheduleItem> GeneratePaymentSchedule(MortgageInformation mortgageInformation) { var result = new List<PaymentScheduleItem>(); if (mortgageInformation == null || mortgageInformation.Term < 1 || mortgageInformation.LoanAmount <= 0) { return result; } var currentPaymentDate = mortgageInformation.FirstPaymentDate; var numOfPayments = NumberOfMonthlyPayments(mortgageInformation.PaymentFrequency, mortgageInformation.Term); var calculatedCurrentBalance = mortgageInformation.LoanAmount; var calculatedPreviousRate = mortgageInformation.AnnualInterestRate; var calculatedPreviousPaymentDue = 0m; var cmltvTaxReturned = 0m; for (int i = 1; i <= numOfPayments && calculatedCurrentBalance > 0; i++) { var item = new PaymentScheduleItem(); item.PaymentNumber = i; item.IntrestRate = CalculateInterestRate(mortgageInformation, i, calculatedPreviousRate); item.PaymentDate = CalculatePaymentDate(mortgageInformation, i, currentPaymentDate); item.IntrestDue = CalculateInterestDue(mortgageInformation, item.IntrestRate, calculatedCurrentBalance); item.PaymentDue = CalculatePaymentDue(mortgageInformation, i, item.IntrestRate, item.IntrestDue, calculatedCurrentBalance, calculatedPreviousRate, calculatedPreviousPaymentDue); item.ExtraPayments = CalculateExtraPayments(mortgageInformation, i); item.PrincipalPaid = CalculatePrincipalPaid(item.PaymentDue, item.IntrestDue, item.ExtraPayments); item.Balance = CalculateCurrentBalance(calculatedCurrentBalance, item.PrincipalPaid); item.TaxReturned = CalculateTaxReturned(mortgageInformation.TaxBracket, item.IntrestDue); result.Add(item); currentPaymentDate = item.PaymentDate; cmltvTaxReturned += item.TaxReturned; item.CmltvTaxReturned = cmltvTaxReturned; calculatedPreviousRate = item.IntrestRate; calculatedPreviousPaymentDue = item.PaymentDue; calculatedCurrentBalance = item.Balance; } return result; }
private decimal CalculateInterestRate(MortgageInformation mortgageInformation, int i, decimal calculatedPreviousRate) { if (mortgageInformation.RateType == MortgageEnums.RateType.Variable && i > 1) { var rate = calculatedPreviousRate; if (mortgageInformation.PeriodsBetweenAdjustments != 0 && i >= (int)mortgageInformation.PaymentFrequency * mortgageInformation.YearsRateRemainsFixed) { if (mortgageInformation.PeriodsBetweenAdjustments == 0 || (i - 1) % mortgageInformation.PeriodsBetweenAdjustments == 0) { rate = Math.Max(mortgageInformation.IntrestRateMin, calculatedPreviousRate + mortgageInformation.EstimatedAdjustment); } return Math.Min(mortgageInformation.IntrestRateCap, rate); } } return mortgageInformation.AnnualInterestRate; }
private decimal CalculatePaymentDue(MortgageInformation mortgageInformation, int i, decimal intrestRate, decimal intrestDue, decimal currentBalance, decimal calculatedPreviousRate, decimal calculatedPreviousPaymentDue) { decimal paymentDue; var cp = (decimal)mortgageInformation.CompoundPeriod; var pf = (decimal)mortgageInformation.PaymentFrequency; var fullBalancePlusIntrest = currentBalance + intrestDue; var nper = mortgageInformation.Term * pf; if (i == nper) { paymentDue = currentBalance + intrestDue; } else { if (intrestRate == calculatedPreviousRate && i > 1) { paymentDue = calculatedPreviousPaymentDue; } //TODO handle Acc Bi-Weekly //TODO handle Acc Weekly else { var value = 1 + intrestRate / cp; var power = cp / pf; var result = (Math.Pow((double)value, (double)power) - 1); var pmt = -Financial.Pmt(result, (double)nper - i + 1, (double)currentBalance); paymentDue = (decimal)Math.Round(pmt, 2); } } return Math.Min(fullBalancePlusIntrest, paymentDue); }
private DateTime CalculatePaymentDate(MortgageInformation mortgageInformation, int i, DateTime currentPaymentDate) { switch (mortgageInformation.PaymentFrequency) { case MortgageEnums.PaymentFrequency.Monthly: return i == 1 ? currentPaymentDate : currentPaymentDate.AddMonths(1); case MortgageEnums.PaymentFrequency.SemiMonthly://TODO case MortgageEnums.PaymentFrequency.BiWeekly://TODO case MortgageEnums.PaymentFrequency.Weekly://TODO default: return currentPaymentDate.AddMonths(i); } }
private MortgageInformation BuildMortgageInformation(MortgageRequest mortgageRequest) { RateInformation rateInfo = BuildRateInfo(mortgageRequest); PaymentInformation payInfo = BuildPaymentInfo(mortgageRequest); ExtraPayments extraPayments = BuildExtraPayments(mortgageRequest); var mortgageInfo = new MortgageInformation(rateInfo, payInfo, extraPayments) { LoanAmount = mortgageRequest.LoanAmount, AnnualInterestRate = mortgageRequest.AnnualInterestRate, Term = mortgageRequest.Term, CompoundPeriod = mortgageRequest.CompoundPeriod, PaymentFrequency = mortgageRequest.PaymentFrequency, TaxBracket = mortgageRequest.TaxBracket }; return mortgageInfo; }