/// <summary> /// Deal settle. /// </summary> /// <param name="dealDate"></param> /// <param name="settC"></param> /// <param name="hols"></param> /// <returns></returns> public static DateTime SettFromDeal(DateTime dealDate, BondSettlementEnum settC, IBusinessCalendar hols) { switch (settC) { case BondSettlementEnum.SC_dealDate: return(dealDate); case BondSettlementEnum.SC_1bd: return(hols.Advance(dealDate, OffsetHelper.FromInterval(IntervalHelper.FromDays(1), DayTypeEnum.Business), BusinessDayConventionEnum.FOLLOWING)); case BondSettlementEnum.SC_2bd: return(hols.Advance(dealDate, OffsetHelper.FromInterval(IntervalHelper.FromDays(2), DayTypeEnum.Business), BusinessDayConventionEnum.FOLLOWING)); case BondSettlementEnum.SC_1b1cd: return(hols.Advance(dealDate, OffsetHelper.FromInterval(IntervalHelper.FromDays(1), DayTypeEnum.Business), BusinessDayConventionEnum.FOLLOWING).AddDays(1)); case BondSettlementEnum.SC_3bd: case BondSettlementEnum.SC_3bd_6bdLO: return(hols.Advance(dealDate, OffsetHelper.FromInterval(IntervalHelper.FromDays(3), DayTypeEnum.Business), BusinessDayConventionEnum.FOLLOWING)); case BondSettlementEnum.SC_3b1cd: return(hols.Advance(dealDate, OffsetHelper.FromInterval(IntervalHelper.FromDays(3), DayTypeEnum.Business), BusinessDayConventionEnum.FOLLOWING).AddDays(1)); case BondSettlementEnum.SC_4bd: case BondSettlementEnum.SC_4bd_6bdLO: return(hols.Advance(dealDate, OffsetHelper.FromInterval(IntervalHelper.FromDays(4), DayTypeEnum.Business), BusinessDayConventionEnum.FOLLOWING)); case BondSettlementEnum.SC_5bd: return(hols.Advance(dealDate, OffsetHelper.FromInterval(IntervalHelper.FromDays(5), DayTypeEnum.Business), BusinessDayConventionEnum.FOLLOWING)); case BondSettlementEnum.SC_7bd: return(hols.Advance(dealDate, OffsetHelper.FromInterval(IntervalHelper.FromDays(7), DayTypeEnum.Business), BusinessDayConventionEnum.FOLLOWING)); case BondSettlementEnum.SC_3d: return(hols.Roll(dealDate.AddDays(3), BusinessDayConventionEnum.FOLLOWING)); case BondSettlementEnum.SC_7d: return(hols.Roll(dealDate.AddDays(7), BusinessDayConventionEnum.FOLLOWING)); case BondSettlementEnum.SC_7c1bd: return(hols.Advance(dealDate, OffsetHelper.FromInterval(IntervalHelper.FromDays(7), DayTypeEnum.Business), BusinessDayConventionEnum.FOLLOWING)); case BondSettlementEnum.SC_3cd: return(hols.Roll(dealDate.AddDays(3), BusinessDayConventionEnum.FOLLOWING)); // case BondSettlementHelper.BondSettlementEnum.SC_Canada: // return default: return(hols.Advance(dealDate, OffsetHelper.FromInterval(IntervalHelper.FromDays(1), DayTypeEnum.Business), BusinessDayConventionEnum.FOLLOWING)); } /* switch (settC) * { * case SC_Canada: * CalendarDate(ym, mm, dm, maturityDate); * return TCs->NextBizDay(dealDate, 2 + (dealDate <= UnadjustedDate(ym - 3, mm, dm))); * * case SC_Austria: return TCs->NextBizDay(dealDate + 15 - DayOfWeek(dealDate), 0); * * case SC_Australia: * CalendarDate(ym, mm, dm, maturityDate); * return TCs->NextBizDay(dealDate, dealDate > UnadjustedDate(ym, mm - 6, dm) ? 1 : 3); * * case SC_SouthAfrica: * settDate = dealDate + 15 - DayOfWeek(dealDate + 4); * if (!TCs->IsBizDay(settDate + 1)) settDate--; * return settDate; * } * return dealDate;*/ }
/// <summary> /// Gets the adjusted date schedule. /// </summary> /// <param name="unadjustedPeriodDates">The unadjusted Dates.</param> /// <param name="businessDayConvention">The business day convention.</param> /// <param name="paymentCalendar">The payment Calendar.</param> /// <returns></returns> public static List <DateTime> GetAdjustedDateSchedule(IEnumerable <DateTime> unadjustedPeriodDates, BusinessDayConventionEnum businessDayConvention, IBusinessCalendar paymentCalendar) { IEnumerable <DateTime> adjustedPeriodDates = unadjustedPeriodDates.Select(a => paymentCalendar.Roll(a, businessDayConvention)); return(adjustedPeriodDates.ToList()); }
/// <summary> /// Derives the adjusted date if not already provided. /// </summary> /// <param name="adjustableOrAdjustedDate">this may contain the adjustedDate, an unadjusted Date and business Centre</param> /// <param name="businessCalendar">THe business calendar must be provided, no namespace is required and can be null</param> /// <returns></returns> public static DateTime?GetAdjustedDate(IBusinessCalendar businessCalendar, AdjustableOrAdjustedDate adjustableOrAdjustedDate) { var result = AdjustableOrAdjustedDateHelper.Contains(adjustableOrAdjustedDate, ItemsChoiceType.adjustedDate, out var date); if (result) { return(((IdentifiedDate)date).Value); } result = AdjustableOrAdjustedDateHelper.Contains(adjustableOrAdjustedDate, ItemsChoiceType.unadjustedDate, out date); var bda = AdjustableOrAdjustedDateHelper.Contains(adjustableOrAdjustedDate, ItemsChoiceType.dateAdjustments, out var businessDayAdjustments); if (result && date != null) { DateTime unadjustedDate = ((IdentifiedDate)date).Value; if (bda && businessCalendar != null) { if (businessDayAdjustments is BusinessDayAdjustments adjustments) { return(businessCalendar.Roll(unadjustedDate, adjustments.businessDayConvention)); } } return(unadjustedDate); } return(null); }
/// <summary> /// Gets the adjusted date schedule. /// </summary> /// <param name="businessCalendar">The businessCalendar.</param> /// <param name="effectiveDate">The effective date.</param> /// <param name="intervalToTerminationDate">The interval to termination date.</param> /// <param name="periodInterval">The period interval.</param> /// <param name="businessDayAdjustments">The business day adjustments.</param> /// <returns></returns> public static List <DateTime> GetAdjustedDateSchedule(DateTime effectiveDate, Period intervalToTerminationDate, Period periodInterval, BusinessDayAdjustments businessDayAdjustments, IBusinessCalendar businessCalendar) { List <DateTime> unadjustedPeriodDates = DateScheduler.GetUnadjustedDateSchedule(effectiveDate, intervalToTerminationDate, periodInterval); IEnumerable <DateTime> adjustedPeriodDates = unadjustedPeriodDates.Select(a => businessCalendar.Roll(a, businessDayAdjustments.businessDayConvention)); return(adjustedPeriodDates.Distinct().ToList()); }
/// <summary> /// Process a PPD Grid. The result is a Market structure that camn be published. /// </summary> /// <param name="logger">The logger</param> /// <param name="cache">The cache.</param> /// <param name="swapCurve">The latest rate curve</param> /// <param name="ppdGrid">The raw Points Per Day matrix supplied from the subscriber</param> /// <param name="id">The id to use in publishing the curve</param> /// <param name="nameSpace">The client namespace</param> /// <returns></returns> public static Market ProcessSwaption(ILogger logger, ICoreCache cache, Market swapCurve, SwaptionPPDGrid ppdGrid, string id, string nameSpace) { var mkt = swapCurve; var curve = new SimpleRateCurve(mkt); // List the values so we can build our ATM vols var atmVols = new Dictionary <SimpleKey, decimal>(); // Create a calendar to use to modify the date // default to be Sydney... IBusinessCalendar bc = BusinessCenterHelper.ToBusinessCalendar(cache, new[] { "AUSY" }, nameSpace); //BusinessCalendarHelper("AUSY"); // Use some logic to get the spot date to use // LPM Spot lag is 2 days (modfollowing) DateTime spotDate = curve.GetSpotDate(); // Extract each surface and build an ATM engine therefrom // Build a list of all possible engines foreach (string e in ExpiryKeys) { // Assume frequency = 4 months until 3 years tenor is reached Period expiration = PeriodHelper.Parse(e); double expiryYearFraction = expiration.ToYearFraction(); foreach (string t in TenorKeys) { // Create a Swaprate for each expiry/tenor pair // Assume frequency = 4 months until 3 years tenor is reached double tenorYearFraction = PeriodHelper.Parse(t).ToYearFraction(); int frequency = tenorYearFraction < 4 ? 4 : 2; // Calculation date // Discount factors // Offsets (elapsed days) var rates = new SwapRate(logger, cache, nameSpace, "AUSY", curve.BaseDate, "ACT/365.FIXED", curve.GetDiscountFactors(), curve.GetDiscountFactorOffsets(), frequency, BusinessDayConventionEnum.MODFOLLOWING); // Calculate the volatility given PPD and swap curve DateTime expiry = bc.Roll(expiration.Add(spotDate), BusinessDayConventionEnum.FOLLOWING); decimal vol = CalculateAtmVolatility(rates, expiry, ppdGrid, expiryYearFraction, tenorYearFraction); atmVols.Add(new SimpleKey(e, t), vol); } } var vols = new object[atmVols.Count + 1, 3]; var i = 1; vols[0, 0] = "Expiry"; vols[0, 1] = "Tenor"; vols[0, 2] = "0"; foreach (var key in atmVols.Keys) { vols[i, 0] = key.Expiry; vols[i, 1] = key.Tenor; vols[i, 2] = atmVols[key]; i++; } DateTime buildDateTime = swapCurve.Items1[0].buildDateTime; var volSurface = new VolatilitySurface(vols, new VolatilitySurfaceIdentifier(id), curve.BaseDate, buildDateTime); return(CreateMarketDocument(volSurface.GetFpMLData())); }
/// <summary> /// Converts to a date time. /// </summary> /// <param name="cache"></param> /// <param name="unadjustedDate"></param> /// <param name="businessDayAdjustments"></param> /// <param name="offset"></param> /// <param name="nameSpace"></param> /// <returns></returns> public static DateTime ToAdjustedDate(ICoreCache cache, DateTime unadjustedDate, BusinessDayAdjustments businessDayAdjustments, Offset offset, string nameSpace) { if (DayTypeEnum.Business != offset.dayType && DayTypeEnum.Calendar != offset.dayType) { throw new NotSupportedException( $"Only {DayTypeEnum.Business}, {DayTypeEnum.Calendar} day types supported of Offset type."); } IBusinessCalendar businessCalendar = BusinessCenterHelper.ToBusinessCalendar(cache, businessDayAdjustments.businessCenters, nameSpace); int periodMultiplier = Int32.Parse(offset.periodMultiplier); // offset using calendar days // switch (offset.dayType) { case DayTypeEnum.Business: { switch (offset.period) { case PeriodEnum.D: { // Advance using given number of business days // int periodMultiplierSign = Math.Sign(periodMultiplier); DateTime offsetedDate = unadjustedDate; while (periodMultiplier-- > 0) { offsetedDate = offsetedDate.AddDays(periodMultiplierSign); offsetedDate = businessCalendar.Roll(offsetedDate, businessDayAdjustments.businessDayConvention); } return(offsetedDate); } default: throw new NotSupportedException( $"{offset.period} not supported in conjunction with '{offset.dayType} day type'"); } //~switch(offset.period) } case DayTypeEnum.Calendar: { // Convert offset to period. DateTime adjustedDate = offset.Add(unadjustedDate); return(adjustedDate); } default: { throw new NotSupportedException( $"Only {DayTypeEnum.Business}, {DayTypeEnum.Calendar} day types supported of Offset type."); } } }
private void AddCashFlows(ILogger logger, ICoreCache cache, IBusinessCalendar fixingCalendar, IBusinessCalendar paymentCalendar, Fra fraFpML, bool isBuyer, String nameSpace) { EffectiveDate = fraFpML.adjustedEffectiveDate.Value; TerminationDate = fraFpML.adjustedTerminationDate; if (paymentCalendar == null) { paymentCalendar = BusinessCenterHelper.ToBusinessCalendar(cache, fraFpML.paymentDate.dateAdjustments.businessCenters, nameSpace); } if (fixingCalendar == null) { fixingCalendar = BusinessCenterHelper.ToBusinessCalendar(cache, fraFpML.fixingDateOffset.businessCenters, nameSpace); } DateTime unadjustedPaymentDate = fraFpML.paymentDate.unadjustedDate.Value; var notional = MoneyHelper.GetAmount(fraFpML.notional.amount, fraFpML.notional.currency); PaymentDate = paymentCalendar.Roll(unadjustedPaymentDate, BusinessDayConventionHelper.Parse(fraFpML.paymentDate.dateAdjustments.businessDayConvention.ToString())); DateTime adjustedFixingDate = GetResetDate(logger, cache, fixingCalendar, fraFpML, nameSpace); var interval = fraFpML.indexTenor[0]; var floatingInterest = new PriceableFloatingRateCoupon(fraFpML.id + "FloatingCoupon_1" , isBuyer , EffectiveDate , TerminationDate , adjustedFixingDate , fraFpML.dayCountFraction , 0.0m , FixedRate , null , isBuyer ? MoneyHelper.Neg(notional) : notional , PaymentDate , new ForecastRateIndex { floatingRateIndex = fraFpML.floatingRateIndex, indexTenor = interval } , null , null , fraFpML.fraDiscounting , paymentCalendar , fixingCalendar) { ForecastRateInterpolation = ForecastRateInterpolation }; // Combine two cashflows into one leg // FloatingCoupon = floatingInterest;//fraFpML.fraDiscounting, }
/// <summary> /// Converts to an adjustable date type. /// </summary> /// <param name="adjustableDate"></param> /// <param name="cache"></param> /// <param name="nameSpace"></param> /// <returns></returns> public static DateTime ToAdjustedDate(ICoreCache cache, AdjustableDate adjustableDate, string nameSpace) { if (null == adjustableDate) { throw new ArgumentNullException(nameof(adjustableDate)); } // handle BusinessDatConventionEnum is NONE as a special case, since there might be no business centers provided. // if ((null == adjustableDate.dateAdjustments) || (BusinessDayConventionEnum.NONE == adjustableDate.dateAdjustments.businessDayConvention)) { return(adjustableDate.unadjustedDate.Value); } IBusinessCalendar businessCalendar = BusinessCenterHelper.ToBusinessCalendar(cache, adjustableDate.dateAdjustments.businessCenters, nameSpace); DateTime result = businessCalendar.Roll(adjustableDate.unadjustedDate.Value, adjustableDate.dateAdjustments.businessDayConvention); return(result); }
/// <summary> /// Rolls the specified date using the underlying calendars. /// </summary> /// <param name="businessCalendar">The calendars.</param> /// <param name="date">The date.</param> /// <param name="businessDayConvention">The business day convention.</param> /// <returns></returns> public static DateTime Roll(IBusinessCalendar businessCalendar, DateTime date, string businessDayConvention) { BusinessDayConventionEnum dayConvention = BusinessDayConventionHelper.Parse(businessDayConvention); return(businessCalendar.Roll(date, dayConvention)); }