Ejemplo n.º 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);
            }
        }
        public void TestInitialize()
        {
            _nodeA = new Node <string>("Chiang Mai");
            _nodeB = new Node <string>("Lampang");
            _nodeC = new Node <string>("Sukhothai");
            _nodeD = new Node <string>("Ayuthaya");
            _nodeE = new Node <string>("Bangkok");

            var graph = new Graph <string>();

            // Add node
            graph.AddNode(_nodeA);
            graph.AddNode(_nodeB);
            graph.AddNode(_nodeC);
            graph.AddNode(_nodeD);
            graph.AddNode(_nodeE);

            // Add edges
            graph.AddEdge(_nodeA, _nodeB, 3);
            graph.AddEdge(_nodeA, _nodeC, 5);
            graph.AddEdge(_nodeB, _nodeA, 3);
            graph.AddEdge(_nodeB, _nodeC, 1);
            graph.AddEdge(_nodeB, _nodeD, 2);
            graph.AddEdge(_nodeC, _nodeA, 5);
            graph.AddEdge(_nodeC, _nodeB, 1);
            graph.AddEdge(_nodeC, _nodeD, 3);
            graph.AddEdge(_nodeC, _nodeE, 6);
            graph.AddEdge(_nodeD, _nodeB, 2);
            graph.AddEdge(_nodeD, _nodeC, 3);
            graph.AddEdge(_nodeD, _nodeE, 4);
            graph.AddEdge(_nodeE, _nodeC, 6);
            graph.AddEdge(_nodeE, _nodeD, 4);

            _pathEngine = new PathEngine <string>(graph);
        }
Ejemplo n.º 3
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();
 }
Ejemplo n.º 4
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.º 5
0
        public static void AddRate <T>(this PathEngine engine, T rateFeature) where T : IRateFeature
        {
            var rateCollection = engine.Features.GetFeature <IRatesFeature>();

            rateCollection.AddRate(rateFeature);
            if (rateFeature is IPathProcess process)
            {
                engine.AddPathProcess(process);
            }
        }
Ejemplo n.º 6
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();
        }
Ejemplo n.º 7
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();
        }
Ejemplo n.º 8
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.º 9
0
        static void FindShortestPath()
        {
            // Step 1: Create node
            var nodeA = new Node <string>("Chiang Mai");
            var nodeB = new Node <string>("Lampang");
            var nodeC = new Node <string>("Sukhothai");
            var nodeD = new Node <string>("Ayuthaya");
            var nodeE = new Node <string>("Bangkok");

            // Step 2: Create graph data
            var graph = new Graph <string>();

            // Step 3: Add node
            graph.AddNode(nodeA);
            graph.AddNode(nodeB);
            graph.AddNode(nodeC);
            graph.AddNode(nodeD);
            graph.AddNode(nodeE);

            // Step 4: Add edges
            graph.AddEdge(nodeA, nodeB, 3);
            graph.AddEdge(nodeA, nodeC, 5);
            graph.AddEdge(nodeB, nodeA, 3);
            graph.AddEdge(nodeB, nodeC, 1);
            graph.AddEdge(nodeB, nodeD, 2);
            graph.AddEdge(nodeC, nodeA, 5);
            graph.AddEdge(nodeC, nodeB, 1);
            graph.AddEdge(nodeC, nodeD, 3);
            graph.AddEdge(nodeC, nodeE, 6);
            graph.AddEdge(nodeD, nodeB, 2);
            graph.AddEdge(nodeD, nodeC, 3);
            graph.AddEdge(nodeD, nodeE, 4);
            graph.AddEdge(nodeE, nodeC, 6);
            graph.AddEdge(nodeE, nodeD, 4);

            // Step 5: Create path engine and call function
            var pathEngine = new PathEngine <string>(graph);
            var pathResult = pathEngine.FindShortestPath(nodeA, nodeE);

            // Display path result
            Console.WriteLine($"Total cost from {pathResult.From} to {pathResult.To} is {pathResult.TotalCost}");
            Console.WriteLine("============================================");

            foreach (var path in pathResult.Paths)
            {
                Console.WriteLine(path.ToString());
            }

            Console.WriteLine("============================================");
            Console.ReadKey();
        }
        public List <Model.PathAction> GetKeyboardPath(string searchTerm, string keyboardType)
        {
            List <Model.PathAction> pathActions = new List <Model.PathAction>();

            KeyboardType type;

            if (Enum.TryParse(keyboardType, out type))
            {
                Model.Keyboard keyboard = _keyboards.GetKeyboard(type);

                PathEngine engine = new PathEngine(searchTerm, keyboard);
                return(engine.GeneratePath());
            }
            else
            {
                throw new InvalidKeyboardTypeException($"{keyboardType} is not a valid keyboard type.");
            }
        }
