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(); } }
/// <summary> /// </summary> /// <param name="cache"></param> /// <param name="interestRateStream"></param> /// <param name="listCalculationPeriods"></param> /// <param name="fixingCalendar"></param> /// <param name="nameSpace"></param> /// <returns></returns> /// <exception cref="NotSupportedException"></exception> /// <exception cref="NotImplementedException"></exception> public static List <DateTime> GetAdjustedResetDates(ICoreCache cache, InterestRateStream interestRateStream, List <CalculationPeriod> listCalculationPeriods, IBusinessCalendar fixingCalendar, string nameSpace) { var adjustedResetDates = new List <DateTime>(); ResetDates resetDates = interestRateStream.resetDates; Period resetFrequency = IntervalHelper.FromFrequency(resetDates.resetFrequency); Period calculationPeriodFrequency = IntervalHelper.FromFrequency(interestRateStream.calculationPeriodDates.calculationPeriodFrequency); if (resetFrequency.period != calculationPeriodFrequency.period) { throw new NotSupportedException( $"Reset period type ({resetFrequency.period}) and calculation period type ({calculationPeriodFrequency.period}) are different. This is not supported."); } if (int.Parse(resetFrequency.periodMultiplier) != int.Parse(calculationPeriodFrequency.periodMultiplier)) { throw new NotSupportedException( $"Reset period frequency ({resetFrequency.period}) is not equal to calculation period frequency ({calculationPeriodFrequency.period}). This is not supported."); } BusinessDayAdjustments resetDatesAdjustments = resetDates.resetDatesAdjustments; ResetRelativeToEnum resetRelativeTo = resetDates.resetRelativeTo; if (fixingCalendar == null) { fixingCalendar = BusinessCenterHelper.ToBusinessCalendar(cache, resetDatesAdjustments.businessCenters, nameSpace); } foreach (CalculationPeriod calculationPeriodsInPaymentPeriod in listCalculationPeriods) { switch (resetRelativeTo) { case ResetRelativeToEnum.CalculationPeriodStartDate: { DateTime unadjustedResetDate = calculationPeriodsInPaymentPeriod.unadjustedStartDate; DateTime adjustedResetDate = AdjustedDateHelper.ToAdjustedDate(fixingCalendar, unadjustedResetDate, resetDatesAdjustments); adjustedResetDates.Add(adjustedResetDate); break; } case ResetRelativeToEnum.CalculationPeriodEndDate: { DateTime unadjustedResetDate = calculationPeriodsInPaymentPeriod.unadjustedEndDate; DateTime adjustedResetDate = AdjustedDateHelper.ToAdjustedDate(fixingCalendar, unadjustedResetDate, resetDatesAdjustments); adjustedResetDates.Add(adjustedResetDate); break; } default: { throw new NotImplementedException("resetRelativeTo"); } } } return(adjustedResetDates); }
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); }
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); }