public static double CalculateAnnuity(
            DateTime repaymentPeriodStartDate,
            DateTime firstInstallmentDate,
            int numberOfInstallments,
            int installmentFrequencyPeriod,
            SimpleUnitOfTime installmentFrequencyUnitOfTime,
            double ratePercentage,
            SimpleUnitOfTime rateUnitOfTime,
            bool isCompound,
            CalendarBasisKind calendarBasis,
            double principalAmount,
            bool adjustFirstInstallment = false)
        {
            DateTime d2 = firstInstallmentDate.AddPeriod(installmentFrequencyPeriod * (numberOfInstallments - 1), installmentFrequencyUnitOfTime);

            double   dummyAnnuity = 100;
            double   outstanding  = 0;
            double   basis        = 0;
            double   interest     = 0;
            DateTime d1;

            while (d2 > firstInstallmentDate)
            {
                d1          = d2.AddPeriod(-installmentFrequencyPeriod, installmentFrequencyUnitOfTime);
                basis       = outstanding + dummyAnnuity;
                interest    = InterestCalculation.CalculateInterest(d2, d1, d1, ratePercentage, rateUnitOfTime.CharLiteral(), isCompound, calendarBasis, basis).Sum(it => it.Interest);
                outstanding = basis + interest;
                d2          = d1;
            }

            d1 = repaymentPeriodStartDate;

            if (adjustFirstInstallment)
            {
                var prevDate = firstInstallmentDate.AddPeriod(-installmentFrequencyPeriod, installmentFrequencyUnitOfTime);
                if (prevDate < repaymentPeriodStartDate)
                {
                    d1 = prevDate;
                }
            }
            basis       = outstanding + dummyAnnuity;
            interest    = InterestCalculation.CalculateInterest(d2, d1, d1, ratePercentage, rateUnitOfTime.CharLiteral(), isCompound, calendarBasis, basis).Sum(it => it.Interest);
            outstanding = basis + interest;

            return(principalAmount / outstanding * dummyAnnuity);
        }
Ejemplo n.º 2
0
        private static decimal Yearfrac(DateTime startDate, DateTime endDate, CalendarBasisKind dayCount)
        {
            decimal nbDaysInPeriod = (decimal)(endDate - startDate).Days;

            switch (dayCount)
            {
            case (CalendarBasisKind.CalendarAct360):
                return(nbDaysInPeriod / (decimal)360);

            case (CalendarBasisKind.CalendarAct365L):
            case (CalendarBasisKind.CalendarAct365Fixed):
                return(nbDaysInPeriod / (decimal)365);

            case (CalendarBasisKind.Calendar30A360):
            case (CalendarBasisKind.Calendar30E360):
                decimal result = (endDate.Year - startDate.Year) * 360 + (endDate.Month - startDate.Month) * 30 + (Math.Min(endDate.Day, 30) - Math.Min(startDate.Day, 30));
                return(result / 360);

            default:
                return(GetActAct(startDate, endDate));
            }
        }
Ejemplo n.º 3
0
        public decimal MonthlyRate()
        {
            bool isCompound = false;
            CalendarBasisKind calendarBasis = CalendarBasisKind.CalendarActActISDA;
            double            yearlyRate    = 0;
            var ir = Conditions.InterestRates.FirstOrDefault(it => it.Kind == InterestRateKinds.RegularInterest);

            if (ir != null)
            {
                isCompound    = ir.IsCompound;
                calendarBasis = ir.CalendarBasis;
                yearlyRate    = Convert.ToDouble(ir.CalculatedRate / 100);
            }

            double monthlyRate = yearlyRate / 12;

            if (isCompound)
            {
                monthlyRate = Math.Pow(1 + yearlyRate, 1 / 12) - 1;
            }

            return(Convert.ToDecimal(monthlyRate));
        }