Ejemplo n.º 11
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);
        }
Ejemplo n.º 12
0
        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);
            }
        }
Ejemplo n.º 13
0
        public OutputPathsToImage(PathEngine engine, int width, int height)
        {
            var image = new Image <Argb32>(width, height);
            var rnd   = new Random();

            var minMax = engine.BlockSet.Select(b => b.RawData.MinMax()).Aggregate((currentValues, next) => (System.Math.Min(currentValues.min, next.min), System.Math.Max(currentValues.max, next.max)));

            var range           = minMax.max - minMax.min;
            var pixelsPerPointY = height / range;
            var pixelsPerPointX = width / engine.BlockSet.Steps;

            foreach (var block in engine.BlockSet)
            {
                for (var factor = 0; factor < block.Factors; factor++)
                {
                    for (var path = 0; path < block.NumberOfPaths; path++)
                    {
                        var indexOfPath = block.GetIndexOfPathStart(path, factor);
                        var bytes       = new byte[3];
                        rnd.NextBytes(bytes);
                        var pen    = new ImageSharp.Drawing.Pens.Pen <Argb32>(new Argb32(bytes[0], bytes[1], bytes[2]), 2.0f);
                        var points = new Vector2[block.NumberOfSteps];
                        for (var step = 0; step < block.NumberOfSteps; step++)
                        {
                            var nextX = (float)(step * pixelsPerPointX);
                            var nextY = (float)((block[indexOfPath + step * Vector <double> .Count] - minMax.min) * pixelsPerPointY);
                            points[step] = new Vector2(nextX, nextY);
                        }
                        image.DrawLines(pen, points);
                    }
                }
            }
            using (var fs = System.IO.File.Create("C:\\code\\output.png"))
            {
                image.SaveAsPng(fs);
            }
        }
Ejemplo n.º 14
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);
        }
