Ejemplo n.º 1
0
        public void LVMC_PathsGenerated()
        {
            var origin = DateTime.Now.Date;

            using var engine = new PathEngine(2.IntPow(IsCoverageOnly ? 6 : 12))
                  {
                      Parallelize = false
                  };

            engine.AddPathProcess(new Random.MersenneTwister.MersenneTwister64()
            {
                UseNormalInverse = true,
                UseAnthithetic   = true
            });

            var tenorsStr  = new[] { "1m", "2m", "3m", "6m" };
            var tenors     = tenorsStr.Select(x => new Frequency(x));
            var expiries   = tenors.Select(t => origin.AddPeriod(RollType.F, new Calendar(), t)).ToArray();
            var deltaKs    = new[] { 0.1, 0.25, 0.5, 0.75, 0.9 };
            var smileVols  = new[] { 0.32, 0.3, 0.29, 0.3, 0.32 };
            var vols       = Enumerable.Repeat(smileVols, expiries.Length).ToArray();
            var tExp       = (origin.AddMonths(6) - origin).TotalDays / 365.0;
            var volSurface = new GridVolSurface(origin, deltaKs, expiries, vols,
                                                StrikeType.ForwardDelta, Interpolator1DType.GaussianKernel,
                                                Interpolator1DType.LinearInVariance, DayCountBasis.Act365F);

            var fwdCurve = new Func <double, double>(t => { return(900 + 100 * t / tExp); });
            var asset    = new LVSingleAsset
                           (
                startDate: origin,
                expiryDate: origin.AddMonths(6),
                volSurface: volSurface,
                forwardCurve: fwdCurve,
                nTimeSteps: IsCoverageOnly ? 3 : 100,
                name: "TestAsset"
                           );

            engine.AddPathProcess(asset);
            var payoff  = new EuropeanPut("TestAsset", 900, origin.AddMonths(6));
            var payoff2 = new EuropeanCall("TestAsset", 0, origin.AddMonths(6));

            engine.AddPathProcess(payoff);
            engine.AddPathProcess(payoff2);
            engine.SetupFeatures();
            engine.RunProcess();

            var pv       = payoff.AverageResult;
            var blackVol = volSurface.GetVolForAbsoluteStrike(900, origin.AddMonths(6), fwdCurve(tExp));
            var blackPv  = BlackFunctions.BlackPV(fwdCurve(tExp), 900, 0, tExp, blackVol, OptionType.P);

            if (!IsCoverageOnly)
            {
                Assert.True(System.Math.Abs(blackPv / pv - 1.0) < 0.02);
                var fwd = payoff2.AverageResult;
                Assert.True(System.Math.Abs(fwdCurve(tExp) / fwd - 1.0) < 0.005);
            }
        }
