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); }
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); }
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(); }
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"); } }
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); }
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); } }
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); } }
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); }
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); }
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; }
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()); }
public CorrelationTimeVector(string labelX, string labelY, double[] correlations, double[] times, Interpolator1DType interpKind = Interpolator1DType.LinearFlatExtrap) : this(labelX, new[] { labelY }, new[] { correlations }, times, interpKind) { }
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); }
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); }
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)); }
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); }