예제 #1
0
        public SecondDerivativeOp(int direction, FdmMesher mesher)
            : base(direction, mesher)
        {
            FdmLinearOpLayout   layout  = mesher.layout();
            FdmLinearOpIterator endIter = layout.end();

            for (FdmLinearOpIterator iter = layout.begin(); iter != endIter; ++iter)
            {
                int    i  = iter.index();
                double?hm = mesher.dminus(iter, direction_);
                double?hp = mesher.dplus(iter, direction_);

                double?zetam1 = hm * (hm + hp);
                double?zeta0  = hm * hp;
                double?zetap1 = hp * (hm + hp);

                int co = iter.coordinates()[direction_];
                if (co == 0 || co == layout.dim()[direction] - 1)
                {
                    lower_[i] = diag_[i] = upper_[i] = 0.0;
                }
                else
                {
                    lower_[i] = 2.0 / zetam1.Value;
                    diag_[i]  = -2.0 / zeta0.Value;
                    upper_[i] = 2.0 / zetap1.Value;
                }
            }
        }
예제 #2
0
        public FdmHestonEquityPart(FdmMesher mesher,
                                   YieldTermStructure rTS,
                                   YieldTermStructure qTS,
                                   FdmQuantoHelper quantoHelper      = null,
                                   LocalVolTermStructure leverageFct = null)
        {
            varianceValues_ = new Vector(0.5 * mesher.locations(1));
            dxMap_          = new FirstDerivativeOp(0, mesher);
            dxxMap_         = new SecondDerivativeOp(0, mesher).mult(0.5 * mesher.locations(1));
            mapT_           = new TripleBandLinearOp(0, mesher);
            mesher_         = mesher;
            rTS_            = rTS;
            qTS_            = qTS;
            quantoHelper_   = quantoHelper;
            leverageFct_    = leverageFct;

            // on the boundary s_min and s_max the second derivative
            // d^2V/dS^2 is zero and due to Ito's Lemma the variance term
            // in the drift should vanish.
            FdmLinearOpLayout   layout  = mesher_.layout();
            FdmLinearOpIterator endIter = layout.end();

            for (FdmLinearOpIterator iter = layout.begin(); iter != endIter;
                 ++iter)
            {
                if (iter.coordinates()[0] == 0 ||
                    iter.coordinates()[0] == layout.dim()[0] - 1)
                {
                    varianceValues_[iter.index()] = 0.0;
                }
            }
            volatilityValues_ = Vector.Sqrt(2 * varianceValues_);
        }
예제 #3
0
        public Fdm1DimSolver(FdmSolverDesc solverDesc,
                             FdmSchemeDesc schemeDesc,
                             FdmLinearOpComposite op)
        {
            solverDesc_     = solverDesc;
            schemeDesc_     = schemeDesc;
            op_             = op;
            thetaCondition_ = new FdmSnapshotCondition(
                0.99 * Math.Min(1.0 / 365.0,
                                solverDesc.condition.stoppingTimes().empty()
                            ? solverDesc.maturity
                            : solverDesc.condition.stoppingTimes().First()));

            conditions_ = FdmStepConditionComposite.joinConditions(thetaCondition_,
                                                                   solverDesc.condition);
            x_             = new InitializedList <double>(solverDesc.mesher.layout().size());
            initialValues_ = new InitializedList <double>(solverDesc.mesher.layout().size());
            resultValues_  = new Vector(solverDesc.mesher.layout().size());

            FdmMesher         mesher = solverDesc.mesher;
            FdmLinearOpLayout layout = mesher.layout();

            FdmLinearOpIterator endIter = layout.end();

            for (FdmLinearOpIterator iter = layout.begin(); iter != endIter;
                 ++iter)
            {
                initialValues_[iter.index()]
                    = solverDesc_.calculator.avgInnerValue(iter,
                                                           solverDesc.maturity);
                x_[iter.index()] = mesher.location(iter, 0);
            }
        }
