public static RiskyFlySurface ToRiskyFlySurfaceStepFlat(this Dictionary <DateTime, IInterpolator1D> smiles, DateTime valDate, IPriceCurve priceCurve, List <DateTime> allExpiries, ICurrencyProvider currencyProvider) { var wingDeltas = new[] { 0.25, 0.1 }; var expiries = smiles.Keys.ToArray(); var expiriesDouble = expiries.Select(e => e.ToOADate()).ToArray(); var atmVols = smiles.Select(x => x.Value.Interpolate(0.5)).ToArray(); var riskies = smiles.Select(x => wingDeltas.Select(w => x.Value.Interpolate(1.0 - w) - x.Value.Interpolate(w)) .ToArray()) .ToArray(); var flies = smiles.Select((x, ix) => wingDeltas.Select(w => (x.Value.Interpolate(1.0 - w) + x.Value.Interpolate(w)) / 2.0 - atmVols[ix]) .ToArray()) .ToArray(); SmoothSmiles(wingDeltas, smiles, ref riskies, ref flies); var fwds = allExpiries.Select(x => priceCurve.GetPriceForDate(x)).ToArray(); var atmInterp = InterpolatorFactory.GetInterpolator(expiriesDouble, atmVols, Interpolator1DType.LinearInVariance); var riskyInterps = wingDeltas.Select((w, ixw) => InterpolatorFactory.GetInterpolator(expiriesDouble, riskies.Select(r => r[ixw]).ToArray(), Interpolator1DType.LinearFlatExtrap)).ToArray(); var flyInterps = wingDeltas.Select((w, ixw) => InterpolatorFactory.GetInterpolator(expiriesDouble, flies.Select(f => f[ixw]).ToArray(), Interpolator1DType.LinearFlatExtrap)).ToArray(); var expandedRiskies = allExpiries.Select(e => wingDeltas.Select((w, ixw) => riskyInterps[ixw].Interpolate(e.ToOADate())).ToArray()).ToArray(); var expandedFlies = allExpiries.Select(e => wingDeltas.Select((w, ixw) => flyInterps[ixw].Interpolate(e.ToOADate())).ToArray()).ToArray(); var expandedAtms = allExpiries.Select(e => atmInterp.Interpolate(e.ToOADate())).ToArray(); var expandedFwds = allExpiries.Select(e => priceCurve.GetPriceForDate(e)).ToArray(); var o = new RiskyFlySurface(valDate, expandedAtms, allExpiries.ToArray(), wingDeltas, expandedRiskies, expandedFlies, expandedFwds, WingQuoteType.Arithmatic, AtmVolType.ZeroDeltaStraddle, Interpolator1DType.CubicSpline, Interpolator1DType.NextValue) { Currency = currencyProvider.GetCurrency("USD") }; return(o); }
public static object SurfaceFromCube( [ExcelArgument(Description = "Output Surface name")] string SurfaceName, [ExcelArgument(Description = "Cube name")] string CubeName, [ExcelArgument(Description = "Build date")] DateTime BuildDate, [ExcelArgument(Description = "Currency")] string Currency, [ExcelArgument(Description = "Asset Id")] string AssetId, [ExcelArgument(Description = "Stike Interpolation - default GaussianKernel")] object StrikeInterpolation, [ExcelArgument(Description = "Time Interpolation - default LinearInVariance")] object TimeInterpolation) { return(ExcelHelper.Execute(_logger, () => { var cube = ContainerStores.GetObjectCache <ICube>().GetObjectOrThrow(CubeName, $"Cube {CubeName} not found"); var strikeInterpType = StrikeInterpolation.OptionalExcel("GaussianKernel"); var timeInterpType = TimeInterpolation.OptionalExcel("LinearInVariance"); if (!Enum.TryParse(strikeInterpType, out Interpolator1DType siType)) { return $"Could not parse strike interpolator type - {strikeInterpType}"; } if (!Enum.TryParse(timeInterpType, out Interpolator1DType tiType)) { return $"Could not parse time interpolator type - {timeInterpType}"; } var rrbf = RiskyFlySurface.FromCube(cube.Value, BuildDate, siType, tiType); rrbf.AssetId = AssetId; rrbf.Name = AssetId; if (!string.IsNullOrWhiteSpace(Currency)) { rrbf.Currency = ContainerStores.CurrencyProvider.GetCurrency(Currency); } return ExcelHelper.PushToCache <IVolSurface>(rrbf, SurfaceName); })); }
public void SABRSurfaceRRBF() { //flat surface var origin = new DateTime(2017, 02, 07); var expiry = origin.AddYears(1); var t = (expiry - origin).TotalDays / 365.0; var fwd = 1.5; var vol = 0.32; var rr = new[] { new[] { 0.02, 0.03 } }; var bf = new[] { new[] { 0.005, 0.007 } }; Func <double, double> fwdCurve = (tt => { return(fwd); }); var surface = new SabrVolSurface(origin, new[] { vol }, new[] { expiry }, new[] { 0.25, 0.1 }, rr, bf, new[] { 100.0 }, WingQuoteType.Arithmatic, AtmVolType.ZeroDeltaStraddle, Interpolator1DType.Linear); var gSurface = new RiskyFlySurface(origin, new[] { vol }, new[] { expiry }, new[] { 0.25, 0.1 }, rr, bf, new[] { 100.0 }, WingQuoteType.Arithmatic, AtmVolType.ZeroDeltaStraddle, Interpolator1DType.Linear, Interpolator1DType.Linear); var atmK = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, 0.5, 0.0, t, vol); Assert.Equal(vol, surface.GetVolForAbsoluteStrike(atmK, expiry, fwd), 2); var v25c = gSurface.GetVolForDeltaStrike(0.75, expiry, fwd); var v25p = gSurface.GetVolForDeltaStrike(0.25, expiry, fwd); var k25c = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, 0.25, 0.0, t, v25c); var k25p = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -0.25, 0.0, t, v25p); var t25c = surface.GetVolForAbsoluteStrike(k25c, expiry, fwd); var t25p = surface.GetVolForAbsoluteStrike(k25p, expiry, fwd); Assert.Equal(rr[0][0], t25c - t25p, 2); }
public void RiskyFlySimple() { //flat surface var origin = new DateTime(2017, 02, 07); var atms = new double[] { 0.3, 0.32, 0.34 }; var fwds = new double[] { 100, 102, 110 }; var maturities = new DateTime[] { new DateTime(2017, 04, 06), new DateTime(2017, 06, 07), new DateTime(2017, 08, 07) }; var wingDeltas = new[] { 0.1, 0.25 }; var riskies = new[] { new[] { 0.025, 0.015 }, new[] { 0.025, 0.015 }, new[] { 0.025, 0.015 } }; var flies = new[] { new[] { 0.0025, 0.0015 }, new[] { 0.0025, 0.0015 }, new[] { 0.0025, 0.0015 } }; var surface = new RiskyFlySurface( origin, atms, maturities, wingDeltas, riskies, flies, fwds, WingQuoteType.Simple, AtmVolType.ZeroDeltaStraddle, Interpolator1DType.Linear, Interpolator1DType.LinearInVariance); Assert.Equal(atms[1], surface.GetVolForDeltaStrike(0.5, maturities[1], fwds[1])); var cube = surface.ToCube(); Assert.Equal(fwds[0], cube.GetAllRows().First().Value); var recon = RiskyFlySurface.FromCube(cube, origin, Interpolator1DType.Linear, Interpolator1DType.LinearInVariance); Assert.Equal(surface.GetVolForDeltaStrike(0.5, maturities[1], fwds[1]), recon.GetVolForDeltaStrike(0.5, maturities[1], fwds[1])); var quotes = surface.DisplayQuotes(); Assert.Equal(maturities[0], (DateTime)quotes[1, 0]); }
public void RiskyFlySerialization() { var origin = new DateTime(2017, 02, 07); var atms = new double[] { 0.3, 0.32, 0.34 }; var fwds = new double[] { 100, 102, 110 }; var maturities = new DateTime[] { new DateTime(2017, 04, 06), new DateTime(2017, 06, 07), new DateTime(2017, 08, 07) }; var wingDeltas = new[] { 0.1, 0.25 }; var riskies = new[] { new[] { 0.025, 0.015 }, new[] { 0.025, 0.015 }, new[] { 0.025, 0.015 } }; var flies = new[] { new[] { 0.0025, 0.0015 }, new[] { 0.0025, 0.0015 }, new[] { 0.0025, 0.0015 } }; var surface = new RiskyFlySurface( origin, atms, maturities, wingDeltas, riskies, flies, fwds, WingQuoteType.Simple, AtmVolType.ZeroDeltaStraddle, Interpolator1DType.Linear, Interpolator1DType.LinearInVariance); Assert.Equal(atms[1], surface.GetVolForDeltaStrike(0.5, maturities[1], fwds[1])); var binSer = new BinarySerializer(); binSer.PrepareObjectGraph(surface); var span = binSer.SerializeObjectGraph(); var binDeser = new BinaryDeserializer(); var surface2 = (ObjectWithLists)binDeser.DeserializeObjectGraph(span); Assert.Equal(atms[1], surface.GetVolForDeltaStrike(0.5, maturities[1], fwds[1])); }
public static RiskyFlySurface ToATMSurface(this Dictionary <DateTime, IInterpolator1D> smiles, DateTime valDate, double[] fwds) { var wingDeltas = new[] { 0.25 }; var expiries = smiles.Keys.ToArray(); var atmVols = smiles.Select(x => x.Value.Interpolate(0.5)).ToArray(); var riskies = smiles.Select(x => new[] { 0.0 }).ToArray(); var flies = smiles.Select(x => new[] { 0.0 }).ToArray(); var o = new RiskyFlySurface(valDate, atmVols, expiries, wingDeltas, riskies, flies, fwds, WingQuoteType.Arithmatic, AtmVolType.ZeroDeltaStraddle, Interpolator1DType.Linear, Interpolator1DType.LinearInVariance); return(o); }
public static RiskyFlySurface ToRiskyFlySurface(this Dictionary <DateTime, IInterpolator1D> smiles, DateTime valDate, double[] fwds) { var wingDeltas = new[] { 0.25, 0.1 }; var expiries = smiles.Keys.ToArray(); var atmVols = smiles.Select(x => x.Value.Interpolate(0.5)).ToArray(); var riskies = smiles.Select(x => wingDeltas.Select(w => x.Value.Interpolate(1.0 - w) - x.Value.Interpolate(w)) .ToArray()) .ToArray(); var flies = smiles.Select((x, ix) => wingDeltas.Select(w => (x.Value.Interpolate(1.0 - w) + x.Value.Interpolate(w)) / 2.0 - atmVols[ix]) .ToArray()) .ToArray(); var o = new RiskyFlySurface(valDate, atmVols, expiries, wingDeltas, riskies, flies, fwds, WingQuoteType.Arithmatic, AtmVolType.ZeroDeltaStraddle, Interpolator1DType.CubicSpline, Interpolator1DType.LinearInVariance); return(o); }
public void CompositeSmimleFacts_LocalVol() { var origin = new DateTime(2017, 02, 07); var expiry = origin.AddMonths(2); var tExp = origin.CalculateYearFraction(expiry, DayCountBasis.Act365F); var fwdCurveAsset = new Func <double, double>(t => { return(100); }); var fwdCurveFx = new Func <double, double>(t => { return(15); }); var volAsset = 0.32; var volFx = 0.16; var correl = 0.25; var surfaceAsset = new RiskyFlySurface(origin, new[] { volAsset }, new[] { expiry }, new[] { 0.25, 0.1 }, new[] { new[] { 0.02, 0.03 } }, new[] { new[] { 0.005, 0.007 } }, new[] { 100.0 }, WingQuoteType.Arithmatic, AtmVolType.ZeroDeltaStraddle, Interpolator1DType.GaussianKernel, Interpolator1DType.Linear) { FlatDeltaSmileInExtreme = true }; var surfaceFx = new RiskyFlySurface(origin, new[] { volFx }, new[] { expiry }, new[] { 0.25, 0.1 }, new[] { new[] { 0.015, 0.025 } }, new[] { new[] { 0.005, 0.007 } }, new[] { 0.1 }, WingQuoteType.Arithmatic, AtmVolType.ZeroDeltaStraddle, Interpolator1DType.GaussianKernel, Interpolator1DType.Linear) { FlatDeltaSmileInExtreme = true }; //var surfaceAsset = new SabrVolSurface(origin, new[] { volAsset }, new[] { expiry }, new[] { 0.25, 0.1 }, new[] { new[] { 0.02, 0.03 } }, new[] { new[] { 0.005, 0.007 } }, new[] { 100.0 }, WingQuoteType.Arithmatic, AtmVolType.ZeroDeltaStraddle, Interpolator1DType.Linear); //var surfaceFx = new SabrVolSurface(origin, new[] { volFx }, new[] { expiry }, new[] { 0.25, 0.1 }, new[] { new[] { 0.015, 0.025 } }, new[] { new[] { 0.005, 0.007 } }, new[] { 0.1 }, WingQuoteType.Arithmatic, AtmVolType.ZeroDeltaStraddle, Interpolator1DType.Linear); //var surfaceAsset = new SVIVolSurface(origin, new[] { volAsset }, new[] { expiry }, new[] { 0.25, 0.1 }, new[] { new[] { 0.02, 0.03 } }, new[] { new[] { 0.005, 0.007 } }, new[] { 100.0 }, WingQuoteType.Arithmatic, AtmVolType.ZeroDeltaStraddle, Interpolator1DType.Linear); //var surfaceFx = new SVIVolSurface(origin, new[] { volFx }, new[] { expiry }, new[] { 0.25, 0.1 }, new[] { new[] { 0.015, 0.025 } }, new[] { new[] { 0.005, 0.007 } }, new[] { 0.1 }, WingQuoteType.Arithmatic, AtmVolType.ZeroDeltaStraddle, Interpolator1DType.Linear); var invFx = new InverseFxSurface("inv", surfaceFx, TestProviderHelper.CurrencyProvider); var surfaceCompo = surfaceAsset.GenerateCompositeSmile(invFx, 200, expiry, 100, 1.0 / 15, correl); //setup MC using var engine = new PathEngine(2.IntPow(IsCoverageOnly?5:15)); engine.AddPathProcess( new Qwack.Random.MersenneTwister.MersenneTwister64 { UseNormalInverse = true }); var correlMatrix = new double[][] { new double[] { 1.0, correl }, new double[] { correl, 1.0 }, }; engine.AddPathProcess(new Cholesky(correlMatrix)); var asset1 = new TurboSkewSingleAsset ( startDate: origin, expiryDate: expiry, volSurface: surfaceAsset, forwardCurve: fwdCurveAsset, nTimeSteps: 1, name: "Asset" ); var asset2 = new TurboSkewSingleAsset ( startDate: origin, expiryDate: expiry, volSurface: surfaceFx, forwardCurve: fwdCurveFx, nTimeSteps: 1, name: "USD/ZAR" ); engine.AddPathProcess(asset1); engine.AddPathProcess(asset2); var strike = 1500; var product = new EuropeanOption { AssetId = "Asset", CallPut = OptionType.C, ExpiryDate = expiry, PaymentCurrency = TestProviderHelper.CurrencyProvider["ZAR"], PaymentDate = expiry, Notional = 1.0, SpotLag = new Frequency("0b"), Strike = strike, FxConversionType = FxConversionType.ConvertThenAverage }; var productAsset = new EuropeanOption { AssetId = "Asset", CallPut = OptionType.C, ExpiryDate = expiry, PaymentCurrency = TestProviderHelper.CurrencyProvider["USD"], PaymentDate = expiry, Notional = 1.0, SpotLag = new Frequency("0b"), Strike = 100, FxConversionType = FxConversionType.None }; var productFx = new EuropeanOption { AssetId = "USD/ZAR", CallPut = OptionType.C, ExpiryDate = expiry, PaymentCurrency = TestProviderHelper.CurrencyProvider["ZAR"], PaymentDate = expiry, Notional = 1.0, SpotLag = new Frequency("0b"), Strike = 0.1, FxConversionType = FxConversionType.None }; var pathProduct = new AssetPathPayoff(product, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider, TestProviderHelper.CurrencyProvider["ZAR"]); var pathProductAsset = new AssetPathPayoff(productAsset, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider, TestProviderHelper.CurrencyProvider["ZAR"]); var pathProductFx = new AssetPathPayoff(productFx, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider, TestProviderHelper.CurrencyProvider["ZAR"]); engine.AddPathProcess(pathProduct); engine.AddPathProcess(pathProductAsset); engine.AddPathProcess(pathProductFx); engine.SetupFeatures(); engine.RunProcess(); var q = pathProduct.ResultsByPath; var qq = q.Average(); var productIv = BlackFunctions.BlackImpliedVol(1500, strike, 0.0, tExp, pathProduct.AverageResult, OptionType.C); var productAssetIv = BlackFunctions.BlackImpliedVol(100, 100, 0.0, tExp, pathProductAsset.AverageResult, OptionType.C); var productFxIv = BlackFunctions.BlackImpliedVol(10, 10, 0.0, tExp, pathProductFx.AverageResult, OptionType.C); Assert.True(Abs(productIv - surfaceCompo.Interpolate(strike)) < 0.01); }
public static object CreateRiskyFlyVolSurface( [ExcelArgument(Description = "Object name")] string ObjectName, [ExcelArgument(Description = "Asset Id")] string AssetId, [ExcelArgument(Description = "Origin date")] DateTime OriginDate, [ExcelArgument(Description = "Wing deltas")] double[] WingDeltas, [ExcelArgument(Description = "Expiries")] double[] Expiries, [ExcelArgument(Description = "ATM Volatilities")] double[] ATMVols, [ExcelArgument(Description = "Risk Reversal quotes")] double[,] Riskies, [ExcelArgument(Description = "Butterfly quotes")] double[,] Flies, [ExcelArgument(Description = "Forwards or price curve object")] object FwdsOrCurve, [ExcelArgument(Description = "ATM vol type - default zero-delta straddle")] object ATMType, [ExcelArgument(Description = "Wing quote type - Simple or Market")] object WingType, [ExcelArgument(Description = "Stike Interpolation - default GaussianKernel")] object StrikeInterpolation, [ExcelArgument(Description = "Time Interpolation - default LinearInVariance")] object TimeInterpolation, [ExcelArgument(Description = "Pillar labels (optional)")] object PillarLabels, [ExcelArgument(Description = "Currency - default USD")] object Currency, [ExcelArgument(Description = "Override spot lag - default none")] object SpotLag) { return(ExcelHelper.Execute(_logger, () => { var labels = (PillarLabels is ExcelMissing) ? null : ((object[, ])PillarLabels).ObjectRangeToVector <string>(); var ccyStr = Currency.OptionalExcel("USD"); ContainerStores.SessionContainer.GetService <ICalendarProvider>().Collection.TryGetCalendar(ccyStr, out var ccyCal); var atmType = ATMType.OptionalExcel("ZeroDeltaStraddle"); var wingType = WingType.OptionalExcel("Simple"); var strikeInterpType = StrikeInterpolation.OptionalExcel("GaussianKernel"); var timeInterpType = TimeInterpolation.OptionalExcel("LinearInVariance"); var expiries = ExcelHelper.ToDateTimeArray(Expiries); var rr = Riskies.SquareToJagged <double>(); var bf = Flies.SquareToJagged <double>(); if (!Enum.TryParse(wingType, out WingQuoteType wType)) { return $"Could not parse wing quote type - {wingType}"; } if (!Enum.TryParse(atmType, out AtmVolType aType)) { return $"Could not parse atm quote type - {atmType}"; } if (!Enum.TryParse(strikeInterpType, out Interpolator1DType siType)) { return $"Could not parse strike interpolator type - {strikeInterpType}"; } if (!Enum.TryParse(timeInterpType, out Interpolator1DType tiType)) { return $"Could not parse time interpolator type - {timeInterpType}"; } double[] fwds = null; if (FwdsOrCurve is double) { fwds = new double[] { (double)FwdsOrCurve }; } else if (FwdsOrCurve is string) { if (!ContainerStores.GetObjectCache <IPriceCurve>().TryGetObject(FwdsOrCurve as string, out var curve)) { return $"Could not find fwd curve with name - {FwdsOrCurve as string}"; } fwds = expiries.Select(e => curve.Value.GetPriceForDate(e)).ToArray(); } else { fwds = ((object[, ])FwdsOrCurve).ObjectRangeToVector <double>(); } var surface = new RiskyFlySurface(OriginDate, ATMVols, expiries, WingDeltas, rr, bf, fwds, wType, aType, siType, tiType, labels) { Currency = ContainerStores.CurrencyProvider[ccyStr], Name = AssetId ?? ObjectName, AssetId = AssetId ?? ObjectName, }; if (SpotLag != null && !(SpotLag is ExcelMissing)) { surface.OverrideSpotLag = new Frequency((string)SpotLag); } return ExcelHelper.PushToCache <IVolSurface>(surface, ObjectName); })); }