Ejemplo n.º 2
0
        public void LVMC_PathsGenerated()
        {
            var origin = DateTime.Now.Date;
            var engine = new PathEngine(2.IntPow(17));

            //engine.AddPathProcess(new Random.MersenneTwister.MersenneTwister64()
            //{
            //    UseNormalInverse = true,
            //    UseAnthithetic = false
            //});
            engine.AddPathProcess(new Random.Sobol.SobolShiftedPathGenerator(new Random.Sobol.SobolDirectionNumbers(s_directionNumbers), 0)
            {
                UseNormalInverse = true
            });
            var tenorsStr = new[] { "1m", "2m", "3m", "6m", "9m", "1y" };
            var tenors    = tenorsStr.Select(x => new Frequency(x));
            var expiries  = tenors.Select(t => origin.AddPeriod(RollType.F, new Calendar(), t)).ToArray();
            var deltaKs   = new[] { -0.1, -0.25, -0.5, -0.75, -0.9 };
            var smileVols = new[] { 0.32, 0.3, 0.29, 0.3, 0.32 };
            var vols      = Enumerable.Repeat(smileVols, expiries.Length).ToArray();

            var volSurface = new GridVolSurface(origin, deltaKs, expiries, vols,
                                                Core.Basic.StrikeType.ForwardDelta, Interpolator1DType.LinearFlatExtrap,
                                                Interpolator1DType.LinearInVariance, DayCountBasis.Act365F);

            var fwdCurve = new Func <double, double>(t => { return(900 + 100 * t); });
            var asset    = new LVSingleAsset
                           (
                startDate: origin,
                expiryDate: origin.AddYears(1),
                volSurface: volSurface,
                forwardCurve: fwdCurve,
                nTimeSteps: 365,
                name: "TestAsset"
                           );

            engine.AddPathProcess(asset);
            var payoff  = new EuropeanPut("TestAsset", 900, origin.AddYears(1));
            var payoff2 = new EuropeanCall("TestAsset", 0, origin.AddYears(1));

            engine.AddPathProcess(payoff);
            engine.AddPathProcess(payoff2);
            engine.SetupFeatures();
            engine.RunProcess();
            var pv       = payoff.AverageResult;
            var blackVol = volSurface.GetVolForAbsoluteStrike(900, origin.AddYears(1), fwdCurve(1.0));
            var blackPv  = BlackFunctions.BlackPV(1000, 900, 0, 1, blackVol, OptionType.P);

            Assert.Equal(blackPv, pv, 0);
            var fwd = payoff2.AverageResult;

            Assert.True(System.Math.Abs(fwdCurve(1) / fwd - 1.0) < 0.001);
            //var output = new OutputPathsToImage(engine,2000,1000);
        }
Ejemplo n.º 3
0
 public static object CreateGridVolSurface(
     [ExcelArgument(Description = "Object name")] string ObjectName,
     [ExcelArgument(Description = "Origin date")] DateTime OriginDate,
     [ExcelArgument(Description = "Strikes")] double[] Strikes,
     [ExcelArgument(Description = "Expiries")] double[] Expiries,
     [ExcelArgument(Description = "Volatilities")] double[,] Volatilities,
     [ExcelArgument(Description = "Stike Type - default Absolute")] object StrikeType,
     [ExcelArgument(Description = "Stike Interpolation - default Linear")] object StrikeInterpolation,
     [ExcelArgument(Description = "Time Interpolation - default Linear")] object TimeInterpolation
     )
 {
     return(ExcelHelper.Execute(_logger, () =>
     {
         var stikeType = StrikeType.OptionalExcel <string>("Absolute");
         var expiries = ExcelHelper.ToDateTimeArray(Expiries);
         var surface = new GridVolSurface(OriginDate, Strikes, expiries, Volatilities.SquareToJagged());
         var cache = ContainerStores.GetObjectCache <GridVolSurface>();
         cache.PutObject(ObjectName, new SessionItem <GridVolSurface> {
             Name = ObjectName, Value = surface
         });
         return ObjectName + '¬' + cache.GetObject(ObjectName).Version;
     }));
 }