예제 #4
0
        public FdmDividendHandler(DividendSchedule schedule,
                                  FdmMesher mesher,
                                  Date referenceDate,
                                  DayCounter dayCounter,
                                  int equityDirection)
        {
            x_               = new Vector(mesher.layout().dim()[equityDirection]);
            mesher_          = mesher;
            equityDirection_ = equityDirection;

            dividends_     = new List <double>();
            dividendDates_ = new List <Date>();
            dividendTimes_ = new List <double>();

            foreach (Dividend iter in schedule)
            {
                dividends_.Add(iter.amount());
                dividendDates_.Add(iter.date());
                dividendTimes_.Add(
                    dayCounter.yearFraction(referenceDate, iter.date()));
            }

            Vector tmp     = mesher_.locations(equityDirection);
            int    spacing = mesher_.layout().spacing()[equityDirection];

            for (int i = 0; i < x_.size(); ++i)
            {
                x_[i] = Math.Exp(tmp[i * spacing]);
            }
        }
 public FdmLogInnerValue(Payoff payoff,
                         FdmMesher mesher,
                         int direction)
 {
     payoff_         = payoff;
     mesher_         = mesher;
     direction_      = direction;
     avgInnerValues_ = new List <double>();
 }
예제 #6
0
 public FdmHestonVariancePart(
     FdmMesher mesher,
     YieldTermStructure rTS,
     double sigma, double kappa, double theta)
 {
     dyMap_ = new SecondDerivativeOp(1, mesher)
              .mult(0.5 * sigma * sigma * mesher.locations(1))
              .add(new FirstDerivativeOp(1, mesher)
                   .mult(kappa * (theta - mesher.locations(1))));
     mapT_ = new TripleBandLinearOp(1, mesher);
     rTS_  = rTS;
 }
예제 #7
0
 public FdmHullWhiteOp(FdmMesher mesher,
                       HullWhite model,
                       int direction)
 {
     x_     = mesher.locations(direction);
     dzMap_ = new TripleBandLinearOp(new FirstDerivativeOp(direction, mesher).mult(-1.0 * x_ * model.a()).add(
                                         new SecondDerivativeOp(direction, mesher).mult(0.5 * model.sigma() * model.sigma()
                                                                                        * new Vector(mesher.layout().size(), 1.0))));
     mapT_      = new TripleBandLinearOp(direction, mesher);
     direction_ = direction;
     model_     = model;
 }
        public FdmBermudanStepCondition(List <Date> exerciseDates,
                                        Date referenceDate,
                                        DayCounter dayCounter,
                                        FdmMesher mesher,
                                        FdmInnerValueCalculator calculator)
        {
            mesher_     = mesher;
            calculator_ = calculator;

            exerciseTimes_ = new List <double>();
            foreach (Date iter in exerciseDates)
            {
                exerciseTimes_.Add(
                    dayCounter.yearFraction(referenceDate, iter));
            }
        }
