Пример #1
0
        public Dictionary <string, IrCurve> ImplyContainedCurves(DateTime buildDate, Interpolator1DType interpType)
        {
            var o = new Dictionary <string, IrCurve>();

            foreach (var curveName in SolveCurves)
            {
                var pillars = this.Where(x => x.SolveCurve == curveName)
                              .Select(x => x.PillarDate)
                              .OrderBy(x => x)
                              .ToArray();
                if (pillars.Distinct().Count() != pillars.Count())
                {
                    throw new Exception($"More than one instrument has the same solve pillar on curve {curveName}");
                }

                var dummyRates = pillars.Select(x => 0.05).ToArray();
                var ccy        = _currencyProvider.GetCurrency(curveName.Split('.')[0]);
                var colSpec    = (curveName.Contains("[")) ? curveName.Split('[').Last().Trim("[]".ToCharArray()) : curveName.Split('.').Last();
                if (o.Values.Any(v => v.CollateralSpec == colSpec))
                {
                    colSpec = colSpec + "_" + curveName;
                }

                var irCurve = new IrCurve(pillars, dummyRates, buildDate, curveName, interpType, ccy, colSpec);
                o.Add(curveName, irCurve);
            }
            return(o);
        }
Пример #2
0
        public SabrVolSurface(DateTime originDate, double[][] strikes, DateTime[] expiries, double[][] vols, Func <double, double> forwardCurve,
                              Interpolator1DType timeInterpType, DayCountBasis timeBasis)
        {
            TimeInterpolatorType = timeInterpType;
            TimeBasis            = timeBasis;

            Build(originDate, strikes, expiries, vols, forwardCurve);
        }
Пример #3
0
 public CorrelationTimeVector(string labelX, string[] labelsY, double[][] correlations, double[] times, Interpolator1DType interpKind = Interpolator1DType.LinearFlatExtrap)
     : this()
 {
     LabelsX      = new[] { labelX };
     LabelsY      = labelsY;
     Correlations = correlations;
     _times       = times;
     _interpType  = interpKind;
     _interps     = correlations.Select(c => InterpolatorFactory.GetInterpolator(times, c, interpKind)).ToArray();
 }
Пример #4
0
        public static IInterpolator1D GetInterpolator(double[] x, double[] y, Interpolator1DType kind, bool noCopy = false, bool isSorted = false)
        {
            if (!noCopy)
            {
                var newx = new double[x.Length];
                var newy = new double[y.Length];
                Buffer.BlockCopy(x, 0, newx, 0, x.Length * 8);
                Buffer.BlockCopy(y, 0, newy, 0, y.Length * 8);
                x = newx;
                y = newy;
            }
            if (!isSorted)
            {
                Array.Sort(x, y);
            }
            switch (kind)
            {
            case Interpolator1DType.LinearFlatExtrap:
                if (x.Length < 50)
                {
                    return(new LinearInterpolatorFlatExtrapNoBinSearch(x, y));
                }
                else
                {
                    return(new LinearInterpolatorFlatExtrap(x, y));
                }

            case Interpolator1DType.Linear:
                return(new LinearInterpolator(x, y));

            case Interpolator1DType.LinearInVariance:
                return(new LinearInVarianceInterpolator(x, y));

            case Interpolator1DType.GaussianKernel:
                return(new GaussianKernelInterpolator(x, y));

            case Interpolator1DType.NextValue:
                return(new NextInterpolator(x, y));

            case Interpolator1DType.PreviousValue:
                return(new PreviousInterpolator(x, y));

            case Interpolator1DType.CubicSpline:
                return(new CubicHermiteSplineInterpolator(x, y));

            case Interpolator1DType.MonotoneCubicSpline:
                return(new CubicHermiteSplineInterpolator(x, y, true));

            case Interpolator1DType.DummyPoint:
                return(new DummyPointInterpolator(y.First()));

            default:
                throw new InvalidOperationException($"We don't have a way of making a {kind} interpolator");
            }
        }