Ejemplo n.º 4
0
        public void LVMCDualPathsGenerated(double correlation)
        {
            var origin = DateTime.Now.Date;

            using var engine = new PathEngine(2.IntPow(IsCoverageOnly ? 6 : 8))
                  {
                      Parallelize = false
                  };

            engine.AddPathProcess(new Random.MersenneTwister.MersenneTwister64()
            {
                UseNormalInverse = true,
                UseAnthithetic   = false,
            });

            engine.IncrementDepth();

            var correlMatrix = new double[][]
            {
                new double[] { 1.0, correlation },
                new double[] { correlation, 1.0 },
            };

            engine.AddPathProcess(new Cholesky(correlMatrix));

            engine.IncrementDepth();

            var tenorsStr = new[] { "1m", "2m", "3m", "6m" };
            var tenors    = tenorsStr.Select(x => new Frequency(x));
            var expiries  = tenors.Select(t => origin.AddPeriod(RollType.F, new Calendar(), t)).ToArray();
            var deltaKs   = new[] { -0.1, -0.25, -0.5, -0.75, -0.9 };
            var smileVols = new[] { 0.32, 0.3, 0.29, 0.3, 0.32 };
            var vols      = Enumerable.Repeat(smileVols, expiries.Length).ToArray();

            var volSurface = new GridVolSurface(origin, deltaKs, expiries, vols,
                                                StrikeType.ForwardDelta, Interpolator1DType.GaussianKernel,
                                                Interpolator1DType.LinearInVariance, DayCountBasis.Act365F);

            var fwdCurve1 = new Func <double, double>(t => { return(1000); });
            var asset1    = new LVSingleAsset
                            (
                startDate: origin,
                expiryDate: origin.AddMonths(6),
                volSurface: volSurface,
                forwardCurve: fwdCurve1,
                nTimeSteps: IsCoverageOnly ? 3 : 100,
                name: "TestAsset1"
                            );
            var fwdCurve2 = new Func <double, double>(t => { return(1000); });
            var asset2    = new LVSingleAsset
                            (
                startDate: origin,
                expiryDate: origin.AddMonths(6),
                volSurface: volSurface,
                forwardCurve: fwdCurve2,
                nTimeSteps: IsCoverageOnly ? 3 : 100,
                name: "TestAsset2"
                            );

            engine.AddPathProcess(asset1);
            engine.AddPathProcess(asset2);

            engine.IncrementDepth();

            var correl = new Correlation("TestAsset1", "TestAsset2");

            engine.AddPathProcess(correl);


            engine.SetupFeatures();
            engine.RunProcess();

            var corr    = correl.AverageResult;
            var errCorr = correl.ResultStdError;

            if (!IsCoverageOnly)
            {
                Assert.Equal(correlation, corr, 1);
            }
        }
