示例#1
0
        public void testTripleBandMapSolve()
        {
            int[]      dims = new int[] { 100, 400 };
            List <int> dim  = new List <int>(dims);

            FdmLinearOpLayout layout = new FdmLinearOpLayout(dim);

            List <Pair <double?, double?> > boundaries = new List <Pair <double?, double?> > ();

            boundaries.Add(new Pair <double?, double?>(0, 1.0));
            boundaries.Add(new Pair <double?, double?>(0, 1.0));

            FdmMesher mesher = new UniformGridMesher(layout, boundaries);

            FirstDerivativeOp dy = new FirstDerivativeOp(1, mesher);

            dy.axpyb(new Vector(1, 2.0), dy, dy, new Vector(1, 1.0));

            // check copy constructor
            FirstDerivativeOp copyOfDy = new FirstDerivativeOp(dy);

            Vector u = new Vector(layout.size());

            for (int i = 0; i < layout.size(); ++i)
            {
                u[i] = Math.Sin(0.1 * i) + Math.Cos(0.35 * i);
            }

            Vector t = new Vector(dy.solve_splitting(copyOfDy.apply(u), 1.0, 0.0));

            for (int i = 0; i < u.size(); ++i)
            {
                if (Math.Abs(u[i] - t[i]) > 1e-6)
                {
                    QAssert.Fail("solve and apply are not consistent "
                                 + "\n expected      : " + u[i]
                                 + "\n calculated    : " + t[i]);
                }
            }

            FirstDerivativeOp dx = new FirstDerivativeOp(0, mesher);

            dx.axpyb(new Vector(), dx, dx, new Vector(1, 1.0));

            FirstDerivativeOp copyOfDx = new FirstDerivativeOp(0, mesher);

            // check assignment
            copyOfDx = dx;

            t = dx.solve_splitting(copyOfDx.apply(u), 1.0, 0.0);
            for (int i = 0; i < u.size(); ++i)
            {
                if (Math.Abs(u[i] - t[i]) > 1e-6)
                {
                    QAssert.Fail("solve and apply are not consistent "
                                 + "\n expected      : " + u[i]
                                 + "\n calculated    : " + t[i]);
                }
            }

            SecondDerivativeOp dxx = new SecondDerivativeOp(0, mesher);

            dxx.axpyb(new Vector(1, 0.5), dxx, dx, new Vector(1, 1.0));

            // check of copy constructor
            SecondDerivativeOp copyOfDxx = new SecondDerivativeOp(dxx);

            t = dxx.solve_splitting(copyOfDxx.apply(u), 1.0, 0.0);

            for (int i = 0; i < u.size(); ++i)
            {
                if (Math.Abs(u[i] - t[i]) > 1e-6)
                {
                    QAssert.Fail("solve and apply are not consistent "
                                 + "\n expected      : " + u[i]
                                 + "\n calculated    : " + t[i]);
                }
            }

            //check assignment operator
            copyOfDxx.add(new SecondDerivativeOp(1, mesher));
            copyOfDxx = dxx;

            t = dxx.solve_splitting(copyOfDxx.apply(u), 1.0, 0.0);

            for (int i = 0; i < u.size(); ++i)
            {
                if (Math.Abs(u[i] - t[i]) > 1e-6)
                {
                    QAssert.Fail("solve and apply are not consistent "
                                 + "\n expected      : " + u[i]
                                 + "\n calculated    : " + t[i]);
                }
            }
        }