Ejemplo n.º 15
0
        static void FindShortestPath()
        {
            // Step 1: Create node
            var nodeA = new Node <string>("Station A", 0);
            var nodeB = new Node <string>("Station B", 1);
            var nodeC = new Node <string>("SStation C", 2);
            var nodeD = new Node <string>("Station D", 3);
            var nodeE = new Node <string>("Station E", 4);
            var nodeF = new Node <string>("Station F", 5);

            // Step 2: Create graph data
            var graph = new Graph <string>();

            // Step 3: Add node

            graph.AddNode(nodeA);
            graph.AddNode(nodeB);
            graph.AddNode(nodeC);
            graph.AddNode(nodeD);
            graph.AddNode(nodeE);
            graph.AddNode(nodeF);



            // Step 4: Add edges
            graph.AddEdge(nodeA, nodeB, 0, 3);
            graph.AddEdge(nodeA, nodeC, 1, 5);
            graph.AddEdge(nodeB, nodeA, 2, 3);
            graph.AddEdge(nodeB, nodeC, 3, 1);
            graph.AddEdge(nodeB, nodeD, 4, 2);
            graph.AddEdge(nodeC, nodeA, 5, 5);
            graph.AddEdge(nodeC, nodeB, 6, 1);
            graph.AddEdge(nodeC, nodeD, 7, 3);
            graph.AddEdge(nodeC, nodeE, 8, 6);
            graph.AddEdge(nodeD, nodeB, 9, 2);
            graph.AddEdge(nodeD, nodeC, 10, 3);
            graph.AddEdge(nodeD, nodeE, 11, 4);
            graph.AddEdge(nodeE, nodeC, 12, 6);
            graph.AddEdge(nodeE, nodeD, 13, 4);
            graph.AddEdge(nodeF, nodeC, 14, 6);
            graph.AddEdge(nodeF, nodeD, 15, 4);

            /////////add OD pairs/////
            graph.AddOD(nodeA, nodeF, 0, 100);
            graph.AddOD(nodeA, nodeD, 1, 100);
            ////////////////
            graph.CreateNodeEdgeRelation();
            // Step 5: Create path engine and call function
            var pathEngine = new PathEngine <string>(graph);
            var pathResult = pathEngine.FindShortestPath(nodeA, nodeF);

            for (int w = 0; w < graph.ODs.Count; ++w)
            {
                var sp = pathEngine.FindShortestPath(graph.ODs[w].Origin, graph.ODs[w].Dest);
                Console.WriteLine(graph.ODs[w]);
                for (int i = 0; i < sp.PathEdgeList.Count; i++)
                {
                    Console.WriteLine(sp.PathEdgeList[i].Id);
                    graph.Edges[sp.PathEdgeList[i].Id].Flow = graph.ODs[w].Demand + graph.Edges[sp.PathEdgeList[i].Id].Flow;
                    Console.WriteLine("flow ={0}", graph.Edges[sp.PathEdgeList[i].Id].Flow);
                    graph.Edges[sp.PathEdgeList[i].Id].getCost();
                }
            }

            for (int i = 0; i < graph.Nodes[0].OutGoingEdges.Count; i++)
            {
                int edgeid = graph.Nodes[0].OutGoingEdges[i].Id;
                Console.WriteLine("edge {0} leaving node 0/A", graph.Nodes[0].OutGoingEdges[i].Id);
            }
            // Display path result
            Console.WriteLine($"Total cost from {pathResult.From} to {pathResult.To} is {pathResult.TotalCost}");
            Console.WriteLine("============================================");

            foreach (var path in pathResult.PathEdgeList)
            {
                Console.WriteLine(path.ToString());
                Console.WriteLine(path.Id);
            }

            Console.WriteLine("============================================");
            Console.ReadKey();
        }
Ejemplo n.º 16
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.º 17
0
 void Awake()
 {
     Instance = this;
 }
Ejemplo n.º 18
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);
        }
