Пример #1
0
        public FdBlackScholesVanillaEngine(
            GeneralizedBlackScholesProcess process,
            FdmQuantoHelper quantoHelper = null,
            int tGrid = 100, int xGrid = 100, int dampingSteps = 0,
            FdmSchemeDesc schemeDesc            = null,
            bool localVol                       = false,
            double?illegalLocalVolOverwrite     = null,
            CashDividendModel cashDividendModel = CashDividendModel.Spot)
        {
            process_                  = process;
            tGrid_                    = tGrid;
            xGrid_                    = xGrid;
            dampingSteps_             = dampingSteps;
            schemeDesc_               = schemeDesc == null ? new FdmSchemeDesc().Douglas() : schemeDesc;
            localVol_                 = localVol;
            illegalLocalVolOverwrite_ = illegalLocalVolOverwrite;
            quantoHelper_             = quantoHelper;

            process_.registerWith(update);
        }
Пример #2
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;
 }
Пример #3
0
 public MakeFdBlackScholesVanillaEngine withQuantoHelper(FdmQuantoHelper quantoHelper)
 {
     quantoHelper_ = quantoHelper;
     return(this);
 }
Пример #4
0
        public FdmBlackScholesMesher(int size,
                                     GeneralizedBlackScholesProcess process,
                                     double maturity, double strike,
                                     double?xMinConstraint = null,
                                     double?xMaxConstraint = null,
                                     double eps            = 0.0001,
                                     double scaleFactor    = 1.5,
                                     Pair <double?, double?> cPoint
                                     = null,
                                     DividendSchedule dividendSchedule = null,
                                     FdmQuantoHelper fdmQuantoHelper   = null,
                                     double spotAdjustment             = 0.0)
            : base(size)
        {
            double S = process.x0();

            Utils.QL_REQUIRE(S > 0.0, () => "negative or null underlying given");

            dividendSchedule = dividendSchedule == null ? new DividendSchedule() : dividendSchedule;
            List <pair_double> intermediateSteps = new List <pair_double>();

            for (int i = 0; i < dividendSchedule.Count &&
                 process.time(dividendSchedule[i].date()) <= maturity; ++i)
            {
                intermediateSteps.Add(
                    new pair_double(
                        process.time(dividendSchedule[i].date()),
                        dividendSchedule[i].amount()
                        ));
            }

            int intermediateTimeSteps = (int)Math.Max(2, 24.0 * maturity);

            for (int i = 0; i < intermediateTimeSteps; ++i)
            {
                intermediateSteps.Add(
                    new pair_double((i + 1) * (maturity / intermediateTimeSteps), 0.0));
            }

            intermediateSteps.Sort();

            Handle <YieldTermStructure> rTS = process.riskFreeRate();
            Handle <YieldTermStructure> qTS = fdmQuantoHelper != null
                                          ? new Handle <YieldTermStructure>(
                new QuantoTermStructure(process.dividendYield(),
                                        process.riskFreeRate(),
                                        new Handle <YieldTermStructure>(fdmQuantoHelper.foreignTermStructure()),
                                        process.blackVolatility(),
                                        strike,
                                        new Handle <BlackVolTermStructure>(fdmQuantoHelper.fxVolatilityTermStructure()),
                                        fdmQuantoHelper.exchRateATMlevel(),
                                        fdmQuantoHelper.equityFxCorrelation()))
                                          : process.dividendYield();

            double lastDivTime = 0.0;
            double fwd = S + spotAdjustment;
            double mi = fwd, ma = fwd;

            for (int i = 0; i < intermediateSteps.Count; ++i)
            {
                double divTime   = intermediateSteps[i].first;
                double divAmount = intermediateSteps[i].second;

                fwd = fwd / rTS.currentLink().discount(divTime) * rTS.currentLink().discount(lastDivTime)
                      * qTS.currentLink().discount(divTime) / qTS.currentLink().discount(lastDivTime);

                mi = Math.Min(mi, fwd); ma = Math.Max(ma, fwd);

                fwd -= divAmount;

                mi = Math.Min(mi, fwd); ma = Math.Max(ma, fwd);

                lastDivTime = divTime;
            }

            // Set the grid boundaries
            double normInvEps = new InverseCumulativeNormal().value(1 - eps);
            double sigmaSqrtT
                = process.blackVolatility().currentLink().blackVol(maturity, strike)
                  * Math.Sqrt(maturity);

            double?xMin = Math.Log(mi) - sigmaSqrtT * normInvEps * scaleFactor;
            double?xMax = Math.Log(ma) + sigmaSqrtT * normInvEps * scaleFactor;

            if (xMinConstraint != null)
            {
                xMin = xMinConstraint;
            }
            if (xMaxConstraint != null)
            {
                xMax = xMaxConstraint;
            }

            Fdm1dMesher helper;

            if (cPoint != null &&
                cPoint.first != null &&
                Math.Log(cPoint.first.Value) >= xMin && Math.Log(cPoint.first.Value) <= xMax)
            {
                helper = new Concentrating1dMesher(xMin.Value, xMax.Value, size,
                                                   new Pair <double?, double?>(Math.Log(cPoint.first.Value), cPoint.second));
            }
            else
            {
                helper = new Uniform1dMesher(xMin.Value, xMax.Value, size);
            }

            locations_ = helper.locations();
            for (int i = 0; i < locations_.Count; ++i)
            {
                dplus_[i]  = helper.dplus(i);
                dminus_[i] = helper.dminus(i);
            }
        }