Exemplo n.º 1
0
        /// <summary>
        /// Return a Cashflows object containing array of the payment calculation periods and array of principal exchanges.
        /// </summary>
        /// <param name="paymentCalendar"> </param>
        /// <param name="interestRateStream">The interest rate stream.</param>
        /// <param name="rollDates">The list of roll dates.</param>
        /// <returns></returns>
        public static Cashflows GetCashflows(List <DateTime> rollDates, IBusinessCalendar paymentCalendar, InterestRateStream interestRateStream)
        {
            CalculationPeriodsPrincipalExchangesAndStubs calculationPeriodsPrincipalExchangesAndStubs =
                StreamCashflowsGenerator.GenerateCalculationPeriodsPrincipalExchangesAndStubsFromRollDates(interestRateStream, rollDates, paymentCalendar);

            return(GetCashfows(interestRateStream, calculationPeriodsPrincipalExchangesAndStubs, paymentCalendar));
        }
        private static void GeneratePeriodsBackward(DateTime firstRollDate, CalculationPeriodFrequency frequency,
                                                    BusinessDayAdjustments calculationPeriodDatesAdjustments,
                                                    CalculationPeriodsPrincipalExchangesAndStubs result,
                                                    DateTime adjustedEffectiveDate, StubPeriodTypeEnum?initialStubType
                                                    , IBusinessCalendar paymentCalendar)
        {
            DateTime periodEndDate               = firstRollDate;
            DateTime periodStartDate             = AddPeriod(periodEndDate, IntervalHelper.FromFrequency(frequency), -1);
            bool     encounteredShortInitialStub = false;

            //if (paymentCalendar == null)
            //{
            //    paymentCalendar = BusinessCenterHelper.ToBusinessCalendar(cache, calculationPeriodDatesAdjustments.businessCenters);
            //}
            do
            {
                var calculationPeriod = new CalculationPeriod();
                //  Apply ROLL CONVENTION (NOT A BUSINESS DAY CONVENTION!) to unadjusted period start and end dates.
                //
                DateTime rollConventionAdjustedPeriodStartDate = periodStartDate;
                DateTime rollConventionAdjustedPeriodEndDate   = periodEndDate;
                var      frequencyPeriod = EnumHelper.Parse <PeriodEnum>(frequency.period, true);
                if (frequencyPeriod != PeriodEnum.D)//adjust if the frequency is NOT expressed in days
                {
                    rollConventionAdjustedPeriodStartDate = RollConventionEnumHelper.AdjustDate(frequency.rollConvention, periodStartDate);
                    rollConventionAdjustedPeriodEndDate   = RollConventionEnumHelper.AdjustDate(frequency.rollConvention, periodEndDate);
                }
                CalculationPeriodHelper.SetUnadjustedDates(calculationPeriod, rollConventionAdjustedPeriodStartDate, rollConventionAdjustedPeriodEndDate);
                //  Set adjusted period dates
                //
                DateTime adjustedPeriodStartDate = AdjustedDateHelper.ToAdjustedDate(paymentCalendar, rollConventionAdjustedPeriodStartDate, calculationPeriodDatesAdjustments);
                DateTime adjustedPeriodEndDate   = AdjustedDateHelper.ToAdjustedDate(paymentCalendar, rollConventionAdjustedPeriodEndDate, calculationPeriodDatesAdjustments);
                CalculationPeriodHelper.SetAdjustedDates(calculationPeriod, adjustedPeriodStartDate, adjustedPeriodEndDate);
                //if (calculationPeriod.unadjustedStartDate > adjustedEffectiveDate)
                if (calculationPeriod.adjustedStartDate > adjustedEffectiveDate)
                {
                    result.InsertFirst(calculationPeriod);
                    periodEndDate   = periodStartDate;
                    periodStartDate = AddPeriod(periodEndDate, IntervalHelper.FromFrequency(frequency), -1);
                }
                //else if (calculationPeriod.unadjustedStartDate == adjustedEffectiveDate)//first period - not stub
                else if (calculationPeriod.adjustedStartDate == adjustedEffectiveDate)//first period - not stub
                {
                    result.InsertFirst(calculationPeriod);
                    break;
                }
                else//first period - short stub (merge with next period if a long stub specified)
                {
                    encounteredShortInitialStub = true;
                    //calculationPeriod.unadjustedStartDate = adjustedEffectiveDate;
                    calculationPeriod.adjustedStartDate = adjustedEffectiveDate;
                    result.InitialStubCalculationPeriod = calculationPeriod;
                    break;
                }
            } while (true);
            if (encounteredShortInitialStub && initialStubType == StubPeriodTypeEnum.LongInitial)
            {
                result.CreateLongInitialStub();
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Return a Cashflows object containing array of the payment calculation periods and array of principal exchanges.
        /// </summary>
        /// <param name="interestRateStream">The interest rate stream.</param>
        /// <param name="fixingCalendar"> </param>
        /// <param name="paymentCalendar"> </param>
        /// <returns></returns>
        public static Cashflows GetCashflows(InterestRateStream interestRateStream, IBusinessCalendar fixingCalendar, IBusinessCalendar paymentCalendar)
        {
            CalculationPeriodsPrincipalExchangesAndStubs calculationPeriodsPrincipalExchangesAndStubs =
                StreamCashflowsGenerator.GenerateCalculationPeriodsPrincipalExchangesAndStubs(interestRateStream, fixingCalendar, paymentCalendar);

            return(GetCashfows(interestRateStream, calculationPeriodsPrincipalExchangesAndStubs, paymentCalendar));
        }
Exemplo n.º 4
0
        private static Cashflows GetCashfows(
            InterestRateStream interestRateStream, CalculationPeriodsPrincipalExchangesAndStubs calculationPeriodsPrincipalExchangesAndStubs,
            IBusinessCalendar paymentCalendar)
        {
            // Assign notionals, rates, cap/floor rate, etc
            //
            StreamCashflowsGenerator.UpdateCalculationPeriodsData(interestRateStream, calculationPeriodsPrincipalExchangesAndStubs);
            List <PaymentCalculationPeriod> paymentCalculationPeriods = StreamCashflowsGenerator.GetPaymentCalculationPeriods(interestRateStream, calculationPeriodsPrincipalExchangesAndStubs, paymentCalendar);
            Calculation calculation = XsdClassesFieldResolver.CalculationPeriodAmountGetCalculation(interestRateStream.calculationPeriodAmount);

            UpdateNumberOfDaysAndYearFraction(paymentCalculationPeriods, calculation);
            return(CashflowsFactory.Create(paymentCalculationPeriods, calculationPeriodsPrincipalExchangesAndStubs.GetAllPrincipalExchanges(), true));//TODO THe cashflowsmatch paraqmeter at the end could be a problem!
        }
Exemplo n.º 5
0
        public List <DateTime> BuildDates(ILogger logger, ICoreCache cache, String nameSpace, BillSwapPricerDatesRange billSwapPricerDatesRange, IBusinessCalendar paymentCalendar)
        {
            CalculationPeriodFrequency frequency   = CalculationPeriodFrequencyHelper.Parse(billSwapPricerDatesRange.RollFrequency, billSwapPricerDatesRange.RollConvention);
            StubPeriodTypeEnum?        initialStub = null;

            if (!String.IsNullOrEmpty(billSwapPricerDatesRange.InitialStubPeriod))
            {
                initialStub = EnumHelper.Parse <StubPeriodTypeEnum>(billSwapPricerDatesRange.InitialStubPeriod);
            }
            StubPeriodTypeEnum?finalStub = null;

            if (!String.IsNullOrEmpty(billSwapPricerDatesRange.FinalStubPeriod))
            {
                finalStub = EnumHelper.Parse <StubPeriodTypeEnum>(billSwapPricerDatesRange.FinalStubPeriod);
            }
            //BusinessDayAdjustments adjustments = BusinessDayAdjustmentsHelper.Create(BusinessDayConventionEnum.NONE, "");
            //if (paymentCalendar == null)
            //{
            //    paymentCalendar = BusinessCenterHelper.ToBusinessCalendar(cache, adjustments.businessCenters);//Make sure this builds a valid calendar!
            //}
            BusinessDayAdjustments calculationPeriodDayAdjustments = BusinessDayAdjustmentsHelper.Create(billSwapPricerDatesRange.BusinessDayConvention, billSwapPricerDatesRange.Calendar);

            if (paymentCalendar == null)
            {
                paymentCalendar = BusinessCenterHelper.ToBusinessCalendar(cache, calculationPeriodDayAdjustments.businessCenters, nameSpace);
            }
            CalculationPeriodsPrincipalExchangesAndStubs result = CalculationPeriodGenerator.GenerateAdjustedCalculationPeriods(
                billSwapPricerDatesRange.StartDate,
                billSwapPricerDatesRange.EndDate,
                billSwapPricerDatesRange.FirstRegularPeriodStartDate,
                frequency,
                calculationPeriodDayAdjustments,
                initialStub,
                finalStub,
                paymentCalendar
                );

            foreach (CalculationPeriod regularCalculationPeriod in result.GetRegularAndStubPeriods())
            {
                // Adjust both startDate & endDate of period
                //
                CalculationPeriodHelper.SetAdjustedDates(regularCalculationPeriod,
                                                         AdjustedDateHelper.ToAdjustedDate(paymentCalendar, regularCalculationPeriod.unadjustedStartDate, calculationPeriodDayAdjustments),
                                                         AdjustedDateHelper.ToAdjustedDate(paymentCalendar, regularCalculationPeriod.unadjustedEndDate, calculationPeriodDayAdjustments));
            }
            var listResult = result.GetRegularAndStubPeriods().Select(regularCalculationPeriod => regularCalculationPeriod.adjustedStartDate).ToList();

            listResult.Add(result.GetRegularAndStubPeriods()[result.GetRegularAndStubPeriods().Count - 1].adjustedEndDate);
            return(listResult);
        }
        public static CalculationPeriodsPrincipalExchangesAndStubs GenerateAdjustedCalculationPeriods(
            DateTime unadjustedEffectiveDate,
            DateTime unadjustedTerminationDate,
            DateTime unadjustedFirstRollDate, //this one is still UN adjusted
            CalculationPeriodFrequency frequency,
            BusinessDayAdjustments calculationPeriodDatesAdjustments,
            StubPeriodTypeEnum?initialStubType,
            StubPeriodTypeEnum?finalStubType,
            IBusinessCalendar paymentCalendar)
        {
            #region Param check

            if (initialStubType.HasValue)
            {
                if ((initialStubType != StubPeriodTypeEnum.LongInitial) && (initialStubType != StubPeriodTypeEnum.ShortInitial))
                {
                    throw new ArgumentOutOfRangeException(nameof(initialStubType), initialStubType, "Wrong stub type.");
                }
            }
            if (finalStubType.HasValue)
            {
                if ((finalStubType == StubPeriodTypeEnum.LongFinal) && (initialStubType == StubPeriodTypeEnum.ShortFinal))
                {
                    throw new ArgumentOutOfRangeException(nameof(finalStubType), finalStubType, "Wrong stub type.");
                }
            }
//            if (!RollConventionEnumHelper.IsAdjusted(frequency.rollConvention, unadjustedFirstRollDate))
//            {
//                string message = String.Format("First roll date {0}, should be pre-adjusted according to RollConvention {1}", unadjustedFirstRollDate, frequency.rollConvention);
//                throw new Exception(message);
//            }

            #endregion

            var result = new CalculationPeriodsPrincipalExchangesAndStubs();
            //  Start calculations from 'first roll date' and generate dates backwards and forwards
            //
            //  Generate periods backwards (toward the unadjustedEffectiveDate)
            //
            GeneratePeriodsBackward(unadjustedFirstRollDate, frequency, calculationPeriodDatesAdjustments, result, unadjustedEffectiveDate, initialStubType, paymentCalendar);
            //  Generate periods forwards (toward the unadjustedTerminationDate)
            //
            GeneratePeriodsForward(unadjustedFirstRollDate, frequency, calculationPeriodDatesAdjustments, result, unadjustedTerminationDate, finalStubType, paymentCalendar);
            return(result);
        }
        //public static CalculationPeriodsPrincipalExchangesAndStubs GenerateUnadjustedCalculationPeriods(
        //                                                    IBusinessCalendar paymentCalendar,
        //                                                    DateTime unadjustedStartDate,
        //                                                    DateTime unadjustedEndDate,
        //                                                    CalculationPeriodFrequency frequency,
        //                                                    StubPeriodTypeEnum? initialStubType,
        //                                                    StubPeriodTypeEnum? finalStubType
        //                                                )
        //{
        //    // If first roll date not specified - calculate it from the start date.
        //    //
        //    DateTime unadjustedFirstRollDate = AddPeriod(unadjustedStartDate, frequency, 1);
        //    return GenerateUnadjustedCalculationPeriods(unadjustedStartDate, unadjustedEndDate, unadjustedFirstRollDate, frequency, initialStubType, finalStubType);
        //}

        public static CalculationPeriodsPrincipalExchangesAndStubs GenerateAdjustedCalculationPeriods(

            DateTime unadjustedStartDate,
            DateTime unadjustedTerminationDate,
            DateTime?firstUnadjustedRegularPeriodStartDate,
            DateTime?lastUnadjustedRegularPeriodEndDate,
            CalculationPeriodFrequency frequency,
            BusinessDayAdjustments calculationPeriodDatesAdjustments,
            IBusinessCalendar paymentCalendar)
        {
            var result = new CalculationPeriodsPrincipalExchangesAndStubs();

            //  Generate periods backwards (toward the unadjustedEffectiveDate)
            //
            GeneratePeriods(unadjustedStartDate, unadjustedTerminationDate, firstUnadjustedRegularPeriodStartDate,
                            lastUnadjustedRegularPeriodEndDate, frequency, calculationPeriodDatesAdjustments, result, paymentCalendar);
            result.CalculationPeriods.Sort((calculationPeriod1, calculationPeriod2) =>
                                           calculationPeriod1.adjustedEndDate.CompareTo(calculationPeriod2.adjustedEndDate));
            return(result);
        }
        public static void GeneratePeriods(DateTime unadjustedStartDate,
                                           DateTime unadjustedTerminationDate,
                                           DateTime?firstUnadjustedRegularPeriodStartDate,
                                           DateTime?lastUnadjustedRegularPeriodEndDate,
                                           //StubPeriodTypeEnum? initialStubType,
                                           //StubPeriodTypeEnum? finalStubType,
                                           CalculationPeriodFrequency frequency,
                                           BusinessDayAdjustments calculationPeriodDatesAdjustments,
                                           CalculationPeriodsPrincipalExchangesAndStubs result,
                                           IBusinessCalendar paymentCalendar)
        {
            DateTime periodEndDate = unadjustedTerminationDate;
            DateTime periodStartDate;
            bool     isInitialStub = firstUnadjustedRegularPeriodStartDate != null;
            var      startDate     = unadjustedStartDate;

            if (isInitialStub)
            {
                startDate = (DateTime)firstUnadjustedRegularPeriodStartDate;
            }
            var isFinalStub = lastUnadjustedRegularPeriodEndDate != null;

            if (isFinalStub)
            {
                periodStartDate = (DateTime)lastUnadjustedRegularPeriodEndDate;
            }
            else
            {
                periodStartDate = AddPeriod(periodEndDate, IntervalHelper.FromFrequency(frequency), -1);
            }
            var isFirstPeriod = true;

            do
            {
                var calculationPeriod = Create(periodStartDate, periodEndDate, frequency,
                                               calculationPeriodDatesAdjustments, paymentCalendar, isFirstPeriod);
                isFirstPeriod = false;
                //adjust for roll convention.
                periodStartDate = calculationPeriod.unadjustedStartDate;
                periodEndDate   = calculationPeriod.unadjustedEndDate;
                if (isFinalStub)//Always at least one period.
                {
                    result.FinalStubCalculationPeriod = calculationPeriod;
                    periodEndDate   = periodStartDate;
                    periodStartDate = AddPeriod(periodEndDate, IntervalHelper.FromFrequency(frequency), -1);
                    isFinalStub     = false;
                }
                else if (calculationPeriod.unadjustedStartDate.Date >= startDate.Date)
                {
                    result.Add(calculationPeriod);
                    periodEndDate   = periodStartDate;
                    periodStartDate = AddPeriod(periodEndDate, IntervalHelper.FromFrequency(frequency), -1);
                }
                else if (calculationPeriod.unadjustedStartDate.Date == startDate.Date)//first period - not stub
                {
                    result.Add(calculationPeriod);
                    break;
                }
                else if (calculationPeriod.unadjustedStartDate.Date < startDate.Date)//first period - not stub
                {
                    var number = result.CalculationPeriods.Count;
                    result.CalculationPeriods[number - 1].unadjustedStartDate = startDate.Date;
                    result.CalculationPeriods[number - 1].adjustedStartDate   = startDate.Date;
                    break;
                }
                if (calculationPeriod.unadjustedEndDate.Date <= startDate.Date)//first period - not stub
                {
                    break;
                }
            } while (true);
            if (isInitialStub)//TODO -Fix the unadjustedstartdate which is affected by the roll convention.
            {
                var calculationPeriod = CreateStub(unadjustedStartDate, startDate.Date,
                                                   calculationPeriodDatesAdjustments, paymentCalendar);
                result.InitialStubCalculationPeriod = calculationPeriod;
            }
        }
        public static List <PaymentCalculationPeriod> GetPaymentCalculationPeriods(InterestRateStream interestRateStream,
                                                                                   CalculationPeriodsPrincipalExchangesAndStubs listCalculationPeriods,
                                                                                   IBusinessCalendar paymentCalendar)
        {
            var result = new List <PaymentCalculationPeriod>();
            // Calculate how much calculation periods comprise one payment calculation period
            //
            PaymentDates paymentDates               = interestRateStream.paymentDates;
            Period       paymentFrequency           = IntervalHelper.FromFrequency(paymentDates.paymentFrequency);
            Period       calculationPeriodFrequency = IntervalHelper.FromFrequency(interestRateStream.calculationPeriodDates.calculationPeriodFrequency);

            //  If the payment frequency is less frequent than the frequency defined in the calculation period dates component
            //then more than one calculation period will contribute to e payment amount.
            //  A payment frequency more frequent than the calculation period frequency
            //or one that is not a multiple of the calculation period frequency is invalid.
            if (paymentFrequency.period != calculationPeriodFrequency.period)
            {
                throw new NotSupportedException(
                          $"Payment period type ({paymentFrequency.period}) and calculation period type ({calculationPeriodFrequency.period}) are different. This is not supported.");
            }
            if (0 != int.Parse(paymentFrequency.periodMultiplier) % int.Parse(calculationPeriodFrequency.periodMultiplier))
            {
                throw new NotSupportedException(String.Format("Payment period frequency  is not a multiple of the calculation period frequency. This is not supported."));
            }
            if (int.Parse(paymentFrequency.periodMultiplier) < int.Parse(calculationPeriodFrequency.periodMultiplier))
            {
                throw new NotSupportedException(String.Format("A payment frequency more frequent than the calculation period frequency. This is not supported."));
            }
            int calculationPeriodsInPaymentPeriod = int.Parse(paymentFrequency.periodMultiplier) / int.Parse(calculationPeriodFrequency.periodMultiplier);
            IEnumerable <List <CalculationPeriod> > listOfCalculationPeriodsInSinglePayPeriod = SplitCalculationPeriodsByPaymentPeriods(listCalculationPeriods, calculationPeriodsInPaymentPeriod);
            Offset paymentDaysOffset = paymentDates.paymentDaysOffset;
            BusinessDayAdjustments paymentDatesBusinessDayAdjustments = paymentDates.paymentDatesAdjustments;
            PayRelativeToEnum      payRelativeTo = paymentDates.payRelativeTo;

            //if (paymentCalendar == null)
            //{
            //    paymentCalendar = BusinessCenterHelper.ToBusinessCalendar(cache, paymentDatesBusinessDayAdjustments.businessCenters);
            //}
            // Initial stub
            //
            if (listCalculationPeriods.HasInitialStub)
            {
                var paymentCalculationPeriod = new PaymentCalculationPeriod
                {
                    adjustedPaymentDate =
                        CalculatePaymentDate(paymentDates, payRelativeTo,
                                             new List <CalculationPeriod>(
                                                 new[]
                    {
                        listCalculationPeriods.
                        InitialStubCalculationPeriod
                    }), paymentDaysOffset,
                                             paymentDatesBusinessDayAdjustments, paymentCalendar),
                    adjustedPaymentDateSpecified = true
                };
                XsdClassesFieldResolver.SetPaymentCalculationPeriodCalculationPeriodArray(paymentCalculationPeriod, new[] { listCalculationPeriods.InitialStubCalculationPeriod });
                result.Add(paymentCalculationPeriod);
            }
            //  Regular periods
            //
            foreach (List <CalculationPeriod> calculationPeriodsInPamentPeriod in listOfCalculationPeriodsInSinglePayPeriod)
            {
                var paymentCalculationPeriod = new PaymentCalculationPeriod
                {
                    adjustedPaymentDate =
                        CalculatePaymentDate(paymentDates, payRelativeTo,
                                             calculationPeriodsInPamentPeriod,
                                             paymentDaysOffset,
                                             paymentDatesBusinessDayAdjustments, paymentCalendar),
                    adjustedPaymentDateSpecified = true
                };
                XsdClassesFieldResolver.SetPaymentCalculationPeriodCalculationPeriodArray(paymentCalculationPeriod, calculationPeriodsInPamentPeriod.ToArray());
                result.Add(paymentCalculationPeriod);
            }
            // Final stub
            //
            if (listCalculationPeriods.HasFinalStub)
            {
                var paymentCalculationPeriod = new PaymentCalculationPeriod
                {
                    adjustedPaymentDate =
                        CalculatePaymentDate(paymentDates, payRelativeTo,
                                             new List <CalculationPeriod>(
                                                 new[]
                    {
                        listCalculationPeriods.
                        FinalStubCalculationPeriod
                    }), paymentDaysOffset,
                                             paymentDatesBusinessDayAdjustments, paymentCalendar),
                    adjustedPaymentDateSpecified = true
                };
                XsdClassesFieldResolver.SetPaymentCalculationPeriodCalculationPeriodArray(paymentCalculationPeriod, new[] { listCalculationPeriods.FinalStubCalculationPeriod });
                result.Add(paymentCalculationPeriod);
            }
            return(result);
        }
        /// <summary>
        /// Update calculation periods with rates/notional.
        /// </summary>
        /// <param name="interestRateStream"></param>
        /// <param name="calculationPeriodsPrincipalExchangesAndStubs"></param>
        public static void UpdateCalculationPeriodsData(InterestRateStream interestRateStream, CalculationPeriodsPrincipalExchangesAndStubs calculationPeriodsPrincipalExchangesAndStubs)
        {
            Calculation calculation      = XsdClassesFieldResolver.CalculationPeriodAmountGetCalculation(interestRateStream.calculationPeriodAmount);
            Notional    notionalSchedule = XsdClassesFieldResolver.CalculationGetNotionalSchedule(calculation);

            #region Generate FUTURE amounts for principle exchanges

            //  Initial PE
            //
            if (null != calculationPeriodsPrincipalExchangesAndStubs.InitialPrincipalExchange)
            {
                //  initial OUTflow
                //
                decimal initialNotionalValue = ScheduleHelper.GetValue(notionalSchedule.notionalStepSchedule, calculationPeriodsPrincipalExchangesAndStubs.InitialPrincipalExchange.adjustedPrincipalExchangeDate);
                calculationPeriodsPrincipalExchangesAndStubs.InitialPrincipalExchange.principalExchangeAmount          = -initialNotionalValue;
                calculationPeriodsPrincipalExchangesAndStubs.InitialPrincipalExchange.principalExchangeAmountSpecified = true;
            }
            //  intermediatory PE
            //
            foreach (PrincipalExchange intermediatoryExchange in calculationPeriodsPrincipalExchangesAndStubs.IntermediatePrincipalExchanges)
            {
                DateTime principleExchangeDate = intermediatoryExchange.adjustedPrincipalExchangeDate;
                //value at the day before principle exchange day
                //
                decimal prevNotionalValue = ScheduleHelper.GetValue(notionalSchedule.notionalStepSchedule, principleExchangeDate.AddDays(-1));
                //value at principle exchange day ..
                //
                decimal newNotionalValue        = ScheduleHelper.GetValue(notionalSchedule.notionalStepSchedule, principleExchangeDate);
                decimal principalExchangeAmount = prevNotionalValue - newNotionalValue;
                intermediatoryExchange.principalExchangeAmount          = principalExchangeAmount;
                intermediatoryExchange.principalExchangeAmountSpecified = true;
            }
            //  Final PE
            //
            if (null != calculationPeriodsPrincipalExchangesAndStubs.FinalPrincipalExchange)
            {
                // pay the rest ot the notional back
                //
                decimal newNotionalValue = ScheduleHelper.GetValue(notionalSchedule.notionalStepSchedule,
                                                                   calculationPeriodsPrincipalExchangesAndStubs.FinalPrincipalExchange.adjustedPrincipalExchangeDate);
                calculationPeriodsPrincipalExchangesAndStubs.FinalPrincipalExchange.principalExchangeAmount          = newNotionalValue;
                calculationPeriodsPrincipalExchangesAndStubs.FinalPrincipalExchange.principalExchangeAmountSpecified = true;
            }

            #endregion

            //  Process standard calculation periods
            //
            foreach (CalculationPeriod calculationPeriod in calculationPeriodsPrincipalExchangesAndStubs.CalculationPeriods)
            {
                UpdateCalculationPeriodData(calculation, calculationPeriod, notionalSchedule);
            }
            // Process stub calculation periods
            //
            if (null != interestRateStream.stubCalculationPeriodAmount)
            {
                if ((null == interestRateStream.stubCalculationPeriodAmount.initialStub) &&
                    (null == interestRateStream.stubCalculationPeriodAmount.finalStub))
                {
                    throw new System.Exception(
                              "interestRateStream.stubCalculationPeriodAmount.initialStub && interestRateStream.stubCalculationPeriodAmount.finalStub are null");
                }
                StubValue initialStub = interestRateStream.stubCalculationPeriodAmount.initialStub;
                StubValue finalStub   = interestRateStream.stubCalculationPeriodAmount.finalStub;
                if (null != calculationPeriodsPrincipalExchangesAndStubs.InitialStubCalculationPeriod && null != initialStub)
                {
                    UpdateStubCalculationPeriodData(interestRateStream, calculationPeriodsPrincipalExchangesAndStubs.InitialStubCalculationPeriod, initialStub, notionalSchedule);
                }
                if (null != calculationPeriodsPrincipalExchangesAndStubs.FinalStubCalculationPeriod && null != finalStub)
                {
                    UpdateStubCalculationPeriodData(interestRateStream, calculationPeriodsPrincipalExchangesAndStubs.FinalStubCalculationPeriod, finalStub, notionalSchedule);
                }
            }
            else
            {
                foreach (CalculationPeriod calculationPeriod in new[] { calculationPeriodsPrincipalExchangesAndStubs.InitialStubCalculationPeriod, calculationPeriodsPrincipalExchangesAndStubs.FinalStubCalculationPeriod })
                {
                    if (null != calculationPeriod)
                    {
                        UpdateCalculationPeriodData(calculation, calculationPeriod, notionalSchedule);
                    }
                }
            }
        }
        /// <summary>
        /// Don't generate stubs?
        /// </summary>
        /// <param name="interestRateStream"></param>
        /// <param name="rollDates">from #1st roll date to last roll date (last roll dates is effectively the end of the swap)</param>
        /// <param name="paymentCalendar"></param>
        /// <returns></returns>
        public static CalculationPeriodsPrincipalExchangesAndStubs GenerateCalculationPeriodsPrincipalExchangesAndStubsFromRollDates(InterestRateStream interestRateStream,
                                                                                                                                     List <DateTime> rollDates,
                                                                                                                                     IBusinessCalendar paymentCalendar)
        {
            CalculationPeriodDates calculationPeriodDates  = interestRateStream.calculationPeriodDates;
            AdjustableDate         adjustableEffectiveDate = XsdClassesFieldResolver.CalculationPeriodDatesGetEffectiveDate(calculationPeriodDates);
            var result = new CalculationPeriodsPrincipalExchangesAndStubs();

            for (int rollDateIndex = 0; rollDateIndex < rollDates.Count - 1; ++rollDateIndex)
            {
                DateTime startOfThePeriod  = rollDates[rollDateIndex];
                DateTime endOfThePeriod    = rollDates[rollDateIndex + 1];
                var      calculationPeriod = new CalculationPeriod();
                //  Set adjusted period dates
                //
                CalculationPeriodHelper.SetAdjustedDates(calculationPeriod,
                                                         startOfThePeriod,
                                                         endOfThePeriod);
                result.Add(calculationPeriod);
            }
            //  Add principle exchanges if this need is defined in parametric representation of the interest rate steam.
            //
            if (null != interestRateStream.principalExchanges)
            {
                //  Initial PE
                //
                if (interestRateStream.principalExchanges.initialExchange)
                {
                    //if (paymentCalendar == null)
                    //{
                    //    paymentCalendar = BusinessCenterHelper.ToBusinessCalendar(cache, adjustableEffectiveDate.dateAdjustments.businessCenters);
                    //}
                    PrincipalExchange initialExchange = PrincipalExchangeHelper.Create(AdjustedDateHelper.ToAdjustedDate(paymentCalendar, adjustableEffectiveDate));
                    result.InitialPrincipalExchange = initialExchange;
                }
                //  intermediatory PE
                //
                if (interestRateStream.principalExchanges.intermediateExchange)
                {
                    // Generate a list of intermediatory PE exchanges
                    //
                    Calculation calculation      = XsdClassesFieldResolver.CalculationPeriodAmountGetCalculation(interestRateStream.calculationPeriodAmount);
                    Notional    notionalSchedule = XsdClassesFieldResolver.CalculationGetNotionalSchedule(calculation);
                    if (null != notionalSchedule.notionalStepSchedule.step)//there should be steps - otherwise NO interm. exchanges.
                    {
                        foreach (DateTime stepDate in ScheduleHelper.GetStepDates(notionalSchedule.notionalStepSchedule))
                        {
                            PrincipalExchange intermediatoryExchange = PrincipalExchangeHelper.Create(stepDate);
                            result.Add(intermediatoryExchange);
                        }
                    }
                }
                //AdjustableDate adjustableTerminationDate = XsdClassesFieldResolver.CalculationPeriodDates_GetTerminationDate(calculationPeriodDates);
                DateTime lastRollDate = rollDates[rollDates.Count - 1];
                //  Final PE
                //
                if (interestRateStream.principalExchanges.finalExchange)
                {
                    //PrincipalExchange finalExchange = PrincipalExchangeHelper.Create(DateTypesHelper.ToAdjustedDate(adjustableTerminationDate));
                    PrincipalExchange finalExchange = PrincipalExchangeHelper.Create(lastRollDate);
                    result.FinalPrincipalExchange = finalExchange;
                }
            }
            return(result);
        }
        public static CalculationPeriodsPrincipalExchangesAndStubs GenerateCalculationPeriodsPrincipalExchangesAndStubs(
            InterestRateStream interestRateStream, IBusinessCalendar fixingCalendar, IBusinessCalendar paymentCalendar)
        {
            CalculationPeriodDates calculationPeriodDates    = interestRateStream.calculationPeriodDates;
            AdjustableDate         adjustableEffectiveDate   = XsdClassesFieldResolver.CalculationPeriodDatesGetEffectiveDate(calculationPeriodDates);
            AdjustableDate         adjustableTerminationDate = XsdClassesFieldResolver.CalculationPeriodDatesGetTerminationDate(calculationPeriodDates);
            AdjustableDate         adjustableFirstPeriodDate = adjustableEffectiveDate;
            DateTime?firstRegularPeriodStartDate             =
                XsdClassesFieldResolver.CalculationPeriodDatesGetFirstRegularPeriodStartDate(calculationPeriodDates);
            var tempDate = XsdClassesFieldResolver.CalculationPeriodDatesGetFirstPeriodStartDate(calculationPeriodDates);

            if (tempDate != null && firstRegularPeriodStartDate != null)
            {
                adjustableFirstPeriodDate = tempDate;
                Frequency frequency = calculationPeriodDates.calculationPeriodFrequency;
                var       startDate = CalculationPeriodGenerator.AddPeriod((DateTime)firstRegularPeriodStartDate, IntervalHelper.FromFrequency(frequency), -1);
                adjustableFirstPeriodDate.unadjustedDate = IdentifiedDateHelper.Create(startDate);
            }
            DateTime?lastRegularPeriodEndDate =
                XsdClassesFieldResolver.CalculationPeriodDatesGetLastRegularPeriodEndDate(calculationPeriodDates);
            //            This assumes automatic adjustment of calculationperiods.
            CalculationPeriodsPrincipalExchangesAndStubs result = CalculationPeriodGenerator.GenerateAdjustedCalculationPeriods(
                adjustableFirstPeriodDate.unadjustedDate.Value,
                adjustableTerminationDate.unadjustedDate.Value,
                firstRegularPeriodStartDate,
                lastRegularPeriodEndDate,
                calculationPeriodDates.calculationPeriodFrequency,
                calculationPeriodDates.calculationPeriodDatesAdjustments,
                paymentCalendar);
            //Determine whether the reset dates must be calcuated.
            Calculation calculation = XsdClassesFieldResolver.CalculationPeriodAmountGetCalculation(interestRateStream.calculationPeriodAmount);

            //  Add principle exchanges if this need is defined in parametric representation of the interest rate steam.
            //
            if (null != interestRateStream.principalExchanges)
            {
                //if (paymentCalendar == null)
                //{
                //    paymentCalendar = BusinessCenterHelper.ToBusinessCalendar(cache, adjustableEffectiveDate.dateAdjustments.businessCenters);
                //}
                //  Initial PE
                //
                if (interestRateStream.principalExchanges.initialExchange)
                {
                    PrincipalExchange initialExchange = PrincipalExchangeHelper.Create(AdjustedDateHelper.ToAdjustedDate(paymentCalendar, adjustableEffectiveDate));
                    result.InitialPrincipalExchange = initialExchange;
                }
                //  intermediatory PE
                //
                if (interestRateStream.principalExchanges.intermediateExchange)
                {
                    // Generate a list of intermediatory PE exchanges
                    //
                    Notional notionalSchedule = XsdClassesFieldResolver.CalculationGetNotionalSchedule(calculation);
                    if (null != notionalSchedule.notionalStepSchedule.step)//there should be steps - otherwise NO interm. exchanges.
                    {
                        foreach (DateTime stepDate in ScheduleHelper.GetStepDates(notionalSchedule.notionalStepSchedule))
                        {
                            PrincipalExchange intermediatoryExchange = PrincipalExchangeHelper.Create(stepDate);
                            result.Add(intermediatoryExchange);
                        }
                    }
                }
                //  Final PE
                // Assume the same calendar is used for the termination date as well!
                if (interestRateStream.principalExchanges.finalExchange)
                {
                    PrincipalExchange finalExchange = PrincipalExchangeHelper.Create(AdjustedDateHelper.ToAdjustedDate(paymentCalendar, adjustableTerminationDate));
                    result.FinalPrincipalExchange = finalExchange;
                }
            }
            //Only does upfront resetRelativeTo start date.
            if (interestRateStream.resetDates != null && calculation.Items[0].GetType() == typeof(FloatingRateCalculation))
            {
                //Get the fixing date convention.
                var fixingDateConvention = interestRateStream.resetDates.resetDatesAdjustments;
                //if (fixingCalendar == null)
                //{
                //    fixingCalendar = BusinessCenterHelper.ToBusinessCalendar(cache, fixingDateConvention.businessCenters);
                //}
                foreach (var calculationPeriod in result.CalculationPeriods)
                {
                    if (calculationPeriod.adjustedStartDateSpecified)
                    {
                        //Set the adjusted fixing date.
                        var adjustedFixingDate = AdjustedDateHelper.ToAdjustedDate(fixingCalendar, calculationPeriod.adjustedStartDate,
                                                                                   fixingDateConvention);
                        var floatingRateDefinition = new FloatingRateDefinition();
                        var rateObservation        = new RateObservation
                        {
                            observedRateSpecified       = false,
                            adjustedFixingDateSpecified = true,
                            adjustedFixingDate          = adjustedFixingDate
                        };
                        floatingRateDefinition.rateObservation = new[] { rateObservation };
                        calculationPeriod.Item1 = floatingRateDefinition;
                    }
                }
                //The initial stub period.
                if (result.InitialStubCalculationPeriod != null)
                {
                    if (result.InitialStubCalculationPeriod.adjustedStartDateSpecified)
                    {
                        //Set the adjusted fixing date.
                        var adjustedFixingDate = AdjustedDateHelper.ToAdjustedDate(fixingCalendar, result.InitialStubCalculationPeriod.adjustedStartDate,
                                                                                   fixingDateConvention);
                        var floatingRateDefinition = new FloatingRateDefinition();
                        var rateObservation        = new RateObservation
                        {
                            observedRateSpecified       = false,
                            adjustedFixingDateSpecified = true,
                            adjustedFixingDate          = adjustedFixingDate
                        };
                        floatingRateDefinition.rateObservation    = new[] { rateObservation };
                        result.InitialStubCalculationPeriod.Item1 = floatingRateDefinition;
                    }
                }
                //The final stub period
                if (result.FinalStubCalculationPeriod != null)
                {
                    if (result.FinalStubCalculationPeriod.adjustedStartDateSpecified)
                    {
                        //Set the adjusted fixing date.
                        var adjustedFixingDate = AdjustedDateHelper.ToAdjustedDate(fixingCalendar, result.FinalStubCalculationPeriod.adjustedStartDate,
                                                                                   fixingDateConvention);
                        var floatingRateDefinition = new FloatingRateDefinition();
                        var rateObservation        = new RateObservation
                        {
                            observedRateSpecified       = false,
                            adjustedFixingDateSpecified = true,
                            adjustedFixingDate          = adjustedFixingDate
                        };
                        floatingRateDefinition.rateObservation  = new[] { rateObservation };
                        result.FinalStubCalculationPeriod.Item1 = floatingRateDefinition;
                    }
                }
            }
            return(result);
        }
        private static IEnumerable <List <CalculationPeriod> > SplitCalculationPeriodsByPaymentPeriods(CalculationPeriodsPrincipalExchangesAndStubs calculationPeriods, int calculationPeriodsInPaymentPeriod)
        {
            var result = new List <List <CalculationPeriod> >();

            if (0 != calculationPeriods.CalculationPeriods.Count % calculationPeriodsInPaymentPeriod)
            {
                throw new System.Exception(
                          $"Invalid number of calculation periods {calculationPeriods.CalculationPeriods.Count}. Calculation periods per payment period : {calculationPeriodsInPaymentPeriod}");
            }
            int calculationPeriodIndex = 0;

            while (calculationPeriodIndex < calculationPeriods.CalculationPeriods.Count)
            {
                List <CalculationPeriod> item = calculationPeriods.CalculationPeriods.GetRange(calculationPeriodIndex, calculationPeriodsInPaymentPeriod);
                result.Add(item);
                calculationPeriodIndex += calculationPeriodsInPaymentPeriod;
            }
            return(result);
        }