/// <summary> /// Use Direct SQL commands feature implementation based on EntityFramework Core /// </summary> /// <param name="conf">Channel configuration</param> /// <param name="context">Lazy disposable wrapper around DbContext</param> public static void UseEfCoreDirectSqlCommand(this ChannelConfiguration <CommandChannel <Tecture.Features.SqlStroke.Command> > conf, ILazyDisposable <DbContext> context, InterpolatorFactory fac = null) { if (fac == null) { fac = new InterpolatorFactory(); } var fe = new EFCore_DirectSql_CommandFeature(context, conf.Channel, fac); conf.ForCommand(fe, new EFCore_DirectSql_Saver(fe)); }
/// <summary> /// Use Direct SQL aspect implementation based on EntityFramework Core /// </summary> /// <param name="conf">Channel configuration</param> /// <param name="context">Lazy disposable wrapper around DbContext</param> public static void UseEfCoreDirectSql(this ChannelBinding <CommandQueryChannel <Tecture.Aspects.DirectSql.DirectSql.Command, Tecture.Aspects.DirectSql.DirectSql.Query> > conf, ILazyDisposable <DbContext> context, InterpolatorFactory fac = null) { if (fac == null) { fac = new InterpolatorFactory(); } conf.UseEfCoreDirectSqlCommand(context, fac); conf.UseEfCoreDirectSqlQuery(context, fac); }
/// <summary> /// Use Direct SQL commands aspect implementation based on EntityFramework Core /// </summary> /// <param name="conf">Channel configuration</param> /// <param name="context">Lazy disposable wrapper around DbContext</param> public static void UseEfCoreDirectSqlCommand(this ChannelBinding <CommandChannel <Tecture.Aspects.DirectSql.DirectSql.Command> > conf, ILazyDisposable <DbContext> context, InterpolatorFactory fac = null) { if (fac == null) { fac = new InterpolatorFactory(); } var fe = new EFCore_DirectSql_CommandAspect(context, conf.Channel, fac); conf.ForCommand(fe); }
public void Build(DateTime originDate, double[] strikes, DateTime[] expiries, double[][] vols) { OriginDate = originDate; Strikes = strikes; Expiries = expiries; Volatilities = vols; ExpiriesDouble = Expiries.Select(t => TimeBasis.CalculateYearFraction(originDate, t)).ToArray(); _interpolators = vols.Select((v, ix) => InterpolatorFactory.GetInterpolator(Strikes, v, StrikeInterpolatorType)).ToArray(); }
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 void Build(DateTime originDate, double[][] strikes, DateTime[] expiries, double[][] vols, Func <double, double> forwardCurve) { OriginDate = originDate; Expiries = expiries; ExpiriesDouble = Expiries.Select(t => TimeBasis.CalculateYearFraction(originDate, t)).ToArray(); if (Expiries.Length != strikes.Length) { throw new InvalidOperationException("Expiries and first dimension of Strikes must of same length"); } if (Expiries.Length != vols.Length) { throw new InvalidOperationException("Expiries and first dimension of Vols must of same length"); } Alphas = new double[Expiries.Length]; Betas = new double[Expiries.Length]; Nus = new double[Expiries.Length]; Rhos = new double[Expiries.Length]; for (var i = 0; i < expiries.Length; i++) { var vs = vols[i]; var ks = strikes[i]; var t = ExpiriesDouble[i]; var fwd = forwardCurve(t); Betas[i] = 1.0; Func <double[], double[]> errorFunc = (x => { var err = ks.Select((k, ix) => vs[ix] - SABR.CalcImpVol_Beta1(fwd, k, t, x[0], x[1], x[2])); return(err.ToArray()); }); var n2Sol = new Math.Solvers.GaussNewton { ObjectiveFunction = errorFunc, InitialGuess = new double[] { vs.Average(), 0.1, 0.1 }, Tollerance = 1e-8, JacobianBump = 0.0000001 }; var paramArr = n2Sol.Solve(); Alphas[i] = paramArr[0]; Rhos[i] = paramArr[1]; Nus[i] = paramArr[2]; } _alphaInterp = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Alphas, TimeInterpolatorType); _betaInterp = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Betas, TimeInterpolatorType); _rhoInterp = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Rhos, TimeInterpolatorType); _nuInterp = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Nus, TimeInterpolatorType); }
public void CanInterpolateFact() { var xs = new double[] { 0.1, 0.25, 0.5, 0.75, 0.9 }; var ys = new double[] { 0.32, 0.32, 0.34, 0.36, 0.38 }; var interp = InterpolatorFactory.GetInterpolator(xs, ys, Interpolator1DType.GaussianKernel); //test pillar values are returned for (var i = 0; i < xs.Length; i++) { Assert.Equal(ys[i], interp.Interpolate(xs[i]), 10); } }
public static IInterpolator1D GenerateCDF(this IVolSurface surface, int numSamples, DateTime expiry, double fwd, bool returnInverse = false) { var deltaKLow = 0.0000001; var deltaKHi = 0.9999999; var kStepD = (deltaKHi - deltaKLow) / (numSamples + 3); var deltaKBump = deltaKLow / 10; var t = surface.OriginDate.CalculateYearFraction(expiry, DayCountBasis.Act365F); var x = new double[numSamples + 2]; var y = new double[numSamples + 2]; for (var i = 0; i < x.Length; i++) { var deltaKNew = deltaKLow + i * kStepD; var mStrike = deltaKNew - deltaKBump / 2; var pStrike = deltaKNew + deltaKBump / 2; var mStrikeVol = surface.GetVolForDeltaStrike(mStrike, t, fwd); var mk = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -mStrike, 0, t, mStrikeVol); var pStrikeVol = surface.GetVolForDeltaStrike(pStrike, t, fwd); var pk = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -pStrike, 0, t, pStrikeVol); if (i == 0) { x[0] = mk / 2.0; y[0] = 0; continue; } if (i == x.Length - 1) { x[i] = pk * 2; y[i] = 1; continue; } var dkAbs = (pk - mk); var pPut = BlackFunctions.BlackPV(fwd, pk, 0, t, pStrikeVol, OptionType.P); var mPut = BlackFunctions.BlackPV(fwd, mk, 0, t, mStrikeVol, OptionType.P); var digital = (pPut - mPut) / dkAbs; y[i] = digital; x[i] = (mk + pk) / 2.0; } return(returnInverse ? InterpolatorFactory.GetInterpolator(y, x, Interpolator1DType.LinearFlatExtrap) : InterpolatorFactory.GetInterpolator(x, y, Interpolator1DType.LinearFlatExtrap)); }
public static IInterpolator1D GeneratePDF(this IVolSurface surface, int numSamples, DateTime expiry, double fwd) { var deltaK = fwd * 0.0001; var t = surface.OriginDate.CalculateYearFraction(expiry, DayCountBasis.Act365F); var lowStrikeVol = surface.GetVolForDeltaStrike(0.0001, t, fwd); var lowStrike = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -0.0001, 0, t, lowStrikeVol); var hiStrikeVol = surface.GetVolForDeltaStrike(0.9999, t, fwd); var hiStrike = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -0.9999, 0, t, hiStrikeVol); var x = new double[numSamples + 2]; var y = new double[numSamples + 2]; var k = lowStrike; var kStep = (hiStrike - lowStrike) / numSamples; for (var i = 0; i < x.Length; i++) { if (i == 0) { x[0] = lowStrike / 2.0; y[0] = 0; continue; } if (i == x.Length - 1) { x[i] = k * 2; y[i] = 0; continue; } var volLow = surface.GetVolForAbsoluteStrike(k - deltaK, t, fwd); var callLow = BlackFunctions.BlackPV(fwd, k - deltaK, 0, t, volLow, OptionType.C); var volMid = surface.GetVolForAbsoluteStrike(k, t, fwd); var callMid = BlackFunctions.BlackPV(fwd, k, 0, t, volMid, OptionType.C); var volHi = surface.GetVolForAbsoluteStrike(k + deltaK, t, fwd); var callHi = BlackFunctions.BlackPV(fwd, k + deltaK, 0, t, volHi, OptionType.C); var digitalLo = (callLow - callMid) / deltaK; var digitalHi = (callMid - callHi) / deltaK; y[i] = (digitalLo - digitalHi) / deltaK; x[i] = k; k += kStep; } var firstPass = InterpolatorFactory.GetInterpolator(x, y, Interpolator1DType.LinearFlatExtrap); var totalY = ((IIntegrableInterpolator)firstPass).DefiniteIntegral(x.First(), x.Last()); y = y.Select(v => v / totalY).ToArray(); return(InterpolatorFactory.GetInterpolator(x, y, Interpolator1DType.LinearFlatExtrap)); }
private double GetAbsStrikeForDelta(double fwd, double deltaStrike, double maturity) { var cp = deltaStrike < 0 ? OptionType.Put : OptionType.Call; Func <double, double> testFunc = (absK => { var interpForStrike = InterpolatorFactory.GetInterpolator(ExpiriesDouble, ExpiriesDouble.Select(e => GetVolForAbsoluteStrike(absK, e, fwd)).ToArray(), TimeInterpolatorType); var vol2 = interpForStrike.Interpolate(maturity); var deltaK = BlackFunctions.BlackDelta(fwd, absK, 0, maturity, vol2, cp); return(deltaK - deltaStrike); }); var solvedStrike = Math.Solvers.Brent.BrentsMethodSolve(testFunc, 0.000000001, 50 * fwd, 1e-8); return(solvedStrike); }
public double GetVolForDeltaStrike(double deltaStrike, double maturity, double forward) { if (deltaStrike > 1.0 || deltaStrike < -1.0) { throw new ArgumentOutOfRangeException($"Delta strike must be in range -1.0 < x < 1.0 - value was {deltaStrike}"); } var key = $"{deltaStrike:f6}~{maturity:f3}~{forward:f6}"; if (_allowCaching && _deltaVolCache.TryGetValue(key, out var vol)) { return(vol); } if (StrikeType == StrikeType.ForwardDelta) { var interpForStrike = InterpolatorFactory.GetInterpolator(ExpiriesDouble, _interpolators.Select(x => x.Interpolate(deltaStrike)).ToArray(), TimeInterpolatorType); vol = interpForStrike.Interpolate(maturity); } else { var fwd = forward; var cp = deltaStrike < 0 ? OptionType.Put : OptionType.Call; Func <double, double> testFunc = (absK => { var interpForStrike = InterpolatorFactory.GetInterpolator(ExpiriesDouble, _interpolators.Select(x => x.Interpolate(absK)).ToArray(), TimeInterpolatorType); var vol2 = interpForStrike.Interpolate(maturity); var deltaK = BlackFunctions.BlackDelta(fwd, absK, 0, maturity, vol2, cp); return(deltaK - Abs(deltaStrike)); }); var solvedStrike = Math.Solvers.Brent.BrentsMethodSolve(testFunc, 0.000000001, 10 * fwd, 1e-8); var interpForSolvedStrike = InterpolatorFactory.GetInterpolator(ExpiriesDouble, _interpolators.Select(x => x.Interpolate(solvedStrike)).ToArray(), TimeInterpolatorType); vol = interpForSolvedStrike.Interpolate(maturity); } if (_allowCaching) { _deltaVolCache[key] = vol; } return(vol); }
private void Initialize() { var pillarsAsDoubles = _pillarDates.Select(x => x.ToOADate()).ToArray(); switch (_curveType) { case SparsePriceCurveType.Coal: _interpA = InterpolatorFactory.GetInterpolator(pillarsAsDoubles, _prices, Interpolator1DType.LinearFlatExtrap); var allDates = _pillarDates.First().CalendarDaysInPeriod(_pillarDates.Last()); var monthlyDates = allDates.Select(x => x.NthLastSpecificWeekDay(DayOfWeek.Friday, 1)).Distinct(); var monthlyPillars = monthlyDates.Select(x => x.ToOADate()).ToArray(); var monthlyPrices = _interpA.Many(monthlyPillars).ToArray(); _interpB = InterpolatorFactory.GetInterpolator(monthlyPillars, monthlyPrices, Interpolator1DType.NextValue); break; } }
public void CanInterpolateFact() { var xs = new double[] { 0.1, 0.25, 0.5, 0.75, 0.9 }; var ys = new double[] { 0.32, 0.32, 0.34, 0.36, 0.38 }; var interp = InterpolatorFactory.GetInterpolator(xs, ys, Interpolator1DType.GaussianKernel); //test pillar values are returned for (var i = 0; i < xs.Length; i++) { Assert.Equal(ys[i], interp.Interpolate(xs[i]), 10); } var gk = new GaussianKernelInterpolator(); Assert.Throws <NotImplementedException>(() => interp.Bump(0, 0)); Assert.Throws <NotImplementedException>(() => interp.UpdateY(0, 0)); Assert.Throws <NotImplementedException>(() => interp.Sensitivity(0)); }
public void Finish(FeatureCollection collection) { if (!_timesteps.IsComplete) { return; } //drifts and vols... _drifts = new double[_timesteps.TimeStepCount]; _lvInterps = new IInterpolator1D[_timesteps.TimeStepCount - 1]; var strikes = new double[_timesteps.TimeStepCount][]; for (var t = 0; t < strikes.Length; t++) { strikes[t] = new double[98]; var fwd = _forwardCurve(_timesteps.Times[t]); var atmVol = _surface.GetVolForDeltaStrike(fwd, _timesteps.Times[t], fwd); for (var k = 0; k < strikes[t].Length; k++) { var deltaK = -(0.01 + 0.01 * k); strikes[t][k] = Options.BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, deltaK, 0, _timesteps.Times[t], atmVol); } } var lvSurface = Options.LocalVol.ComputeLocalVarianceOnGrid(_surface, strikes, _timesteps.Times, _forwardCurve); for (var t = 0; t < _lvInterps.Length; t++) { _lvInterps[t] = InterpolatorFactory.GetInterpolator(strikes[t], lvSurface[t], t == 0 ? Interpolator1DType.DummyPoint : Interpolator1DType.LinearFlatExtrap); } var prevSpot = _forwardCurve(0); for (var t = 1; t < _drifts.Length; t++) { var spot = _forwardCurve(_timesteps.Times[t]); _drifts[t] = System.Math.Log(spot / prevSpot) / _timesteps.TimeSteps[t]; prevSpot = spot; } _isComplete = true; }
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 static IInterpolator1D GenerateCDF(this IInterpolator1D smile, int numSamples, double t, double fwd) { var deltaK = fwd * 0.0001; var atmVol = smile.Interpolate(fwd); var lowStrike = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -0.0001, 0, t, atmVol); var hiStrike = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -0.9999, 0, t, atmVol); var x = new double[numSamples + 2]; var y = new double[numSamples + 2]; var k = lowStrike; var kStep = (hiStrike - lowStrike) / numSamples; for (var i = 0; i < x.Length; i++) { if (i == 0) { x[0] = k / 2.0; y[0] = 0; continue; } if (i == x.Length - 1) { x[i] = k * 2; y[i] = 1; continue; } var volLow = smile.Interpolate(k - deltaK / 2.0); var putLow = BlackFunctions.BlackPV(fwd, k - deltaK / 2.0, 0, t, volLow, OptionType.P); var volHi = smile.Interpolate(k + deltaK / 2.0); var putHi = BlackFunctions.BlackPV(fwd, k + deltaK / 2.0, 0, t, volHi, OptionType.P); var digital = (putHi - putLow) / deltaK; y[i] = digital; x[i] = k; k += kStep; } return(InterpolatorFactory.GetInterpolator(x, y, Interpolator1DType.Linear)); }
public static object Create1dInterpolatorSafe( [ExcelArgument(Description = "Object name")] string ObjectName, [ExcelArgument(Description = "Array of X values")] object[] X, [ExcelArgument(Description = "Array of Y values")] object[] Y, [ExcelArgument(Description = "Type of interpolator, e.g. Linear")] string InterpolatorType) { return(ExcelHelper.Execute(_logger, () => { var interpType = InterpolatorType.OptionalExcel <string>("Linear"); if (!Enum.TryParse(interpType, out Interpolator1DType iType)) { return $"Could not parse 1d interpolator type - {interpType}"; } if (X.Length != Y.Length) { throw new Exception("Input vectors must be same length"); } var xList = new List <double>(); var yList = new List <double>(); for (var i = 0; i < X.Length; i++) { if (X[i] is double && Y[i] is double) { xList.Add((double)X[i]); yList.Add((double)Y[i]); } } var iObj = InterpolatorFactory.GetInterpolator(xList.ToArray(), yList.ToArray(), iType); var cache = ContainerStores.GetObjectCache <IInterpolator1D>(); cache.PutObject(ObjectName, new SessionItem <IInterpolator1D> { Name = ObjectName, Value = iObj }); return ObjectName + '¬' + cache.GetObject(ObjectName).Version; })); }
public static object Create1dInterpolator( [ExcelArgument(Description = "Object name")] string ObjectName, [ExcelArgument(Description = "Array of X values")] double[] X, [ExcelArgument(Description = "Array of Y values")] double[] Y, [ExcelArgument(Description = "Type of interpolator, e.g. Linear")] string InterpolatorType) { return(ExcelHelper.Execute(_logger, () => { var interpType = InterpolatorType.OptionalExcel <string>("Linear"); if (!Enum.TryParse(interpType, out Interpolator1DType iType)) { return $"Could not parse 1d interpolator type - {interpType}"; } var iObj = InterpolatorFactory.GetInterpolator(X, Y, iType); var cache = ContainerStores.GetObjectCache <IInterpolator1D>(); cache.PutObject(ObjectName, new SessionItem <IInterpolator1D> { Name = ObjectName, Value = iObj }); return ObjectName + '¬' + cache.GetObject(ObjectName).Version; })); }
public double Dvdk(double strike, DateTime expiry, double fwd) { if (StrikeType == StrikeType.ForwardDelta) { var t = TimeBasis.CalculateYearFraction(OriginDate, expiry); var pillarIx = Array.BinarySearch(Expiries, expiry); var interpForMaturity = pillarIx > 0 ? _interpolators[pillarIx] : InterpolatorFactory.GetInterpolator(Strikes, Strikes.Select(k => GetVolForDeltaStrike(k, expiry, fwd)).ToArray(), StrikeInterpolatorType); var deltaK = GetDeltaStrikeForAbs(fwd, strike, t); var vol = GetVolForAbsoluteStrike(strike, expiry, fwd); var gamma = BlackFunctions.BlackGamma(fwd, strike, 0.0, t, vol); return(interpForMaturity.FirstDerivative(deltaK) * gamma); } else { var interpForMaturity = InterpolatorFactory.GetInterpolator(Strikes, Strikes.Select(k => GetVolForAbsoluteStrike(k, expiry, fwd)).ToArray(), StrikeInterpolatorType); return(interpForMaturity.FirstDerivative(strike)); } }
public static IInterpolator1D GeneratePremiumInterpolator(this IVolSurface surface, int numSamples, double t, double fwd, OptionType cp) { var lowStrikeVol = surface.GetVolForDeltaStrike(0.001, t, fwd); var lowStrike = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -0.001, 0, t, lowStrikeVol); var hiStrikeVol = surface.GetVolForDeltaStrike(0.999, t, fwd); var hiStrike = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -0.999, 0, t, hiStrikeVol); var x = new double[numSamples + 2]; var y = new double[numSamples + 2]; var k = lowStrike; var kStep = (hiStrike - lowStrike) / (numSamples + 1.0); var vol = surface.GetVolForAbsoluteStrike(k / 10, t, fwd); var call = BlackFunctions.BlackPV(fwd, k / 10, 0, t, vol, cp); y[0] = call; x[0] = k / 10; for (var i = 0; i < x.Length - 1; i++) { vol = surface.GetVolForAbsoluteStrike(k, t, fwd); call = BlackFunctions.BlackPV(fwd, k, 0, t, vol, cp); y[i + 1] = call; x[i + 1] = k; k += kStep; } vol = surface.GetVolForAbsoluteStrike(k * 10, t, fwd); call = BlackFunctions.BlackPV(fwd, k * 10, 0, t, vol, cp); y[x.Length - 1] = call; x[x.Length - 1] = k * 10; return(InterpolatorFactory.GetInterpolator(x, y, Interpolator1DType.MonotoneCubicSpline)); }
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 static IInterpolator1D GenerateCompositeSmileB(this IVolSurface surface, IVolSurface fxSurface, int numSamples, DateTime expiry, double fwdAsset, double fwdFx, double correlation, bool strikesInDeltaSpace = false) { var t = surface.OriginDate.CalculateYearFraction(expiry, DayCountBasis.Act365F); var fxInv = new InverseFxSurface("fxInv", fxSurface as IATMVolSurface, null); var atmFx = fxSurface.GetVolForDeltaStrike(0.5, t, fwdFx); var atmA = surface.GetVolForDeltaStrike(0.5, t, fwdAsset); var compoFwd = fwdAsset * fwdFx; var atmCompo = Sqrt(atmFx * atmFx + atmA * atmA + 2.0 * correlation * atmA * atmFx); var lowK = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(compoFwd, -0.01, 0, t, atmCompo); var hiK = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(compoFwd, -0.99, 0, t, atmCompo); //var cdfInvFx = fxSurface.GenerateCDF2(numSamples * 10, expiry, fwdFx, true); //var cdfInvAsset = surface.GenerateCDF2(numSamples * 10, expiry, fwdAsset, true); //var yFx = new Func<double, double>(z => cdfInvFx.Interpolate(Statistics.NormSDist(z))); //var yAsset = new Func<double, double>(z => cdfInvAsset.Interpolate(Statistics.NormSDist(z))); var fxCDFCache = new Dictionary <double, double>(); var assetCDFCache = new Dictionary <double, double>(); var yFx = new Func <double, double>(z => { if (fxCDFCache.TryGetValue(z, out var K)) { return(K); } K = fxInv.InverseCDF(expiry, 1.0 / fwdFx, Statistics.NormSDist(z)); fxCDFCache.Add(z, K); return(K); }); var yAsset = new Func <double, double>(z => { if (assetCDFCache.TryGetValue(z, out var K)) { return(K); } K = surface.InverseCDF(expiry, fwdAsset, Statistics.NormSDist(z)); assetCDFCache.Add(z, K); return(K); }); //var fxCDFCache = new Dictionary<double, double>(); //var assetCDFCache = new Dictionary<double, double>(); //var putFx = fxInv.GeneratePremiumInterpolator(numSamples * 10, expiry, 1.0/fwdFx, OptionType.P); //var putAsset = surface.GeneratePremiumInterpolator(numSamples * 10, expiry, fwdAsset, OptionType.P); //var yFx = new Func<double, double>(z => //{ // if (fxCDFCache.TryGetValue(z, out var K)) return K; // K = InverseCDF(putFx, t, 1.0/fwdFx, Statistics.NormSDist(z)); // fxCDFCache.Add(z, K); // return K; //}); //var yAsset = new Func<double, double>(z => //{ // if (assetCDFCache.TryGetValue(z, out var K)) return K; // K = InverseCDF(putAsset, t, fwdAsset, Statistics.NormSDist(z)); // var kl = assetCDFCache.Keys.ToList(); // var closerIx = kl.BinarySearch(z); // var keyIx = ~closerIx; // if (closerIx < 0 && z < 0 && kl.Count > keyIx) // { // if (assetCDFCache[kl[keyIx]] < K) // K = assetCDFCache[kl[keyIx]]; // } // assetCDFCache.Add(z, K); // return K; //}); var payoff = new Func <double, double, double, double>((z1, z2, kQ) => Max(kQ * yFx(z2) - yAsset(z1), 0)); var integrand = new Func <double, double, double, double>((z1, z2, kQ) => payoff(z1, z2, kQ) * BivariateNormal.PDF(z1, z2, -correlation)); var kStep = (hiK - lowK) / numSamples; var ks = Enumerable.Range(0, numSamples).Select(kk => lowK + kk * kStep).ToArray(); var premiums = new double[ks.Length]; var vols = new double[ks.Length]; for (var i = 0; i < ks.Length; i++) { var ik = new Func <double, double, double>((z1, z2) => integrand(z1, z2, ks[i])); var pk = Integration.TwoDimensionalGaussLegendre(ik, -5, 5, -5, 5, 16); //var pk = Integration.TwoDimensionalSimpsons(ik, -5, 5, -5, 5, 100); pk *= fwdFx; var volK = BlackFunctions.BlackImpliedVol(compoFwd, ks[i], 0.0, t, pk, OptionType.P); vols[i] = volK; premiums[i] = pk; } if (strikesInDeltaSpace) { ks = ks.Select((ak, ix) => - BlackFunctions.BlackDelta(compoFwd, ak, 0.0, t, vols[ix], OptionType.P)).ToArray(); } return(InterpolatorFactory.GetInterpolator(ks, vols, Interpolator1DType.CubicSpline)); }
private void UpdateInterpolator() => _interp = InterpolatorFactory.GetInterpolator(_strikes, _currentGuess, _interpType);
/// <summary> /// Use Direct SQL query aspect implementation based on EntityFramework Core /// </summary> /// <param name="conf">Channel configuration</param> /// <param name="context">Lazy disposable wrapper around DbContext</param> public static void UseEfCoreDirectSqlQuery(this ChannelBinding <QueryChannel <Tecture.Aspects.DirectSql.DirectSql.Query> > conf, ILazyDisposable <DbContext> context, InterpolatorFactory fac = null) { if (fac == null) { fac = new InterpolatorFactory(); } conf.ForQuery(new EFCore_DirectSql_QueryAspect(context, conf.Channel, fac)); }
public static Dictionary <DateTime, IInterpolator1D> ToDeltaSmiles(this List <ListedOptionSettlementRecord> optionSettlements, Dictionary <string, double> futuresPrices, SmileOrderOfPrecedence orderOfP = SmileOrderOfPrecedence.UseOTM) { var output = new Dictionary <DateTime, IInterpolator1D>(); var byExpiry = optionSettlements.GroupBy(r => r.ExpiryDate).OrderBy(o => o.Key); foreach (var expGroup in byExpiry) { var expiry = expGroup.Key; if (expGroup.Select(x => x.UnderlyingFuturesCode).Distinct().Count() != 1) { throw new Exception($"Inconsistent underlying contracts for expiry {expiry}"); } if (expGroup.Select(x => x.ValDate).Distinct().Count() != 1) { throw new Exception($"Inconsistent value dates for expiry {expiry}"); } var t = expGroup.First().ValDate.CalculateYearFraction(expiry, DayCountBasis.ACT365F); var futCode = expGroup.First().UnderlyingFuturesCode; if (!futuresPrices.TryGetValue(futCode, out var fut)) { throw new Exception($"No future price found for contract {futCode}"); } var filtered = new List <SmilePoint>(); var byStrike = expGroup.GroupBy(e => e.Strike).OrderBy(o => o.Key); foreach (var strikeGrp in byStrike) { var k = strikeGrp.Key; if (strikeGrp.Count() > 2) { throw new Exception($"Did not expect more than two options at strike {k}"); } switch (orderOfP) { case SmileOrderOfPrecedence.Average: { var v = strikeGrp.Average(s => s.ImpliedVol); filtered.Add( new SmilePoint { Strike = -BlackFunctions.BlackDelta(fut, k, 0.0, t, v, OptionType.P), ImpliedVol = v }); break; } case SmileOrderOfPrecedence.UseOTM: { ListedOptionSettlementRecord r; if (fut > k) { r = strikeGrp.Where(sg => sg.CallPut == OptionType.P).SingleOrDefault(); } else { r = strikeGrp.Where(sg => sg.CallPut == OptionType.C).SingleOrDefault(); } if (r != null && r.ImpliedVol > 1e-8) { filtered.Add( new SmilePoint { Strike = -BlackFunctions.BlackDelta(fut, k, 0.0, t, r.ImpliedVol, OptionType.P), ImpliedVol = r.ImpliedVol }); } break; } } } //now we have filtered to a single vol per-strike... if (filtered.Any()) { output[expiry] = InterpolatorFactory.GetInterpolator(filtered.Select(f => f.Strike).ToArray(), filtered.Select(f => f.ImpliedVol).ToArray(), Interpolator1DType.CubicSpline); } } return(output); }
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); }
private void Initialize() { var pillarsAsDoubles = PillarDates.Select(x => x.ToOADate()).ToArray(); _interp = InterpolatorFactory.GetInterpolator(pillarsAsDoubles, Contangos, Interpolator1DType.Linear); }
public EFCore_DirectSql_CommandAspect(ILazyDisposable <DbContext> context, Type channel, InterpolatorFactory fac) : base(new EfCoreStokeRuntime(context, channel, fac)) { Context = context; }
public HazzardCurve(TO_HazzardCurve transportObject) : this(transportObject.OriginDate, transportObject.Basis, InterpolatorFactory.GetInterpolator(transportObject.HazzardCurve)) { if (transportObject.ConstantPD.HasValue) { ConstantPD = transportObject.ConstantPD.Value; } }
public EFCore_DirectSql_QueryFeature(ILazyDisposable <DbContext> context, Type channel, InterpolatorFactory fac) : base(new EfCoreStokeRuntime(context, channel, fac)) { _dbContext = context; }