コード例 #1
0
        public void PathsGenerated()
        {
            var vol = 0.32;

            using var engine = new PathEngine(IsCoverageOnly ? 2.IntPow(6) : 2 << 10);
            engine.AddPathProcess(new Random.MersenneTwister.MersenneTwister64()
            {
                UseNormalInverse = true
            });
            var asset2 = new ConstantVolSingleAsset
                         (
                startDate: DateTime.Now.Date,
                expiry: DateTime.Now.Date.AddYears(1),
                vol: vol,
                spot: 500,
                drift: 0.00,
                numberOfSteps: IsCoverageOnly ? 1 : 365,
                name: "TestAsset2"
                         );

            engine.AddPathProcess(asset2);
            var payoff = new EuropeanPut("TestAsset2", 500, DateTime.Now.Date.AddYears(1));

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

            var pv      = payoff.AverageResult;
            var blackPv = BlackFunctions.BlackPV(500, 500, 0, 1, vol, OptionType.P);

            if (!IsCoverageOnly)
            {
                Assert.Equal(blackPv, pv, 0);
            }
        }
コード例 #2
0
 public void TestBlockGeneration()
 {
     using var engine = new PathEngine(4 << 2);
     engine.AddPathProcess(new Random.MersenneTwister.MersenneTwister64());
     engine.AddPathProcess(new FakeAssetProcess("TestUnderlying", numberOfDimensions: 2, timesteps: 10));
     engine.SetupFeatures();
     engine.RunProcess();
 }
コード例 #3
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);
            }
        }
コード例 #4
0
        public void TestBlockGenerationSobolFlipShifted()
        {
            var engine           = new PathEngine(64);
            var directionNumbers = new Random.Sobol.SobolDirectionNumbers("SobolDirectionNumbers.txt");

            engine.AddPathProcess(new Random.Sobol.SobolFlipShiftedPathGenerator(true, directionNumbers));
            engine.AddPathProcess(new FakeAssetProcess("TestUnderlying", numberOfDimensions: 2, timesteps: 10));
            engine.SetupFeatures();
            engine.RunProcess();
        }
コード例 #5
0
        public void RandsWithNoVectors()
        {
            var Paths = (int)System.Math.Pow(2, 14);

            using var engine = new PathEngine(Paths);
            engine.AddPathProcess(new Random.MersenneTwister.MersenneTwister64());
            engine.AddPathProcess(new FakeAssetProcess("TestUnderlying", numberOfDimensions: 2, timesteps: 100));
            engine.SetupFeatures();
            engine.RunProcess();
        }
コード例 #6
0
ファイル: MCLocalVolFacts.cs プロジェクト: mpvyard/qwack
        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);
        }
コード例 #7
0
        public void PathsGenerated()
        {
            var engine = new PathEngine(2 << 8);

            engine.AddPathProcess(new Random.MersenneTwister.MersenneTwister64()
            {
                UseNormalInverse = true
            });
            var asset = new ConstantVolSingleAsset
                        (
                startDate: DateTime.Now.Date,
                expiry: DateTime.Now.Date.AddYears(1),
                vol: 0.30,
                spot: 1000,
                drift: 0.00,
                numberOfSteps: 100,
                name: "TestAsset"
                        );

            engine.AddPathProcess(asset);
            var asset2 = new ConstantVolSingleAsset
                         (
                startDate: DateTime.Now.Date,
                expiry: DateTime.Now.Date.AddYears(1),
                vol: 0.30,
                spot: 500,
                drift: 0.00,
                numberOfSteps: 25,
                name: "TestAsset2"
                         );

            engine.AddPathProcess(asset2);
            var payoff = new EuropeanPut("TestAsset2", 500, DateTime.Now.Date.AddYears(1));

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


            var output = new OutputPathsToImage(engine, 2000, 1000);
        }
コード例 #8
0
ファイル: MCBlackVolFacts.cs プロジェクト: wy6688/qwack
        public void BlackMC_PathsGenerated()
        {
            var origin = DateTime.Now.Date;

            using var engine = new PathEngine(2.IntPow(IsCoverageOnly ? 6 : 15));
            engine.AddPathProcess(new Random.MersenneTwister.MersenneTwister64()
            {
                UseNormalInverse = true,
                UseAnthithetic   = false
            });
            var volSurface = new ConstantVolSurface(origin, 0.32);
            var fwdCurve   = new Func <double, double>(t => { return(900 + 100 * t); });
            var asset      = new BlackSingleAsset
                             (
                startDate: origin,
                expiryDate: origin.AddYears(1),
                volSurface: volSurface,
                forwardCurve: fwdCurve,
                nTimeSteps: IsCoverageOnly ? 1 : 10,
                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 blackPv = BlackFunctions.BlackPV(1000, 900, 0, 1, 0.32, OptionType.P);

            if (!IsCoverageOnly)
            {
                Assert.True(System.Math.Abs(blackPv - pv) < 1.0);
                var fwd = payoff2.AverageResult;
                Assert.True(System.Math.Abs(fwdCurve(1) / fwd - 1.0) < 0.001);
            }
        }
コード例 #9
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);
        }
コード例 #10
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);
            }
        }
コード例 #11
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);
        }