Ejemplo n.º 19
0
        public AssetFxMCModel(DateTime originDate, Portfolio portfolio, IAssetFxModel model, McSettings settings, ICurrencyProvider currencyProvider, IFutureSettingsProvider futureSettingsProvider, ICalendarProvider calendarProvider)
        {
            if (settings.CompactMemoryMode && settings.AveragePathCorrection)
            {
                throw new Exception("Can't use both CompactMemoryMode and PathCorrection");
            }

            _currencyProvider       = currencyProvider;
            _futureSettingsProvider = futureSettingsProvider;
            _calendarProvider       = calendarProvider;
            Engine = new PathEngine(settings.NumberOfPaths)
            {
                Parallelize       = settings.Parallelize,
                CompactMemoryMode = settings.CompactMemoryMode
            };
            OriginDate = originDate;
            Portfolio  = portfolio;
            Model      = model;
            Settings   = settings;
            switch (settings.Generator)
            {
            case RandomGeneratorType.MersenneTwister:
                Engine.AddPathProcess(new Random.MersenneTwister.MersenneTwister64()
                {
                    UseNormalInverse = true,
                    UseAnthithetic   = false
                });
                break;

            case RandomGeneratorType.Sobol:
                var directionNumers = new Random.Sobol.SobolDirectionNumbers(GetSobolFilename());
                Engine.AddPathProcess(new Random.Sobol.SobolPathGenerator(directionNumers, 1000)
                {
                    UseNormalInverse = true
                });
                break;

            case RandomGeneratorType.Constant:
                Engine.AddPathProcess(new Random.Constant.Constant()
                {
                    UseNormalInverse = true,
                });
                break;

            case RandomGeneratorType.FlipFlop:
                Engine.AddPathProcess(new Random.Constant.FlipFlop(settings.CreditSettings.ConfidenceInterval, true));
                break;
            }
            Engine.IncrementDepth();

            if (model.CorrelationMatrix != null)
            {
                if (settings.LocalCorrelation)
                {
                    Engine.AddPathProcess(new CholeskyWithTime(model.CorrelationMatrix, model));
                }
                else
                {
                    Engine.AddPathProcess(new Cholesky(model.CorrelationMatrix));
                }
                Engine.IncrementDepth();
            }

            var lastDate         = portfolio.LastSensitivityDate;
            var assetIds         = portfolio.AssetIds();
            var assetInstruments = portfolio.Instruments
                                   .Where(x => x is IAssetInstrument)
                                   .Select(x => x as IAssetInstrument);
            var fixingsNeeded = new Dictionary <string, List <DateTime> >();

            foreach (var ins in assetInstruments)
            {
                var fixingsForIns = ins.PastFixingDates(originDate);
                if (fixingsForIns.Any())
                {
                    foreach (var kv in fixingsForIns)
                    {
                        if (!fixingsNeeded.ContainsKey(kv.Key))
                        {
                            fixingsNeeded.Add(kv.Key, new List <DateTime>());
                        }
                        fixingsNeeded[kv.Key] = fixingsNeeded[kv.Key].Concat(kv.Value).Distinct().ToList();
                    }
                }
            }

            //asset processes
            var fxAssetsToAdd = new List <string>();
            var corrections   = new Dictionary <string, SimpleAveragePathCorrector>();

            foreach (var assetId in assetIds)
            {
                if (assetId.Length == 7 && assetId[3] == '/')
                {
                    fxAssetsToAdd.Add(assetId);
                    continue;
                }

                if (!(model.GetVolSurface(assetId) is IATMVolSurface surface))
                {
                    throw new Exception($"Vol surface for asset {assetId} could not be cast to IATMVolSurface");
                }
                var fixingDict = fixingsNeeded.ContainsKey(assetId) ? model.GetFixingDictionary(assetId) : null;
                var fixings    = fixingDict != null ?
                                 fixingsNeeded[assetId].ToDictionary(x => x, x => fixingDict.GetFixing(x))
                    : new Dictionary <DateTime, double>();
                var futuresSim = settings.ExpensiveFuturesSimulation &&
                                 (model.GetPriceCurve(assetId).CurveType == PriceCurveType.ICE || model.GetPriceCurve(assetId).CurveType == PriceCurveType.NYMEX);
                if (futuresSim)
                {
                    var fwdCurve = new Func <DateTime, double>(t =>
                    {
                        return(model.GetPriceCurve(assetId).GetPriceForDate(t));
                    });
                    var asset = new BlackFuturesCurve
                                (
                        startDate: originDate,
                        expiryDate: lastDate,
                        volSurface: surface,
                        forwardCurve: fwdCurve,
                        nTimeSteps: settings.NumberOfTimesteps,
                        name: Settings.FuturesMappingTable[assetId],
                        pastFixings: fixings,
                        futureSettingsProvider: _futureSettingsProvider
                                );
                    Engine.AddPathProcess(asset);
                }
                else
                {
                    var fwdCurve = new Func <double, double>(t =>
                    {
                        var c = model.GetPriceCurve(assetId);
                        var d = originDate.AddYearFraction(t, DayCountBasis.ACT365F);
                        if (c is PriceCurve pc)
                        {
                            d = d.AddPeriod(RollType.F, pc.SpotCalendar, pc.SpotLag);
                        }
                        else if (c is ContangoPriceCurve cc)
                        {
                            d = d.AddPeriod(RollType.F, cc.SpotCalendar, cc.SpotLag);
                        }
                        return(c.GetPriceForDate(d));
                    });

                    IATMVolSurface adjSurface  = null;
                    var            correlation = 0.0;

                    if (settings.ReportingCurrency != model.GetPriceCurve(assetId).Currency)
                    {
                        var fxAdjPair    = settings.ReportingCurrency + "/" + model.GetPriceCurve(assetId).Currency;
                        var fxAdjPairInv = model.GetPriceCurve(assetId).Currency + "/" + settings.ReportingCurrency;
                        if (!(model.FundingModel.GetVolSurface(fxAdjPair) is IATMVolSurface adjSurface2))
                        {
                            throw new Exception($"Vol surface for fx pair {fxAdjPair} could not be cast to IATMVolSurface");
                        }
                        adjSurface = adjSurface2;
                        if (model.CorrelationMatrix != null)
                        {
                            if (model.CorrelationMatrix.TryGetCorrelation(fxAdjPair, assetId, out var correl))
                            {
                                correlation = correl;
                            }
                            else if (model.CorrelationMatrix.TryGetCorrelation(fxAdjPairInv, assetId, out var correl2))
                            {
                                correlation = -correl2;
                            }
                        }
                    }

                    if (settings.McModelType == McModelType.LocalVol)
                    {
                        var asset = new LVSingleAsset
                                    (
                            startDate: originDate,
                            expiryDate: lastDate,
                            volSurface: surface,
                            forwardCurve: fwdCurve,
                            nTimeSteps: settings.NumberOfTimesteps,
                            name: assetId,
                            pastFixings: fixings,
                            fxAdjustSurface: adjSurface,
                            fxAssetCorrelation: correlation
                                    );
                        Engine.AddPathProcess(asset);
                    }
                    else if (settings.McModelType == McModelType.TurboSkew)
                    {
                        var asset = new TurboSkewSingleAsset
                                    (
                            startDate: originDate,
                            expiryDate: lastDate,
                            volSurface: surface,
                            forwardCurve: fwdCurve,
                            nTimeSteps: settings.NumberOfTimesteps,
                            name: assetId,
                            pastFixings: fixings,
                            fxAdjustSurface: adjSurface,
                            fxAssetCorrelation: correlation
                                    );
                        Engine.AddPathProcess(asset);
                    }
                    else
                    {
                        var asset = new BlackSingleAsset
                                    (
                            startDate: originDate,
                            expiryDate: lastDate,
                            volSurface: surface,
                            forwardCurve: fwdCurve,
                            nTimeSteps: settings.NumberOfTimesteps,
                            name: assetId,
                            pastFixings: fixings,
                            fxAdjustSurface: adjSurface,
                            fxAssetCorrelation: correlation
                                    );
                        Engine.AddPathProcess(asset);
                    }
                    if (settings.AveragePathCorrection)
                    {
                        corrections.Add(assetId, new SimpleAveragePathCorrector(new SimpleAveragePathCalculator(assetId)
                        {
                            CompactMode = settings.CompactMemoryMode
                        }, surface, fwdCurve, assetId, fixings, adjSurface, correlation));
                    }
                }
            }

            //fx pairs
            var pairsAdded = new List <string>();
            var fxPairs    = portfolio.FxPairs(model).Concat(fxAssetsToAdd);
            var payoutCcys = portfolio.Instruments.Select(i => i.Currency);

            if (payoutCcys.Any(p => p != settings.ReportingCurrency))
            {
                var ccysToAdd  = payoutCcys.Where(p => p != settings.ReportingCurrency).Distinct();
                var pairsToAdd = ccysToAdd.Select(c => $"{c.Ccy}/{settings.ReportingCurrency}");
                fxPairs = fxPairs.Concat(pairsToAdd).Distinct();
            }
            foreach (var fxPair in fxPairs)
            {
                var fxPairName = fxPair;
                var pair       = fxPairName.FxPairFromString(_currencyProvider, _calendarProvider);

                if (pairsAdded.Contains(pair.ToString()))
                {
                    continue;
                }

                if (!(model.FundingModel.VolSurfaces[fxPairName] is IATMVolSurface surface))
                {
                    throw new Exception($"Vol surface for fx pair {fxPairName} could not be cast to IATMVolSurface");
                }

                var fwdCurve = new Func <double, double>(t =>
                {
                    var date     = originDate.AddYearFraction(t, DayCountBasis.ACT365F);
                    var spotDate = pair.SpotDate(date);
                    return(model.FundingModel.GetFxRate(spotDate, fxPairName));
                });

                pairsAdded.Add(pair.ToString());

                if (settings.McModelType == McModelType.LocalVol)
                {
                    var asset = new LVSingleAsset
                                (
                        startDate: originDate,
                        expiryDate: lastDate,
                        volSurface: surface,
                        forwardCurve: fwdCurve,
                        nTimeSteps: settings.NumberOfTimesteps,
                        name: fxPairName
                                );
                    Engine.AddPathProcess(asset);

                    if (settings.AveragePathCorrection)
                    {
                        corrections.Add(fxPairName, new SimpleAveragePathCorrector(new SimpleAveragePathCalculator(fxPairName)
                        {
                            CompactMode = settings.CompactMemoryMode
                        }, surface, fwdCurve, fxPairName));
                    }
                }
                else if (settings.McModelType == McModelType.TurboSkew)
                {
                    if (fxPairName.Substring(fxPairName.Length - 3, 3) != settings.ReportingCurrency)
                    {//needs to be drift-adjusted
                        var fxAdjPair = settings.ReportingCurrency + "/" + fxPairName.Substring(fxPairName.Length - 3, 3);
                        if (!(model.FundingModel.VolSurfaces[fxAdjPair] is IATMVolSurface adjSurface))
                        {
                            throw new Exception($"Vol surface for fx pair {fxAdjPair} could not be cast to IATMVolSurface");
                        }
                        var correlation = fxPair == fxAdjPair ? -1.0 : 0.0;
                        if (correlation != -1.0 && model.CorrelationMatrix != null)
                        {
                            if (model.CorrelationMatrix.TryGetCorrelation(fxAdjPair, fxPair, out var correl))
                            {
                                correlation = correl;
                            }
                        }

                        var asset = new TurboSkewSingleAsset
                                    (
                            startDate: originDate,
                            expiryDate: lastDate,
                            volSurface: surface,
                            forwardCurve: fwdCurve,
                            nTimeSteps: settings.NumberOfTimesteps,
                            name: fxPairName,
                            fxAdjustSurface: adjSurface,
                            fxAssetCorrelation: correlation
                                    );
                        Engine.AddPathProcess(asset);

                        if (settings.AveragePathCorrection)
                        {
                            corrections.Add(fxPairName, new SimpleAveragePathCorrector(new SimpleAveragePathCalculator(fxPairName)
                            {
                                CompactMode = settings.CompactMemoryMode
                            }, surface, fwdCurve, fxPairName, null, adjSurface, correlation));
                        }
                    }
                    else
                    {
                        var asset = new TurboSkewSingleAsset
                                    (
                            startDate: originDate,
                            expiryDate: lastDate,
                            volSurface: surface,
                            forwardCurve: fwdCurve,
                            nTimeSteps: settings.NumberOfTimesteps,
                            name: fxPairName
                                    );
                        Engine.AddPathProcess(asset);

                        if (settings.AveragePathCorrection)
                        {
                            corrections.Add(fxPairName, new SimpleAveragePathCorrector(new SimpleAveragePathCalculator(fxPairName)
                            {
                                CompactMode = settings.CompactMemoryMode
                            }, surface, fwdCurve, fxPairName));
                        }
                    }
                }
                else
                {
                    if (fxPairName.Substring(fxPairName.Length - 3, 3) != settings.ReportingCurrency)
                    {//needs to be drift-adjusted
                        var fxAdjPair = settings.ReportingCurrency + "/" + fxPairName.Substring(fxPairName.Length - 3, 3);
                        if (!(model.FundingModel.VolSurfaces[fxAdjPair] is IATMVolSurface adjSurface))
                        {
                            throw new Exception($"Vol surface for fx pair {fxAdjPair} could not be cast to IATMVolSurface");
                        }
                        var correlation = fxPair == fxAdjPair ? -1.0 : 0.0;
                        if (correlation != -1.0 && model.CorrelationMatrix != null)
                        {
                            if (model.CorrelationMatrix.TryGetCorrelation(fxAdjPair, fxPair, out var correl))
                            {
                                correlation = correl;
                            }
                        }

                        var asset = new BlackSingleAsset
                                    (
                            startDate: originDate,
                            expiryDate: lastDate,
                            volSurface: surface,
                            forwardCurve: fwdCurve,
                            nTimeSteps: settings.NumberOfTimesteps,
                            name: fxPairName,
                            fxAdjustSurface: adjSurface,
                            fxAssetCorrelation: correlation
                                    );
                        Engine.AddPathProcess(asset);

                        if (settings.AveragePathCorrection)
                        {
                            corrections.Add(fxPairName, new SimpleAveragePathCorrector(new SimpleAveragePathCalculator(fxPairName)
                            {
                                CompactMode = settings.CompactMemoryMode
                            }, surface, fwdCurve, fxPairName, null, adjSurface, correlation));
                        }
                    }
                    else
                    {
                        var asset = new BlackSingleAsset
                                    (
                            startDate: originDate,
                            expiryDate: lastDate,
                            volSurface: surface,
                            forwardCurve: fwdCurve,
                            nTimeSteps: settings.NumberOfTimesteps,
                            name: fxPairName
                                    );
                        Engine.AddPathProcess(asset);

                        if (settings.AveragePathCorrection)
                        {
                            corrections.Add(fxPairName, new SimpleAveragePathCorrector(new SimpleAveragePathCalculator(fxPairName)
                            {
                                CompactMode = settings.CompactMemoryMode
                            }, surface, fwdCurve, fxPairName));
                        }
                    }
                }
            }
            //apply path correctin
            if (settings.AveragePathCorrection && corrections.Any())
            {
                Engine.IncrementDepth();
                foreach (var pc in corrections)
                {
                    Engine.AddPathProcess(pc.Value.PathCalc);
                }
                Engine.IncrementDepth();
                foreach (var pc in corrections)
                {
                    Engine.AddPathProcess(pc.Value);
                }
            }

            //payoffs
            Engine.IncrementDepth();
            _payoffs = assetInstruments.ToDictionary(x => x.TradeId, y => new AssetPathPayoff(y, _currencyProvider, _calendarProvider, settings.ReportingCurrency));
            if (!settings.AvoidRegressionForBackPricing && _payoffs.Any(x => x.Value.Regressors != null))
            {
                var regressorsToAdd = _payoffs.Where(x => x.Value.Regressors != null)
                                      .SelectMany(x => x.Value.Regressors)
                                      .Distinct();

                foreach (var regressor in regressorsToAdd)
                {
                    Engine.AddPathProcess(regressor);
                    foreach (var payoff in _payoffs.Where(x => x.Value.Regressors != null))
                    {
                        if (payoff.Value.Regressors.Any(x => x == regressor))
                        {
                            payoff.Value.SetRegressor(regressor);
                        }
                    }
                }

                Engine.IncrementDepth();
            }
            foreach (var product in _payoffs)
            {
                if (settings.AvoidRegressionForBackPricing && (product.Value.AssetInstrument is BackPricingOption || product.Value.AssetInstrument is MultiPeriodBackpricingOption))
                {
                    product.Value.VanillaModel = VanillaModel;
                }

                Engine.AddPathProcess(product.Value);
            }

            var metricsNeedRegression = new[] { BaseMetric.PFE, BaseMetric.KVA, BaseMetric.CVA, BaseMetric.FVA, BaseMetric.EPE };

            //Need to calculate PFE
            if (settings.CreditSettings != null && settings.CreditSettings.ExposureDates != null && settings.ReportingCurrency != null && metricsNeedRegression.Contains(settings.CreditSettings.Metric))//setup for PFE, etc
            {
                Engine.IncrementDepth();

                switch (settings.CreditSettings.PfeRegressorType)
                {
                case PFERegressorType.MultiLinear:
                    _regressor = new LinearPortfolioValueRegressor(settings.CreditSettings.ExposureDates,
                                                                   _payoffs.Values.ToArray(), settings);
                    break;

                case PFERegressorType.MonoLinear:
                    _regressor = new MonoIndexRegressor(settings.CreditSettings.ExposureDates,
                                                        _payoffs.Values.ToArray(), settings, true);
                    break;
                }
                Engine.AddPathProcess(_regressor);
            }

            //Need to calculate expected capital
            if (settings.CreditSettings != null && settings.CreditSettings.ExposureDates != null && settings.ReportingCurrency != null && settings.CreditSettings.Metric == BaseMetric.ExpectedCapital)
            {
                Engine.IncrementDepth();
                _capitalCalc = new ExpectedCapitalCalculator(Portfolio, settings.CreditSettings.CounterpartyRiskWeighting, settings.CreditSettings.AssetIdToHedgeGroupMap, settings.ReportingCurrency, VanillaModel, settings.CreditSettings.ExposureDates);
                Engine.AddPathProcess(_capitalCalc);
            }

            Engine.SetupFeatures();
        }