Пример #5
0
        public GridVolSurface(DateTime originDate, double[] strikes, DateTime[] expiries, double[][] vols,
                              StrikeType strikeType, Interpolator1DType strikeInterpType, Interpolator1DType timeInterpType,
                              DayCountBasis timeBasis)
        {
            StrikeType             = strikeType;
            StrikeInterpolatorType = strikeInterpType;
            TimeInterpolatorType   = timeInterpType;
            TimeBasis = timeBasis;

            Build(originDate, strikes, expiries, vols);
        }
Пример #6
0
        public Generic2dInterpolator(double[][] x, double[] y, double[][] z, Interpolator1DType xType, Interpolator1DType yType)
        {
            _y     = y;
            _xType = xType;
            _yType = yType;

            _yInterps = new IInterpolator1D[_y.Length];
            for (var i = 0; i < _yInterps.Length; i++)
            {
                _yInterps[i] = InterpolatorFactory.GetInterpolator(x[i], z[i], _yType);
            }
        }
Пример #7
0
        public Generic2dInterpolator(double[] x, double[] y, double[,] z, Interpolator1DType xType, Interpolator1DType yType)
        {
            _x     = x;
            _y     = y;
            _z     = z;
            _xType = xType;
            _yType = yType;

            _yInterps = new IInterpolator1D[_y.Length];
            for (var i = 0; i < _yInterps.Length; i++)
            {
                _yInterps[i] = InterpolatorFactory.GetInterpolator(_x, _z.GetRow(i), _yType);
            }
        }
Пример #8
0
        public double[] Solve(ATMStraddleConstraint atmConstraint, RRBFConstraint[] smileConstraints, DateTime buildDate,
                              DateTime expiry, double fwd, double[] strikesToFit, Interpolator1DType interpType)
        {
            _atmConstraint    = atmConstraint;
            _smileConstraints = smileConstraints;

            _numberOfConstraints = smileConstraints.Length * 2 + 1;

            if (strikesToFit.Length != _numberOfConstraints)
            {
                throw new Exception($"{_numberOfConstraints} constraints provided to fit {strikesToFit.Length} strikes");
            }

            _fwd        = fwd;
            _buildDate  = buildDate;
            _tExp       = (expiry - buildDate).TotalDays / 365.0;
            _interpType = interpType;
            _strikes    = strikesToFit;

            if (TrivialSolution(out var vols))
            {
                return(vols);
            }

            _currentGuess = Enumerable.Repeat(atmConstraint.MarketVol, _numberOfConstraints).ToArray();

            SetupConstraints();

            _currentErrors = ComputeErrors(_currentGuess);

            ComputeJacobian();

            for (var i = 0; i < MaxItterations; i++)
            {
                ComputeNextGuess();
                NaNCheck();
                _currentErrors = ComputeErrors(_currentGuess);
                if (_currentErrors.Max(x => Abs(x)) < Tollerance)
                {
                    UsedItterations = i + 1;
                    break;
                }
                ComputeJacobian();
            }

            return(_currentGuess);
        }
Пример #9
0
        public GridVolSurface(DateTime originDate, double[] strikes, DateTime[] expiries, double[][] vols,
                              StrikeType strikeType, Interpolator1DType strikeInterpType, Interpolator1DType timeInterpType,
                              DayCountBasis timeBasis, string[] pillarLabels = null) : base()
        {
            StrikeType             = strikeType;
            StrikeInterpolatorType = strikeInterpType;
            TimeInterpolatorType   = timeInterpType;
            TimeBasis = timeBasis;

            if (pillarLabels == null)
            {
                PillarLabels = expiries.Select(x => x.ToString("yyyy-MM-dd")).ToArray();
            }
            else
            {
                PillarLabels = pillarLabels;
            }

            Build(originDate, strikes, expiries, vols);
        }
Пример #10
0
        public IrCurve(DateTime[] pillars, double[] rates, DateTime buildDate, string name, Interpolator1DType interpKind)
        {
            _interpKind = interpKind;
            _pillars    = new DateTime[pillars.Length];
            pillars.CopyTo(_pillars, 0);
            _rates = new double[_pillars.Length];

            var pillarsD = new double[_pillars.Length];

            _buildDate = buildDate;

            for (var i = 0; i < pillars.Length; i++)
            {
                pillarsD[i] = buildDate.CalculateYearFraction(pillars[i], _basis);
                _rates[i]   = rates[i];
            }

            _interpolator = InterpolatorFactory.GetInterpolator(pillarsD.ToArray(), _rates.ToArray(), interpKind, isSorted: true, noCopy: true);
            _name         = name;
        }