Ejemplo n.º 5
0
        private AssetFxMCModel GetSut()
        {
            var buildDate = DateTime.Parse("2018-10-04");
            var usd       = TestProviderHelper.CurrencyProvider["USD"];
            var zar       = TestProviderHelper.CurrencyProvider["ZAR"];

            TestProviderHelper.CalendarProvider.Collection.TryGetCalendar("NYC", out var usdCal);
            var pair = new FxPair()
            {
                Domestic = zar, Foreign = usd, PrimaryCalendar = usdCal, SpotLag = 2.Bd()
            };

            var dfCurve = new IrCurve(new[] { buildDate, buildDate.AddDays(1000) }, new[] { 0.0, 0.0 }, buildDate, "disco", Interpolator1DType.Linear, usd, "DISCO");

            var dates    = new[] { buildDate, buildDate.AddDays(32), buildDate.AddDays(60), buildDate.AddDays(90) };
            var times    = dates.Select(d => buildDate.CalculateYearFraction(d, DayCountBasis.Act365F)).ToArray();
            var vols     = new[] { 0.32, 0.30, 0.29, 0.28 };
            var comCurve = new PriceCurve(buildDate, dates, new[] { 100.0, 100.0, 100.0, 100.0 }, PriceCurveType.NYMEX, TestProviderHelper.CurrencyProvider)
            {
                Name    = "CL",
                AssetId = "CL"
            };
            var comSurface = new GridVolSurface(buildDate, new[] { 0.5 }, dates, vols.Select(x => new double[] { x }).ToArray(), StrikeType.ForwardDelta, Interpolator1DType.Linear, Interpolator1DType.LinearInVariance, DayCountBasis.Act365F)
            {
                AssetId = "CL"
            };
            var fxSurface = new ConstantVolSurface(buildDate, 0.16)
            {
                AssetId = "USD/ZAR"
            };
            var correlVector = new CorrelationTimeVector("CL", "USD/ZAR", _correls, times);
            var fModel       = new FundingModel(buildDate, new Dictionary <string, IrCurve> {
                { "DISCO", dfCurve }
            }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider);
            var fxM = new FxMatrix(TestProviderHelper.CurrencyProvider);

            fxM.Init(usd, buildDate, new Dictionary <Currency, double>()
            {
                { zar, 14.0 }
            }, new List <FxPair>()
            {
                pair
            }, new Dictionary <Currency, string> {
                { usd, "DISCO" }, { zar, "DISCO" }
            });
            fModel.SetupFx(fxM);
            fModel.VolSurfaces.Add("ZAR/USD", fxSurface);
            fModel.VolSurfaces.Add("USD/ZAR", fxSurface);

            var aModel = new AssetFxModel(buildDate, fModel);

            aModel.AddVolSurface("CL", comSurface);
            aModel.AddPriceCurve("CL", comCurve);
            aModel.CorrelationMatrix = correlVector;

            var product1 = AssetProductFactory.CreateAsianOption(dates[1], dates[1], 1400, "CL", OptionType.Call, usdCal, dates[1], zar);

            product1.TradeId          = "P1";
            product1.DiscountCurve    = "DISCO";
            product1.FxConversionType = FxConversionType.AverageThenConvert;
            var product2 = AssetProductFactory.CreateAsianOption(dates[2], dates[2], 1400, "CL", OptionType.Call, usdCal, dates[2], zar);

            product2.TradeId          = "P2";
            product2.DiscountCurve    = "DISCO";
            product2.FxConversionType = FxConversionType.AverageThenConvert;
            var product3 = AssetProductFactory.CreateAsianOption(dates[3], dates[3], 1400, "CL", OptionType.Call, usdCal, dates[3], zar);

            product3.TradeId          = "P3";
            product3.DiscountCurve    = "DISCO";
            product3.FxConversionType = FxConversionType.AverageThenConvert;

            var pfolio = new Portfolio {
                Instruments = new List <IInstrument> {
                    product1, product2, product3
                }
            };
            var settings = new McSettings
            {
                Generator         = RandomGeneratorType.MersenneTwister,
                NumberOfPaths     = (int)2.0.IntPow(15),
                NumberOfTimesteps = 1,
                ReportingCurrency = zar,
                Parallelize       = false,
                LocalCorrelation  = true,
            };
            var sut = new AssetFxMCModel(buildDate, pfolio, aModel, settings, TestProviderHelper.CurrencyProvider, TestProviderHelper.FutureSettingsProvider, TestProviderHelper.CalendarProvider);

            return(sut);
        }