예제 #9
0
        public NinePointLinearOp(int d0, int d1, FdmMesher mesher)
        {
            d0_     = d0;
            d1_     = d1;
            i00_    = new InitializedList <int>(mesher.layout().size());
            i10_    = new InitializedList <int>(mesher.layout().size());
            i20_    = new InitializedList <int>(mesher.layout().size());
            i01_    = new InitializedList <int>(mesher.layout().size());
            i21_    = new InitializedList <int>(mesher.layout().size());
            i02_    = new InitializedList <int>(mesher.layout().size());
            i12_    = new InitializedList <int>(mesher.layout().size());
            i22_    = new InitializedList <int>(mesher.layout().size());
            a00_    = new InitializedList <double>(mesher.layout().size());
            a10_    = new InitializedList <double>(mesher.layout().size());
            a20_    = new InitializedList <double>(mesher.layout().size());
            a01_    = new InitializedList <double>(mesher.layout().size());
            a11_    = new InitializedList <double>(mesher.layout().size());
            a21_    = new InitializedList <double>(mesher.layout().size());
            a02_    = new InitializedList <double>(mesher.layout().size());
            a12_    = new InitializedList <double>(mesher.layout().size());
            a22_    = new InitializedList <double>(mesher.layout().size());
            mesher_ = mesher;

            Utils.QL_REQUIRE(d0_ != d1_ &&
                             d0_ < mesher.layout().dim().Count &&
                             d1_ < mesher.layout().dim().Count,
                             () => "inconsistent derivative directions");

            FdmLinearOpLayout   layout  = mesher.layout();
            FdmLinearOpIterator endIter = layout.end();

            for (FdmLinearOpIterator iter = layout.begin(); iter != endIter; ++iter)
            {
                int i = iter.index();

                i10_[i] = layout.neighbourhood(iter, d1_, -1);
                i01_[i] = layout.neighbourhood(iter, d0_, -1);
                i21_[i] = layout.neighbourhood(iter, d0_, 1);
                i12_[i] = layout.neighbourhood(iter, d1_, 1);
                i00_[i] = layout.neighbourhood(iter, d0_, -1, d1_, -1);
                i20_[i] = layout.neighbourhood(iter, d0_, 1, d1_, -1);
                i02_[i] = layout.neighbourhood(iter, d0_, -1, d1_, 1);
                i22_[i] = layout.neighbourhood(iter, d0_, 1, d1_, 1);
            }
        }
예제 #10
0
        public FdmHestonOp(FdmMesher mesher,
                           HestonProcess hestonProcess,
                           FdmQuantoHelper quantoHelper      = null,
                           LocalVolTermStructure leverageFct = null)
        {
            correlationMap_ = new SecondOrderMixedDerivativeOp(0, 1, mesher)
                              .mult(hestonProcess.rho() * hestonProcess.sigma()
                                    * mesher.locations(1));

            dyMap_ = new FdmHestonVariancePart(mesher,
                                               hestonProcess.riskFreeRate().currentLink(),
                                               hestonProcess.sigma(),
                                               hestonProcess.kappa(),
                                               hestonProcess.theta());
            dxMap_ = new FdmHestonEquityPart(mesher,
                                             hestonProcess.riskFreeRate().currentLink(),
                                             hestonProcess.dividendYield().currentLink(),
                                             quantoHelper,
                                             leverageFct);
        }
예제 #11
0
 public FdmDirichletBoundary(FdmMesher mesher,
                             double valueOnBoundary, int direction, Side side)
 {
     side_            = side;
     valueOnBoundary_ = valueOnBoundary;
     indices_         = new FdmIndicesOnBoundary(mesher.layout(),
                                                 direction, side).getIndices();
     if (side_ == Side.Lower)
     {
         xExtreme_ = mesher.locations(direction)[0];
     }
     else if (side_ == Side.Upper)
     {
         xExtreme_ = mesher
                     .locations(direction)[mesher.layout().dim()[direction] - 1];
     }
     else
     {
         Utils.QL_FAIL("internal error");
     }
 }
예제 #12
0
        public static FdmStepConditionComposite vanillaComposite(DividendSchedule cashFlow,
                                                                 Exercise exercise,
                                                                 FdmMesher mesher,
                                                                 FdmInnerValueCalculator calculator,
                                                                 Date refDate,
                                                                 DayCounter dayCounter)
        {
            List <List <double> >           stoppingTimes  = new List <List <double> >();
            List <IStepCondition <Vector> > stepConditions = new List <IStepCondition <Vector> >();

            if (!cashFlow.empty())
            {
                FdmDividendHandler dividendCondition =
                    new FdmDividendHandler(cashFlow, mesher,
                                           refDate, dayCounter, 0);

                stepConditions.Add(dividendCondition);
                stoppingTimes.Add(dividendCondition.dividendTimes());
            }

            Utils.QL_REQUIRE(exercise.type() == Exercise.Type.American ||
                             exercise.type() == Exercise.Type.European ||
                             exercise.type() == Exercise.Type.Bermudan,
                             () => "exercise type is not supported");
            if (exercise.type() == Exercise.Type.American)
            {
                stepConditions.Add(new FdmAmericanStepCondition(mesher, calculator));
            }
            else if (exercise.type() == Exercise.Type.Bermudan)
            {
                FdmBermudanStepCondition bermudanCondition =
                    new FdmBermudanStepCondition(exercise.dates(),
                                                 refDate, dayCounter,
                                                 mesher, calculator);
                stepConditions.Add(bermudanCondition);
                stoppingTimes.Add(bermudanCondition.exerciseTimes());
            }

            return(new FdmStepConditionComposite(stoppingTimes, stepConditions));
        }
