/// <summary> /// Gets the unadjusted dates from a meta date scheduler. /// </summary> /// <param name="metaScheduleDefinition"></param> /// <param name="startDate"></param> /// <returns></returns> public static List <DateTime> GetUnadjustedDates(List <Triplet <Period, Period, RollConventionEnum> > metaScheduleDefinition, DateTime startDate) { var offsetsFromStartDateForRollPeriods = new List <Pair <int, RollConventionEnum> >(); foreach (var metaScheduleEntry in metaScheduleDefinition) { var numberOfRolls = (int)IntervalHelper.Div(metaScheduleEntry.Second, metaScheduleEntry.First); if (metaScheduleEntry.First.period != PeriodEnum.M) { throw new System.Exception("Only month-expressed periods are supported."); } var rollsEveryNMonths = int.Parse(metaScheduleEntry.First.periodMultiplier); while (numberOfRolls-- > 0) { var lastOffset = 0; if (offsetsFromStartDateForRollPeriods.Count > 0) { lastOffset = offsetsFromStartDateForRollPeriods[offsetsFromStartDateForRollPeriods.Count - 1].First; } lastOffset += rollsEveryNMonths; offsetsFromStartDateForRollPeriods.Add(new Pair <int, RollConventionEnum>(lastOffset, metaScheduleEntry.Third)); } } // Generates dates from a list of month-expressed offsets. // var result = (from offset in offsetsFromStartDateForRollPeriods let rollDateUnadjusted = startDate.AddMonths(offset.First) select RollConventionEnumHelper.AdjustDate(offset.Second, rollDateUnadjusted)).ToList(); return(RemoveDuplicates(result)); }
/// <summary> /// Gets the unadjusted date schedule. /// </summary> /// <param name="effectiveDate">The effective date.</param> /// <param name="intervalToTerminationDate">The interval to termination date.</param> /// <param name="periodInterval">The period interval.</param> /// <returns></returns> public static List <DateTime> GetUnadjustedDateSchedule(DateTime effectiveDate, Period intervalToTerminationDate, Period periodInterval) { Double divisor = IntervalHelper.Div(intervalToTerminationDate, periodInterval); // The divisor has to be a whole number (i.e. the period must roll to the term date interval if (System.Math.Abs(divisor % 1) > Tolerance) { throw new ArithmeticException("The period frequency will not roll to the supplied termination date interval"); } DateTime termDate = intervalToTerminationDate.Add(effectiveDate); var periodDates = new List <DateTime>(); //DateTime periodStartDate = effectiveDate; int multiplier = periodInterval.GetPeriodMultiplier(); periodDates.Add(effectiveDate); for (int i = 1; i < divisor; i++) { var periodEndDate = DateAdd(effectiveDate, periodInterval.period, multiplier * i); periodDates.Add(periodEndDate); } periodDates.Add(termDate); return(periodDates); }
//<Interval, Interval, RollConventionEnum> /// <summary> /// With custom roll schedule /// </summary> /// <param name="startDate"></param> /// <param name="endDate"></param> /// <param name="rollsMetaSchedule"></param> /// <param name="backwardGeneration"></param> /// <returns></returns> public static List <DateTime> GetUnadjustedDates3(DateTime startDate, DateTime endDate, List <MetaScheduleItem> rollsMetaSchedule, bool backwardGeneration) { var results = new List <DateTime>(); if (backwardGeneration)//from end date to start date { // reverse the meta schedule // var reversedRollsMetaScheduleParam = new List <MetaScheduleItem>(rollsMetaSchedule); reversedRollsMetaScheduleParam.Reverse(); var offsetFromPrevScheduleItem = 0; foreach (var metaScheduleItem in reversedRollsMetaScheduleParam) { var numberOfRolls = (int)IntervalHelper.Div(metaScheduleItem.Period, metaScheduleItem.RollFrequency); if (metaScheduleItem.RollFrequency.period != PeriodEnum.M) { throw new System.Exception("Month periods are the only ones supported."); } var rollsEveryNMonths = int.Parse(metaScheduleItem.RollFrequency.periodMultiplier); var rollNumber = 1; var offsetInMonths = 0; while (numberOfRolls-- > 0) { offsetInMonths = rollNumber * rollsEveryNMonths; var rollDateUnadjusted = endDate.AddMonths(-offsetInMonths + offsetFromPrevScheduleItem); var rollDateRollAdjusted = RollConventionEnumHelper.AdjustDate(metaScheduleItem.RollConvention, rollDateUnadjusted); results.Insert(0, rollDateRollAdjusted); ++rollNumber; } offsetFromPrevScheduleItem -= offsetInMonths; } results.Insert(0, startDate); results.Add(endDate); } else//from start date to end date. { //DateTime rollDate = startDate; results.Add(startDate); var offsetFromPrevScheduleItem = 0; foreach (var metaScheduleItem in rollsMetaSchedule) { var numberOfRolls = (int)IntervalHelper.Div(metaScheduleItem.Period, metaScheduleItem.RollFrequency); if (metaScheduleItem.RollFrequency.period != PeriodEnum.M) { throw new System.Exception("Month periods are the only ones supported."); } var rollsEveryNMonths = int.Parse(metaScheduleItem.RollFrequency.periodMultiplier); var rollNumber = 1; var offsetInMonths = 0; while (numberOfRolls-- > 0) { offsetInMonths = rollNumber * rollsEveryNMonths; var rollDateUnadjusted = startDate.AddMonths(offsetInMonths + +offsetFromPrevScheduleItem); var rollDateRollAdjusted = RollConventionEnumHelper.AdjustDate(metaScheduleItem.RollConvention, rollDateUnadjusted); results.Add(rollDateRollAdjusted); ++rollNumber; } offsetFromPrevScheduleItem += offsetInMonths; } results.Add(endDate); } return(RemoveDuplicates(results)); }
/// <summary> /// Gets the unadjusted dates. /// </summary> /// <param name="metaScheduleDefinition">The meta schedule definition.</param> /// <param name="startDate">The start date.</param> /// <param name="endDate">The end date.</param> /// <param name="defaultInterval">The default interval.</param> /// <param name="defaultRollConvention">The default roll convention.</param> /// <param name="fromStartDate">if set to <c>true</c> [from start date].</param> /// <returns></returns> public static DateTime[] GetUnadjustedDates (List <Triplet <Period, Period, RollConventionEnum> > metaScheduleDefinition , DateTime startDate , DateTime endDate , Period defaultInterval , RollConventionEnum defaultRollConvention , Boolean fromStartDate ) { DateTime firstReg; DateTime lastReg; var result = new List <DateTime>(); List <DateTime> additionalDates; DateTime fromDate = startDate; DateTime toDate = endDate; int intervalMulitplier = 1; if (!fromStartDate) { fromDate = endDate; toDate = startDate; intervalMulitplier = intervalMulitplier * -1; } var offsetsFromStartDateForRollPeriods = new List <Pair <Period, RollConventionEnum> >(); foreach (var metaScheduleEntry in metaScheduleDefinition) { var numberOfRolls = (int)IntervalHelper.Div(metaScheduleEntry.Second, metaScheduleEntry.First); if (numberOfRolls == 0) { throw new System.Exception("Invalid period interval specified. The period interval is greater than the duration interval"); } if (!fromStartDate) { metaScheduleEntry.First.periodMultiplier = (Convert.ToInt32(metaScheduleEntry.First.periodMultiplier) * intervalMulitplier).ToString(CultureInfo.InvariantCulture); } while (numberOfRolls-- > 0) { offsetsFromStartDateForRollPeriods.Add(new Pair <Period, RollConventionEnum>(metaScheduleEntry.First, metaScheduleEntry.Third)); } } if (offsetsFromStartDateForRollPeriods.Count > 0) { // Generates dates from a list of intervals expressed as offsets. DateTime referenceDate = fromDate; foreach (var offset in offsetsFromStartDateForRollPeriods) { if (referenceDate == fromDate) { result.Add(fromDate); } DateTime rollDateUnadjusted = offset.First.Add(referenceDate); DateTime rollConventionDate = DateScheduler.ApplyRollConventionToDate(offset.Second, rollDateUnadjusted); if ((fromStartDate && rollConventionDate > toDate) || (!fromStartDate && rollConventionDate < toDate)) { result.Add(toDate); break; } result.Add(rollConventionDate); referenceDate = rollDateUnadjusted; } // if end date falls after the meta data schedule provided use the defaults if (result.Count > 0) { if ((fromStartDate && result[result.Count - 1] < toDate) || (!fromStartDate && result[result.Count - 1] > toDate)) { if (result[result.Count - 1] < endDate) { additionalDates = fromStartDate ? new List <DateTime>(DateScheduler.GetUnadjustedDatesFromEffectiveDate(result[result.Count - 1], toDate, defaultInterval, defaultRollConvention, out firstReg, out lastReg)) : new List <DateTime>(DateScheduler.GetUnadjustedDatesFromTerminationDate(toDate, result[result.Count - 1], defaultInterval, defaultRollConvention, out firstReg, out lastReg)); result.AddRange(additionalDates); result.Sort(); } } } } else { additionalDates = fromStartDate ? new List <DateTime>(DateScheduler.GetUnadjustedDatesFromEffectiveDate(startDate, toDate, defaultInterval, defaultRollConvention, out firstReg, out lastReg)) : new List <DateTime>(DateScheduler.GetUnadjustedDatesFromTerminationDate(startDate, toDate, defaultInterval, defaultRollConvention, out firstReg, out lastReg)); result.AddRange(additionalDates); } result = RemoveDuplicates(result); result.Sort(); return(result.ToArray()); }