private OCurrency CalculateInterestRepayment(TrancheOptions to, OCurrency remainsInterestAmount, OCurrency remainingOlb, OCurrency olb) { OCurrency result = 0; if (to.ApplyNewInterestOnOLB) { result = (olb + remainingOlb) * to.InterestRate + remainsInterestAmount; } else { if (_currentLoan.UseCents) { OCurrency previousCapitalRepayment = Math.Round(remainingOlb.Value * _currentLoan.GivenTranches[to.Number - 1].InterestRate.Value, 2, MidpointRounding.AwayFromZero); OCurrency newCapitalRepayment = Math.Round(olb.Value * to.InterestRate, 2, MidpointRounding.AwayFromZero); result = newCapitalRepayment + previousCapitalRepayment + remainsInterestAmount; } else { OCurrency previousCapitalRepayment = Math.Round(remainingOlb.Value * _currentLoan.GivenTranches[to.Number - 1].InterestRate.Value, 0, MidpointRounding.AwayFromZero); OCurrency newCapitalRepayment = Math.Round(olb.Value * to.InterestRate, 0, MidpointRounding.AwayFromZero); result = newCapitalRepayment + previousCapitalRepayment + remainsInterestAmount; } } result = RoundResult(_currentLoan.UseCents, result); return(result); }
private OCurrency CalculateCapitalRepayment(TrancheOptions to, Installment installment) { OCurrency result = to.TrancheAmount / to.CountOfNewInstallments + _previousSchedule[installment.Number - 1].CapitalRepayment; result = RoundResult(_currentLoan.UseCents, result); return(result); }
public void AddTranche_Annuity_ApplyNewInterest_Accrual() { ApplicationSettings.GetInstance("").UpdateParameter(OGeneralSettings.ACCOUNTINGPROCESS, OAccountingProcesses.Accrual); Loan loan = _GetLoan(_GetAnnuityProduct(), 1000, 0.025m, 4, new DateTime(2010, 5, 11)); loan.Disburse(new DateTime(2010, 5, 11), true, false); loan.Repay(1, new DateTime(2010, 6, 11), 266m, false, true); loan.Repay(2, new DateTime(2010, 7, 9), 266m, false, true); Assert.AreEqual(loan.GetInstallment(0).IsRepaid, true); Assert.AreEqual(loan.GetInstallment(1).IsRepaid, true); TrancheOptions to = new TrancheOptions { TrancheDate = new DateTime(2010, 7, 15), CountOfNewInstallments = 4, TrancheAmount = 1000, InterestRate = 0.03m, ApplyNewInterestOnOLB = true }; loan.AddTranche(loan.CalculateTranche(to)); _AssertInstallment(loan, 2, "2010-08-16", 46m, 362m); _AssertInstallment(loan, 3, "2010-09-15", 35m, 372m); _AssertInstallment(loan, 4, "2010-10-15", 23m, 384m); _AssertInstallment(loan, 5, "2010-11-15", 12m, 394m); }
private void CheckAndCorrectSumOfCapitalRepayments(TrancheOptions to, Installment installment) { if (installment.Number == _currentLoan.InstallmentList.Count) { OCurrency sumOfCapitalRepayment = 0; foreach (Installment item in _currentLoan.InstallmentList) { sumOfCapitalRepayment += item.CapitalRepayment; } installment.CapitalRepayment += _currentLoan.Amount + to.TrancheAmount - sumOfCapitalRepayment; } }
private OCurrency CalculateInterestRepaymentWithNewInterest(TrancheOptions to, OCurrency remainsInterestAmount, OCurrency remainingOlb, OCurrency olb, OCurrency interestAmount) { OCurrency result; if (to.ApplyNewInterestOnOLB) { result = (olb + remainingOlb) * to.InterestRate + remainsInterestAmount; } else { result = olb * to.InterestRate + interestAmount; } result = RoundResult(_currentLoan.UseCents, result); return(result); }
public TrancheEvent AddTranche(TrancheOptions trancheOptions) { _trancheEvent = new TrancheEvent { Date = trancheOptions.TrancheDate, InterestRate = trancheOptions.InterestRate, Amount = trancheOptions.TrancheAmount, Maturity = trancheOptions.CountOfNewInstallments, StartDate = trancheOptions.TrancheDate, Number = _currentLoan.GivenTranches.Count }; trancheOptions.Number = _trancheEvent.Number; switch (_currentLoan.Product.LoanType) { case OLoanTypes.Flat: { AddFlatTranche(trancheOptions); } break; case OLoanTypes.DecliningFixedPrincipal: { AddFixedPrincipalTranche(trancheOptions); } break; case OLoanTypes.DecliningFixedInstallments: { AddFixedInstallmentTranche(trancheOptions); } break; } _currentLoan.CalculateStartDates(); return(_trancheEvent); }
public TrancheEvent AddTranche(TrancheOptions trancheOptions) { _trancheEvent = new TrancheEvent { Date = trancheOptions.TrancheDate, InterestRate = trancheOptions.InterestRate, Amount = trancheOptions.TrancheAmount, Maturity = trancheOptions.CountOfNewInstallments, StartDate = trancheOptions.TrancheDate, Number = _currentLoan.GivenTranches.Count }; trancheOptions.Number = _trancheEvent.Number; switch (_currentLoan.Product.LoanType) { case OLoanTypes.Flat: { AddFlatTranche(trancheOptions); } break; case OLoanTypes.DecliningFixedPrincipal: { AddFixedPrincipalTranche(trancheOptions); } break; case OLoanTypes.DecliningFixedInstallments: { AddFixedInstallmentTranche(trancheOptions); } break; } _currentLoan.CalculateStartDates(); return _trancheEvent; }
public Loan AddTranche(Loan pContract, IClient pClient, DateTime pDate, int pNbOfMaturity, int pTrancheAmount, bool pApplyNewInterestOnOLB, decimal pNewInterestRate) { using (SqlConnection conn = _loanManager.GetConnection()) using (SqlTransaction sqlTransaction = conn.BeginTransaction()) { try { CheckTranche(pDate, pContract, pTrancheAmount); Loan copyOfLoan = pContract.Copy(); TrancheOptions to = new TrancheOptions { TrancheDate = pDate, CountOfNewInstallments = pNbOfMaturity, TrancheAmount = pTrancheAmount, InterestRate = pNewInterestRate, ApplyNewInterestOnOLB = pApplyNewInterestOnOLB }; TrancheEvent trancheEvent = pContract.CalculateTranche(to); trancheEvent.User = _user; //insert into table TrancheEvent _ePs.FireEvent(trancheEvent, pContract, sqlTransaction); ArchiveInstallments(copyOfLoan, trancheEvent, sqlTransaction); //delete all the old installments of the table Installments _instalmentManager.DeleteInstallments(pContract.Id, sqlTransaction); //insert all the new installments in the table Installments _instalmentManager.AddInstallments(pContract.InstallmentList, pContract.Id, sqlTransaction); //Activate the contract if it's closed because of new tranch if (pContract.Closed) { pContract.ContractStatus = OContractStatus.Active; pContract.Closed = false; _loanManager.UpdateLoan(pContract, sqlTransaction); } //in the feature might be combine UpdateLoan + UpdateLoanWithinTranche _loanManager.UpdateLoanWithinTranche(to.InterestRate, pContract.NbOfInstallments, pContract, sqlTransaction); pContract.Events.Add(trancheEvent); pContract.GivenTranches.Add(trancheEvent); sqlTransaction.Commit(); SetClientStatus(pContract, pClient); return pContract; } catch (Exception ex) { if (sqlTransaction != null) sqlTransaction.Rollback(); throw ex; } } }
private void AddFixedInstallmentTranche(TrancheOptions to) { OCurrency remainsAmount = 0; foreach (Installment installment in _currentLoan.InstallmentList) { if (!installment.IsRepaid) { remainsAmount += installment.CapitalRepayment - installment.PaidCapital; } } OCurrency remainsInterestAmount = _generalSettings.AccountingProcesses == OAccountingProcesses.Accrual ? GenerateEvents.Accrual.CalculateRemainingInterests(_currentLoan, to.TrancheDate) : GenerateEvents.Cash.CalculateRemainingInterests(_currentLoan, to.TrancheDate); remainsInterestAmount = _currentLoan.UseCents ? remainsInterestAmount : Math.Round(remainsInterestAmount.Value, 0, MidpointRounding.AwayFromZero); TrancheExtendMaturity(to.CountOfNewInstallments, to.TrancheDate); OCurrency olb; OCurrency newAmountVpm; OCurrency priviousAmountVpm = 0; if (to.ApplyNewInterestOnOLB) { olb = to.TrancheAmount + remainsAmount; newAmountVpm = _currentLoan.UseCents ? _currentLoan.VPM(olb, to.CountOfNewInstallments, to.InterestRate) : Math.Round(_currentLoan.VPM(olb, to.CountOfNewInstallments, to.InterestRate).Value, 0, MidpointRounding.AwayFromZero); remainsAmount = 0; } else { olb = to.TrancheAmount; newAmountVpm = _currentLoan.UseCents ? _currentLoan.VPM(olb, to.CountOfNewInstallments, to.InterestRate) : Math.Round(_currentLoan.VPM(olb, to.CountOfNewInstallments, to.InterestRate).Value, 0, MidpointRounding.AwayFromZero); priviousAmountVpm = _currentLoan.UseCents ? _currentLoan.VPM(remainsAmount, to.CountOfNewInstallments, (_currentLoan.GivenTranches[to.Number - 1].InterestRate.Value)) : Math.Round((_currentLoan.VPM(remainsAmount, to.CountOfNewInstallments, (_currentLoan.GivenTranches[to.Number - 1].InterestRate.Value))).Value, 0, MidpointRounding.AwayFromZero); } OCurrency _OLB = olb + remainsAmount; foreach (Installment installment in _currentLoan.InstallmentList) { if (!installment.IsRepaid) { installment.InterestsRepayment = _currentLoan.UseCents ? Math.Round(olb.Value * to.InterestRate, 2, MidpointRounding.AwayFromZero) : Math.Round(olb.Value * to.InterestRate, 0, MidpointRounding.AwayFromZero); OCurrency interestAmountForPriviousOlb = _currentLoan.UseCents ? remainsAmount * _currentLoan.GivenTranches[to.Number - 1].InterestRate : Math.Round((remainsAmount * _currentLoan.GivenTranches[to.Number - 1].InterestRate).Value, 0, MidpointRounding.AwayFromZero); installment.CapitalRepayment = newAmountVpm.Value - installment.InterestsRepayment.Value; installment.InterestsRepayment += _currentLoan.UseCents ? Math.Round(interestAmountForPriviousOlb.Value, 2, MidpointRounding.AwayFromZero) : Math.Round(interestAmountForPriviousOlb.Value, 0, MidpointRounding.AwayFromZero); olb -= installment.CapitalRepayment; installment.CapitalRepayment = _currentLoan.UseCents ? Math.Round(installment.CapitalRepayment.Value, 2, MidpointRounding.AwayFromZero) : Math.Round(installment.CapitalRepayment.Value, 0, MidpointRounding.AwayFromZero); OCurrency priviousCapital = priviousAmountVpm - interestAmountForPriviousOlb; installment.CapitalRepayment += _currentLoan.UseCents ? Math.Round(priviousCapital.Value, 2, MidpointRounding.AwayFromZero) : Math.Round(priviousCapital.Value, 0, MidpointRounding.AwayFromZero); remainsAmount -= priviousCapital; installment.InterestsRepayment += _currentLoan.UseCents ? Math.Round(remainsInterestAmount.Value, 2, MidpointRounding.AwayFromZero) : Math.Round(remainsInterestAmount.Value, 0, MidpointRounding.AwayFromZero); remainsInterestAmount = 0; installment.PaidCapital = 0; installment.PaidInterests = 0; } } _currentLoan.InstallmentList[_currentLoan.InstallmentList.Count - 1].CapitalRepayment += _currentLoan.UseCents ? Math.Round(olb.Value + remainsAmount.Value, 2, MidpointRounding.AwayFromZero) : Math.Round(olb.Value + remainsAmount.Value, 0, MidpointRounding.AwayFromZero); //OLB calculation foreach (Installment installment in _currentLoan.InstallmentList) { if (!installment.IsRepaid) { installment.OLB = _OLB; _OLB -= installment.CapitalRepayment; } } _currentLoan.Amount = _currentLoan.Amount + to.TrancheAmount; _currentLoan.InstallmentList[_currentLoan.InstallmentList.Count - 1].CapitalRepayment += _currentLoan.UseCents ? Math.Round(_OLB.Value, 2, MidpointRounding.AwayFromZero) : Math.Round(_OLB.Value, 0, MidpointRounding.AwayFromZero); }
private OCurrency RecalculateInterestForFirstNotPaidInstallment(Installment installment, OCurrency remainingOlb, TrancheOptions to) { OCurrency newInterest = 0; if (installment.ExpectedDate > _previousSchedule[installment.Number - 1].ExpectedDate) { if (installment.Number == 1) { int daysBeforeTranche = (to.TrancheDate - _currentLoan.StartDate).Days; int oldQuantityOfDays = (_previousSchedule[installment.Number - 1].ExpectedDate - _currentLoan.StartDate).Days; newInterest = remainingOlb * _currentLoan.GivenTranches[to.Number - 1].InterestRate / oldQuantityOfDays * daysBeforeTranche + _previousSchedule[installment.Number - 1].InterestsRepayment; } else { int daysBeforeTranche = (to.TrancheDate - _previousSchedule[installment.Number - 2].ExpectedDate).Days; int oldQuantityOfDays = (_previousSchedule[installment.Number - 1].ExpectedDate - _previousSchedule[installment.Number - 2].ExpectedDate).Days; newInterest = remainingOlb * _currentLoan.GivenTranches[to.Number - 1].InterestRate / oldQuantityOfDays * daysBeforeTranche + _previousSchedule[installment.Number - 1].InterestsRepayment; } } else { newInterest = remainingOlb * _currentLoan.GivenTranches[to.Number - 1].InterestRate; } newInterest = RoundResult(_currentLoan.UseCents, newInterest); return(newInterest); }
private void AddFlatTranche(TrancheOptions to) { OCurrency remainsInterestAmount = 0; OCurrency remainsAmount = 0; foreach (Installment installment in _currentLoan.InstallmentList) { if (!installment.IsRepaid) { if (to.TrancheDate > _currentLoan.InstallmentList[installment.Number - 2].ExpectedDate) { remainsInterestAmount += installment.InterestsRepayment * (to.TrancheDate - _currentLoan.InstallmentList[installment.Number - 2].ExpectedDate).Days / _currentLoan.NumberOfDaysInTheInstallment(installment.Number, to.TrancheDate); } remainsAmount += installment.CapitalRepayment - installment.PaidCapital; } } OCurrency interestAmount = !to.ApplyNewInterestOnOLB ? to.TrancheAmount * to.InterestRate + remainsInterestAmount / to.CountOfNewInstallments : (to.TrancheAmount + remainsAmount) * to.InterestRate + remainsInterestAmount / to.CountOfNewInstallments; OCurrency generalInterestAmount = interestAmount; interestAmount = _currentLoan.UseCents ? interestAmount : Math.Round(interestAmount.Value, 0); OCurrency olb = to.TrancheAmount + remainsAmount; TrancheExtendMaturity(to.CountOfNewInstallments, to.TrancheDate); foreach (Installment installment in _currentLoan.InstallmentList) { if (!installment.IsRepaid) { installment.CapitalRepayment = _currentLoan.UseCents ? (to.TrancheAmount + remainsAmount) / to.CountOfNewInstallments : Math.Round( ((to.TrancheAmount + remainsAmount) / to.CountOfNewInstallments).Value, 0); installment.InterestsRepayment = interestAmount; installment.PaidCapital = 0; installment.PaidInterests = 0; installment.OLB = olb; olb -= installment.CapitalRepayment; } } OCurrency lastInstallmentInterest = _currentLoan.InstallmentList[_currentLoan.InstallmentList.Count - 1].InterestsRepayment + generalInterestAmount * to.CountOfNewInstallments - interestAmount * to.CountOfNewInstallments; _currentLoan.InstallmentList[_currentLoan.InstallmentList.Count - 1].InterestsRepayment = _currentLoan.UseCents ? lastInstallmentInterest : Math.Round( lastInstallmentInterest .Value, 0); _currentLoan.InstallmentList[_currentLoan.InstallmentList.Count - 1].CapitalRepayment = _currentLoan.InstallmentList[_currentLoan.InstallmentList.Count - 1].CapitalRepayment + olb; _currentLoan.Amount = _currentLoan.Amount + to.TrancheAmount; }
private OCurrency CalculateInterestRepaymentWithNewInterest(TrancheOptions to, OCurrency remainsInterestAmount, OCurrency remainingOlb, OCurrency olb, OCurrency interestAmount) { OCurrency result; if (to.ApplyNewInterestOnOLB) result= (olb + remainingOlb)*to.InterestRate + remainsInterestAmount; else result = olb * to.InterestRate + interestAmount; result = RoundResult(_currentLoan.UseCents, result); return result; }
public void AddTranche_FixedPrincipal_ApplyNewInterest_Cash() { ApplicationSettings.GetInstance("").UpdateParameter(OGeneralSettings.ACCOUNTINGPROCESS, OAccountingProcesses.Cash); Loan loan = _GetLoan(_GetFixedPrincipalProduct(), 1000, 0.025m, 4, new DateTime(2010, 5, 11)); loan.Disburse(new DateTime(2010, 5, 11), true, false); loan.Repay(1, new DateTime(2010, 6, 11), 275m, false, true); loan.Repay(2, new DateTime(2010, 7, 9), 269m, false, true); Assert.AreEqual(loan.GetInstallment(0).IsRepaid, true); Assert.AreEqual(loan.GetInstallment(1).IsRepaid, true); TrancheOptions to = new TrancheOptions { TrancheDate = new DateTime(2010, 7, 15), CountOfNewInstallments = 4, TrancheAmount = 1000, InterestRate = 0.03m, ApplyNewInterestOnOLB = true }; loan.AddTranche(loan.CalculateTranche(to)); _AssertInstallment(loan, 2, "2010-08-16", 45m, 500m); _AssertInstallment(loan, 3, "2010-09-15", 30m, 500m); _AssertInstallment(loan, 4, "2010-10-15", 15m, 250m); _AssertInstallment(loan, 5, "2010-11-15", 8m, 250m); }
private void AddFixedPrincipalTranche(TrancheOptions to) { OCurrency remainsAmount = 0; // List<Installment> _previousSchedule = new List<Installment>(); int numberRemainInstallment = 0; foreach (Installment installment in _currentLoan.InstallmentList) { // previousSchedule.Add(installment); if (!installment.IsRepaid) { remainsAmount += installment.CapitalRepayment - installment.PaidCapital; numberRemainInstallment++; } } OCurrency olb = to.TrancheAmount; OCurrency remainsInterestAmount = _generalSettings.AccountingProcesses == OAccountingProcesses.Accrual ? GenerateEvents.Accrual.CalculateRemainingInterests(_currentLoan, to.TrancheDate) : GenerateEvents.Cash.CalculateRemainingInterests(_currentLoan, to.TrancheDate); remainsInterestAmount = _currentLoan.UseCents ? remainsInterestAmount : Math.Round(remainsInterestAmount.Value, 0, MidpointRounding.AwayFromZero); TrancheExtendMaturity(to.CountOfNewInstallments, to.TrancheDate); OCurrency remainingOlb = remainsAmount; bool itIsFirstNotRepaidInstallment=true; foreach (Installment installment in _currentLoan.InstallmentList) { if (installment.IsRepaid) continue; if (_previousSchedule.Count >= installment.Number) { if (!_previousSchedule[installment.Number - 1].IsRepaid) { installment.CapitalRepayment = CalculateCapitalRepayment(to, installment); if (itIsFirstNotRepaidInstallment) { OCurrency interestAmount = RecalculateInterestForFirstNotPaidInstallment(installment, remainingOlb, to); installment.InterestsRepayment = CalculateInterestRepaymentWithNewInterest(to, remainsInterestAmount, remainingOlb, olb, interestAmount); itIsFirstNotRepaidInstallment = false; } else { installment.InterestsRepayment = CalculateInterestRepayment(to, remainsInterestAmount, remainingOlb, olb); } installment.OLB = olb + remainingOlb; if (installment.Number!=_previousSchedule.Count) remainingOlb = _previousSchedule[installment.Number].OLB; if (_currentLoan.UseCents) olb -= Math.Round(to.TrancheAmount.Value / to.CountOfNewInstallments, 2, MidpointRounding.AwayFromZero); else { olb -= Math.Round(to.TrancheAmount.Value/to.CountOfNewInstallments, 0, MidpointRounding.AwayFromZero); } installment.PaidCapital = 0; installment.PaidInterests = 0; remainsInterestAmount = 0; } } else { installment.CapitalRepayment = _currentLoan.UseCents ? Math.Round(to.TrancheAmount.Value / to.CountOfNewInstallments, 2, MidpointRounding.AwayFromZero) : Math.Round( (to.TrancheAmount / to.CountOfNewInstallments).Value, 0, MidpointRounding.AwayFromZero); CheckAndCorrectSumOfCapitalRepayments(to, installment); installment.InterestsRepayment = olb.Value * to.InterestRate; installment.InterestsRepayment = _currentLoan.UseCents ? Math.Round(installment.InterestsRepayment.Value, 2, MidpointRounding.AwayFromZero) : Math.Round(installment.InterestsRepayment.Value, 0, MidpointRounding.AwayFromZero); installment.PaidCapital = 0; installment.PaidInterests = 0; installment.OLB = olb; olb -= installment.CapitalRepayment; } } _currentLoan.Amount = _currentLoan.Amount + to.TrancheAmount; }
private void AddFixedPrincipalTranche(TrancheOptions to) { OCurrency remainsAmount = 0; // List<Installment> _previousSchedule = new List<Installment>(); int numberRemainInstallment = 0; foreach (Installment installment in _currentLoan.InstallmentList) { // previousSchedule.Add(installment); if (!installment.IsRepaid) { remainsAmount += installment.CapitalRepayment - installment.PaidCapital; numberRemainInstallment++; } } OCurrency olb = to.TrancheAmount; OCurrency remainsInterestAmount = _generalSettings.AccountingProcesses == OAccountingProcesses.Accrual ? GenerateEvents.Accrual.CalculateRemainingInterests(_currentLoan, to.TrancheDate) : GenerateEvents.Cash.CalculateRemainingInterests(_currentLoan, to.TrancheDate); remainsInterestAmount = _currentLoan.UseCents ? remainsInterestAmount : Math.Round(remainsInterestAmount.Value, 0, MidpointRounding.AwayFromZero); TrancheExtendMaturity(to.CountOfNewInstallments, to.TrancheDate); OCurrency remainingOlb = remainsAmount; bool itIsFirstNotRepaidInstallment = true; foreach (Installment installment in _currentLoan.InstallmentList) { if (installment.IsRepaid) { continue; } if (_previousSchedule.Count >= installment.Number) { if (!_previousSchedule[installment.Number - 1].IsRepaid) { installment.CapitalRepayment = CalculateCapitalRepayment(to, installment); if (itIsFirstNotRepaidInstallment) { OCurrency interestAmount = RecalculateInterestForFirstNotPaidInstallment(installment, remainingOlb, to); installment.InterestsRepayment = CalculateInterestRepaymentWithNewInterest(to, remainsInterestAmount, remainingOlb, olb, interestAmount); itIsFirstNotRepaidInstallment = false; } else { installment.InterestsRepayment = CalculateInterestRepayment(to, remainsInterestAmount, remainingOlb, olb); } installment.OLB = olb + remainingOlb; if (installment.Number != _previousSchedule.Count) { remainingOlb = _previousSchedule[installment.Number].OLB; } if (_currentLoan.UseCents) { olb -= Math.Round(to.TrancheAmount.Value / to.CountOfNewInstallments, 2, MidpointRounding.AwayFromZero); } else { olb -= Math.Round(to.TrancheAmount.Value / to.CountOfNewInstallments, 0, MidpointRounding.AwayFromZero); } installment.PaidCapital = 0; installment.PaidInterests = 0; remainsInterestAmount = 0; } } else { installment.CapitalRepayment = _currentLoan.UseCents ? Math.Round(to.TrancheAmount.Value / to.CountOfNewInstallments, 2, MidpointRounding.AwayFromZero) : Math.Round( (to.TrancheAmount / to.CountOfNewInstallments).Value, 0, MidpointRounding.AwayFromZero); CheckAndCorrectSumOfCapitalRepayments(to, installment); installment.InterestsRepayment = olb.Value * to.InterestRate; installment.InterestsRepayment = _currentLoan.UseCents ? Math.Round(installment.InterestsRepayment.Value, 2, MidpointRounding.AwayFromZero) : Math.Round(installment.InterestsRepayment.Value, 0, MidpointRounding.AwayFromZero); installment.PaidCapital = 0; installment.PaidInterests = 0; installment.OLB = olb; olb -= installment.CapitalRepayment; } } _currentLoan.Amount = _currentLoan.Amount + to.TrancheAmount; }
private void AddFlatTranche(TrancheOptions to) { OCurrency remainsInterestAmount = 0; OCurrency remainsAmount = 0; foreach (Installment installment in _currentLoan.InstallmentList) { if (!installment.IsRepaid) { if (to.TrancheDate > _currentLoan.InstallmentList[installment.Number - 2].ExpectedDate) { remainsInterestAmount += installment.InterestsRepayment * (to.TrancheDate - _currentLoan.InstallmentList[installment.Number - 2].ExpectedDate).Days / _currentLoan.NumberOfDaysInTheInstallment(installment.Number, to.TrancheDate); } remainsAmount += installment.CapitalRepayment - installment.PaidCapital; } } OCurrency interestAmount = !to.ApplyNewInterestOnOLB ? to.TrancheAmount * to.InterestRate + remainsInterestAmount / to.CountOfNewInstallments : (to.TrancheAmount + remainsAmount) * to.InterestRate + remainsInterestAmount / to.CountOfNewInstallments; OCurrency generalInterestAmount = interestAmount; interestAmount = _currentLoan.UseCents ? interestAmount : Math.Round(interestAmount.Value, 0); OCurrency olb = to.TrancheAmount + remainsAmount; TrancheExtendMaturity(to.CountOfNewInstallments, to.TrancheDate); foreach (Installment installment in _currentLoan.InstallmentList) { if (!installment.IsRepaid) { installment.CapitalRepayment = _currentLoan.UseCents ? (to.TrancheAmount + remainsAmount) / to.CountOfNewInstallments : Math.Round( ((to.TrancheAmount + remainsAmount) / to.CountOfNewInstallments).Value, 0); installment.InterestsRepayment = interestAmount; installment.PaidCapital = 0; installment.PaidInterests = 0; installment.OLB = olb; olb -= installment.CapitalRepayment; } } OCurrency lastInstallmentInterest = _currentLoan.InstallmentList[_currentLoan.InstallmentList.Count - 1].InterestsRepayment + generalInterestAmount * to.CountOfNewInstallments - interestAmount * to.CountOfNewInstallments; _currentLoan.InstallmentList[_currentLoan.InstallmentList.Count - 1].InterestsRepayment = _currentLoan.UseCents ? lastInstallmentInterest : Math.Round( lastInstallmentInterest .Value, 0); _currentLoan.InstallmentList[_currentLoan.InstallmentList.Count - 1].CapitalRepayment = _currentLoan.InstallmentList[_currentLoan.InstallmentList.Count - 1].CapitalRepayment + olb; _currentLoan.Amount = _currentLoan.Amount + to.TrancheAmount; }
private OCurrency RecalculateInterestForFirstNotPaidInstallment(Installment installment, OCurrency remainingOlb, TrancheOptions to) { OCurrency newInterest=0; if (installment.ExpectedDate>_previousSchedule[installment.Number-1].ExpectedDate) { if (installment.Number==1) { int daysBeforeTranche = (to.TrancheDate - _currentLoan.StartDate).Days; int oldQuantityOfDays = (_previousSchedule[installment.Number - 1].ExpectedDate - _currentLoan.StartDate).Days; newInterest = remainingOlb * _currentLoan.GivenTranches[to.Number - 1].InterestRate / oldQuantityOfDays * daysBeforeTranche + _previousSchedule[installment.Number - 1].InterestsRepayment; } else { int daysBeforeTranche = (to.TrancheDate - _previousSchedule[installment.Number - 2].ExpectedDate).Days; int oldQuantityOfDays = (_previousSchedule[installment.Number - 1].ExpectedDate - _previousSchedule[installment.Number - 2].ExpectedDate).Days; newInterest = remainingOlb * _currentLoan.GivenTranches[to.Number - 1].InterestRate / oldQuantityOfDays * daysBeforeTranche + _previousSchedule[installment.Number - 1].InterestsRepayment; } } else { newInterest = remainingOlb*_currentLoan.GivenTranches[to.Number - 1].InterestRate; } newInterest = RoundResult(_currentLoan.UseCents, newInterest); return newInterest; }
private void CheckAndCorrectSumOfCapitalRepayments(TrancheOptions to, Installment installment) { if (installment.Number==_currentLoan.InstallmentList.Count) { OCurrency sumOfCapitalRepayment = 0; foreach (Installment item in _currentLoan.InstallmentList) { sumOfCapitalRepayment += item.CapitalRepayment; } installment.CapitalRepayment += _currentLoan.Amount + to.TrancheAmount - sumOfCapitalRepayment; } }
public Loan FakeTranche(Loan pContract, DateTime pDate, int pNbOfMaturity, int pTrancheAmount, bool pApplyNewInterestOnOLB, decimal pNewInterestRate) { Loan fakeContract = pContract.Copy(); TrancheOptions to = new TrancheOptions { TrancheDate = pDate, CountOfNewInstallments = pNbOfMaturity, TrancheAmount = pTrancheAmount, InterestRate = pNewInterestRate, ApplyNewInterestOnOLB = pApplyNewInterestOnOLB }; fakeContract.CalculateTranche(to); return fakeContract; }
public TrancheEvent CalculateTranche(TrancheOptions pTo) { var tranche = new Tranche(this, _generalSettings); return tranche.AddTranche(pTo); }
private OCurrency CalculateCapitalRepayment(TrancheOptions to, Installment installment) { OCurrency result = to.TrancheAmount/to.CountOfNewInstallments + _previousSchedule[installment.Number - 1].CapitalRepayment; result = RoundResult(_currentLoan.UseCents, result); return result; }
private void AddFixedInstallmentTranche(TrancheOptions to) { OCurrency remainsAmount = 0; foreach (Installment installment in _currentLoan.InstallmentList) { if (!installment.IsRepaid) { remainsAmount += installment.CapitalRepayment - installment.PaidCapital; } } OCurrency remainsInterestAmount = _generalSettings.AccountingProcesses == OAccountingProcesses.Accrual ? GenerateEvents.Accrual.CalculateRemainingInterests(_currentLoan, to.TrancheDate) : GenerateEvents.Cash.CalculateRemainingInterests(_currentLoan, to.TrancheDate); remainsInterestAmount = _currentLoan.UseCents ? remainsInterestAmount : Math.Round(remainsInterestAmount.Value, 0, MidpointRounding.AwayFromZero); TrancheExtendMaturity(to.CountOfNewInstallments, to.TrancheDate); OCurrency olb; OCurrency newAmountVpm; OCurrency priviousAmountVpm = 0; if (to.ApplyNewInterestOnOLB) { olb = to.TrancheAmount + remainsAmount; newAmountVpm = _currentLoan.UseCents ? _currentLoan.VPM(olb, to.CountOfNewInstallments, to.InterestRate) : Math.Round(_currentLoan.VPM(olb, to.CountOfNewInstallments, to.InterestRate).Value, 0, MidpointRounding.AwayFromZero); remainsAmount = 0; } else { olb = to.TrancheAmount; newAmountVpm = _currentLoan.UseCents ? _currentLoan.VPM(olb, to.CountOfNewInstallments, to.InterestRate) : Math.Round(_currentLoan.VPM(olb, to.CountOfNewInstallments, to.InterestRate).Value, 0, MidpointRounding.AwayFromZero); priviousAmountVpm = _currentLoan.UseCents ? _currentLoan.VPM(remainsAmount, to.CountOfNewInstallments, (_currentLoan.GivenTranches[to.Number - 1].InterestRate.Value)) : Math.Round((_currentLoan.VPM(remainsAmount, to.CountOfNewInstallments, (_currentLoan.GivenTranches[to.Number - 1].InterestRate.Value))).Value, 0, MidpointRounding.AwayFromZero); } OCurrency _OLB = olb + remainsAmount; foreach (Installment installment in _currentLoan.InstallmentList) { if (!installment.IsRepaid) { installment.InterestsRepayment = _currentLoan.UseCents ? Math.Round(olb.Value * to.InterestRate, 2, MidpointRounding.AwayFromZero) : Math.Round(olb.Value * to.InterestRate, 0, MidpointRounding.AwayFromZero); OCurrency interestAmountForPriviousOlb = _currentLoan.UseCents ? remainsAmount * _currentLoan.GivenTranches[to.Number - 1].InterestRate : Math.Round((remainsAmount * _currentLoan.GivenTranches[to.Number - 1].InterestRate).Value, 0, MidpointRounding.AwayFromZero); installment.CapitalRepayment = newAmountVpm.Value - installment.InterestsRepayment.Value; installment.InterestsRepayment += _currentLoan.UseCents ? Math.Round(interestAmountForPriviousOlb.Value, 2, MidpointRounding.AwayFromZero) : Math.Round(interestAmountForPriviousOlb.Value, 0, MidpointRounding.AwayFromZero); olb -= installment.CapitalRepayment; installment.CapitalRepayment = _currentLoan.UseCents ? Math.Round(installment.CapitalRepayment.Value, 2, MidpointRounding.AwayFromZero) : Math.Round(installment.CapitalRepayment.Value, 0, MidpointRounding.AwayFromZero); OCurrency priviousCapital = priviousAmountVpm - interestAmountForPriviousOlb; installment.CapitalRepayment += _currentLoan.UseCents ? Math.Round(priviousCapital.Value, 2, MidpointRounding.AwayFromZero) : Math.Round(priviousCapital.Value, 0, MidpointRounding.AwayFromZero); remainsAmount -= priviousCapital; installment.InterestsRepayment += _currentLoan.UseCents ? Math.Round(remainsInterestAmount.Value, 2, MidpointRounding.AwayFromZero) : Math.Round(remainsInterestAmount.Value, 0, MidpointRounding.AwayFromZero); remainsInterestAmount = 0; installment.PaidCapital = 0; installment.PaidInterests = 0; } } _currentLoan.InstallmentList[_currentLoan.InstallmentList.Count - 1].CapitalRepayment += _currentLoan.UseCents ? Math.Round(olb.Value + remainsAmount.Value, 2, MidpointRounding.AwayFromZero) : Math.Round(olb.Value + remainsAmount.Value, 0, MidpointRounding.AwayFromZero); //OLB calculation foreach (Installment installment in _currentLoan.InstallmentList) { if (!installment.IsRepaid) { installment.OLB = _OLB; _OLB -= installment.CapitalRepayment; } } _currentLoan.Amount = _currentLoan.Amount + to.TrancheAmount; _currentLoan.InstallmentList[_currentLoan.InstallmentList.Count - 1].CapitalRepayment += _currentLoan.UseCents ? Math.Round(_OLB.Value, 2, MidpointRounding.AwayFromZero) : Math.Round(_OLB.Value, 0, MidpointRounding.AwayFromZero); }
private OCurrency CalculateInterestRepayment(TrancheOptions to, OCurrency remainsInterestAmount, OCurrency remainingOlb, OCurrency olb) { OCurrency result=0; if (to.ApplyNewInterestOnOLB) { result =(olb + remainingOlb)*to.InterestRate + remainsInterestAmount; } else { if (_currentLoan.UseCents) { OCurrency previousCapitalRepayment = Math.Round(remainingOlb.Value*_currentLoan.GivenTranches[to.Number - 1].InterestRate.Value, 2, MidpointRounding.AwayFromZero); OCurrency newCapitalRepayment = Math.Round(olb.Value*to.InterestRate, 2, MidpointRounding.AwayFromZero); result = newCapitalRepayment + previousCapitalRepayment + remainsInterestAmount; } else { OCurrency previousCapitalRepayment = Math.Round(remainingOlb.Value * _currentLoan.GivenTranches[to.Number - 1].InterestRate.Value, 0, MidpointRounding.AwayFromZero); OCurrency newCapitalRepayment = Math.Round(olb.Value * to.InterestRate, 0, MidpointRounding.AwayFromZero); result = newCapitalRepayment + previousCapitalRepayment + remainsInterestAmount; } } result = RoundResult(_currentLoan.UseCents, result); return result; }