예제 #13
0
        public TripleBandLinearOp(int direction, FdmMesher mesher)
        {
            direction_    = direction;
            i0_           = new InitializedList <int>(mesher.layout().size());
            i2_           = new InitializedList <int>(mesher.layout().size());
            reverseIndex_ = new InitializedList <int>(mesher.layout().size());
            lower_        = new InitializedList <double>(mesher.layout().size());
            diag_         = new InitializedList <double>(mesher.layout().size());
            upper_        = new InitializedList <double>(mesher.layout().size());
            mesher_       = mesher;

            FdmLinearOpLayout   layout  = mesher.layout();
            FdmLinearOpIterator endIter = layout.end();

            int        tmp;
            List <int> newDim = new List <int>(layout.dim());

            tmp = newDim[direction_];
            newDim[direction_] = newDim[0];
            newDim[0]          = tmp;

            List <int> newSpacing = new FdmLinearOpLayout(newDim).spacing();

            tmp = newSpacing[direction_];
            newSpacing[direction_] = newSpacing[0];
            newSpacing[0]          = tmp;

            for (FdmLinearOpIterator iter = layout.begin(); iter != endIter; ++iter)
            {
                int i = iter.index();

                i0_[i] = layout.neighbourhood(iter, direction, -1);
                i2_[i] = layout.neighbourhood(iter, direction, 1);

                List <int> coordinates = iter.coordinates();

                int newIndex = coordinates.inner_product(0, coordinates.Count, 0, newSpacing, 0);
                reverseIndex_[newIndex] = i;
            }
        }
예제 #14
0
 public FdmBlackScholesOp(FdmMesher mesher,
                          GeneralizedBlackScholesProcess bsProcess,
                          double strike,
                          bool localVol = false,
                          double?illegalLocalVolOverwrite = null,
                          int direction = 0,
                          FdmQuantoHelper quantoHelper = null)
 {
     mesher_   = mesher;
     rTS_      = bsProcess.riskFreeRate().currentLink();
     qTS_      = bsProcess.dividendYield().currentLink();
     volTS_    = bsProcess.blackVolatility().currentLink();
     localVol_ = (localVol) ? bsProcess.localVolatility().currentLink()
              : null;
     x_      = (localVol) ? new Vector(Vector.Exp(mesher.locations(direction))) : null;
     dxMap_  = new FirstDerivativeOp(direction, mesher);
     dxxMap_ = new SecondDerivativeOp(direction, mesher);
     mapT_   = new TripleBandLinearOp(direction, mesher);
     strike_ = strike;
     illegalLocalVolOverwrite_ = illegalLocalVolOverwrite;
     direction_    = direction;
     quantoHelper_ = quantoHelper;
 }