Ejemplo n.º 4
0
        public override void CalculateOffer(PriceCalculationParameters calculationParameters, OfferPriceCalculation priceCalculator, string feeCurrencyConversionMethod)
        {
            var ignore = priceCalculator.CalculatePrice(this, calculationParameters).Result;

            // isCompound i calendarBasis izvuci tokom CalculatePrice da dodatno opisu Napr
            bool isCompound = false;
            CalendarBasisKind calendarBasis = CalendarBasisKind.CalendarActActISDA;
            double            yearlyRate    = Convert.ToDouble(Napr) / 100;

            var ir = Conditions.InterestRates.FirstOrDefault(it => it.Kind == InterestRateKinds.RegularInterest);

            if (ir != null)
            {
                isCompound    = ir.IsCompound;
                calendarBasis = ir.CalendarBasis;
                yearlyRate    = Convert.ToDouble(ir.CalculatedRate);
                Napr          = Convert.ToDecimal(yearlyRate);
            }


            var startDate = calculationParameters.RequestDate ?? DateTime.Today;

            List <InstallmentPlanRow> rows       = new List <InstallmentPlanRow>();
            List <FeeCondition>       rowFeeList = new List <FeeCondition>();
            List <FeeCondition>       fees       = Conditions.Fees;

            fees = FeeCalculation.PrepareFees(fees, Currency, feeCurrencyConversionMethod);

            decimal  runningAmount = Math.Round(Amount, 2);
            DateTime runningDate   = startDate;

            if (CalculationDate > DateTime.Today)
            {
                CalculationDate = runningDate;
            }
            else
            {
                runningDate = CalculationDate ?? DateTime.Today;
            }

            // SLOBA: Fee scheduling, and scheduling in general has to be improved in advanced calculator.
            decimal totalFeeAmount = 0;

            if (fees != null)
            {
                List <FeeCondition> feeList = fees.FindAll(f => f.Frequency == FeeConditionFrequency.EventTriggered && f.EffectiveDate <= DateTime.Today && f.Currencies.Contains(Currency));
                totalFeeAmount = Math.Round(FeeCalculation.CalculateFee(Amount, feeList), 4);
            }
            NumberOfInstallments = 1;

            /* Disbursment */
            InstallmentPlanRow rowDisbursement = new InstallmentPlanRow();

            rowDisbursement.Date               = runningDate;
            rowDisbursement.Ordinal            = 0;
            rowDisbursement.ActivityKind       = ActivityKind.Disbursement;
            rowDisbursement.Description        = "Loan disbursement";
            rowDisbursement.Disbursement       = Amount;
            rowDisbursement.StartingBalance    = 0;
            rowDisbursement.OutstandingBalance = Amount;
            rowDisbursement.PrincipalRepayment = 0;
            rowDisbursement.InterestRepayment  = 0;
            rowDisbursement.NetCashFlow        = Amount - totalFeeAmount;
            rowDisbursement.Fee      = totalFeeAmount;
            rowDisbursement.YearFrac = 0;
            rows.Add(rowDisbursement);
            int i = -1;

            InstallmentPlanRow rowInterest;
            var intrStartDate = startDate;

            runningDate = runningDate.AddMonths(1);
            while (runningDate <= MaturityDate.Value)
            {
                i++;


                var interest = Math.Round(InterestCalculation.CalculateInterest(intrStartDate, runningDate, runningDate, Convert.ToDouble(yearlyRate), 'Y', isCompound, calendarBasis, Convert.ToDouble(runningAmount))
                                          .Sum(it => it.Interest), 2);

                rowInterest = new InstallmentPlanRow();

                rowInterest.Ordinal            = i + 1;
                rowInterest.Date               = runningDate;
                rowInterest.ActivityKind       = ActivityKind.Repayment;
                rowInterest.Description        = "Interest and fee repayment";
                rowInterest.InterestRepayment  = Convert.ToDecimal(interest);
                rowInterest.PrincipalRepayment = 0;
                rowInterest.Annuity            = rowInterest.InterestRepayment;
                rowInterest.StartingBalance    = Math.Round(runningAmount, 2);
                rowInterest.OutstandingBalance = Math.Round(runningAmount, 2);

                #region Fee calculation
                if (fees != null)
                {
                    decimal totalRowFee = 0;
                    rowFeeList = fees.FindAll(f => f.Frequency == FeeConditionFrequency.Monthly && f.EffectiveDate <= DateTime.Today && f.Currencies.Contains(Currency));
                    if (rowFeeList.Count > 0)
                    {
                        totalRowFee += FeeCalculation.CalculateFee(runningAmount, rowFeeList);
                    }
                    if ((i + 1) % 4 == 0)
                    {
                        rowFeeList = fees.FindAll(f => f.Frequency == FeeConditionFrequency.Quarterly && f.EffectiveDate <= DateTime.Today && f.Currencies.Contains(Currency));
                        if (rowFeeList.Count > 0)
                        {
                            totalRowFee += FeeCalculation.CalculateFee(runningAmount, rowFeeList);
                        }
                    }
                    if ((i + 1) % 6 == 0)
                    {
                        rowFeeList = fees.FindAll(f => f.Frequency == FeeConditionFrequency.Semiyearly && f.EffectiveDate <= DateTime.Today && f.Currencies.Contains(Currency));
                        if (rowFeeList.Count > 0)
                        {
                            totalRowFee += FeeCalculation.CalculateFee(runningAmount, rowFeeList);
                        }
                    }
                    if ((i + 1) % 12 == 0)
                    {
                        rowFeeList = fees.FindAll(f => f.Frequency == FeeConditionFrequency.Yearly && f.EffectiveDate <= DateTime.Today && f.Currencies.Contains(Currency));
                        if (rowFeeList.Count > 0)
                        {
                            totalRowFee += FeeCalculation.CalculateFee(runningAmount, rowFeeList);
                        }
                    }
                    rowInterest.Fee = Math.Round(totalRowFee, 4);
                }
                #endregion
                rowInterest.NetCashFlow = rowInterest.Disbursement - rowInterest.PrincipalRepayment - rowInterest.InterestRepayment - rowInterest.Fee - rowInterest.OtherExpenses;
                rowInterest.YearFrac    = Convert.ToDecimal(InterestCalculation.YearFrac(startDate, runningDate)); //, calendarBasis);
                rows.Add(rowInterest);
                intrStartDate = runningDate;
                runningDate   = runningDate.AddMonths(1);
            }

            i++;

            rowInterest = new InstallmentPlanRow();

            rowInterest.Ordinal            = i + 1;
            rowInterest.Date               = runningDate;
            rowInterest.ActivityKind       = ActivityKind.Repayment;
            rowInterest.Description        = "Principal repayment";
            rowInterest.InterestRepayment  = 0;
            rowInterest.PrincipalRepayment = Amount;
            rowInterest.Annuity            = Amount;
            rowInterest.StartingBalance    = Amount;
            rowInterest.OutstandingBalance = 0;

            #region Fee calculation
            rowInterest.Fee = 0;
            #endregion
            rowInterest.NetCashFlow = rowInterest.Disbursement - rowInterest.PrincipalRepayment - rowInterest.InterestRepayment - rowInterest.Fee - rowInterest.OtherExpenses;
            rowInterest.YearFrac    = Convert.ToDecimal(InterestCalculation.YearFrac(startDate, runningDate)); //, calendarBasis);
            rows.Add(rowInterest);
            NumberOfInstallments = 1;

            // arrangementRequest.InstallmentPlan = rows;
            CalculateAPR(rows);
        }