Ejemplo n.º 6
0
        public void SolveSmileMarket()
        {
            var valDate = new DateTime(2018, 07, 28);
            var expDate = valDate.AddDays(365);
            var tExp    = (expDate - valDate).TotalDays / 365.0;
            var fwd     = 1000;

            double[] strikes = { 0.25, 0.5, 0.75 };

            var atmConstraint = new ATMStraddleConstraint
            {
                ATMVolType = AtmVolType.ZeroDeltaStraddle,
                MarketVol  = 0.32
            };

            var smile25d = new RRBFConstraint
            {
                Delta         = 0.25,
                FlyVol        = 0.01,
                RisykVol      = 0.02,
                WingQuoteType = WingQuoteType.Market
            };

            var s = new AssetSmileSolver();

            if (IsCoverageOnly)
            {
                s.Tollerance = 1;
            }

            var smile = s.Solve(atmConstraint, new[] { smile25d }, valDate, expDate, fwd, strikes, Interpolator1DType.Linear);

            if (!IsCoverageOnly)
            {
                Assert.Equal(atmConstraint.MarketVol, smile[1], 8);
            }

            var surface = new GridVolSurface(valDate, strikes, new[] { expDate }, new[] { smile }, StrikeType.ForwardDelta, Interpolator1DType.Linear, Interpolator1DType.Linear, DayCountBasis.Act365F);

            //reprice market RR structrure off smile, premium must match
            var marketVolC  = atmConstraint.MarketVol + smile25d.FlyVol + 0.5 * smile25d.RisykVol;
            var marketVolP  = atmConstraint.MarketVol + smile25d.FlyVol - 0.5 * smile25d.RisykVol;
            var marketKC25  = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, 0.25, 0, tExp, marketVolC);
            var marketKP25  = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -0.25, 0, tExp, marketVolP);
            var marketC25FV = BlackFunctions.BlackPV(fwd, marketKC25, 0, tExp, marketVolC, OptionType.C);
            var marketP25FV = BlackFunctions.BlackPV(fwd, marketKP25, 0, tExp, marketVolP, OptionType.P);
            var marketRR    = marketC25FV - marketP25FV;

            var volC25d  = surface.GetVolForAbsoluteStrike(marketKC25, expDate, fwd);
            var volP25d  = surface.GetVolForAbsoluteStrike(marketKP25, expDate, fwd);
            var call25FV = BlackFunctions.BlackPV(fwd, marketKC25, 0, tExp, volC25d, OptionType.C);
            var put25FV  = BlackFunctions.BlackPV(fwd, marketKP25, 0, tExp, volP25d, OptionType.P);
            var smileRR  = call25FV - put25FV;

            if (!IsCoverageOnly)
            {
                Assert.Equal(marketRR, smileRR, 8);
            }

            //reprice market BF structrure off smile, premium must match
            var marketVolBF   = atmConstraint.MarketVol + smile25d.FlyVol;
            var marketKBFC25  = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, 0.25, 0, tExp, marketVolBF);
            var marketKBFP25  = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -0.25, 0, tExp, marketVolBF);
            var marketBFC25FV = BlackFunctions.BlackPV(fwd, marketKBFC25, 0, tExp, marketVolBF, OptionType.C);
            var marketBFP25FV = BlackFunctions.BlackPV(fwd, marketKBFP25, 0, tExp, marketVolBF, OptionType.P);
            var marketBF      = marketBFC25FV + marketBFP25FV;

            var volCBF25d  = surface.GetVolForAbsoluteStrike(marketKBFC25, expDate, fwd);
            var volPBF25d  = surface.GetVolForAbsoluteStrike(marketKBFP25, expDate, fwd);
            var callBF25FV = BlackFunctions.BlackPV(fwd, marketKBFC25, 0, tExp, volCBF25d, OptionType.C);
            var putBF25FV  = BlackFunctions.BlackPV(fwd, marketKBFP25, 0, tExp, volPBF25d, OptionType.P);
            var smileBF    = callBF25FV + putBF25FV;

            if (!IsCoverageOnly)
            {
                Assert.Equal(marketBF, smileBF, 8);
            }
        }
Ejemplo n.º 7
0
        public static object CreateGridVolSurface(
            [ExcelArgument(Description = "Object name")] string ObjectName,
            [ExcelArgument(Description = "Asset Id")] string AssetId,
            [ExcelArgument(Description = "Origin date")] DateTime OriginDate,
            [ExcelArgument(Description = "Strikes")] double[] Strikes,
            [ExcelArgument(Description = "Expiries")] double[] Expiries,
            [ExcelArgument(Description = "Volatilities")] double[,] Volatilities,
            [ExcelArgument(Description = "Stike Type - default Absolute")] object StrikeType,
            [ExcelArgument(Description = "Stike Interpolation - default Linear")] object StrikeInterpolation,
            [ExcelArgument(Description = "Time Interpolation - default Linear")] object TimeInterpolation,
            [ExcelArgument(Description = "Time basis - default ACT365F")] object TimeBasis,
            [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 stikeType = StrikeType.OptionalExcel <string>("Absolute");
                var strikeInterpType = StrikeInterpolation.OptionalExcel <string>("Linear");
                var timeInterpType = TimeInterpolation.OptionalExcel <string>("LinearInVariance");
                var timeBasis = TimeBasis.OptionalExcel <string>("ACT365F");

                var expiries = ExcelHelper.ToDateTimeArray(Expiries);

                if (!Enum.TryParse(stikeType, out StrikeType sType))
                {
                    return $"Could not parse strike type - {stikeType}";
                }

                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}";
                }

                if (!Enum.TryParse(timeBasis, out DayCountBasis basis))
                {
                    return $"Could not parse time basis type - {timeBasis}";
                }

                var surface = new GridVolSurface(OriginDate, Strikes, expiries, Volatilities.SquareToJagged(), sType, siType, tiType, basis, 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);
            }));
        }
