Пример #1
0
        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);
        }
Пример #2
0
        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);
            }));
        }
Пример #3
0
        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);
        }
Пример #4
0
        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]);
        }
Пример #5
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]));
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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);
        }
Пример #9
0
        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);
            }));
        }