Ejemplo n.º 5
0
        // SLOBA: term and fees parameters are inconsistently extracted from arrangementRequest
        public void CalculateInstallmentPlan(string feeCurrencyConversionMethod)
        {
            int term = Utility.GetMonthsFromPeriod(Term);
            List <InstallmentPlanRow> rows       = new List <InstallmentPlanRow>();
            List <FeeCondition>       rowFeeList = new List <FeeCondition>();
            List <FeeCondition>       fees       = Conditions.Fees;

            fees = FeeCalculation.PrepareFees(fees, Currency, feeCurrencyConversionMethod);

            decimal  runningAmount = Math.Round(Amount, 2);
            DateTime runningDate   = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 0, 0, 0, 0);

            if (CalculationDate > DateTime.Today)
            {
                CalculationDate = runningDate;
            }
            else
            {
                runningDate = CalculationDate ?? DateTime.Today;
            }
            DateTime startDate = runningDate;

            // SLOBA: Fee scheduling, and scheduling in general has to be improved in advanced calculator.
            decimal totalFeeAmount = 0;

            if (fees != null)
            {
                List <FeeCondition> feeList = fees.FindAll(f => f.Frequency == FeeConditionFrequency.EventTriggered && f.EffectiveDate <= DateTime.Today && f.Currencies.Contains(Currency));
                totalFeeAmount = Math.Round(FeeCalculation.CalculateFee(Amount, feeList), 4);
            }
            NumberOfInstallments = 1;

            bool isCompound = false;
            CalendarBasisKind calendarBasis = CalendarBasisKind.CalendarActActISDA;
            double            yearlyRate    = 0;
            var ir = Conditions.InterestRates.FirstOrDefault(it => it.Kind == InterestRateKinds.RegularInterest);

            if (ir != null)
            {
                isCompound    = ir.IsCompound;
                calendarBasis = ir.CalendarBasis;
                yearlyRate    = Convert.ToDouble(ir.CalculatedRate / 100);
            }

            // this is huge simplification. not good
            double monthlyRate = yearlyRate / 12;

            if (isCompound)
            {
                monthlyRate = Math.Pow(1 + yearlyRate, 1.0000000 / 12.0000000) - 1;
            }

            // SLOBA: Logic for calculating cash flow is done in manner that is later hard to extend. Also columns are hardcoded.
            // SLOBA: This is totally ok for basic calculator though

            /* Disbursment */
            InstallmentPlanRow rowDisbursement = new InstallmentPlanRow();

            rowDisbursement.Date               = runningDate;
            rowDisbursement.Ordinal            = 0;
            rowDisbursement.ActivityKind       = ActivityKind.Disbursement;
            rowDisbursement.Description        = "Loan disbursement";
            rowDisbursement.Disbursement       = Amount;
            rowDisbursement.StartingBalance    = 0;
            rowDisbursement.OutstandingBalance = Amount;
            rowDisbursement.PrincipalRepayment = 0;
            rowDisbursement.InterestRepayment  = 0;
            rowDisbursement.NetCashFlow        = Amount - totalFeeAmount;
            rowDisbursement.Fee      = totalFeeAmount;
            rowDisbursement.YearFrac = 0;
            rows.Add(rowDisbursement);

            for (var i = 0; i < term; i++)
            {
                decimal interest  = Math.Round(runningAmount * Convert.ToDecimal(monthlyRate), 2);
                decimal principal = Math.Round(Annuity - interest, 2);

                if (i == term - 1)
                { // last ... corection for decimal places
                    principal = Math.Round(runningAmount, 2);
                    interest  = Math.Round(Annuity - principal, 2);
                }

                InstallmentPlanRow rowInterest = new InstallmentPlanRow();

                rowInterest.Ordinal            = i + 1;
                runningDate                    = runningDate.AddMonths(1);
                rowInterest.Date               = runningDate;
                rowInterest.ActivityKind       = ActivityKind.Repayment;
                rowInterest.Description        = "Anuity repayment";
                rowInterest.InterestRepayment  = interest;
                rowInterest.PrincipalRepayment = principal;
                rowInterest.Annuity            = Annuity;
                rowInterest.StartingBalance    = Math.Round(runningAmount, 2);
                runningAmount                  = (runningAmount - principal);
                rowInterest.OutstandingBalance = Math.Round(runningAmount, 2);

                #region Fee calculation
                if (fees != null)
                {
                    decimal totalRowFee = 0;
                    rowFeeList = fees.FindAll(f => f.Frequency == FeeConditionFrequency.Monthly && f.EffectiveDate <= DateTime.Today && f.Currencies.Contains(Currency));
                    if (rowFeeList.Count > 0)
                    {
                        totalRowFee += FeeCalculation.CalculateFee(runningAmount, rowFeeList);
                    }
                    if ((i + 1) % 4 == 0)
                    {
                        rowFeeList = fees.FindAll(f => f.Frequency == FeeConditionFrequency.Quarterly && f.EffectiveDate <= DateTime.Today && f.Currencies.Contains(Currency));
                        if (rowFeeList.Count > 0)
                        {
                            totalRowFee += FeeCalculation.CalculateFee(runningAmount, rowFeeList);
                        }
                    }
                    if ((i + 1) % 6 == 0)
                    {
                        rowFeeList = fees.FindAll(f => f.Frequency == FeeConditionFrequency.Semiyearly && f.EffectiveDate <= DateTime.Today && f.Currencies.Contains(Currency));
                        if (rowFeeList.Count > 0)
                        {
                            totalRowFee += FeeCalculation.CalculateFee(runningAmount, rowFeeList);
                        }
                    }
                    if ((i + 1) % 12 == 0)
                    {
                        rowFeeList = fees.FindAll(f => f.Frequency == FeeConditionFrequency.Yearly && f.EffectiveDate <= DateTime.Today && f.Currencies.Contains(Currency));
                        if (rowFeeList.Count > 0)
                        {
                            totalRowFee += FeeCalculation.CalculateFee(runningAmount, rowFeeList);
                        }
                    }
                    rowInterest.Fee = Math.Round(totalRowFee, 4);
                }
                #endregion
                rowInterest.NetCashFlow = rowInterest.Disbursement - rowInterest.PrincipalRepayment - rowInterest.InterestRepayment - rowInterest.Fee - rowInterest.OtherExpenses;
                rowInterest.YearFrac    = Yearfrac(startDate, runningDate, calendarBasis);
                rows.Add(rowInterest);
                NumberOfInstallments += 1;
            }
            // arrangementRequest.InstallmentPlan = rows;
            CalculateAPR(rows);
        }
