/// <summary>Initializes a new instance of the <see cref="SimpleThenPeriodicCompounding" /> class. /// </summary> /// <param name="frequency">The frequency of the compounding to apply after time-to-maturity of one year.</param> internal SimpleThenPeriodicCompounding(IDateScheduleFrequency frequency) { if (frequency == null) { throw new ArgumentNullException("frequency"); } Frequency = frequency; var frequencyTenor = frequency.GetFrequencyTenor(); if (TenorTimeSpan.IsNull(frequencyTenor) == true) { throw new ArgumentException("frequency"); } if (frequencyTenor.Years != 0) { PaymentsPerYear = 1.0 / frequencyTenor.Years; } if (frequencyTenor.Months != 0) { PaymentsPerYear += 12.0 / frequencyTenor.Months; } if (frequencyTenor.Days != 0) { PaymentsPerYear += 365.0 / frequencyTenor.Days; } Name = new IdentifierString(String.Format("Simple;{0}", Frequency.Name.String)); }
/// <summary>Initializes a new instance of the <see cref="PeriodicInterestCompounding"/> class. /// </summary> /// <param name="frequency">The frequency of the compounding.</param> protected internal PeriodicInterestCompounding(IDateScheduleFrequency frequency) { if (frequency == null) { throw new ArgumentNullException("frequency"); } Frequency = frequency; TenorTimeSpan frequencyTenor = frequency.GetFrequencyTenor(); if (TenorTimeSpan.IsNull(frequencyTenor) == true) { throw new ArgumentException("frequency"); } if (frequencyTenor.Years != 0) { PaymentsPerYear = 1.0 / frequencyTenor.Years; } if (frequencyTenor.Months != 0) { PaymentsPerYear += 12.0 / frequencyTenor.Months; } if (frequencyTenor.Days != 0) { PaymentsPerYear += 365.0 / frequencyTenor.Days; } }
/// <summary>Creates a date schedule that contains the start and end dates of the interest periods of each caplets, i.e. T_0, T_1, T_2, ..., where [T_k; T_{k+1}] is the /// interest period of caplet k, k=0,...,n-1; The first caplet is already expired but it is part of the date schedule. /// </summary> /// <param name="referenceDate">The reference date, i.e. the trading date.</param> /// <param name="startDateAndEndDateDescription">A description of the start date of the first caplet as well as the end date of the last caplet, i.e. the start date and the maturity of the cap.</param> /// <param name="marketConventions">The market conventions.</param> /// <param name="holidayCalendar">The holiday calendar.</param> /// <param name="underlyingLiborTenor">A mapping of the null-based index of the start date of each caplet interest period to the tenor of the underlying Libor rate (output).</param> /// <param name="logger">An optional logger.</param> /// <returns> /// The date schedule of the interest periods, i.e. the start and end dates of each caplet; thus T_0, T_1, T_2, ..., where [T_k; T_{k+1}] is the /// interest period of caplet k, k=0,...,n-1; The first caplet is already expired but it is part of the date schedule. /// </returns> public ReadOnlyDateSchedule CreateInterestPeriodDateSchedule(DateTime referenceDate, ITimeframeDescription startDateAndEndDateDescription, ReadOnlyMoneyMarketConventions marketConventions, IHolidayCalendar holidayCalendar, out Func <int, TenorTimeSpan> underlyingLiborTenor, ILogger logger = null) { if (marketConventions == null) { throw new ArgumentNullException("marketConventions"); } if (holidayCalendar == null) { throw new ArgumentNullException("holidayCalendar"); } IBusinessDayConvention businessDayConvention = marketConventions.BusinessDayConvention; DateTime capStartDate, capEndDate; startDateAndEndDateDescription.GetStartAndEndDate(referenceDate, holidayCalendar, out capStartDate, out capEndDate); DateTime lastDate3M = businessDayConvention.GetAdjustedDate(capStartDate.AddTenorTimeSpan(sm_2YTenor), holidayCalendar); // it is the end date of the latest caplet with tenor 3M DateSchedule dateSchedule = new DateSchedule(holidayCalendar, logger: logger); if (capEndDate <= lastDate3M) { dateSchedule.Add(new ForwardDateScheduleRule(referenceDate, startDateAndEndDateDescription, sm_3MLiborRateTenor, businessDayConvention)); underlyingLiborTenor = (i => sm_3MLiborRateTenor.GetFrequencyTenor()); } else { ITimeframeDescription firstPeriod3M = TimeframeDescription.Create(lastDate3M); // applied to reference date='capStartDate' shows [capStartDate; lastDate3M] dateSchedule.Add(new ForwardDateScheduleRule(capStartDate, firstPeriod3M, sm_3MLiborRateTenor, businessDayConvention)); int indexOfLast3MPeriodEndDate = dateSchedule.Count - 1; ITimeframeDescription secondPeriod6M = TimeframeDescription.Create(capEndDate, endDateAdjustment: businessDayConvention); // applied to reference date ='lastDate3M' shows [lastDate3M; capEndDate] dateSchedule.Add(new ForwardDateScheduleRule(lastDate3M, secondPeriod6M, sm_6MLiborRateTenor, businessDayConvention)); underlyingLiborTenor = (i => (i < indexOfLast3MPeriodEndDate) ? sm_3MLiborRateTenor.GetFrequencyTenor() : sm_3MLiborRateTenor.GetFrequencyTenor()); } return(dateSchedule.AsReadOnly()); }
/// <summary>Gets the tenor of the underlying Libor rate if the tenor is equal for each caplet. /// </summary> /// <param name="liborTenor">The (unique) tenor of the underlying Libor rate.</param> /// <returns> /// A value indicating whether <paramref name="liborTenor"/> contains valid data /// and a unique tenor is available. /// </returns> /// <remarks>This method returns the same value as <see cref="IIRCapletTenorConvention.HasUniqueLiborTenor"/>.</remarks> public bool TryGetUniqueUnderlyingLiborTenor(out TenorTimeSpan liborTenor) { liborTenor = m_LiborRateTenor.GetFrequencyTenor(); return(true); }
/// <summary>Adds some <see cref="System.DateTime"/> objects into a specific date schedule. /// </summary> /// <param name="dateSchedule">The date schedule.</param> /// <exception cref="NotOperableException">Thrown, if the current instance it not operable.</exception> public void AddDatesToDateSchedule(DateSchedule dateSchedule) { if (IsOperable == false) { throw new NotOperableException("BackwardDateScheduleRule"); } DateTime firstDate, terminationDate; m_TimeSpanDescription.GetStartAndEndDate(m_ReferenceDate, dateSchedule.HolidayCalendar, out firstDate, out terminationDate, dateSchedule.Logging); if (terminationDate < firstDate) { throw new ArgumentException(String.Format(ExceptionMessages.ArgumentOutOfRangeGreaterEqual, "End date [" + terminationDate.ToShortDateString() + "]", "first date [" + firstDate.ToShortDateString() + "]")); } dateSchedule.Add(terminationDate); // add the end date // gets the date which is used as 'base date' for the date generation loop: DateTime seed = terminationDate; if ((m_LastRegularDate != null) && (m_LastRegularDate.HasValue)) // 'last regular date' is given { seed = m_LastRegularDate.Value; if (seed > terminationDate) { throw new ArgumentException(String.Format(ExceptionMessages.ArgumentOutOfRangeLessEqual, "Last regular date [" + seed.ToShortDateString() + "]", "end date [" + terminationDate.ToShortDateString() + "]")); } } if (m_SeedBusinessDayConvention != null) // perhaps adjust the 'base date' which is used for the date generation loop { seed = m_SeedBusinessDayConvention.GetAdjustedDate(seed, dateSchedule.HolidayCalendar); } else { seed = m_BusinessDayConvention.GetAdjustedDate(seed, dateSchedule.HolidayCalendar); } dateSchedule.Add(seed); // gets the exit condition for the loop: DateTime exitDate = firstDate; // perhaps not a business day if ((m_FirstRegularDate != null) && (m_FirstRegularDate.HasValue)) { exitDate = m_FirstRegularDate.Value; if (exitDate > seed) { throw new ArgumentException(String.Format(ExceptionMessages.ArgumentOutOfRangeLessEqual, "First regular date [" + exitDate.ToShortDateString() + "]", "last [regular] date [" + seed.ToShortDateString() + "]")); } } if (m_Frequency.IsOnceFrequency()) // end date and seed date are already added { if (exitDate != firstDate) // perhaps add the first regular date { dateSchedule.Add(exitDate); // one may apply the business day convention to the first regular date } } else // do the loop with respect to the frequency { TenorTimeSpan frequencyTenor = m_Frequency.GetFrequencyTenor(); DateTime runningDate = m_BusinessDayConvention.GetAdjustedDate(seed.AddTenorTimeSpan(frequencyTenor), dateSchedule.HolidayCalendar); int periodIndex = -1; while (runningDate >= exitDate) { dateSchedule.Add(runningDate); periodIndex--; runningDate = seed.AddTenorTimeSpan(frequencyTenor, periodIndex); runningDate = m_BusinessDayConvention.GetAdjustedDate(runningDate, dateSchedule.HolidayCalendar); } } dateSchedule.Add(firstDate); }
/// <summary>Determines whether a specified date schedule frequency is the frequency 'once'. /// </summary> /// <param name="dateScheduleFrequency">The date schedule frequency.</param> /// <returns> /// <c>true</c> if the specified date schedule frequency is the frequency 'once'; otherwise, <c>false</c>. /// </returns> public static bool IsOnceFrequency(this IDateScheduleFrequency dateScheduleFrequency) { return((dateScheduleFrequency != null) ? TenorTimeSpan.IsNull(dateScheduleFrequency.GetFrequencyTenor()) : false); }