Пример #11
0
        public IrCurve(DateTime[] pillars, double[] rates, DateTime buildDate, string name, Interpolator1DType interpKind, Currency ccy, string collateralSpec = null, RateType rateStorageType = RateType.Exponential)
        {
            _interpKind      = interpKind;
            _rateStorageType = rateStorageType;
            _pillars         = new DateTime[pillars.Length];
            pillars.CopyTo(_pillars, 0);
            _rates = new double[_pillars.Length];

            var pillarsD = new double[_pillars.Length];

            _buildDate = buildDate;

            for (var i = 0; i < pillars.Length; i++)
            {
                pillarsD[i] = buildDate.CalculateYearFraction(pillars[i], _basis);
                _rates[i]   = rates[i];
            }

            _interpolator  = InterpolatorFactory.GetInterpolator(pillarsD.ToArray(), _rates.ToArray(), interpKind, isSorted: true, noCopy: true);
            _name          = name;
            Currency       = ccy;
            CollateralSpec = collateralSpec ?? (string.IsNullOrWhiteSpace(_name) ? null :
                                                (_name.Contains("[")) ? _name.Split('[').Last().Trim("[]".ToCharArray()) : _name.Split('.').Last());
        }
Пример #12
0
 public CorrelationTimeVector(string labelX, string labelY, double[] correlations, double[] times, Interpolator1DType interpKind = Interpolator1DType.LinearFlatExtrap) :
     this(labelX, new[] { labelY }, new[] { correlations }, times, interpKind)
 {
 }
Пример #13
0
        public SVIVolSurface(DateTime originDate, double[] ATMVols, DateTime[] expiries, double[] wingDeltas,
                             double[][] riskies, double[][] flies, double[] fwds, WingQuoteType wingQuoteType, AtmVolType atmVolType,
                             Interpolator1DType timeInterpType, SviType sviType = SviType.Raw, string[] pillarLabels = null) : base()
        {
            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][];

            RawParams = new SviRawParameters[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,
                        };
                    }
                    RawParams[i] = f.SolveSviRaw(atmConstraints[i], wingConstraints[i], originDate, expiries[i], fwds[i], true);
                }
            }
            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,
                        };
                    }
                    RawParams[i] = f.SolveSviRaw(atmConstraints[i], wingConstraints[i], originDate, expiries[i], fwds[i], true);
                }
            }

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

            _interps    = new IInterpolator1D[5];
            _interps[0] = InterpolatorFactory.GetInterpolator(ExpiriesDouble, RawParams.Select(x => x.A).ToArray(), TimeInterpolatorType);
            _interps[1] = InterpolatorFactory.GetInterpolator(ExpiriesDouble, RawParams.Select(x => x.B).ToArray(), TimeInterpolatorType);
            _interps[2] = InterpolatorFactory.GetInterpolator(ExpiriesDouble, RawParams.Select(x => x.M).ToArray(), TimeInterpolatorType);
            _interps[3] = InterpolatorFactory.GetInterpolator(ExpiriesDouble, RawParams.Select(x => x.Rho).ToArray(), TimeInterpolatorType);
            _interps[4] = InterpolatorFactory.GetInterpolator(ExpiriesDouble, RawParams.Select(x => x.Sigma).ToArray(), TimeInterpolatorType);
            _fwdsInterp = InterpolatorFactory.GetInterpolator(ExpiriesDouble, fwds, Interpolator1DType.Linear);
        }