示例#2
0
        public void testCrankNicolsonWithDamping()
        {
            SavedSettings backup = new SavedSettings();

            DayCounter dc    = new Actual360();
            Date       today = Date.Today;

            SimpleQuote           spot  = new SimpleQuote(100.0);
            YieldTermStructure    qTS   = Utilities.flatRate(today, 0.06, dc);
            YieldTermStructure    rTS   = Utilities.flatRate(today, 0.06, dc);
            BlackVolTermStructure volTS = Utilities.flatVol(today, 0.35, dc);

            StrikedTypePayoff payoff =
                new CashOrNothingPayoff(Option.Type.Put, 100, 10.0);

            double   maturity = 0.75;
            Date     exDate   = today + Convert.ToInt32(maturity * 360 + 0.5);
            Exercise exercise = new EuropeanExercise(exDate);

            BlackScholesMertonProcess process = new
                                                BlackScholesMertonProcess(new Handle <Quote>(spot),
                                                                          new Handle <YieldTermStructure>(qTS),
                                                                          new Handle <YieldTermStructure>(rTS),
                                                                          new Handle <BlackVolTermStructure>(volTS));
            IPricingEngine engine =
                new AnalyticEuropeanEngine(process);

            VanillaOption opt = new VanillaOption(payoff, exercise);

            opt.setPricingEngine(engine);
            double expectedPV    = opt.NPV();
            double expectedGamma = opt.gamma();

            // fd pricing using implicit damping steps and Crank Nicolson
            int        csSteps = 25, dampingSteps = 3, xGrid = 400;
            List <int> dim = new InitializedList <int>(1, xGrid);

            FdmLinearOpLayout layout       = new FdmLinearOpLayout(dim);
            Fdm1dMesher       equityMesher =
                new FdmBlackScholesMesher(
                    dim[0], process, maturity, payoff.strike(),
                    null, null, 0.0001, 1.5,
                    new Pair <double?, double?>(payoff.strike(), 0.01));

            FdmMesher mesher =
                new FdmMesherComposite(equityMesher);

            FdmBlackScholesOp map =
                new FdmBlackScholesOp(mesher, process, payoff.strike());

            FdmInnerValueCalculator calculator =
                new FdmLogInnerValue(payoff, mesher, 0);

            object rhs = new Vector(layout.size());
            Vector x   = new Vector(layout.size());
            FdmLinearOpIterator endIter = layout.end();

            for (FdmLinearOpIterator iter = layout.begin(); iter != endIter;
                 ++iter)
            {
                (rhs as Vector)[iter.index()] = calculator.avgInnerValue(iter, maturity);
                x[iter.index()] = mesher.location(iter, 0);
            }

            FdmBackwardSolver solver = new FdmBackwardSolver(map, new FdmBoundaryConditionSet(),
                                                             new FdmStepConditionComposite(),
                                                             new FdmSchemeDesc().Douglas());

            solver.rollback(ref rhs, maturity, 0.0, csSteps, dampingSteps);

            MonotonicCubicNaturalSpline spline = new MonotonicCubicNaturalSpline(x, x.Count, rhs as Vector);

            double s               = spot.value();
            double calculatedPV    = spline.value(Math.Log(s));
            double calculatedGamma = (spline.secondDerivative(Math.Log(s))
                                      - spline.derivative(Math.Log(s))) / (s * s);

            double relTol = 2e-3;

            if (Math.Abs(calculatedPV - expectedPV) > relTol * expectedPV)
            {
                QAssert.Fail("Error calculating the PV of the digital option" +
                             "\n rel. tolerance:  " + relTol +
                             "\n expected:        " + expectedPV +
                             "\n calculated:      " + calculatedPV);
            }
            if (Math.Abs(calculatedGamma - expectedGamma) > relTol * expectedGamma)
            {
                QAssert.Fail("Error calculating the Gamma of the digital option" +
                             "\n rel. tolerance:  " + relTol +
                             "\n expected:        " + expectedGamma +
                             "\n calculated:      " + calculatedGamma);
            }
        }
示例#3
0
        public void testFdmLinearOpLayout()
        {
            int[]      dims = new int[] { 5, 7, 8 };
            List <int> dim  = new List <int>(dims);

            FdmLinearOpLayout layout = new FdmLinearOpLayout(dim);

            int calculatedDim = layout.dim().Count;
            int expectedDim   = dim.Count;

            if (calculatedDim != expectedDim)
            {
                QAssert.Fail("index.dimensions() should be " + expectedDim
                             + ", but is " + calculatedDim);
            }

            int calculatedSize = layout.size();
            int expectedSize   = dim.accumulate(0, 3, 1, (x, y) => (x * y));

            if (calculatedSize != expectedSize)
            {
                QAssert.Fail("index.size() should be "
                             + expectedSize + ", but is " + calculatedSize);
            }

            for (int k = 0; k < dim[0]; ++k)
            {
                for (int l = 0; l < dim[1]; ++l)
                {
                    for (int m = 0; m < dim[2]; ++m)
                    {
                        List <int> tmp = new InitializedList <int>(3);
                        tmp[0] = k; tmp[1] = l; tmp[2] = m;

                        int calculatedIndex = layout.index(tmp);
                        int expectedIndex   = k + l * dim[0] + m * dim[0] * dim[1];

                        if (expectedIndex != layout.index(tmp))
                        {
                            QAssert.Fail("index.size() should be " + expectedIndex
                                         + ", but is " + calculatedIndex);
                        }
                    }
                }
            }

            FdmLinearOpIterator iter = layout.begin();

            for (int m = 0; m < dim[2]; ++m)
            {
                for (int l = 0; l < dim[1]; ++l)
                {
                    for (int k = 0; k < dim[0]; ++k, ++iter)
                    {
                        for (int n = 1; n < 4; ++n)
                        {
                            int nn = layout.neighbourhood(iter, 1, n);
                            int calculatedIndex = k + m * dim[0] * dim[1]
                                                  + ((l < dim[1] - n)? l + n
                                              : dim[1] - 1 - (l + n - (dim[1] - 1))) * dim[0];

                            if (nn != calculatedIndex)
                            {
                                QAssert.Fail("next neighbourhood index is " + nn
                                             + " but should be " + calculatedIndex);
                            }
                        }

                        for (int n = 1; n < 7; ++n)
                        {
                            int nn = layout.neighbourhood(iter, 2, -n);
                            int calculatedIndex = k + l * dim[0]
                                                  + ((m < n) ? n - m : m - n) * dim[0] * dim[1];
                            if (nn != calculatedIndex)
                            {
                                QAssert.Fail("next neighbourhood index is " + nn
                                             + " but should be " + calculatedIndex);
                            }
                        }
                    }
                }
            }
        }