Ejemplo n.º 6
0
        public static InterestCalculationResult CalculateInterest(
            DateTime date1,
            DateTime date2,
            DateTime date3,
            double ratePercentage,
            char rateUnitOfTime             = 'Y',
            bool isCompound                 = true,
            CalendarBasisKind calendarBasis = CalendarBasisKind.CalendarActActISDA,
            double amount = 1,
            double?calaculationPrecision = null,
            bool useAnticipativeMethod   = false                                                      // nije kao u PUB, vec znaci da se procenat primenjuje na osnovicu kakva ce biti na date2, za anticipativ kao u PUB, samo obrnuti datume, tako da je date1 > date2
            )
        {
            // TODO: Throw not implemented for unsupported methods
            InterestCalculationResult t = new InterestCalculationResult();

            if (date3 == null)
            {
                date3 = date2;
            }

            if (rateUnitOfTime == 'G')
            {
                rateUnitOfTime = 'Y';
            }

            int      y1, M1, d1, y2, M2, d2, zeroyear = ZeroDate.Year;
            double   s1, s2, daysincalendar, interestdays, BaseAmount = 0, interest = 0, ac;
            DateTime fd1, fd2;

            if (useAnticipativeMethod == false)
            {
                ac = 1;
            }
            else
            {
                ac = -1;
            }

            y1 = DatePart(Year, date1);
            M1 = DatePart(Month, date1);
            d1 = DatePart(Day, date1);
            y2 = DatePart(Year, date2);
            M2 = DatePart(Month, date2);
            d2 = DatePart(Day, date2);

            fd1 = DateAdd(Day, d1 - 1, DateAdd(Month, M1 - 1, DateAdd(Year, y1 - zeroyear, ZeroDate)));
            fd2 = DateAdd(Day, d2 - 1, DateAdd(Month, M2 - 1, DateAdd(Year, y2 - zeroyear, ZeroDate)));

            s1 = (date1 - fd1).TotalDays;
            s2 = (date2 - fd2).TotalDays;

            if (calendarBasis == CalendarBasisKind.Calendar30U360)
            {
                if ((IsEndOfFebruary(fd1) == true) && (IsEndOfFebruary(fd2) == true))
                {
                    d2 = 30;
                    s2 = 0;
                }
                if (IsEndOfFebruary(fd1) == true)
                {
                    d1 = 30;
                    s1 = 0;
                }
                if (d2 == 31 && (d1 == 30 || d1 == 31))
                {
                    d2 = 30;
                }
                if (d1 == 31)
                {
                    d1 = 30;
                }
            }
            else if (calendarBasis == CalendarBasisKind.Calendar30E360)
            {
                if (d1 == 31)
                {
                    d1 = 30;
                }
                if (d2 == 31)
                {
                    d2 = 30;
                }
            }
            else if (calendarBasis == CalendarBasisKind.Calendar30E360ISDA)
            {
                if (IsEndOfMonth(fd1) == true)
                {
                    d1 = 30;
                    if (IsEndOfFebruary(fd1) == true)
                    {
                        s1 = 0;
                    }
                }
                if (IsEndOfMonth(fd2) == true)
                {
                    if (!(IsEndOfFebruary(fd2) == true && date2 == date3)) // isLastPeriod = 1
                    {
                        d2 = 30;
                        if (IsEndOfFebruary(fd2) == true)
                        {
                            s2 = 0;
                        }
                    }
                }
            }
            else if (calendarBasis == CalendarBasisKind.Calendar30A360) // CHECK "30E+/360"
            {
                if (d1 == 31)
                {
                    d1 = 30;
                }
                if (d2 == 31)
                {
                    fd2 = DateAdd(Day, 1, fd2);
                    y2  = fd2.Year;
                    M2  = fd2.Month;
                    d2  = 1;
                }
            }

            double   perc, fract, d13, freq;
            char     ut;
            DateTime dt;

            CalendarBasisKind[] actualMethods = { CalendarBasisKind.CalendarAct360, CalendarBasisKind.CalendarAct364, CalendarBasisKind.CalendarAct365Fixed, CalendarBasisKind.CalendarAct365L, CalendarBasisKind.CalendarActActAFB, CalendarBasisKind.CalendarActActICMA, CalendarBasisKind.CalendarActActISDA };

            bool is30360 = (calendarBasis == CalendarBasisKind.Calendar30A360) ||
                           (calendarBasis == CalendarBasisKind.Calendar30E360) ||
                           (calendarBasis == CalendarBasisKind.Calendar30E360ISDA) ||
                           (calendarBasis == CalendarBasisKind.Calendar30U360);

            if (is30360) //CalendarBasis like '30%/360%'
            {
                if (rateUnitOfTime == 'Y')
                {
                    daysincalendar = 360;
                }
                else if (rateUnitOfTime == 'Q')
                {
                    daysincalendar = 90;
                }
                else if (rateUnitOfTime == 'M')
                {
                    daysincalendar = 30;
                }
                else
                {
                    daysincalendar = 1;
                }

                interestdays = (360 * (y2 - y1) + 30 * (M2 - M1) + (d2 - d1)) + (s2 - s1);

                t.Add(new DateSegment()
                {
                    RowNum             = 1,
                    DateFrom           = date1,
                    DateTo             = date2,
                    DaysInPeriod       = interestdays,
                    DaysInCalendar     = daysincalendar,
                    Rate               = ratePercentage,
                    RateUnitOfTime     = rateUnitOfTime,
                    RateDays           = daysincalendar,
                    BaseAmount         = amount,
                    Interest           = 0,
                    AccumulatedBalance = amount
                });

                //insert into t(DateFrom, DateTo, InterestDays, DaysInCalendar, BaseAmount, Interest)
                //values(date1, date2, cast(date1 as float), cast(date2 as float), cast(fd1 as float), cast(fd2 as float))
                //insert into t(DateFrom, DateTo, InterestDays, DaysInCalendar, BaseAmount, Interest)
                //values(fd1, fd2, cast(date1 as float), cast(date2 as float), cast(fd1 as float), cast(fd2 as float))
            }
            else if (calendarBasis == CalendarBasisKind.CalendarAct365Fixed || calendarBasis == CalendarBasisKind.CalendarAct360) //CalendarBasis in ('Actual/365', 'Actual/360')
            {
                if (calendarBasis == CalendarBasisKind.CalendarAct365Fixed)
                {
                    daysincalendar = 365;
                }
                else
                {
                    daysincalendar = 360;
                }
                fract = 1;
                ut    = 'Y';

                if (rateUnitOfTime == 'Q')
                {
                    fract = 4;
                }
                else if (rateUnitOfTime == 'M')
                {
                    fract = 12;
                }
                else if (rateUnitOfTime == 'D')
                {
                    daysincalendar = 1;
                    fract          = 1;
                    ut             = 'D';
                }

                // pretvaranje stope - videti sa UseAnticipativeMethod
                if (isCompound == true)
                {
                    perc = (Math.Pow(1 + ratePercentage / 100 * ac, fract) - 1) * 100;
                }
                else
                {
                    perc = ratePercentage * fract;
                }

                interestdays = DateDiff(Day, fd1, fd2) + (s2 - s1);

                t.Add(new DateSegment()
                {
                    RowNum             = 1,
                    DateFrom           = date1,
                    DateTo             = date2,
                    DaysInPeriod       = interestdays,
                    DaysInCalendar     = daysincalendar,
                    Rate               = perc,
                    RateUnitOfTime     = ut,
                    RateDays           = daysincalendar,
                    BaseAmount         = amount,
                    Interest           = 0,
                    AccumulatedBalance = amount
                });
            }
            else if (calendarBasis == CalendarBasisKind.CalendarAct365L)
            {
                d13            = DateDiff(Day, date1, date3); // + (s3 - s1)
                freq           = Math.Round(365 / d13, 6);
                daysincalendar = 365;

                if (IsLeapYear(date3) == true && date3.Month >= 3)
                {
                    daysincalendar = 366;
                }
                else if (Math.Abs(freq) > 1 && IsLeapYear(date3) == true)
                {
                    daysincalendar = 366;
                }
                else if (Math.Abs(freq) <= 1)
                {
                    if (date1.Month <= 2 && IsEndOfFebruary(date1) == false) //(dt.Month <= 2 && IsEndOfFebruary(date1) == false)
                    {
                        dt = date1;
                    }
                    else
                    {
                        dt = DateAdd(Year, 1, date1);
                    }
                    while (dt <= date3)
                    {
                        if (IsLeapYear(dt) == true)
                        {
                            daysincalendar = 366;
                            break;
                        }
                        dt = DateAdd(Year, 1, dt);
                    }
                }

                fract = 1;
                ut    = 'Y';

                if (rateUnitOfTime == 'Q')
                {
                    fract = 4;
                }
                else if (rateUnitOfTime == 'M')
                {
                    fract = 12;
                }
                else if (rateUnitOfTime == 'D')
                {
                    fract = DateDiff(Day, fd1, DateAdd(Year, 1, fd1));
                }

                // pretvaranje stope - videti sa UseAnticipativeMethod
                if (isCompound == true)
                {
                    perc = (Math.Pow(1 + ratePercentage / 100 * ac, fract) - 1) * 100;
                }
                else
                {
                    perc = ratePercentage * fract;
                }

                interestdays = DateDiff(Day, fd1, fd2) + (s2 - s1);

                t.Add(new DateSegment()
                {
                    RowNum             = 1,
                    DateFrom           = date1,
                    DateTo             = date2,
                    DaysInPeriod       = interestdays,
                    DaysInCalendar     = daysincalendar,
                    Rate               = perc,
                    RateUnitOfTime     = ut,
                    RateDays           = daysincalendar,
                    BaseAmount         = amount,
                    Interest           = 0,
                    AccumulatedBalance = amount
                });
            }
            else if (calendarBasis == CalendarBasisKind.CalendarActActICMA)
            {
                d13            = DateDiff(Day, date1, date3); // + (s3 - s1)
                freq           = Math.Round(365 / d13, 6);
                daysincalendar = Math.Round(freq * d13, 0);

                fract = 1;
                ut    = 'Y';

                if (rateUnitOfTime == 'Q')
                {
                    fract = 4;
                }
                else if (rateUnitOfTime == 'M')
                {
                    fract = 12;
                }
                else if (rateUnitOfTime == 'D')
                {
                    fract = DateDiff(Day, fd1, DateAdd(Year, 1, fd1));
                }

                // pretvaranje stope - videti sa UseAnticipativeMethod
                if (isCompound == true)
                {
                    perc = (Math.Pow(1 + ratePercentage / 100 * ac, fract) - 1) * 100;
                }
                else
                {
                    perc = ratePercentage * fract;
                }

                interestdays = DateDiff(Day, fd1, fd2) + (s2 - s1);

                t.Add(new DateSegment()
                {
                    RowNum             = 1,
                    DateFrom           = date1,
                    DateTo             = date2,
                    DaysInPeriod       = interestdays,
                    DaysInCalendar     = d13,
                    Rate               = perc,
                    RateUnitOfTime     = ut,
                    RateDays           = daysincalendar,
                    BaseAmount         = amount,
                    Interest           = 0,
                    AccumulatedBalance = amount
                });
            }
            else if (actualMethods.Contains(calendarBasis))//CalendarBasis like 'Actual%'
            {
                if (rateUnitOfTime == 'Y')
                {
                    foreach (DateSegment item in SplitToYearlySegments(date1, date2, rateUnitOfTime))
                    {
                        t.Add(new DateSegment()
                        {
                            RowNum             = item.RowNum,
                            DateFrom           = item.DateFrom,
                            DateTo             = item.DateTo,
                            DaysInPeriod       = item.DaysInPeriod,
                            DaysInCalendar     = item.DaysInCalendar,
                            Rate               = ratePercentage,
                            RateUnitOfTime     = rateUnitOfTime,
                            RateDays           = item.RateDays,
                            BaseAmount         = amount,
                            Interest           = 0,
                            AccumulatedBalance = amount
                        });
                    }
                }
                else //if (RateUnitOfTime == 'Q' || RateUnitOfTime == 'M') -- if RateUnitOfTime in ('Q', 'M')
                {
                    foreach (DateSegment item in SplitToMonthlySegments(date1, date2, rateUnitOfTime))
                    {
                        t.Add(new DateSegment()
                        {
                            RowNum             = item.RowNum,
                            DateFrom           = item.DateFrom,
                            DateTo             = item.DateTo,
                            DaysInPeriod       = item.DaysInPeriod,
                            DaysInCalendar     = item.DaysInCalendar,
                            Rate               = ratePercentage,
                            RateUnitOfTime     = rateUnitOfTime,
                            RateDays           = item.RateDays,
                            BaseAmount         = amount,
                            Interest           = 0,
                            AccumulatedBalance = amount
                        });
                    }
                }
            }

            DateTime?dat = null;
            int      sgn;

            if (date1 > date2)
            {
                sgn = -1;
            }
            else
            {
                sgn = 1;
            }

            if (isCompound == false)
            {
                double factor = (from it in t
                                 select(it.DaysInPeriod / it.RateDays * ratePercentage / 100))
                                .Sum();

                double interestCoefficientBase = (Math.Pow((factor * ac + sgn), sgn * ac) * sgn - 1);
                interest = amount * interestCoefficientBase;

                if (factor != 0)
                {
                    Parallel.ForEach(t, currenItem =>
                    {
                        double interestCoefficient     = (currenItem.DaysInPeriod / currenItem.RateDays * currenItem.Rate / 100) / factor * interestCoefficientBase;
                        currenItem.InterestCoefficient = interestCoefficient;
                        //currenItem.Interest = interestCoefficient * amount;
                        currenItem.Interest = (currenItem.DaysInPeriod / currenItem.RateDays * currenItem.Rate / 100) / factor * interest;
                    });
                }

                for (int i = 0; i < t.Count; i++)
                {
                    BaseAmount = t[i].AccumulatedBalance = (dat == null ? t[i].AccumulatedBalance : BaseAmount) + t[i].Interest;
                    dat        = t[i].DateFrom;
                }
            }
            else
            {
                for (int i = 0; i < t.Count; i++)
                {
                    BaseAmount = (dat == null ? t[i].BaseAmount : BaseAmount + interest);
                    dat        = t[i].DateFrom;
                    double interestCoefficient = (Math.Pow((t[i].Rate / 100 * ac + 1), t[i].DaysInPeriod * ac / t[i].RateDays) - 1);
                    t[i].InterestCoefficient = interestCoefficient;
                    interest                = t[i].Interest = BaseAmount * interestCoefficient;
                    t[i].BaseAmount         = BaseAmount;
                    t[i].AccumulatedBalance = BaseAmount + interest;
                }
            }

            return(t);
        }