Пример #14
0
        public RiskyFlySurface(DateTime originDate, double[] ATMVols, DateTime[] expiries, double[] wingDeltas,
                               double[][] riskies, double[][] flies, double[] fwds, WingQuoteType wingQuoteType, AtmVolType atmVolType,
                               Interpolator1DType strikeInterpType, 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 strikes = new double[2 * wingDeltas.Length + 1];
            var vols    = new double[expiries.Length][];

            if (riskies.SelectMany(x => x).All(x => x == 0) && flies.SelectMany(x => x).All(x => x == 0))
            {
                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];
                }

                for (var t = 0; t < expiries.Length; t++)
                {
                    vols[t] = Enumerable.Repeat(ATMVols[t], strikes.Length).ToArray();
                }
            }
            else
            {
                var atmConstraints = ATMVols.Select(a => new ATMStraddleConstraint
                {
                    ATMVolType = atmVolType,
                    MarketVol  = a
                }).ToArray();

                var needsFlip = wingDeltas.First() > wingDeltas.Last();
                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 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,
                            };
                        }
                        vols[i] = f.Solve(atmConstraints[i], wingConstraints[i], originDate, expiries[i], fwds[i], strikes, strikeInterpType);
                    }
                }
                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,
                            };
                        }
                        vols[i] = f.Solve(atmConstraints[i], wingConstraints[i], originDate, expiries[i], fwds[i], strikes, strikeInterpType);
                    }
                }
            }

            StrikeInterpolatorType = strikeInterpType;
            TimeInterpolatorType   = timeInterpType;
            Expiries       = expiries;
            ExpiriesDouble = expiries.Select(x => x.ToOADate()).ToArray();
            Strikes        = strikes;
            StrikeType     = StrikeType.ForwardDelta;

            ATMs          = ATMVols;
            Riskies       = riskies;
            Flies         = flies;
            WingDeltas    = wingDeltas;
            Forwards      = fwds;
            WingQuoteType = wingQuoteType;
            AtmVolType    = atmVolType;

            base.Build(originDate, strikes, expiries, vols);
        }
Пример #15
0
        public static RiskyFlySurface FromCube(ICube cube, DateTime buildDate, Interpolator1DType strikeInterpType = Interpolator1DType.GaussianKernel, Interpolator1DType timeInterpType = Interpolator1DType.LinearInVariance)
        {
            var rows   = cube.GetAllRows();
            var deltas = cube.KeysForField("PointDelta")
                         .Where(x => (double)x != 0.5)
                         .Select(x => (double)x)
                         .OrderBy(x => x)
                         .ToList();
            var fwds      = new Dictionary <DateTime, double>();
            var atms      = new Dictionary <DateTime, double>();
            var rrs       = new Dictionary <DateTime, double[]>();
            var bfs       = new Dictionary <DateTime, double[]>();
            var quoteType = WingQuoteType.Simple;
            var atmType   = AtmVolType.ZeroDeltaStraddle;

            foreach (var row in rows)
            {
                var r = row.ToDictionary(cube.DataTypes.Keys.ToArray());
                var d = (DateTime)r["PointDate"];
                switch ((string)r["PointType"])
                {
                case "Forward":
                    fwds[d] = row.Value;
                    break;

                case "ATM":
                    atms[d] = row.Value;
                    atmType = (AtmVolType)Enum.Parse(typeof(AtmVolType), (string)r["QuoteType"]);
                    break;

                case "RR":
                    var delta = (double)r["PointDelta"];
                    if (!rrs.ContainsKey(d))
                    {
                        rrs[d] = new double[deltas.Count];
                    }
                    var dIx = deltas.IndexOf(delta);
                    rrs[d][dIx] = row.Value;
                    quoteType   = (WingQuoteType)Enum.Parse(typeof(WingQuoteType), (string)r["QuoteType"]);
                    break;

                case "BF":
                    var delta2 = (double)r["PointDelta"];
                    if (!bfs.ContainsKey(d))
                    {
                        bfs[d] = new double[deltas.Count];
                    }
                    var dIx2 = deltas.IndexOf(delta2);
                    bfs[d][dIx2] = row.Value;
                    break;
                }
            }

            var expArr = atms.OrderBy(x => x.Key).Select(x => x.Key).ToArray();
            var atmArr = atms.OrderBy(x => x.Key).Select(x => x.Value).ToArray();
            var fwdArr = fwds.OrderBy(x => x.Key).Select(x => x.Value).ToArray();
            var rrArr  = rrs.OrderBy(x => x.Key).Select(x => x.Value).ToArray();
            var bfArr  = bfs.OrderBy(x => x.Key).Select(x => x.Value).ToArray();

            return(new RiskyFlySurface(buildDate, atmArr, expArr, deltas.ToArray(), rrArr, bfArr, fwdArr, quoteType, atmType, strikeInterpType, timeInterpType));
        }
Пример #16
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);
        }