/// <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"); } }
/// <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)); }
/// <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); }
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); }
/// <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); }
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 }
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);
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); }
public double CalcImpVol_Beta1(double k, SABRParameters currentSABR) => SABR.CalcImpVol_Beta1(_fwd, k, _tExp, currentSABR.Alpha, currentSABR.Rho, currentSABR.Nu);