/// <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);
        }
        /// <summary>
        /// Create an Interpolated calibration engine. Such an engine is designed for a single value
        /// derived from a set of base engines.
        /// </summary>
        /// <param name="settings">The settings object to use</param>
        /// <param name="calibrationEngineId">The id of this engine</param>
        /// <param name="engines">The array of engine handles to use</param>
        /// <param name="atmVolatility">The ATM volatility</param>
        /// <param name="assetPrice">Asset Price to use</param>
        /// <param name="optionExpiry">The ATM pointer</param>
        /// <param name="tenor">The tenor to create the new engine for. This must be a valid tenor</param>
        private static SortedDictionary <SABRKey, SABRCalibrationEngine> BuildEngineCollection(SABRCalibrationSettings settings, string calibrationEngineId, IEnumerable <KeyValuePair <SABRKey, SABRCalibrationEngine> > engines, decimal atmVolatility, decimal assetPrice, string optionExpiry, string tenor)
        {
            var engineCollection = new SortedDictionary <SABRKey, SABRCalibrationEngine>(new SABRKey());
            var exerciseTime     = (decimal)SABRHelper.GenerateDayValue(optionExpiry, 365.0d);
            var indexTenor       = (decimal)SABRHelper.GenerateDayValue(tenor, 365.0d);
            // Create a new instance of the engine
            var calibrationEngine =
                new SABRCalibrationEngine(calibrationEngineId, settings, engines, atmVolatility, assetPrice, exerciseTime, indexTenor);

            // Calibrate the engine
            calibrationEngine.CalibrateInterpSABRModel();
            // Add the new engine to our collection
            var key = new SABRKey(optionExpiry, tenor);

            engineCollection.Add(key, calibrationEngine);
            return(engineCollection);
        }
        /// <summary>
        /// Calculate the SABR implied volatility for the strike value.
        /// This method uses the calibration engine indexed by the exerciseTime/assetCode pair
        /// When an ATM engine is used then the assetCode is ignored.
        /// </summary>
        /// <param name="engineHandle">The CalibrationEngine to use</param>
        /// <param name="exerciseTime">Option Expiry index</param>
        /// <param name="assetCode">Swap Tenor index</param>
        /// <param name="strike">The strike to calculate Volatility for</param>
        /// <returns></returns>
        public decimal SABRInterpolateVolatility(string engineHandle, string exerciseTime, string assetCode, decimal strike)
        {
            decimal result = 0;
            string  errmsg = "";

            // Only process if the engine object holder holds the engine for this exercise/asset key
            if (_sabrEngines.ContainsKey(engineHandle))
            {
                // Extract the information we need from this engine holder
                var engine = _sabrEngines[engineHandle];
                var key    = new SABRKey(SABRHelper.GenerateTenorLabel(exerciseTime), SABRHelper.GenerateTenorLabel(assetCode));
                // Check that the engine for this exercise/asset key exists
                if (engine.ContainsKey(key))
                {
                    SABRCalibrationEngine calibrationEngine = engine[key];
                    if (!calibrationEngine.IsSABRModelCalibrated)
                    {
                        throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "SABR Engine with key: {0}:{1} is not calibrated", new object[] { key.Expiry, key.Tenor }));
                    }
                    // Create SABRImpliedVolatility parameters
                    decimal assetPrice  = _engineRatesGrid.ContainsKey(engineHandle) ? _engineRatesGrid[engineHandle].GetAssetPrice(exerciseTime, assetCode) : calibrationEngine.AssetPrice;
                    decimal strikeValue = strike;
                    var     expiry      = (decimal)SABRHelper.GenerateDayValue(exerciseTime, 365.0d);
                    //decimal strikeValue = strike / 100.0m;
                    // build an ImpliedVolatility object
                    SABRParameters parameters = calibrationEngine.GetSABRParameters;
                    var            vol        = new SABRImpliedVolatility(parameters, true);
                    // value the strike (interpolate as necessary)
                    if (!vol.SABRInterpolatedVolatility(assetPrice, expiry, strikeValue, ref errmsg, ref result, true))
                    {
                        throw new ArgumentException(errmsg);
                    }
                }
                else
                {
                    throw new ArgumentException("The Calibration Engine with Key(" + exerciseTime + "," + assetCode + ") not found.");
                }
            }
            else
            {
                throw new ArgumentException("Calibration Engine " + engineHandle + " not found.");
            }
            return(result);
        }
        /// <summary>
        /// Create an ATM calibration engine. Such an engine is designed for a single value
        /// </summary>
        /// <param name="settings">The settings object to use</param>
        /// <param name="calibrationEngineId">The id of this engine</param>
        /// <param name="nu">Nu value</param>
        /// <param name="rho">Rho value</param>
        /// <param name="atmVolatility">The ATM volatility</param>
        /// <param name="assetPrice">Asset Price to use</param>
        /// <param name="optionExpiry">The ATM pointer</param>
        /// <param name="assetCode">The ATM identifiier (if used)</param>
        private static SortedDictionary <SABRKey, SABRCalibrationEngine> BuildEngineCollection(SABRCalibrationSettings settings,
                                                                                               string calibrationEngineId, decimal nu, decimal rho, decimal atmVolatility, decimal assetPrice,
                                                                                               string optionExpiry, string assetCode)
        {
            // basic setup
            var engineCollection = new SortedDictionary <SABRKey, SABRCalibrationEngine>(new SABRKey());
            var exerciseTime     = (decimal)SABRHelper.GenerateDayValue(optionExpiry, 365.0d);
            // Create a new instance of the engine
            var calibrationEngine =
                new SABRCalibrationEngine(calibrationEngineId, settings, nu, rho, atmVolatility, assetPrice,
                                          exerciseTime);

            // Calibrate the engine
            calibrationEngine.CalibrateATMSABRModel();
            // Add the new engine to our collection
            SABRKey key = assetCode != null ? new SABRKey(optionExpiry, assetCode) : new SABRKey(optionExpiry);

            engineCollection.Add(key, calibrationEngine);
            return(engineCollection);
        }