Ejemplo n.º 8
0
        public void LVMC_TriplePathsGenerated(double correlationAB, double correlationAC, double correlationBC)
        {
            var origin = DateTime.Now.Date;
            var engine = new PathEngine(2.IntPow(15));

            engine.AddPathProcess(new Random.MersenneTwister.MersenneTwister64()
            {
                UseNormalInverse = true,
                UseAnthithetic   = false
            });

            var correlMatrix = new double[][]
            {
                new double[] { 1.0, correlationAB, correlationAC },
                new double[] { correlationAB, 1.0, correlationBC },
                new double[] { correlationAC, correlationBC, 1.0 },
            };

            engine.AddPathProcess(new Cholesky(correlMatrix));

            var tenorsStr = new[] { "1m", "2m", "3m", "6m", "9m", "1y" };
            var tenors    = tenorsStr.Select(x => new Frequency(x));
            var expiries  = tenors.Select(t => origin.AddPeriod(RollType.F, new Calendar(), t)).ToArray();
            var deltaKs   = new[] { -0.1, -0.25, -0.5, -0.75, -0.9 };
            var smileVols = new[] { 0.32, 0.3, 0.29, 0.3, 0.32 };
            var vols      = Enumerable.Repeat(smileVols, expiries.Length).ToArray();

            var volSurface = new GridVolSurface(origin, deltaKs, expiries, vols,
                                                Core.Basic.StrikeType.ForwardDelta, Interpolator1DType.LinearFlatExtrap,
                                                Interpolator1DType.LinearInVariance, DayCountBasis.Act365F);

            var fwdCurve1 = new Func <double, double>(t => { return(1000); });
            var fwdCurve2 = new Func <double, double>(t => { return(1000); });
            var fwdCurve3 = new Func <double, double>(t => { return(1000); });

            var assetA = new LVSingleAsset
                         (
                startDate: origin,
                expiryDate: origin.AddYears(1),
                volSurface: volSurface,
                forwardCurve: fwdCurve1,
                nTimeSteps: 365,
                name: "TestAssetA"
                         );
            var assetB = new LVSingleAsset
                         (
                startDate: origin,
                expiryDate: origin.AddYears(1),
                volSurface: volSurface,
                forwardCurve: fwdCurve2,
                nTimeSteps: 365,
                name: "TestAssetB"
                         );
            var assetC = new LVSingleAsset
                         (
                startDate: origin,
                expiryDate: origin.AddYears(1),
                volSurface: volSurface,
                forwardCurve: fwdCurve3,
                nTimeSteps: 365,
                name: "TestAssetC"
                         );

            engine.AddPathProcess(assetA);
            engine.AddPathProcess(assetB);
            engine.AddPathProcess(assetC);

            var correlAB = new Correlation("TestAssetA", "TestAssetB");
            var correlAC = new Correlation("TestAssetA", "TestAssetC");
            var correlBC = new Correlation("TestAssetB", "TestAssetC");

            engine.AddPathProcess(correlAB);
            engine.AddPathProcess(correlAC);
            engine.AddPathProcess(correlBC);

            engine.SetupFeatures();
            engine.RunProcess();

            Assert.Equal(correlationAB, correlAB.AverageResult, 2);
            Assert.Equal(correlationAC, correlAC.AverageResult, 2);
            Assert.Equal(correlationBC, correlBC.AverageResult, 2);
        }