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);
            }
        }
Example #7
0
        /// <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);
            }
        }
Example #9
0
        /// <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);
        }