예제 #15
0
        public FirstDerivativeOp(int direction, FdmMesher mesher)
            : base(direction, mesher)
        {
            FdmLinearOpLayout   layout  = mesher.layout();
            FdmLinearOpIterator endIter = layout.end();

            for (FdmLinearOpIterator iter = layout.begin(); iter != endIter; ++iter)
            {
                int    i  = iter.index();
                double?hm = mesher.dminus(iter, direction_);
                double?hp = mesher.dplus(iter, direction_);

                double?zetam1 = hm * (hm + hp);
                double?zeta0  = hm * hp;
                double?zetap1 = hp * (hm + hp);

                if (iter.coordinates()[direction_] == 0)
                {
                    //upwinding scheme
                    lower_[i] = 0.0;
                    diag_[i]  = -(upper_[i] = 1 / hp.Value);
                }
                else if (iter.coordinates()[direction_]
                         == layout.dim()[direction] - 1)
                {
                    // downwinding scheme
                    lower_[i] = -(diag_[i] = 1 / hm.Value);
                    upper_[i] = 0.0;
                }
                else
                {
                    lower_[i] = -hp.Value / zetam1.Value;
                    diag_[i]  = (hp.Value - hm.Value) / zeta0.Value;
                    upper_[i] = hm.Value / zetap1.Value;
                }
            }
        }
 public FdmAffineModelSwapInnerValue(
     ModelType disModel,
     ModelType fwdModel,
     VanillaSwap swap,
     Dictionary <double, Date> exerciseDates,
     FdmMesher mesher,
     int direction)
 {
     disModel_  = disModel;
     fwdModel_  = fwdModel;
     mesher_    = mesher;
     direction_ = direction;
     swap_      = new VanillaSwap(swap.swapType,
                                  swap.nominal,
                                  swap.fixedSchedule(),
                                  swap.fixedRate,
                                  swap.fixedDayCount(),
                                  swap.floatingSchedule(),
                                  swap.iborIndex().clone(fwdTs_),
                                  swap.spread,
                                  swap.floatingDayCount(),
                                  null);
     exerciseDates_ = exerciseDates;
 }
예제 #17
0
 public FdmAmericanStepCondition(FdmMesher mesher, FdmInnerValueCalculator calculator)
 {
     mesher_     = mesher;
     calculator_ = calculator;
 }
