/// <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> /// Process a CapFloor ATM parvVols structure. /// The process Bootstraps the parVols using the supplied ratecurve /// </summary> /// <param name="logger">The logger</param> /// <param name="cache">The cache.</param> /// <param name="nameSpace"></param> /// <param name="rateCurve"></param> /// <param name="capFloor"></param> /// <returns></returns> private static Market ProcessCapFloorATM(ILogger logger, ICoreCache cache, string nameSpace, Market rateCurve, CapFloorATMMatrix capFloor) { var id = capFloor.id; var expiry = capFloor.GetExpiries(); var vols = capFloor.GetVolatilities(); var mkt = rateCurve; var curve = new SimpleRateCurve(mkt); var discountFactorDates = curve.GetDiscountFactorDates(); var discountFactors = curve.GetDiscountFactors(); var volType = capFloor.GetVolatilityTypes(); var atmVols = new Dictionary <string, decimal>(); var settings = CreateCapFloorProperties(capFloor.GetVolatilitySettings()); // Create an internal matrix object from the raw data var matrix = new CapFloorVolatilityMatrix(id, expiry, volType, vols, null, discountFactorDates, ArrayUtilities.ArrayToDecimal(discountFactors)); // Create an ATM engine from the matrix var engines = CreateEngines(logger, cache, nameSpace, id, matrix, settings); // Add the default interpolation to use const ExpiryInterpolationType volatilityInterpolation = ExpiryInterpolationType.Linear; if (engines != null) { var vol = new CapletExpiryInterpolatedVolatility(engines[0], volatilityInterpolation); // List the values so we can build our ATM vols var keys = ExpiryKeys.Split(','); // Create a calendar to use to modify the date var businessCalendar = settings.GetValue("BusinessCalendar", "AUSY"); var bc = BusinessCenterHelper.ToBusinessCalendar(cache, new[] { businessCalendar }, nameSpace); // Use some logic to get the spot date to use // LPM Spot lag is 2 days (modfollowing) var spotDate = curve.GetSpotDate(); var rollConvention = settings.GetValue("RollConvention", BusinessDayConventionEnum.FOLLOWING); spotDate = spotDate == curve.GetBaseDate() ? bc.Roll(spotDate.Add(new TimeSpan(2, 0, 0, 0)), rollConvention) : spotDate; //// Extract each surface and build an ATM engine therefrom //// Build a list of all possible engines foreach (var key in keys) { // Calculate the volatility for each target key var tv = PeriodHelper.Parse(key); var target = tv.period == PeriodEnum.D ? bc.Roll(spotDate.AddDays(Convert.ToInt32(tv.periodMultiplier)), rollConvention) : bc.Roll(spotDate.AddMonths(Convert.ToInt32(tv.periodMultiplier)), rollConvention); atmVols.Add(key, vol.ComputeCapletVolatility(target)); } } var outputVols = new object[atmVols.Count + 1, 2]; var i = 1; //Expiry 0 outputVols[0, 0] = "Expiry"; outputVols[0, 1] = "0"; foreach (var key in atmVols.Keys) { outputVols[i, 0] = key; outputVols[i, 1] = atmVols[key]; i++; } DateTime buildDateTime = rateCurve.Items1[0].buildDateTime; var volSurface = new VolatilitySurface(outputVols, new VolatilitySurfaceIdentifier(id), curve.BaseDate, buildDateTime); return(CreateMarketDocument(volSurface.GetFpMLData())); }