Esempio n. 1
0
        /// <summary>
        /// Get the SABR Calibration engine parameter for the provided options
        /// The exercise/tenor pair form the key to the correct calibration engine
        /// from an underlying store.
        /// </summary>
        /// <param name="param">The parameter type to return</param>
        /// <param name="engineHandle">The engine to use</param>
        /// <returns></returns>
        public decimal GetSABRParameter(CalibrationParameter param, string engineHandle)
        {
            SmileCalibrationEngine smileEngine;

            if (_sabrEngines.ContainsKey(engineHandle))
            {
                smileEngine = _sabrEngines[engineHandle];
            }
            else
            {
                throw new ArgumentException("SABR Smile Calibration engine not found.");
            }
            var            calibrationEngine = smileEngine.SABRCalibrationEngine;
            SABRParameters parameters        = calibrationEngine.GetSABRParameters;

            switch (param)
            {
            case CalibrationParameter.Alpha:
                return(parameters.Alpha);

            case CalibrationParameter.Beta:
                return(parameters.Beta);

            case CalibrationParameter.Nu:
                return(parameters.Nu);

            case CalibrationParameter.Rho:
                return(parameters.Rho);

            default:
                throw new ArgumentException("Unknown Calibration Parameter request");
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Values at.
        /// </summary>
        /// <param name="axisValue">The axis value.</param>
        /// <param name="extrapolation">if set to <c>true</c> [extrapolation].</param>
        /// <returns></returns>
        public double ValueAt(double axisValue, bool extrapolation)
        {
            string        engineHandle      = SettingsHandle;
            decimal       time              = Convert.ToDecimal(ExpiryTime);
            const decimal tenor             = 0;
            var           calibrationEngine =
                new SABRCalibrationEngine(engineHandle,
                                          CalibrationSettings,
                                          EngineHandles,
                                          AtmVolatility,
                                          AssetPrice,
                                          time,
                                          tenor
                                          );

            calibrationEngine.CalibrateInterpSABRModel();
            var sabrParameters = new SABRParameters(calibrationEngine.GetSABRParameters.Alpha,
                                                    calibrationEngine.GetSABRParameters.Beta,
                                                    calibrationEngine.GetSABRParameters.Nu,
                                                    calibrationEngine.GetSABRParameters.Rho);
            var     sabrImpliedVol = new SABRImpliedVolatility(sabrParameters, false);
            var     value          = Convert.ToDecimal(axisValue) * AssetPrice;
            string  errMsg         = "Error interpolating";
            decimal result         = 0.0m;

            sabrImpliedVol.SABRInterpolatedVolatility(AssetPrice, time, value, ref errMsg, ref result, true);
            return(Convert.ToDouble(result));
        }
Esempio n. 3
0
        /// <summary>
        /// Master (wrapper) function that checks the validity of the
        /// SABR parameters.
        /// Valid bounds/ranges for the SABR parameters are defined in the
        /// functions the check the individual SABR parameters.
        /// </summary>
        /// <param name="sabrParameters">Object that contains all the
        /// SABR parameters.</param>
        /// <param name="errorMessage">Container for any possible error
        /// message.</param>
        /// <returns>
        /// True if all SABR parameters are valid, otherwise
        /// false.
        /// </returns>
        public static bool CheckSABRParameters(SABRParameters sabrParameters,
                                               ref string errorMessage)
        {
            // Initialise the error message container.
            errorMessage = "";
            // Check SABR parameter alpha.
            var areAllParametersValid =
                CheckSABRParameterAlpha(sabrParameters.Alpha,
                                        ref errorMessage);

            if (!areAllParametersValid)
            {
                return(areAllParametersValid);
            }
            // Check SABR parameter beta.
            areAllParametersValid = CheckSABRParameterBeta(sabrParameters.Beta,
                                                           ref errorMessage);
            if (!areAllParametersValid)
            {
                return(areAllParametersValid);
            }
            // Check SABR parameter nu.
            areAllParametersValid = CheckSABRParameterNu(sabrParameters.Nu,
                                                         ref errorMessage);
            if (!areAllParametersValid)
            {
                return(areAllParametersValid);
            }
            // Check SABR parameter rho.
            areAllParametersValid = CheckSABRParameterRho(sabrParameters.Rho,
                                                          ref errorMessage);
            return(areAllParametersValid);
        }
        public void TestCheckSABRParameterNu()
        {
            _nu = -0.4m;
            _isValidSABRParameter =
                SABRParameters.CheckSABRParameterNu(_nu, ref _errorMessage);
            const string expected = "SABR parameter nu cannot be negative.";

            Assert.IsFalse(_isValidSABRParameter);
            Assert.AreEqual(expected, _errorMessage);
        }
        public void TestCheckSABRParameterRho()
        {
            _rho = 1.001m;
            _isValidSABRParameter =
                SABRParameters.CheckSABRParameterRho(_rho, ref _errorMessage);
            const string expected = "SABR parameter rho not in the range (-1,1)";

            Assert.IsFalse(_isValidSABRParameter);
            Assert.AreEqual(expected, _errorMessage);
        }
        public void TestCheckSABRParamterAlpha()
        {
            _alpha = 0.0m;
            _isValidSABRParameter =
                SABRParameters.CheckSABRParameterAlpha(_alpha, ref _errorMessage);
            const string expected = "SABR parameter alpha must be positive.";

            Assert.IsFalse(_isValidSABRParameter);
            Assert.AreEqual(expected, _errorMessage);
        }
Esempio n. 7
0
        private double[] ComputeErrorsSABR(SABRParameters currentSABR)
        {
            var volFunc = new Func <double, double>(k => CalcImpVol_Beta1(k, currentSABR));
            var o       = ComputeErrorsGeneric(volFunc, true);

            if (currentSABR.Rho > 1.0 || currentSABR.Rho < -1.0 || currentSABR.Alpha < 0.0 || currentSABR.Nu < 0.0)
            {
                o = o.Select(x => x * 1e10).ToArray();
            }
            return(o);
        }
        public void TestSABRParameters()
        {
            // Test: object instantiation.
            SABRParameters sabrParameters =
                new SABRParameters(_alpha, _beta, _nu, _rho);

            Assert.IsNotNull(sabrParameters);

            // Test: data mapped to the correct private fields.
            Assert.AreEqual(_alpha, sabrParameters.Alpha);
            Assert.AreEqual(_beta, sabrParameters.Beta);
            Assert.AreEqual(_nu, sabrParameters.Nu);
            Assert.AreEqual(_rho, sabrParameters.Rho);
        }
Esempio n. 9
0
        /// <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="strikes">The strikes to calculate Volatility for</param>
        /// <returns></returns>
        public decimal[] SABRInterpolateVolatilities(string engineHandle, string exerciseTime, string assetCode,
                                                     decimal[] strikes)
        {
            // Only process if the engine object holder holds the engine for this exercise/asset key
            if (!_sabrEngines.ContainsKey(engineHandle))
            {
                throw new System.Exception("Calibration Engine " + engineHandle + " not found.");
            }
            // Extract the information we need from this engine holder
            SortedDictionary <SABRKey, SABRCalibrationEngine> engine = _sabrEngines[engineHandle];
            var key = new SABRKey(GenerateTenorLabel(exerciseTime), GenerateTenorLabel(assetCode));

            // Check that the engine for this exercise/asset key exists
            if (!engine.ContainsKey(key))
            {
                throw new System.Exception("The Calibration Engine with Key(" + exerciseTime + "," + assetCode + ") not found.");
            }
            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 expiry = GenerateDayValue(exerciseTime, 365.0m);
            // build an ImpliedVolatility object
            SABRParameters parameters = calibrationEngine.GetSABRParameters;
            var            vol        = new SABRImpliedVolatility(parameters, true);
            // value the strike (interpolate as necessary)
            var results = new List <decimal>(strikes.Length);

            foreach (decimal strike in strikes)
            {
                string  errmsg = "";
                decimal result = 0;
                if (!vol.SABRInterpolatedVolatility(assetPrice, expiry, strike, ref errmsg, ref result, true))
                {
                    throw new System.Exception(errmsg);
                }
                results.Add(result);
            }
            return(results.ToArray());
        }
 public void Initialisation()
 {
     _alpha        = 15.53173d / 100.0d;
     _assetPrice   = 3.98d / 100.0d;
     _beta         = 1.0d;
     _exerciseTime = 5.0d;
     _expected     = 0.0d;
     _nu           = 40.0d / 100.0d;
     _result       = 0.0d;
     _rho          = -33.0d / 100.0d;
     _strike       = _assetPrice;
     _checkImpliedVolParameters = true;
     _checkSABRParameters       = true;
     _isSuccessful   = true;
     _errorMessage   = "";
     _sabrParameters = new SABRParameters(_alpha, _beta, _nu, _rho);
 }
        /// <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);
        }
Esempio n. 12
0
        public SABRParameters SolveSABR(ATMStraddleConstraint atmConstraint, RRBFConstraint[] smileConstraints, DateTime buildDate,
                                        DateTime expiry, double fwd, double beta = 1.0, bool vegaWeightedFit = true)
        {
            _atmConstraint    = atmConstraint;
            _smileConstraints = smileConstraints;

            _numberOfConstraints = smileConstraints.Length * 2 + 1;
            _vegaWeighted        = vegaWeightedFit;

            _fwd       = fwd;
            _buildDate = buildDate;
            _tExp      = (expiry - buildDate).TotalDays / 365.0;

            var startingPoint = new[] { atmConstraint.MarketVol, Sqrt(atmConstraint.MarketVol), smileConstraints.Average(x => x.RisykVol) >= 0 ? 0.1 : -0.1 };
            var initialStep   = new[] { 0.1, 0.25, 0.25 };

            var currentError = new Func <double[], double>(x =>
            {
                var currentSABR = new SABRParameters
                {
                    Alpha = x[0],
                    Beta  = beta,
                    Nu    = x[1],
                    Rho   = x[2],
                };

                var e = ComputeErrorsSABR(currentSABR);
                return(e.Sum(ee => ee * ee));
            });

            SetupConstraints();

            var optimal = NelderMead.MethodSolve(currentError, startingPoint, initialStep, 1e-8, 10000);

            return(new SABRParameters
            {
                Alpha = optimal[0],
                Beta = beta,
                Nu = optimal[1],
                Rho = optimal[2],
            });
        }
        public void TestCheckSABRParameterBeta()
        {
            // Check the case beta < 0.0.
            _beta = -0.1m;
            _isValidSABRParameter =
                SABRParameters.CheckSABRParameterBeta(_beta, ref _errorMessage);
            const string expected =
                "SABR parameter beta not in the range [0,1].";

            Assert.IsFalse(_isValidSABRParameter);
            Assert.AreEqual(expected, _errorMessage);

            // Check the case beta > 1.0.
            _beta = 1.03m;
            _isValidSABRParameter =
                SABRParameters.CheckSABRParameterBeta(_beta, ref _errorMessage);

            Assert.IsFalse(_isValidSABRParameter);
            Assert.AreEqual(expected, _errorMessage);
        }
        /// <summary>
        /// Get the SABR Calibration engine parameter for the provided options
        /// The exercise/tenor pair form the key to the correct calibration engine
        /// from an underlying store.
        /// </summary>
        /// <param name="param">The parameter type to return</param>
        /// <param name="engine">The engine to use</param>
        /// <param name="pExercise">The exercise (option expiry) part of the key</param>
        /// <param name="pTenor">The tenor (asset code) part of the key</param>
        /// <returns></returns>
        public decimal GetSABRParameter(CalibrationParameter param, string engine, string pExercise, string pTenor)
        {
            string exercise = SABRHelper.GenerateTenorLabel(pExercise);
            string tenor    = SABRHelper.GenerateTenorLabel(pTenor);

            if (!_sabrEngines.ContainsKey(engine))
            {
                throw new ArgumentException("Calibration Engine " + engine + " not found.");
            }
            SortedDictionary <SABRKey, SABRCalibrationEngine> sabrEngines = _sabrEngines[engine];
            var key = new SABRKey(exercise, tenor);

            if (!sabrEngines.ContainsKey(key))
            {
                throw new ArgumentException("The Calibration Engine with Key(" + exercise + "," + tenor + ") not found.");
            }
            SABRCalibrationEngine calibrationEngine = sabrEngines[key];
            SABRParameters        parameters        = calibrationEngine.GetSABRParameters;

            switch (param)
            {
            case CalibrationParameter.Alpha:
                return(parameters.Alpha);

            case CalibrationParameter.Beta:
                return(parameters.Beta);

            case CalibrationParameter.Nu:
                return(parameters.Nu);

            case CalibrationParameter.Rho:
                return(parameters.Rho);

            default:
                throw new ArgumentException("Unknown Calibration Parameter request");
            }
        }
        public void TestSabrInterpolatedVolatilityComputeXDouble()
        {
            const double   Alpha          = 0.219540520585315;
            const double   Beta           = 1;
            const double   Nu             = 0.0000000000021506467396720648;
            const double   Rho            = 0.999999999999999;
            SABRParameters sabrParameters = new SABRParameters(Alpha, Beta, Nu, Rho);

            const double AssetPrice   = 0.07226393165;
            const double ExerciseTime = 1d / 12;
            const double Strike       = 0.0722905443874852823;
            const bool   CheckImpliedVolParameters = false;
            double       answer = 0;
            string       error  = "";

            SABRImpliedVolatility impliedVolObject = new SABRImpliedVolatility(sabrParameters, CheckImpliedVolParameters);

            bool result = impliedVolObject.SABRInterpolatedVolatility(AssetPrice, ExerciseTime, Strike,
                                                                      ref error, ref answer, CheckImpliedVolParameters);

            Assert.IsTrue(result);
            Assert.AreEqual("", error);
            Assert.AreEqual(6.72317387E-15, answer, 1E-23);
        }
        public void TestSABRInterpolatedVolatility()
        {
            #region Tests: SABR Implied Volatility for beta = 0.0

            // Test computation of the SABR implied volatility for
            // the case beta = 0.0.
            _alpha = 0.60897d / 100d;
            _beta  = 0.0d;
            _nu    = 32.0d / 100d;
            _rho   = 17.0d / 100d;
            _checkSABRParameters = false;
            SABRParameters sabrParameters1 =
                new SABRParameters(_alpha, _beta, _nu, _rho);

            SABRImpliedVolatility impliedVolObj1 =
                new SABRImpliedVolatility(sabrParameters1,
                                          _checkSABRParameters);

            // Strike = ATM - 200bp.
            _strike   = _assetPrice - 200.0d / 10000d;
            _expected = 23.96039d / 100d;
            const double tolerance1 = 1.0E-5d;

            _isSuccessful =
                impliedVolObj1.SABRInterpolatedVolatility(
                    _assetPrice,
                    _exerciseTime,
                    _strike,
                    ref _errorMessage,
                    ref _result,
                    _checkImpliedVolParameters);

            Assert.IsTrue(_isSuccessful);
            Assert.AreEqual(_expected,
                            _result,
                            tolerance1);

            // Strike = ATM.
            _strike   = _assetPrice;
            _expected = 15.99991d / 100d;

            _isSuccessful =
                impliedVolObj1.SABRInterpolatedVolatility(
                    _assetPrice,
                    _exerciseTime,
                    _strike,
                    ref _errorMessage,
                    ref _result,
                    _checkImpliedVolParameters);

            Assert.IsTrue(_isSuccessful);
            Assert.AreEqual(_expected,
                            _result,
                            tolerance1);

            // Strike = ATM + 200bp.
            _strike   = _assetPrice + 200.0d / 10000d;
            _expected = 15.62789d / 100d;

            _isSuccessful =
                impliedVolObj1.SABRInterpolatedVolatility(
                    _assetPrice,
                    _exerciseTime,
                    _strike,
                    ref _errorMessage,
                    ref _result,
                    _checkImpliedVolParameters);

            Assert.IsTrue(_isSuccessful);
            Assert.AreEqual(_expected,
                            _result,
                            tolerance1);

            #endregion Tests: SABR Implied Volatility for beta = 0.0

            #region Tests: SABR Implied Volatility for beta = 0.5

            // Test computation of the SABR implied volatility for
            // the case beta = 0.5.
            _alpha = 3.05473d / 100d;
            _beta  = 0.5d;
            _nu    = 34.0d / 100d;
            _rho   = -11.0d / 100d;
            _checkSABRParameters = false;
            SABRParameters sabrParameters2 =
                new SABRParameters(_alpha, _beta, _nu, _rho);

            SABRImpliedVolatility impliedVolObj2 =
                new SABRImpliedVolatility(sabrParameters2,
                                          _checkSABRParameters);

            // Strike = ATM - 200bp.
            _strike   = _assetPrice - 200.0d / 10000d;
            _expected = 23.73848d / 100d;
            const double tolerance2 = 1.0E-5d;

            _isSuccessful =
                impliedVolObj2.SABRInterpolatedVolatility(_assetPrice,
                                                          _exerciseTime,
                                                          _strike,
                                                          ref _errorMessage,
                                                          ref _result,
                                                          _checkSABRParameters);
            Assert.IsTrue(_isSuccessful);
            Assert.AreEqual(_expected,
                            _result,
                            tolerance2);

            // Strike = ATM
            _strike   = _assetPrice;
            _expected = 16.00001d / 100d;

            _isSuccessful =
                impliedVolObj2.SABRInterpolatedVolatility(_assetPrice,
                                                          _exerciseTime,
                                                          _strike,
                                                          ref _errorMessage,
                                                          ref _result,
                                                          _checkSABRParameters);
            Assert.IsTrue(_isSuccessful);
            Assert.AreEqual(_expected,
                            _result,
                            tolerance2);

            // Strike = ATM + 200bp
            _strike   = _assetPrice + 200.0d / 10000d;
            _expected = 15.75552d / 100d;

            _isSuccessful =
                impliedVolObj2.SABRInterpolatedVolatility(_assetPrice,
                                                          _exerciseTime,
                                                          _strike,
                                                          ref _errorMessage,
                                                          ref _result,
                                                          _checkSABRParameters);
            Assert.IsTrue(_isSuccessful);
            Assert.AreEqual(_expected,
                            _result,
                            tolerance2);


            #endregion Tests: SABR Implied Volatility for beta = 0.5

            #region Tests: SABR Implied Volatility for beta = 1.0

            // Test computation of the SABR implied volatility for
            // the case beta = 1.0.
            _alpha = 15.53173d / 100d;
            _beta  = 1.0d;
            _nu    = 40.0d / 100d;
            _rho   = -33.0d / 100d;
            _checkSABRParameters = false;
            SABRParameters sabrParameters3 =
                new SABRParameters(_alpha, _beta, _nu, _rho);

            SABRImpliedVolatility impliedVolObj3 =
                new SABRImpliedVolatility(sabrParameters3,
                                          _checkSABRParameters);

            // Strike = ATM - 200bp.
            _strike   = _assetPrice - 200.0d / 10000d;
            _expected = 23.79395d / 100d;
            const double tolerance3 = 1.0E-5d;

            _isSuccessful =
                impliedVolObj3.SABRInterpolatedVolatility
                    (_assetPrice,
                    _exerciseTime,
                    _strike,
                    ref _errorMessage,
                    ref _result,
                    _checkImpliedVolParameters);

            Assert.IsTrue(_isSuccessful);
            Assert.AreEqual(_expected,
                            _result,
                            tolerance3);

            // Strike = ATM
            _strike   = _assetPrice;
            _expected = 16.00000d / 100d;

            _isSuccessful =
                impliedVolObj3.SABRInterpolatedVolatility
                    (_assetPrice,
                    _exerciseTime,
                    _strike,
                    ref _errorMessage,
                    ref _result,
                    _checkImpliedVolParameters);

            Assert.IsTrue(_isSuccessful);
            Assert.AreEqual(_expected,
                            _result,
                            tolerance3);

            // Strike = ATM + 200bp
            _strike   = _assetPrice + 200.0d / 10000d;
            _expected = 16.05579d / 100d;

            _isSuccessful =
                impliedVolObj3.SABRInterpolatedVolatility
                    (_assetPrice,
                    _exerciseTime,
                    _strike,
                    ref _errorMessage,
                    ref _result,
                    _checkImpliedVolParameters);

            Assert.IsTrue(_isSuccessful);
            Assert.AreEqual(_expected,
                            _result,
                            tolerance3);


            #endregion Tests: SABR Implied Volatility for beta = 1.0
        }
Esempio n. 17
0
 public static double GetVolForAbsoluteStrike(double strike, double maturity, double forward, SABRParameters sabrParams) => sabrParams.Beta >= 1.0
         ? SABR.CalcImpVol_Beta1(forward, strike, maturity, sabrParams.Alpha, sabrParams.Rho, sabrParams.Nu)
         : SABR.CalcImpVol_Hagan(forward, strike, maturity, sabrParams.Alpha, sabrParams.Beta, sabrParams.Rho, sabrParams.Nu);
Esempio n. 18
0
        public SabrVolSurface(DateTime originDate, double[] ATMVols, DateTime[] expiries, double[] wingDeltas,
                              double[][] riskies, double[][] flies, double[] fwds, WingQuoteType wingQuoteType, AtmVolType atmVolType,
                              Interpolator1DType timeInterpType, string[] pillarLabels = null)
        {
            if (pillarLabels == null)
            {
                PillarLabels = expiries.Select(x => x.ToString("yyyy-MM-dd")).ToArray();
            }
            else
            {
                PillarLabels = pillarLabels;
            }

            if (ATMVols.Length != expiries.Length || expiries.Length != riskies.Length || riskies.Length != flies.Length)
            {
                throw new Exception("Inputs do not have consistent time dimensions");
            }

            if (wingDeltas.Length != riskies[0].Length || riskies[0].Length != flies[0].Length)
            {
                throw new Exception("Inputs do not have consistent strike dimensions");
            }

            var atmConstraints = ATMVols.Select(a => new ATMStraddleConstraint
            {
                ATMVolType = atmVolType,
                MarketVol  = a
            }).ToArray();

            var needsFlip = wingDeltas.First() > wingDeltas.Last();
            var strikes   = new double[2 * wingDeltas.Length + 1];

            if (needsFlip)
            {
                for (var s = 0; s < wingDeltas.Length; s++)
                {
                    strikes[s] = wingDeltas[wingDeltas.Length - 1 - s];
                    strikes[strikes.Length - 1 - s] = 1.0 - wingDeltas[wingDeltas.Length - 1 - s];
                }
            }
            else
            {
                for (var s = 0; s < wingDeltas.Length; s++)
                {
                    strikes[s] = wingDeltas[s];
                    strikes[strikes.Length - 1 - s] = 1.0 - wingDeltas[s];
                }
            }
            strikes[wingDeltas.Length] = 0.5;

            var wingConstraints = new RRBFConstraint[expiries.Length][];
            var parameters      = new SABRParameters[expiries.Length];
            var f = new AssetSmileSolver();

            if (needsFlip)
            {
                for (var i = 0; i < wingConstraints.Length; i++)
                {
                    var offset = wingDeltas.Length - 1;
                    wingConstraints[i] = new RRBFConstraint[wingDeltas.Length];
                    for (var j = 0; j < wingConstraints[i].Length; j++)
                    {
                        wingConstraints[i][j] = new RRBFConstraint
                        {
                            Delta         = wingDeltas[offset - j],
                            FlyVol        = flies[i][offset - j],
                            RisykVol      = riskies[i][offset - j],
                            WingQuoteType = wingQuoteType,
                        };
                    }
                    parameters[i] = f.SolveSABR(atmConstraints[i], wingConstraints[i], originDate, expiries[i], fwds[i], 1.0);
                }
            }
            else
            {
                for (var i = 0; i < wingConstraints.Length; i++)
                {
                    wingConstraints[i] = new RRBFConstraint[wingDeltas.Length];
                    for (var j = 0; j < wingConstraints[i].Length; j++)
                    {
                        wingConstraints[i][j] = new RRBFConstraint
                        {
                            Delta         = wingDeltas[j],
                            FlyVol        = flies[i][j],
                            RisykVol      = riskies[i][j],
                            WingQuoteType = wingQuoteType,
                        };
                    }
                    parameters[i] = f.SolveSABR(atmConstraints[i], wingConstraints[i], originDate, expiries[i], fwds[i], 1.0);
                }
            }

            OriginDate           = originDate;
            TimeInterpolatorType = timeInterpType;
            Expiries             = expiries;
            ExpiriesDouble       = expiries.Select(x => originDate.CalculateYearFraction(x, TimeBasis)).ToArray();

            Alphas = parameters.Select(x => x.Alpha).ToArray();
            Betas  = parameters.Select(x => x.Beta).ToArray();
            Nus    = parameters.Select(x => x.Nu).ToArray();
            Rhos   = parameters.Select(x => x.Rho).ToArray();

            _alphaInterp = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Alphas, TimeInterpolatorType);
            _betaInterp  = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Betas, TimeInterpolatorType);
            _rhoInterp   = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Rhos, TimeInterpolatorType);
            _nuInterp    = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Nus, TimeInterpolatorType);
            _fwdsInterp  = InterpolatorFactory.GetInterpolator(ExpiriesDouble, fwds, TimeInterpolatorType);
        }
Esempio n. 19
0
 public double CalcImpVol_Beta1(double k, SABRParameters currentSABR) => SABR.CalcImpVol_Beta1(_fwd, k, _tExp, currentSABR.Alpha, currentSABR.Rho, currentSABR.Nu);