public void GetVolatilityTest() { var target = new SwaptionDataMatrix(_volTenors, _volStrikes, _volExpiry, _volData, _id); decimal actual; const decimal expected = 10.26m / 100.0m; string tenor = "2yr"; decimal strike = -0.50m; try { actual = target.GetVolatility(tenor, strike); Assert.AreEqual(expected, actual); } catch (ArgumentException ex) { Assert.AreEqual("The matrix is malformed. No volatilities are available.", ex.Message); } tenor = "22yr"; strike = -7.50m; try { actual = target.GetVolatility(tenor, strike); Assert.AreEqual(expected, actual); } catch (ArgumentException ex) { Assert.AreEqual("The matrix is malformed. No volatilities are available.", ex.Message); } }
public void GetVolatilityTest1() { var target = new SwaptionDataMatrix(_volTenors, _volStrikes, _volExpiry, _volData, _id); decimal actual; const decimal expected = 9.83m / 100.0m; Period tenor = PeriodHelper.Parse("2yr"); decimal strike = 50.0m / 10000.0m; try { actual = target.GetVolatility(tenor, strike); Assert.AreEqual(expected, actual); } catch (ArgumentException ex) { Assert.AreEqual("The matrix is malformed. No volatilities are available.", ex.Message); } tenor = PeriodHelper.Parse("32yr"); strike = 50.0m / 10000.0m; try { actual = target.GetVolatility(tenor, strike); Assert.AreEqual(expected, actual); } catch (ArgumentException ex) { Assert.AreEqual("The matrix is malformed. No volatilities are available.", ex.Message); } }
public void GetVolatilityTest5() { var target = new SwaptionDataMatrix(_volTenors, _volStrikes, _volExpiry, _volData, _id); const decimal expected = 10.26m / 100.0m; var actual = new decimal[0]; Period tenor = PeriodHelper.Parse("2yr"); try { actual = target.GetVolatility(tenor); CollectionAssert.Contains(actual, expected); } catch (ArgumentException ex) { Assert.AreEqual("The matrix is malformed. No volatilities are available.", ex.Message); } var expected1 = new decimal[actual.Length]; Array.Copy(actual, expected1, actual.Length); const string tenor1 = "2yr"; try { int i = 0; actual = target.GetVolatility(tenor1); foreach (decimal d in actual) { Assert.AreEqual(expected1[i++], d); } } catch (ArgumentException ex) { Assert.AreEqual("The matrix is malformed. No volatilities are available.", ex.Message); } }
public void GetVolatilityTest4() { var target = new SwaptionDataMatrix(_volTenors, _volStrikes, _volExpiry, _volData, _id); const decimal expected = 10.26m / 100.0m; decimal[] actual; Period tenor = PeriodHelper.Parse("2yr"); try { actual = target.GetVolatility(tenor); CollectionAssert.Contains(actual, expected); } catch (ArgumentException ex) { Assert.AreEqual("The matrix is malformed. No volatilities are available.", ex.Message); } tenor = PeriodHelper.Parse("21yr"); try { actual = target.GetVolatility(tenor); CollectionAssert.Contains(actual, expected); } catch (ArgumentException ex) { Assert.AreEqual("The matrix is malformed. No volatilities are available.", ex.Message); } }
public void GetStrikesTest() { var target = new SwaptionDataMatrix(_volTenors, _volStrikes, _volExpiry, _volData, _id); decimal[] expected = _strikes; decimal[] actual = target.GetStrikes(); for (int i = 0; i < expected.Length; i++) { Assert.AreEqual(expected[i], actual[i]); } }
public void GetExpiryTest() { var target = new SwaptionDataMatrix(_volTenors, _volStrikes, _volExpiry, _volData, _id); string expected = _volExpiry; try { string actual = target.GetExpiry(); Assert.AreEqual(PeriodHelper.Parse(expected).ToString(), actual); } catch (ArgumentException ex) { Assert.AreEqual("The matrix is malformed. No expiry available.", ex.Message); } }
/// <summary> /// Parse the raw volatilities to create the labels and values arrays /// required by a SwaptionDataGrid{T,U} used to store the data /// for use by the SABR Calibration routines /// </summary> /// <param name="rawVolatility">The raw volatility data</param> /// <param name="expiry">The expiry for this grid</param> /// <returns>the rawdata as a SwaptiondataGrid</returns> private static SwaptionDataMatrix ParseVolatilityInput(object[,] rawVolatility, string expiry) { // Set the upper/lower bounds of the converted array int hi1D = rawVolatility.GetUpperBound(0); int hi2D = rawVolatility.GetUpperBound(1); // Create and populate the data arrays used to build the SwaptionDataGrid // The columns represent tenors, the rows option expiries var strikes = new decimal[hi2D]; var tenors = new string[hi1D]; for (int idx = 1; idx <= hi2D; idx++) { string strike = rawVolatility[0, idx].ToString(); // If contains ATM then parse and assume it is in BP if (strike.Contains("ATM")) { strike = strike.Replace("ATM", "").Replace(" ", ""); if (strike == "") { strike = "0"; } strikes[idx - 1] = decimal.Parse(strike) / 10000; } else // otherwise just take the numbers as they are { strikes[idx - 1] = (decimal)rawVolatility[0, idx]; } } for (int idx = 1; idx <= hi1D; idx++) { tenors[idx - 1] = rawVolatility[idx, 0].ToString(); } // Add arrays for the values var values = new decimal[hi1D][]; for (int idx = 1; idx <= hi1D; idx++) { values[idx - 1] = new decimal[hi2D]; for (int jdx = 1; jdx <= hi2D; jdx++) { values[idx - 1][jdx - 1] = decimal.Parse(rawVolatility[idx, jdx].ToString()); } } var grid = new SwaptionDataMatrix(tenors, strikes, expiry, values); return(grid); }
public void GetTenorsTest() { var target = new SwaptionDataMatrix(_volTenors, _volStrikes, _volExpiry, _volData, _id); string[] expected = _volTenors; try { string[] actual = target.GetTenors(); for (int i = 0; i < expected.Length; i++) { Assert.AreEqual(PeriodHelper.Parse(expected[i]).ToString(), actual[i]); } } catch (ArgumentException ex) { Assert.AreEqual("The matrix is malformed. No swap tenors available.", ex.Message); } }
/// <summary> /// Generate a new set of full calibration engines for the supplied data. /// Add or overwrite the engine store for the new engine. /// Each engineId will point to a set of engines indexed by swap tenor and option expiry /// Calibration assumes that the format of the grid data is as follows: /// /// + XXXX | lbl0 | lbl1 | ... | lbln + /// | lbl0 | d[0,0] | d[0,1] | ... | d[0,n] | /// | lbl1 | d[1,0] | d[1,1] | ... | d[1,n] | /// | ... | ... | ... | ... | ... | /// + lbln | d[n,0] | d[n,1] | ... | d[n,n] + /// /// </summary> /// <param name="engineHandle">Calibration Engine handle</param> /// <param name="settingsHandle">Calibartion settings handle</param> /// <param name="rawVols">A grid of volatilities (with row/column labels)</param> /// <param name="rawAssets">A grid of asset values</param> /// <param name="optionEx">The ption expiry to index against</param> /// <returns></returns> public string SABRCalibrateModel(string engineHandle, string settingsHandle, object[,] rawVols, object[,] rawAssets, string optionEx) { // Create the asset and volatility data grids SwaptionDataMatrix volatilityGrid = ParseVolatilityInput(rawVols, optionEx); ForwardRatesMatrix assetGrid = ParseAssetInputWithInterpolation(rawAssets); // Retrieve the calibration settings to use with this calibration engine if (!_sabrSettings.ContainsKey(settingsHandle)) { throw new ArgumentException($"Configuration '{settingsHandle}' has not been set up."); } SABRCalibrationSettings settings = _sabrSettings[settingsHandle]; // Generate the CalibrationEngine Id string calibrationEngineId = engineHandle; string optionExpiry = GenerateTenorLabel(optionEx); // Create a new engine holder object SortedDictionary <SABRKey, SABRCalibrationEngine> sabrEngine = BuildEngineCollection(volatilityGrid, assetGrid, settings, calibrationEngineId, optionExpiry); // We have an asset grid (forward rates) with this engine type so we should keep it // for future reference (that is during the lifetime of this session) if (_engineRatesGrid.ContainsKey(engineHandle)) { _engineRatesGrid[engineHandle] = assetGrid; } else { _engineRatesGrid.Add(engineHandle, assetGrid); } // Add the SABREngine to the persistent store if (_sabrEngines.ContainsKey(calibrationEngineId)) { _sabrEngines[calibrationEngineId] = sabrEngine; } else { _sabrEngines.Add(calibrationEngineId, sabrEngine); } return(engineHandle); }
/// <summary> /// Parse the raw volatilities to create the labels and values arrays /// required by a <see cref="SwaptionDataMatrix"/> used to store the data /// for use by the SABR Calibration routines /// </summary> /// <param name="strikes">An array of strikes.</param> /// <param name="rawVolatility">The raw volatility data</param> /// <param name="expiry">The expiry for this grid</param> /// <param name="tenors">An array of expiry tenors.</param> /// <returns>the rawdata as a SwaptiondataGrid</returns> private static SwaptionDataMatrix ParseVolatilityInput(String[] tenors, decimal[] strikes, Decimal[,] rawVolatility, string expiry) { // Set the upper/lower bounds of the converted array int hi1D = rawVolatility.GetUpperBound(0) + 1; int hi2D = rawVolatility.GetUpperBound(1) + 1; // Create and populate the data arrays used to build the SwaptionDataGrid // The columns represent tenors, the rows option expiries // Add arrays for the values var values = new decimal[hi1D][]; for (int idx = 0; idx < hi1D; idx++) { values[idx] = new decimal[hi2D]; for (int jdx = 0; jdx < hi2D; jdx++) { values[idx][jdx] = rawVolatility[idx, jdx]; } } var grid = new SwaptionDataMatrix(tenors, strikes, expiry, values); return(grid); }
/// <summary> /// Create a full calibration model.This version uses the volatility grid to generate an engine /// for each swap tenor (row values) /// </summary> /// <param name="volatilityGrid">The vols grid</param> /// <param name="assetGrid">The asset grid</param> /// <param name="settings">The SABR settings</param> /// <param name="calibrationEngineId">The id of this engine</param> /// <param name="optionExpiry">The ATM pointer</param> private static SortedDictionary <SABRKey, SABRCalibrationEngine> BuildEngineCollection(SwaptionDataMatrix volatilityGrid, ForwardRatesMatrix assetGrid, SABRCalibrationSettings settings, string calibrationEngineId, string optionExpiry) { var engineCollection = new SortedDictionary <SABRKey, SABRCalibrationEngine>(new SABRKey()); // Generate a new entry in the engineCollection for each row in the volatility grid foreach (string tenor in volatilityGrid.GetTenors()) { var assetPrice = assetGrid.GetAssetPrice(optionExpiry, tenor); var exerciseTime = (decimal)SABRHelper.GenerateDayValue(optionExpiry, 365.0d); // Generate the Vols and Strikes lists for the engine List <decimal> vols = volatilityGrid.GetVolatility(tenor).ToList(); List <decimal> strikes = volatilityGrid.GetStrikes().Select(strike => assetPrice + strike).ToList(); // Only add a new Calibration Engine (and Calibrate it) if the vols are greater than 0 if (!SABRHelper.ValidateData(vols)) { continue; } // Create a new instance of the engine var calibrationEngine = new SABRCalibrationEngine(calibrationEngineId, settings, strikes, vols, assetPrice, exerciseTime); // Calibrate the engine calibrationEngine.CalibrateSABRModel(); // Add the new engine to our collection var key = new SABRKey(optionExpiry, tenor); engineCollection.Add(key, calibrationEngine); } return(engineCollection); }