예제 #18
0
        public SecondOrderMixedDerivativeOp(int d0, int d1, FdmMesher mesher)
            : base(d0, d1, mesher)
        {
            FdmLinearOpLayout   layout  = mesher.layout();
            FdmLinearOpIterator endIter = layout.end();

            for (FdmLinearOpIterator iter = layout.begin(); iter != endIter; ++iter)
            {
                int    i     = iter.index();
                double?hm_d0 = mesher.dminus(iter, d0_);
                double?hp_d0 = mesher.dplus(iter, d0_);
                double?hm_d1 = mesher.dminus(iter, d1_);
                double?hp_d1 = mesher.dplus(iter, d1_);

                double?zetam1 = hm_d0 * (hm_d0 + hp_d0);
                double?zeta0  = hm_d0 * hp_d0;
                double?zetap1 = hp_d0 * (hm_d0 + hp_d0);
                double?phim1  = hm_d1 * (hm_d1 + hp_d1);
                double?phi0   = hm_d1 * hp_d1;
                double?phip1  = hp_d1 * (hm_d1 + hp_d1);

                int c0 = iter.coordinates()[d0_];
                int c1 = iter.coordinates()[d1_];
                if (c0 == 0 && c1 == 0)
                {
                    // lower left corner
                    a00_[i] = a01_[i] = a02_[i] = a10_[i] = a20_[i] = 0.0;
                    a11_[i] = a22_[i] = 1.0 / (hp_d0.Value * hp_d1.Value);
                    a21_[i] = a12_[i] = -a11_[i];
                }
                else if (c0 == layout.dim()[d0_] - 1 && c1 == 0)
                {
                    // upper left corner
                    a22_[i] = a21_[i] = a20_[i] = a10_[i] = a00_[i] = 0.0;
                    a01_[i] = a12_[i] = 1.0 / (hm_d0.Value * hp_d1.Value);
                    a11_[i] = a02_[i] = -a01_[i];
                }
                else if (c0 == 0 && c1 == layout.dim()[d1_] - 1)
                {
                    // lower right corner
                    a00_[i] = a01_[i] = a02_[i] = a12_[i] = a22_[i] = 0.0;
                    a10_[i] = a21_[i] = 1.0 / (hp_d0.Value * hm_d1.Value);
                    a20_[i] = a11_[i] = -a10_[i];
                }
                else if (c0 == layout.dim()[d0_] - 1 && c1 == layout.dim()[d1_] - 1)
                {
                    // upper right corner
                    a20_[i] = a21_[i] = a22_[i] = a12_[i] = a02_[i] = 0.0;
                    a00_[i] = a11_[i] = 1.0 / (hm_d0.Value * hm_d1.Value);
                    a10_[i] = a01_[i] = -a00_[i];
                }
                else if (c0 == 0)
                {
                    // lower side
                    a00_[i] = a01_[i] = a02_[i] = 0.0;
                    a10_[i] = hp_d1.Value / (hp_d0.Value * phim1.Value);
                    a20_[i] = -a10_[i];
                    a21_[i] = (hp_d1.Value - hm_d1.Value) / (hp_d0.Value * phi0.Value);
                    a11_[i] = -a21_[i];
                    a22_[i] = hm_d1.Value / (hp_d0.Value * phip1.Value);
                    a12_[i] = -a22_[i];
                }
                else if (c0 == layout.dim()[d0_] - 1)
                {
                    // upper side
                    a20_[i] = a21_[i] = a22_[i] = 0.0;
                    a00_[i] = hp_d1.Value / (hm_d0.Value * phim1.Value);
                    a10_[i] = -a00_[i];
                    a11_[i] = (hp_d1.Value - hm_d1.Value) / (hm_d0.Value * phi0.Value);
                    a01_[i] = -a11_[i];
                    a12_[i] = hm_d1.Value / (hm_d0.Value * phip1.Value);
                    a02_[i] = -a12_[i];
                }
                else if (c1 == 0)
                {
                    // left side
                    a00_[i] = a10_[i] = a20_[i] = 0.0;
                    a01_[i] = hp_d0.Value / (zetam1.Value * hp_d1.Value);
                    a02_[i] = -a01_[i];
                    a12_[i] = (hp_d0.Value - hm_d0.Value) / (zeta0.Value * hp_d1.Value);
                    a11_[i] = -a12_[i];
                    a22_[i] = hm_d0.Value / (zetap1.Value * hp_d1.Value);
                    a21_[i] = -a22_[i];
                }
                else if (c1 == layout.dim()[d1_] - 1)
                {
                    // right side
                    a22_[i] = a12_[i] = a02_[i] = 0.0;
                    a00_[i] = hp_d0.Value / (zetam1.Value * hm_d1.Value);
                    a01_[i] = -a00_[i];
                    a11_[i] = (hp_d0.Value - hm_d0.Value) / (zeta0.Value * hm_d1.Value);
                    a10_[i] = -a11_[i];
                    a21_[i] = hm_d0.Value / (zetap1.Value * hm_d1.Value);
                    a20_[i] = -a21_[i];
                }
                else
                {
                    a00_[i] = hp_d0.Value * hp_d1.Value / (zetam1.Value * phim1.Value);
                    a10_[i] = -(hp_d0.Value - hm_d0.Value) * hp_d1.Value / (zeta0.Value * phim1.Value);
                    a20_[i] = -hm_d0.Value * hp_d1.Value / (zetap1.Value * phim1.Value);
                    a01_[i] = -hp_d0.Value * (hp_d1.Value - hm_d1.Value) / (zetam1.Value * phi0.Value);
                    a11_[i] = (hp_d0.Value - hm_d0.Value) * (hp_d1.Value - hm_d1.Value) / (zeta0.Value * phi0.Value);
                    a21_[i] = hm_d0.Value * (hp_d1.Value - hm_d1.Value) / (zetap1.Value * phi0.Value);
                    a02_[i] = -hp_d0.Value * hm_d1.Value / (zetam1.Value * phip1.Value);
                    a12_[i] = hm_d1.Value * (hp_d0.Value - hm_d0.Value) / (zeta0.Value * phip1.Value);
                    a22_[i] = hm_d0.Value * hm_d1.Value / (zetap1.Value * phip1.Value);
                }
            }
        }
 public FdmLogBasketInnerValue(BasketPayoff payoff,
                               FdmMesher mesher)
 {
     payoff_ = payoff;
     mesher_ = mesher;
 }