Example #1
0
        public static PaymentResult CalculateBalanceWithPayment(double interestRate, double payment, double balance, int year, int month)
        {
            PaymentResult ret = new PaymentResult();

            double newrate      = interestRate * 0.01;
            double periodicrate = (newrate / 365);

            double interest = balance * periodicrate * DateTime.DaysInMonth(year, month);

            ret.Interest = interest;

            if (interest > payment)
            {
                throw new Exception("Debit of $" + balance.ToString() + " with a rate of " + interestRate.ToString() + "% has a payment that is too low to cover interest!");
            }

            double red = (payment - interest);

            if (red < balance)
            {
                ret.NewBalance = balance - red;
                ret.Principal  = red;
            }
            else
            {
                ret.NewBalance = balance - interest;
                ret.Principal  = red;
                ret.NewBalance = 0;
            }

            return(ret);
        }
        public List <DebtPayment> ProcessPlan(bool Snowball, SnowballApproaches approach, double initialSnowballPayment, DateTime?initialSnowballStart = null)
        {
            DateTime startProcess = DateTime.Now;

            DateTime           cur          = DateTime.Now;
            List <DebtPayment> DebtPayments = new List <DebtPayment>();

            if (initialSnowballStart == null)
            {
                initialSnowballStart = DateTime.Now;
            }
            double TotalIntrest = 0;

            foreach (Debt d in Debts)
            {
                d.Balance = d.OriginalBalance;

                if (d.FirstPaymentDate < cur)
                {
                    cur = d.FirstPaymentDate;
                }
            }

            while (GetTotalBalance() > 0)
            {
                double curExtra = cur >= initialSnowballStart && Snowball ? initialSnowballPayment : 0;

                if (Snowball)
                {
                    foreach (ExtraPayment ep in ExtraPayments.Where(x => x.Enabled == true))
                    {
                        curExtra = curExtra + ep.IsItTimeToApply(cur.Month, cur.Year);
                    }
                }

                List <Debt> debtOrder = new List <Debt>();
                switch (approach)
                {
                case SnowballApproaches.MyOrder:
                    debtOrder = Debts.ToList();
                    break;

                case SnowballApproaches.LowestBalanceFirst:
                    debtOrder = Debts.OrderBy(x => x.OriginalBalance).ToList();
                    break;

                case SnowballApproaches.HighestInterestFirst:
                    debtOrder = Debts.OrderByDescending(x => x.IntrestRate).ToList();
                    break;
                }


                foreach (Debt d in debtOrder)
                {
                    if (d.Balance > 0 && d.Enabled && cur >= d.FirstPaymentDate)
                    {
                        double extra = 0;

                        if (d.Balance >= curExtra)
                        {
                            extra    = curExtra;
                            curExtra = 0;
                        }
                        else
                        {
                            extra    = d.Balance;
                            curExtra = curExtra - d.Balance;
                        }

                        PaymentResult pr = Debt.CalculateBalanceWithPayment(d.IntrestRate, d.Payment + extra, d.Balance, cur.Year, cur.Month);
                        d.Balance     = pr.NewBalance;
                        TotalIntrest += pr.Interest;

                        DebtPayment dp = new DebtPayment();
                        dp.Intrest           = Math.Round(pr.Interest, 2);
                        dp.Balance           = Math.Round(pr.NewBalance, 2);
                        dp.Name              = d.Name;
                        dp.Payment           = Math.Round(d.Payment + extra, 2);
                        dp.ExtraPaid         = extra;
                        dp.Principal         = Math.Round(pr.Principal, 2);
                        dp.TotalBalance      = Math.Round(GetTotalBalance(), 2);
                        dp.TotalInterestPaid = Math.Round(TotalIntrest, 2);
                        dp.Date              = cur.Month.ToString() + "/" + cur.Year.ToString();

                        DebtPayments.Add(dp);

                        if (Snowball)
                        {
                            if (d.Balance == 0)
                            {
                                Debt snowballTo = new Debt();
                                snowballTo.Balance = 9999999999;

                                foreach (Debt dm in Debts)
                                {
                                    if (dm.Enabled && dm.Balance < snowballTo.Balance && dm.Balance > 0)
                                    {
                                        snowballTo = dm;
                                    }
                                }

                                initialSnowballPayment += d.Payment;
                                //snowballTo.Payment += d.Payment;
                            }
                        }
                    }
                }

                cur = cur.AddMonths(1);

                if (cur.Year > 2050)
                {
                    break;
                }
            }

            AccumulatorCollection acPrincipal = new AccumulatorCollection();
            AccumulatorCollection acInterest  = new AccumulatorCollection();

            for (int x = 0; x < DebtPayments.Count; x++)
            {
                acInterest.AddTo(DebtPayments[x].Date, DebtPayments[x].Intrest);
                acPrincipal.AddTo(DebtPayments[x].Date, DebtPayments[x].Principal);
            }

            for (int x = 0; x < DebtPayments.Count; x++)
            {
                DebtPayments[x].TotalMonthlyInterest  = acInterest.GetMonthAccumulation(DebtPayments[x].Date);
                DebtPayments[x].TotalMonthlyPrincipal = acPrincipal.GetMonthAccumulation(DebtPayments[x].Date);
            }


            TimeSpan finishedProcess = DateTime.Now - startProcess;

            Debug.WriteLine($"Process Took: {finishedProcess.TotalSeconds} seconds");

            return(DebtPayments);
        }